Example Code for Arduino-Sleep Depth
This sample code connects to the LoRaWAN network in OTAA mode. It sends data (the string "DFRobot") every 10 seconds, receives downlink messages (with ACK or data), uses the screen to display network connection, transmission and reception status, and supports the identification and processing of wake-up sources (button wake-up).
Hardware Preparation
- DFR0994 Romeo ESP32-S3 x 1
- LoRaWAN Indoor Gateway (868MHz Version) or LoRaWAN Indoor Gateway (915MHz Version) x1
Software Preparation
- Download Arduino IDE: Click to download Arduino IDE
- Add ESP32 board to Arduino IDE
- Please install the DFRobot_LoRaWAN_ESP32S3 library before use.
- About how to install the library?
Note:
- LoRaWAN protocol stack version: 1.0.3
- You need to set the data parsing format to "text" on the gateway.
Sample Code
#include "DFRobot_LoRaWAN.h"
#define BTN_PIN 18 // GPIO2, 3, 11, 12, 13 can all trigger external wake-up
LCD_OnBoard screen;
#define BG_COLOR COLOR_RGB565_BLACK // Screen background color
#define TEXT_COLOR COLOR_RGB565_GREEN // Screen font color
#define TEXT_FONT &FreeMono9pt7b // font
#define TEXT_SIZE 1 // Screen font size
#define LINE_HEIGHT 18 // Line height
#define POX_X 0 // Screen print position X coordinate
#define POX_Y 15 // Screen print position Y coordinate
#define LINE_1 0 // Line number
#define LINE_2 1
#define LINE_3 2
#define LINE_4 3
#define APP_INTERVAL_MS 10000
const uint8_t DevEUI[8] = {0xDF, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
const uint8_t AppEUI[8] = {0xDF, 0xB7, 0xB7, 0xB7, 0xB7, 0x00, 0x00, 0x00};
const uint8_t AppKey[16] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};
uint8_t buffer[255];
uint8_t port = 2;
LoRaWAN_Node node(DevEUI, AppEUI, AppKey, CLASS_A);
// Rejoin count
RTC_DATA_ATTR uint8_t CurReJoinTimes = 0;
// Downlink Reception Success Flag
uint8_t rxFlag = 1;
uint32_t prevTimeStamp = 0;
const char* wakeup_reason_strings[] =
{
"ESP_SLEEP_WAKEUP_UNDEFINED",
"ESP_SLEEP_WAKEUP_ALL",
"ESP_SLEEP_WAKEUP_EXT0",
"ESP_SLEEP_WAKEUP_EXT1",
"ESP_SLEEP_WAKEUP_TIMER",
"ESP_SLEEP_WAKEUP_TOUCHPAD",
"ESP_SLEEP_WAKEUP_ULP",
"ESP_SLEEP_WAKEUP_GPIO",
"ESP_SLEEP_WAKEUP_UART",
"ESP_SLEEP_WAKEUP_WIFI",
"ESP_SLEEP_WAKEUP_COCPU",
"ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG",
"ESP_SLEEP_WAKEUP_BT"
};
// Join network callback function
void joinCb(bool isOk, int16_t rssi, int8_t snr)
{
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
if(isOk){
CurReJoinTimes = 0;
printf("JOIN SUCCESS\n");
printf("JoinAccept Packet rssi = %d snr = %d\n", rssi, snr);
printf("NetID = %06X\n", node.getNetID());
printf("DevAddr = %08X\n", node.getDevAddr());
uint8_t * NwkSKey = node.getNwkSKey();
uint8_t * AppSKey = node.getAppSKey();
printf("NwkSKey=0X");
for(uint8_t i= 0; i < 16; i++){
printf("%02X", NwkSKey[i]);
}
printf("\n");
printf("AppSKey=0X");
for(uint8_t i = 0; i < 16; i++){
printf("%02X", AppSKey[i]);
}
printf("\n");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("JOIN SUCCESS");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_2);
screen.printf("Accept Packet");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_3);
screen.printf("Rssi = %d", rssi);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_4);
screen.printf("Snr = %d", snr);
delay(5000);
node.deepSleepMs(APP_INTERVAL_MS); // Deep sleep after successful network join
}else{
printf("OTAA join error\n");
printf("Check Whether the device has been registered on the gateway!\n");
printf("deviceEUI and appKey are the same as the devices registered on the gateway\n");
printf("Ensure that there is a gateway nearby\n");
printf("Check whether the antenna is normal\n");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("OTAA join Err!");
delay(2000);
// Backoff join procedure
CurReJoinTimes++;
// printf("\n\n------CurReJoinTimes = %d------\n\n", CurReJoinTimes);
uint64_t backoff_time_ms = 5000 * (1ULL << (CurReJoinTimes - 1));
backoff_time_ms = (backoff_time_ms > 300000) ? 300000 : backoff_time_ms;
node.deepSleepMs(backoff_time_ms);
}
}
void userSendConfirmedPacket(void)
{
const char * data = "DFRobot";
uint32_t datalen = strlen(data);
memcpy(buffer, data, datalen);
node.sendConfirmedPacket(port, buffer, /*size=*/datalen);
rxFlag = 0;
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("Sending...");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_2);
screen.printf("Confirmed");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_3);
screen.printf("Packet");
}
// Receive data callback function
void rxCb(void *buffer, uint16_t size, uint8_t port, int16_t rssi, int8_t snr, bool ackReceived, uint16_t uplinkCounter, uint16_t downlinkCounter)
{
rxFlag = 1;
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
if(ackReceived == true){
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("this is a ACK");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_2);
screen.printf("Rssi = %d", rssi);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_3);
screen.printf("Snr = %d", snr);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_4);
screen.printf("DownCount = %d", downlinkCounter);
}
delay(3000);
node.deepSleepMs(APP_INTERVAL_MS); // MCU sleep for a specified duration
}
// Handle button-triggered wakeup: display node info and return to sleep
void buttonWakeupHandler()
{
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("buttonCB");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_2);
screen.printf("dataRate: %d\n", node.getDataRate());
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_3);
screen.printf("txEirp: %d\n", node.getEIRP());
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_4);
screen.printf("netID: %d\n", node.getNetID());
printf("LastDownlinkCounter = %d\n", node.getLastDownCounter());
printf("LastUplinkCounter = %d\n", node.getLastUplinkCounter());
delay(5000);
node.deepSleepMs(APP_INTERVAL_MS); // MCU sleep for a specified duration
}
void setup()
{
Serial.begin(115200);
screen.begin();
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("WakeUp");
delay(2000);
// Set to wake up using a button press
esp_sleep_enable_ext0_wakeup((gpio_num_t )BTN_PIN, LOW);
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
if (wakeup_reason >= ESP_SLEEP_WAKEUP_UNDEFINED && wakeup_reason <= ESP_SLEEP_WAKEUP_BT) {
printf("\n\n------Wakeup reason: [%s]------\n\n", wakeup_reason_strings[wakeup_reason]);
} else {
printf("\n\n------Wakeup reason: [UNKNOWN]------\n\n");
}
if (wakeup_reason == ESP_SLEEP_WAKEUP_EXT0) {
buttonWakeupHandler();
}
if(!(node.init(/*dataRate=*/DR_4, /*txEirp=*/16))){ // Initialize the LoRaWAN node, set the data rate and Tx Eirp
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("LoRaWAN Init");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_2);
screen.printf("Failed!");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_3);
screen.printf("Please Check:");
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_4);
screen.printf("DR or Region");
while(1);
}
node.setRxCB(rxCb); // Set the callback function for receiving data
if(!node.isJoined()) {
screen.fillScreen(BG_COLOR);
screen.setTextColor(TEXT_COLOR);
screen.setFont(TEXT_FONT);
screen.setTextSize(TEXT_SIZE);
screen.setCursor(POX_X, POX_Y + LINE_HEIGHT * LINE_1);
screen.printf("Join Request");
node.join(joinCb); // Join the LoRaWAN network
} else {
userSendConfirmedPacket(); // Send data
}
}
void loop()
{
// Prevent prolonged downlink waiting from blocking deep sleep and increasing power consumption
uint32_t currTimeStamp = TimerGetCurrentTime();
if (currTimeStamp - prevTimeStamp >= APP_INTERVAL_MS * 2) {
prevTimeStamp = currTimeStamp;
if (!rxFlag) {
node.deepSleepMs(APP_INTERVAL_MS);
}
}
delay(1000);
}
Was this article helpful?
