From 0c72fecb9a5a635bcaee97f833ec87d827e40491 Mon Sep 17 00:00:00 2001 From: tigoe Date: Fri, 28 Apr 2017 16:35:16 -0400 Subject: [PATCH] Added new examples and tests --- .../LoRaDumpRegisters/LoRaDumpRegisters.ino | 26 ++++ examples/LoRaDuplex/LoRaDuplex.ino | 101 ++++++++++++++ .../LoRaDuplexCallback/LoRaDuplexCallback.ino | 100 ++++++++++++++ examples/LoRaSetSpread/LoRaSetSpread.ino | 81 +++++++++++ examples/LoRaSetSyncWord/LoRaSetSyncWord.ino | 77 +++++++++++ test/LoRaDumpRegisters/LoRaDumpRegisters.ino | 26 ++++ .../LoRaDuplexAutoContinuous.ino | 129 ++++++++++++++++++ 7 files changed, 540 insertions(+) create mode 100644 examples/LoRaDumpRegisters/LoRaDumpRegisters.ino create mode 100644 examples/LoRaDuplex/LoRaDuplex.ino create mode 100644 examples/LoRaDuplexCallback/LoRaDuplexCallback.ino create mode 100644 examples/LoRaSetSpread/LoRaSetSpread.ino create mode 100644 examples/LoRaSetSyncWord/LoRaSetSyncWord.ino create mode 100644 test/LoRaDumpRegisters/LoRaDumpRegisters.ino create mode 100644 test/LoRaDuplexAutoContinuous/LoRaDuplexAutoContinuous.ino diff --git a/examples/LoRaDumpRegisters/LoRaDumpRegisters.ino b/examples/LoRaDumpRegisters/LoRaDumpRegisters.ino new file mode 100644 index 0000000..6f6a7b4 --- /dev/null +++ b/examples/LoRaDumpRegisters/LoRaDumpRegisters.ino @@ -0,0 +1,26 @@ +/* + LoRa register dump + context: Arduino + +*/ +#include // include libraries +#include + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Receiver"); + LoRa.setPins(7, 6, 1); // set CS, reset, IRQ pin + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + LoRa.sleep(); + LoRa.dumpRegisters(Serial); +} + + +void loop() { + +} + diff --git a/examples/LoRaDuplex/LoRaDuplex.ino b/examples/LoRaDuplex/LoRaDuplex.ino new file mode 100644 index 0000000..bfdeadc --- /dev/null +++ b/examples/LoRaDuplex/LoRaDuplex.ino @@ -0,0 +1,101 @@ +/* + LoRa Duplex communication + + Sends a message every half second, and polls continually + for new incoming messages. Implements a one-byte addressing scheme, + with 0xFF as the broadcast address. + + Uses readString() from Stream class to read payload. The Stream class' + timeout may affect other functuons, like the radio's callback. For an + + created 28 April 2017 + by Tom Igoe +*/ +#include // include libraries +#include +const int csPin = 7; // LoRa radio chip select +const int resetPin = 6; // LoRa radio reset +const int irqPin = 1; // change for your board; must be a hardware interrupt pin + +String outgoing; // outgoing message +byte msgCount = 0; // count of outgoing messages +byte localAddress = 0xBB; // address of this device +byte destination = 0xFF; // destination to send to +long lastSendTime = 0; // last send time +int interval = 2000; // interval between sends + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Duplex"); + LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin + + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + + LoRa.setTimeout(10); // set Stream timeout of 10ms + Serial.println("LoRa init succeeded."); +} + +void loop() { + if (millis() - lastSendTime > interval) { + String message = "HeLoRa World!"; // send a message + sendMessage(message); + Serial.println("Sending " + message); + lastSendTime = millis(); // timestamp the message + interval = random(2000) + 1000; // 2-3 seconds + } + + // parse for a packet, and call onReceive with the result: + onReceive(LoRa.parsePacket()); + +} + +void sendMessage(String outgoing) { + LoRa.beginPacket(); // start packet + LoRa.write(destination); // add destination address + LoRa.write(localAddress); // add sender address + LoRa.write(msgCount); // add message ID + LoRa.write(outgoing.length()); // add payload length + LoRa.print(outgoing); // add payload + LoRa.endPacket(); // finish packet and send it + msgCount++; // increment message ID +} + + +void onReceive(int packetSize) { + if (packetSize == 0) return; // if there's no packet, return + + // read packet header bytes: + int recipient = LoRa.read(); // recipient address + byte sender = LoRa.read(); // sender address + byte incomingMsgId = LoRa.read(); // incoming msg ID + byte incomingLength = LoRa.read(); // incoming msg length + String incoming = ""; + while (LoRa.available()) { + incoming += (char)LoRa.read(); + } + if (incomingLength != incoming.length()) { // check length for error + Serial.println("error: message length does not match length"); + return; // skip rest of function + } + + // if the recipient isn't this device or broadcast, + if (recipient != localAddress && recipient != 0xFF) { + Serial.println("This message is not for me."); + return; // skip rest of function + } + + // if message is for this device, or broadcast, print details: + Serial.println("Received from:" + String(sender, HEX)); + Serial.println("Sent to:" + String(recipient, HEX)); + Serial.println("Message ID:" + String(incomingMsgId)); + Serial.println("Message length:" + String(incomingLength)); + Serial.println("Message:" + incoming); + Serial.println("RSSI:" + String(LoRa.packetRssi())); + Serial.println("Snr:" + String(LoRa.packetSnr())); + Serial.println(); +} + diff --git a/examples/LoRaDuplexCallback/LoRaDuplexCallback.ino b/examples/LoRaDuplexCallback/LoRaDuplexCallback.ino new file mode 100644 index 0000000..ddb4b74 --- /dev/null +++ b/examples/LoRaDuplexCallback/LoRaDuplexCallback.ino @@ -0,0 +1,100 @@ +/* + LoRa Duplex communication wth callback + + Sends a message every half second, and uses callback + for new incoming messages. Implements a one-byte addressing scheme, + with 0xFF as the broadcast address. + + Note: while sending, LoRa radio is not listening for incoming messages. + Note2: when using the callback method, you can't use any of the Stream + functions that rely on the timeout, such as readString, parseInt(), etc. + + created 28 April 2017 + by Tom Igoe +*/ +#include // include libraries +#include +const int csPin = 7; // LoRa radio chip select +const int resetPin = 6; // LoRa radio reset +const int irqPin = 1; // change for your board; must be a hardware interrupt pin + +String outgoing; // outgoing message +byte msgCount = 0; // count of outgoing messages +byte localAddress = 0xBB; // address of this device +byte destination = 0xFF; // destination to send to +long lastSendTime = 0; // last send time +int interval = 2000; // interval between sends + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Duplex with callback"); + LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin + + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + + LoRa.onReceive(onReceive); + LoRa.receive(); + Serial.println("LoRa init succeeded."); +} + +void loop() { + if (millis() - lastSendTime > interval) { + String message = "HeLoRa World!"; // send a message + sendMessage(message); + Serial.println("Sending " + message); + lastSendTime = millis(); // timestamp the message + interval = random(2000) + 1000; // 2-3 seconds + LoRa.receive(); // go back into receive mode + } +} + +void sendMessage(String outgoing) { + LoRa.beginPacket(); // start packet + LoRa.write(destination); // add destination address + LoRa.write(localAddress); // add sender address + LoRa.write(msgCount); // add message ID + LoRa.write(outgoing.length()); // add payload length + LoRa.print(outgoing); // add payload + LoRa.endPacket(); // finish packet and send it + msgCount++; // increment message ID +} + + +void onReceive(int packetSize) { + if (packetSize == 0) return; // if there's no packet, return + + // read packet header bytes: + int recipient = LoRa.read(); // recipient address + byte sender = LoRa.read(); // sender address + byte incomingMsgId = LoRa.read(); // incoming msg ID + byte incomingLength = LoRa.read(); // incoming msg length + String incoming = ""; // payload of packet + while (LoRa.available()) { // can't use readString() in callback, so + incoming += (char)LoRa.read(); // add bytes one by one + } + if (incomingLength != incoming.length()) { // check length for error + Serial.println("error: message length does not match length"); + return; // skip rest of function + } + + // if the recipient isn't this device or broadcast, + if (recipient != localAddress && recipient != 0xFF) { + Serial.println("This message is not for me."); + return; // skip rest of function + } + + // if message is for this device, or broadcast, print details: + Serial.println("Received from:" + String(sender, HEX)); + Serial.println("Sent to:" + String(recipient, HEX)); + Serial.println("Message ID:" + String(incomingMsgId)); + Serial.println("Message length:" + String(incomingLength)); + Serial.println("Message:" + incoming); + Serial.println("RSSI:" + String(LoRa.packetRssi())); + Serial.println("Snr:" + String(LoRa.packetSnr())); + Serial.println(); +} + diff --git a/examples/LoRaSetSpread/LoRaSetSpread.ino b/examples/LoRaSetSpread/LoRaSetSpread.ino new file mode 100644 index 0000000..7a7f0b7 --- /dev/null +++ b/examples/LoRaSetSpread/LoRaSetSpread.ino @@ -0,0 +1,81 @@ +/* + LoRa Duplex communication with Spreading Factor + + Sends a message every half second, and polls continually + for new incoming messages. Sets the LoRa radio's spreading factor. + + Spreading factor affects how far apart the radio's transmissions + are, across the available bandwidth. Radios with different spreading + factors will not receive each other's transmissions. This is one way you + can filter out radios you want to ignore, without making an addressing scheme. + + Spreading factor affects reliability of transmission at high rates, however, + so avoid a hugh spreading factor when you're sending continually. + + See the Semtech datasheete, http://www.semtech.com/images/datasheet/sx1276.pdf + for more on Spreading Factor. + + created 28 April 2017 + by Tom Igoe +*/ +#include // include libraries +#include +const int csPin = 7; // LoRa radio chip select +const int resetPin = 6; // LoRa radio reset +const int irqPin = 1; // change for your board; must be a hardware interrupt pin + +byte msgCount = 0; // count of outgoing messages +int interval = 2000; // interval between sends +long lastSendTime = 0; // time of last packet send + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Duplex"); + LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin + + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + LoRa.setSpreadingFactor(8); // ranges from 6-12,default 7 see API docs + Serial.println("LoRa init succeeded."); +} + +void loop() { + if (millis() - lastSendTime > interval) { + String message = "HeLoRa World! "; // send a message + message += msgCount; + sendMessage(message); + Serial.println("Sending " + message); + lastSendTime = millis(); // timestamp the message + interval = random(2000) + 1000; // 2-3 seconds + msgCount++; + } + + // parse for a packet, and call onReceive with the result: + onReceive(LoRa.parsePacket()); +} + +void sendMessage(String outgoing) { + LoRa.beginPacket(); // start packet + LoRa.print(outgoing); // add payload + LoRa.endPacket(); // finish packet and send it + msgCount++; // increment message ID +} + + +void onReceive(int packetSize) { + if (packetSize == 0) return; // if there's no packet, return + + // read packet header bytes: + String incoming = ""; + while (LoRa.available()) { + incoming += (char)LoRa.read(); + } + Serial.println("Message:" + incoming); + Serial.println("RSSI:" + String(LoRa.packetRssi())); + Serial.println("Snr:" + String(LoRa.packetSnr())); + Serial.println(); +} + diff --git a/examples/LoRaSetSyncWord/LoRaSetSyncWord.ino b/examples/LoRaSetSyncWord/LoRaSetSyncWord.ino new file mode 100644 index 0000000..be0ea88 --- /dev/null +++ b/examples/LoRaSetSyncWord/LoRaSetSyncWord.ino @@ -0,0 +1,77 @@ +/* + LoRa Duplex communication with Sync Word + + Sends a message every half second, and polls continually + for new incoming messages. Sets the LoRa radio's Sync Word. + + Spreading factor is basically the radio's network ID. Radios with different + Sync Words will not receive each other's transmissions. This is one way you + can filter out radios you want to ignore, without making an addressing scheme. + + See the Semtech datasheet, http://www.semtech.com/images/datasheet/sx1276.pdf + for more on Sync Word. + + created 28 April 2017 + by Tom Igoe +*/ +#include // include libraries +#include +const int csPin = 7; // LoRa radio chip select +const int resetPin = 6; // LoRa radio reset +const int irqPin = 1; // change for your board; must be a hardware interrupt pin + +byte msgCount = 0; // count of outgoing messages +int interval = 2000; // interval between sends +long lastSendTime = 0; // time of last packet send + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Duplex"); + LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin + + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + LoRa.setSyncWord(F3); // ranges from 0-0xFF, default 0x34, see API docs + Serial.println("LoRa init succeeded."); +} + +void loop() { + if (millis() - lastSendTime > interval) { + String message = "HeLoRa World! "; // send a message + message += msgCount; + sendMessage(message); + Serial.println("Sending " + message); + lastSendTime = millis(); // timestamp the message + interval = random(2000) + 1000; // 2-3 seconds + msgCount++; + } + + // parse for a packet, and call onReceive with the result: + onReceive(LoRa.parsePacket()); +} + +void sendMessage(String outgoing) { + LoRa.beginPacket(); // start packet + LoRa.print(outgoing); // add payload + LoRa.endPacket(); // finish packet and send it + msgCount++; // increment message ID +} + + +void onReceive(int packetSize) { + if (packetSize == 0) return; // if there's no packet, return + + // read packet header bytes: + String incoming = ""; + while (LoRa.available()) { + incoming += (char)LoRa.read(); + } + Serial.println("Message:" + incoming); + Serial.println("RSSI:" + String(LoRa.packetRssi())); + Serial.println("Snr:" + String(LoRa.packetSnr())); + Serial.println(); +} + diff --git a/test/LoRaDumpRegisters/LoRaDumpRegisters.ino b/test/LoRaDumpRegisters/LoRaDumpRegisters.ino new file mode 100644 index 0000000..6f6a7b4 --- /dev/null +++ b/test/LoRaDumpRegisters/LoRaDumpRegisters.ino @@ -0,0 +1,26 @@ +/* + LoRa register dump + context: Arduino + +*/ +#include // include libraries +#include + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Receiver"); + LoRa.setPins(7, 6, 1); // set CS, reset, IRQ pin + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + LoRa.sleep(); + LoRa.dumpRegisters(Serial); +} + + +void loop() { + +} + diff --git a/test/LoRaDuplexAutoContinuous/LoRaDuplexAutoContinuous.ino b/test/LoRaDuplexAutoContinuous/LoRaDuplexAutoContinuous.ino new file mode 100644 index 0000000..6dfb1b0 --- /dev/null +++ b/test/LoRaDuplexAutoContinuous/LoRaDuplexAutoContinuous.ino @@ -0,0 +1,129 @@ +/* + LoRa Duplex communication with callback + context: Arduino + + This sketch is for testing transmission between two devices, one an Uno, + and one not an Uno (a MKRZero, in my case). The #defines are there for that + reason,and should be removed before making this a real example. + + It sends every half second, and polls continually for new packets. + + There's a block that's commented out in the loop that lets you change the + sync word on one device, to test sync address filtering. The SyncWordTest.xslx + spreadsheet shows some typical results. +*/ +#include // include libraries +#include + +#if defined (__AVR_ATmega328P__) +#define irqPin 2 +#define addr 0xFD +#define netId 0x18 +#define change 1 +#else +#define irqPin 1 +#define addr 0xFE +#define netId 0x18 +#define change 0 +#endif + +String message; // outgoing message +byte messageId = 0; // ID of outgoing message +byte localAddress = addr; // address of this device +byte destination = 0xFF; // destination to send to +byte syncWord = netId; // Sync word (network ID) +long lastSend = 0; + +void setup() { + while (!Serial); + Serial.begin(9600); // initialize serial + Serial.println("LoRa Receiver"); + LoRa.setPins(7, 6, irqPin); // set CS, reset, IRQ pin + if (!LoRa.begin(915E6)) { // initialize ratio at 915Mhz + Serial.println("LoRa init failed. Check your connections."); + while (true); // if failed, do nothing + } + LoRa.sleep(); + LoRa.setSyncWord(syncWord); + LoRa.idle(); + // register the receive callback + LoRa.onReceive(onReceive); + + // put the radio into receive mode + LoRa.receive(); + LoRa.setTimeout(10); // set Stream timeout of 10ms + Serial.println("LoRa init succeeded."); + + Serial.println("Sync Word:" + String(syncWord, HEX)); + Serial.println("Local Addr:" + String(localAddress, HEX)); + Serial.println(); + Serial.print("Received from:\t"); + Serial.print("Sent to:\t"); + Serial.print("Message ID:\t"); + Serial.print("Message length:\t"); + Serial.print("Message:\t"); + Serial.print("Sender's sync word:\t"); + Serial.print("RSSI:\t"); + Serial.println("Snr:"); +} + +void loop() { + if (millis() - lastSend > 500) { + message = "sender's syncWord:\t"; // send a message; tab automatically + message += String(syncWord, HEX); // separates the sync word into its own column + sendMessage(message); + lastSend = millis(); + } + // Change the sync word once every 10 messages: + //if(messageId % 10 == 0 && change == 1) { + // LoRa.sleep(); + // LoRa.setSyncWord(syncWord++); + // LoRa.idle(); + //} +} + +void sendMessage(String outgoing) { + LoRa.beginPacket(); // start packet + LoRa.write(destination); // add destination address + LoRa.write(localAddress); // add sender address + LoRa.write(messageId); // add message ID + LoRa.write(outgoing.length()); // add payload length + LoRa.print(outgoing); // add payload + LoRa.endPacket(); // finish packet and send it + messageId++; // increment message ID +} + + +void onReceive(int packetSize) { + // read packet header bytes: + int recipient = LoRa.read(); // recipient address + byte sender = LoRa.read(); // sender address + byte latestMessage = LoRa.read(); // incoming msg ID + byte msgLength = LoRa.read(); // incoming msg length + String incoming = LoRa.readString();// payload of packet + + if (msgLength != incoming.length()) { // check length for error + Serial.println("error: message length does not match length"); + } + // if the recipient isn't this device or broadcast, + if (recipient != localAddress && recipient != 0xFF) { + Serial.println("This message is not for me."); + return; // skip rest of loop + } + // if message is for this device, or broadcast, print details: + Serial.print(sender, HEX); + Serial.print("\t"); + Serial.print(recipient, HEX); + Serial.print("\t"); + Serial.print(latestMessage); + Serial.print("\t"); + Serial.print(msgLength); + Serial.print("\t"); + Serial.print(incoming); + Serial.print("\t"); + Serial.print(LoRa.packetRssi()); // print RSSI of packet + Serial.print("\t"); + Serial.print(LoRa.packetSnr()); + Serial.println(); +} +