![](/media/cache/profiles/944dfbba4ac84a1f27331875a01963fd.jpg.50x50_q85.jpg)
Two way data over LoRaWAN using Multitech mDot
This is example firmware for the Multitech mDot. It demonstrates how to:
- Do two-way data.
- Sleep aggressively and only wake up when the wake-up pin is triggered.
- Handle errors, retries and duty cycle errors.
- Cache data in non-volatile storage.
Based on mbed OS 5.1, hard faults against mbed OS 5.3 unfortunately. Can be compiled with GCC and ARMCC (but not IAR).
To do a new transmission, short pin D6 / PA_1.
Diff: main.cpp
- Revision:
- 2:ff17ce021cfb
- Parent:
- 0:20fbd6f66b11
- Child:
- 3:ac5101a47080
--- a/main.cpp Tue Jan 03 13:30:12 2017 +0000 +++ b/main.cpp Tue Jan 03 16:05:47 2017 +0000 @@ -10,9 +10,8 @@ #define BUILTIN_LED_ON 0 #define BUILTIN_LED_OFF 1 -static const char LORIOT_DEV_ADDR[] = "01F83E96"; // Use the big endian version here -static const char LORIOT_NWK_S_KEY[] = "6B11E4D0814BE7BC5707920B4B3545D6"; // NWKSKEY -static const char LORIOT_APP_S_KEY[] = "5C79DCD7E2CCB93A83730BC7A9BC6CFE"; // APPSKEY +static const char APP_EUI[] = "BE7A000000000393"; +static const char APP_KEY[] = "CF977DE56163FB1055A530CF7B82A56A"; static mDot* dot; @@ -74,14 +73,14 @@ logError("failed to recv %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); return true; // sending succeeded, just recv failed } - + if (recv_data.size() > 0) { printf("[INFO] received %d bytes:", recv_data.size()); for (size_t ix = 0; ix < recv_data.size(); ix++) { printf(" %02x", recv_data[ix]); } printf("\r\n"); - + if (recv_data[0] == 1) { led = BUILTIN_LED_ON; } @@ -89,16 +88,16 @@ led = BUILTIN_LED_OFF; } } - + return true; } } static void wakeUpCallback() { logInfo("woke up, fromInterrupt=%d", woke_from_interrupt); - + bool wfi = woke_from_interrupt; - + // if we were woken up by RTC_ALARM, first up the counter if (wfi) { // reset the interrupt var @@ -106,23 +105,23 @@ up_counter(); } - + bool sent = send_data(); // not sent? try again in 5 minutes... if (!sent) { uint32_t sleep_time = 5 * 60; - + // if woke from button press, check duty cycle first... if (wfi) { // hmm.. something went wrong. Probably duty cycle, see next Tx frame // get the next transmission frame (in whole seconds) sleep_time = ceil(static_cast<float>(dot->getNextTxMs()) / 1000.0f); - + // Tx window open, but no success? Try again in 30s. if (sleep_time == 0) sleep_time = 30; } - + logInfo("Going back to sleep (RTC_ALARM), time=%d", sleep_time); dot->sleep(sleep_time, mDot::RTC_ALARM, false); } @@ -149,6 +148,10 @@ // print library version information logInfo("version: %s", dot->getId().c_str()); + std::vector<uint8_t> devEui = dot->getDeviceId(); + logInfo("device eui: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + devEui[0], devEui[1], devEui[2], devEui[3], devEui[4], devEui[5], devEui[6], devEui[7]); + //******************************************* // configuration //******************************************* @@ -160,12 +163,6 @@ // set up the mDot with our network information: frequency sub band, network name, and network password // these can all be saved in NVM so they don't need to be set every time - see mDot::saveConfig() - // set join mode to MANUAL so the mDot doesn't have to rejoin after sleeping - logInfo("setting join mode to MANUAL"); - if ((ret = dot->setJoinMode(mDot::MANUAL)) != mDot::MDOT_OK) { - logError("failed to set join mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); - } - logInfo("setting public network"); if ((ret = dot->setPublicNetwork(true)) != mDot::MDOT_OK) { logError("failed to set public network %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); @@ -177,7 +174,7 @@ } // set up the network keys - ParseKeys::initialize(dot, LORIOT_DEV_ADDR, LORIOT_NWK_S_KEY, LORIOT_APP_S_KEY); + ParseKeys::initializeOta(dot, APP_EUI, APP_KEY); // a higher spreading factor allows for longer range but lower throughput // in the 915 (US) frequency band, spreading factors 7 - 10 are available @@ -204,6 +201,14 @@ logError("failed to save configuration"); } + // OTA JOIN sequence, remove when using personalized mode + logInfo("joining network"); + if ((ret = dot->joinNetwork()) != mDot::MDOT_OK ) { + logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str()); + return false; + } + logInfo("joined network successfully"); + //******************************************* // end of configuration //*******************************************