/* RadioLib LoRaWAN End Device Reference Example This example joins a LoRaWAN network and will send uplink packets. Before you start, you will have to register your device at https://www.thethingsnetwork.org/ After your device is registered, you can run this example. The device will join the network and start uploading data. Also, most of the possible and available functions are shown here for reference. LoRaWAN v1.1 requires the use of EEPROM (persistent storage). Please refer to the 'persistent' example once you are familiar with LoRaWAN. Running this examples REQUIRES you to check "Resets DevNonces" on your LoRaWAN dashboard. Refer to the network's documentation on how to do this. For default module settings, see the wiki page https://github.com/jgromes/RadioLib/wiki/Default-configuration For full API reference, see the GitHub Pages https://jgromes.github.io/RadioLib/ For LoRaWAN details, see the wiki page https://github.com/jgromes/RadioLib/wiki/LoRaWAN */ #include "config.h" // include the library #include void setup() { Serial.begin(115200); while (!Serial); // Wait for serial to be initalised delay(2000); // Give time to switch to the serial monitor Serial.println(F("\nSetup")); int16_t state = 0; // return value for calls to RadioLib Serial.println(F("Initalise the radio")); state = radio.begin(); debug(state != RADIOLIB_ERR_NONE, F("Initalise radio failed"), state, true); // Override the default join rate // uint8_t joinDR = 3; Serial.println(F("Join ('login') to the LoRaWAN Network")); state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, true); debug(state < RADIOLIB_ERR_NONE, F("Join failed"), state, true); // Print the DevAddr Serial.print("[LoRaWAN] DevAddr: "); Serial.println(node.getDevAddr(), HEX); // Disable the ADR algorithm (on by default which is preferable) node.setADR(false); // Set a fixed datarate & make it persistent (not normal) node.setDatarate(4); // Enable CSMA which tries to minimize packet loss by searching // for a free channel before actually sending an uplink node.setCSMA(6, 2, true); // Manages uplink intervals to the TTN Fair Use Policy node.setDutyCycle(true, 1250); // Enable the dwell time limits - 400ms is the limit for the US node.setDwellTime(true, 400); Serial.println(F("Ready!\n")); } // setup void loop() { int state = RADIOLIB_ERR_NONE; // set battery fill level - the LoRaWAN network server // may periodically request this information // 0 = external power source // 1 = lowest (empty battery) // 254 = highest (full battery) // 255 = unable to measure uint8_t battLevel = 146; node.setDeviceStatus(battLevel); // Read some inputs uint8_t Digital1 = digitalRead(2); uint16_t Analog1 = analogRead(A0); // Build payload byte array uint8_t uplinkPayload[3]; uplinkPayload[0] = Digital1; uplinkPayload[1] = highByte(Analog1); // See notes for high/lowByte functions uplinkPayload[2] = lowByte(Analog1); uint8_t downlinkPayload[10]; // Make sure this fits your plans! size_t downlinkSize; // To hold the actual payload size rec'd // you can also retrieve additional information about an uplink or // downlink by passing a reference to LoRaWANEvent_t structure LoRaWANEvent_t uplinkDetails; LoRaWANEvent_t downlinkDetails; uint8_t Port = 10; // Retrieve the last uplink frame counter uint32_t fcntUp = node.getFcntUp(); // Send a confirmed uplink every 64th frame // and also request the LinkCheck and DeviceTime MAC commands if(fcntUp % 64 == 0) { Serial.println(F("[LoRaWAN] Requesting LinkCheck and DeviceTime")); node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_LINK_CHECK); node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_DEVICE_TIME); state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize, true, &uplinkDetails, &downlinkDetails); } else { state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize); } debug((state != RADIOLIB_ERR_RX_TIMEOUT) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false); if(state == RADIOLIB_ERR_NONE) { // Did we get a downlink with data for us if (downlinkSize > 0) { Serial.println(F("Downlink data: ")); arrayDump(downlinkPayload, downlinkSize); } else { Serial.println(F("")); } // print RSSI (Received Signal Strength Indicator) Serial.print(F("[LoRaWAN] RSSI:\t\t")); Serial.print(radio.getRSSI()); Serial.println(F(" dBm")); // print SNR (Signal-to-Noise Ratio) Serial.print(F("[LoRaWAN] SNR:\t\t")); Serial.print(radio.getSNR()); Serial.println(F(" dB")); // print frequency error Serial.print(F("[LoRaWAN] Frequency error:\t")); Serial.print(radio.getFrequencyError()); Serial.println(F(" Hz")); // print extra information about the event Serial.println(F("[LoRaWAN] Event information:")); Serial.print(F("[LoRaWAN] Confirmed:\t")); Serial.println(downlinkDetails.confirmed); Serial.print(F("[LoRaWAN] Confirming:\t")); Serial.println(downlinkDetails.confirming); Serial.print(F("[LoRaWAN] Datarate:\t")); Serial.println(downlinkDetails.datarate); Serial.print(F("[LoRaWAN] Frequency:\t")); Serial.print(downlinkDetails.freq, 3); Serial.println(F(" MHz")); Serial.print(F("[LoRaWAN] Output power:\t")); Serial.print(downlinkDetails.power); Serial.println(F(" dBm")); Serial.print(F("[LoRaWAN] Frame count:\t")); Serial.println(downlinkDetails.fcnt); Serial.print(F("[LoRaWAN] Port:\t\t")); Serial.println(downlinkDetails.port); uint8_t margin = 0; uint8_t gwCnt = 0; if(node.getMacLinkCheckAns(&margin, &gwCnt) == RADIOLIB_ERR_NONE) { Serial.print(F("[LoRaWAN] LinkCheck margin:\t")); Serial.println(margin); Serial.print(F("[LoRaWAN] LinkCheck count:\t")); Serial.println(gwCnt); } uint32_t networkTime = 0; uint8_t fracSecond = 0; if(node.getMacDeviceTimeAns(&networkTime, &fracSecond, true) == RADIOLIB_ERR_NONE) { Serial.print(F("[LoRaWAN] DeviceTime Unix:\t")); Serial.println(networkTime); Serial.print(F("[LoRaWAN] DeviceTime second:\t1/")); Serial.println(fracSecond); } } // wait before sending another packet uint32_t minimumDelay = uplinkIntervalSeconds * 1000UL; uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per FUP & law!) uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows Serial.print(F("[LoRaWAN] Next uplink in ")); Serial.print(delayMs/1000); Serial.println(F("s")); delay(delayMs); } // loop