From 8bbdb34d8e6848cd8887b69ab595761f9d14423a Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Fri, 8 Sep 2023 15:32:12 +0200 Subject: [PATCH] STM32duinoLoraWan new example going to sleep and sending packet Modifying the basic.ino to add sleeping period After LoraWan is connected, it periodically goes to sleep and send a packet on device wakeUp Signed-off-by: Francois Ramu --- examples/LowPowerLoraWan/LowPowerLoraWan.ino | 136 +++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 examples/LowPowerLoraWan/LowPowerLoraWan.ino diff --git a/examples/LowPowerLoraWan/LowPowerLoraWan.ino b/examples/LowPowerLoraWan/LowPowerLoraWan.ino new file mode 100644 index 0000000..c0d5291 --- /dev/null +++ b/examples/LowPowerLoraWan/LowPowerLoraWan.ino @@ -0,0 +1,136 @@ +/** + * This is an example that demonstrates how to configure the + * library, join the network, send regular packets and print any + * downlink packets received when the lowpower mode is enabled. + * This example is using the RTC in MIX (binary and BCD) mode + * and the lowPower mode to set an Alarm (ALARM_A) before going to sleep + * When alarm Wakes up the system, it send a packet over the LoraWan + * + * Revised BSD License - https://spdx.org/licenses/BSD-3-Clause.html + */ +#include +#include +#include + +STM32LoRaWAN modem; +extern STM32RTC rtc; + +char payload[27]; /* packet to be sent */ + +bool connected = false; /* LoraWan connection ready */ + +/* Change this value to set alarm match offset in millisecond */ +static uint32_t atime = 4000; + +// Declare it volatile since it's incremented inside an interrupt +volatile int alarmMatch_counter = 0; + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); + + Serial.begin(115200); + Serial.println("Start"); + modem.begin(EU868); + + /* rtc is already init'd in MIX mode by the LoraWan */ + rtc.setTime(21, 51, 20); + rtc.setDate(2, 3, 4, 5); + + // Configure join method by (un)commenting the right method + // call, and fill in credentials in that method call. + connected = modem.joinOTAA(/* AppEui */ "0000000000000000", /* AppKey */ "00000000000000000000000000000000", /* DevEui */ "0000000000000000"); + //connected = modem.joinABP(/* DevAddr */ "00000000", /* NwkSKey */ "00000000000000000000000000000000", /* AppSKey */ "00000000000000000000000000000000"); + + if (connected) { + Serial.println("Joined"); + } else { + Serial.println("Join failed"); + while (true) /* infinite loop */; + } + + // Configure low power + LowPower.begin(); + LowPower.enableWakeupFrom(&rtc, alarmMatch, &atime); + + // Configure first alarm in 6 second then it will be done in the rtc callback + rtc.setAlarmEpoch(rtc.getEpoch() + 6); +} + +void loop() { + Serial.print("Alarm Match: "); + Serial.print(alarmMatch_counter); + Serial.println(" times."); + Serial.flush(); + digitalWrite(LED_BUILTIN, HIGH); + LowPower.deepSleep(); + digitalWrite(LED_BUILTIN, LOW); + LowPower.deepSleep(); + + /* Alarm has matched 2 times before reching this point */ + if (connected) { + send_packet(); + } else { + Serial.printf("Alarm at %02d:%02d:%02d\r\n", + rtc.getHours(), rtc.getMinutes(), rtc.getSeconds()); + } +} + +void send_packet() +{ + /* prepare the Tx packet : get date and format string */ + sprintf((char *)payload, "%02d/%02d/%04d - %02d:%02d:%02d", + rtc.getMonth(), rtc.getDay(), 2000 + rtc.getYear(), + rtc.getHours(), rtc.getMinutes(), rtc.getSeconds()); + + modem.setPort(10); + modem.beginPacket(); + modem.write(payload, sizeof(payload)); + if (modem.endPacket() == sizeof(payload)) { + Serial.println("Sent packet"); + } else { + Serial.println("Failed to send packet"); + } + + if (modem.available()) { + Serial.print("Received packet on port "); + Serial.print(modem.getDownlinkPort()); + Serial.print(":"); + while (modem.available()) { + uint8_t b = modem.read(); + Serial.print(" "); + Serial.print(b >> 4, HEX); + Serial.print(b & 0xF, HEX); + } + Serial.println(); + } +} + +void alarmMatch(void* data) +{ + // This function will be called once on device wakeup + // You can do some little operations here (like changing variables which will be used in the loop) + // Remember to avoid calling delay() and long running functions since this functions executes in interrupt context + uint32_t epoc; + uint32_t epoc_ms; + uint32_t sec = 0; + uint32_t _millis = 1000; + + if (data != NULL) { + _millis = *(uint32_t*)data; + } + + sec = _millis / 1000; + + _millis = _millis % 1000; + epoc = rtc.getEpoch(&epoc_ms); + + //Update epoch_ms - might need to add a second to epoch + epoc_ms += _millis; + if (epoc_ms >= 1000) { + sec ++; + epoc_ms -= 1000; + } + alarmMatch_counter++; + // set the alarm again + rtc.setAlarmEpoch(epoc + sec, STM32RTC::MATCH_SS, epoc_ms); +}