Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deep sleep and example #189

Merged
merged 1 commit into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 205 additions & 0 deletions examples/class_a_otaa_esp_deepsleep/class_a_otaa_esp_deepsleep.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/**
* Example of OTAA device with ESP8266 or ESP32 using deep sleep wihtout losing LoRaWAN settings.
* A minimum number of pin is also used in this example. For slighly faster processing,
* DIO0 and DIO1 should be used.
*/
#include <Arduino.h>
#include <lorawan.h>

// OTAA credentials
const char *devEui = "0000000000000000";
const char *appEui = "0000000000000000";
const char *appKey = "00000000000000000000000000000000";

unsigned int counter = 0; // message counter

char myStr[50];
char outStr[255];
byte recvStatus = 0;

const sRFM_pins RFM_pins = {
.CS = 15,
.RST = 2, //Could be connected to the reset ESP pin of ESP8266, if so put -1
.DIO0 = 0,
.DIO1 = 4,
.DIO2 = -1,
.DIO5 = -1,
};

struct RTCRAM
{
unsigned char DevEUI[8];
unsigned char AppEUI[8];
unsigned char AppKey[16];
unsigned char DevNonce[2];
unsigned char AppNonce[3];
unsigned char NetID[3];
unsigned char Address_Tx[4];
unsigned char NwkSKey[16];
unsigned char AppSKey[16];
unsigned int Frame_Counter_Tx;
sSettings LoRa_Settings;
unsigned int counter;
};
#if defined(ESP32)
RTC_DATA_ATTR RTCRAM rtcRAM;
#else
RTCRAM rtcRAM;
#endif

void deepsleep(uint64_t us)
{
Serial.println("We go to deep sleep");
delay(10);
lora.sleep();
#if defined(ESP8266)
ESP.deepSleep(us, WAKE_RF_DISABLED);
#elif defined(ESP32)
esp_sleep_enable_timer_wakeup(us);
esp_deep_sleep_start();
#else
Serial.print("Deep sleep not supported by this example");
#endif
}

void saveVariableRTC()
{
memcpy(rtcRAM.DevEUI, lora.DevEUI, sizeof(rtcRAM.DevEUI));
memcpy(rtcRAM.AppEUI, lora.AppEUI, sizeof(rtcRAM.AppEUI));
memcpy(rtcRAM.AppKey, lora.AppKey, sizeof(rtcRAM.AppKey));
memcpy(rtcRAM.DevNonce, lora.DevNonce, sizeof(rtcRAM.DevNonce));
memcpy(rtcRAM.AppNonce, lora.AppNonce, sizeof(rtcRAM.AppNonce));
memcpy(rtcRAM.NetID, lora.NetID, sizeof(rtcRAM.NetID));
memcpy(rtcRAM.Address_Tx, lora.Address_Tx, sizeof(rtcRAM.Address_Tx));
memcpy(rtcRAM.NwkSKey, lora.NwkSKey, sizeof(rtcRAM.NwkSKey));
memcpy(rtcRAM.AppSKey, lora.AppSKey, sizeof(rtcRAM.AppSKey));
memcpy(&rtcRAM.Frame_Counter_Tx, &lora.Frame_Counter_Tx, sizeof(rtcRAM.Frame_Counter_Tx));
memcpy(&rtcRAM.LoRa_Settings, &lora.LoRa_Settings, sizeof(rtcRAM.LoRa_Settings));
memcpy(&rtcRAM.counter, &counter, sizeof(rtcRAM.counter));
#if defined(ESP8266)
ESP.rtcUserMemoryWrite(32, (uint32_t *)&rtcRAM, sizeof(rtcRAM));
#endif
}

void loadVariableRTC()
{
#if defined(ESP8266)
ESP.rtcUserMemoryRead(32, (uint32_t *)&rtcRAM, sizeof(rtcRAM));
#endif
memcpy(lora.DevEUI, rtcRAM.DevEUI, sizeof(rtcRAM.DevEUI));
memcpy(lora.AppEUI, rtcRAM.AppEUI, sizeof(rtcRAM.AppEUI));
memcpy(lora.AppKey, rtcRAM.AppKey, sizeof(rtcRAM.AppKey));
memcpy(lora.DevNonce, rtcRAM.DevNonce, sizeof(rtcRAM.DevNonce));
memcpy(lora.AppNonce, rtcRAM.AppNonce, sizeof(rtcRAM.AppNonce));
memcpy(lora.NetID, rtcRAM.NetID, sizeof(rtcRAM.NetID));
memcpy(lora.Address_Tx, rtcRAM.Address_Tx, sizeof(rtcRAM.Address_Tx));
memcpy(lora.NwkSKey, rtcRAM.NwkSKey, sizeof(rtcRAM.NwkSKey));
memcpy(lora.AppSKey, rtcRAM.AppSKey, sizeof(rtcRAM.AppSKey));
memcpy(&lora.Frame_Counter_Tx, &rtcRAM.Frame_Counter_Tx, sizeof(rtcRAM.Frame_Counter_Tx));
memcpy(&lora.LoRa_Settings, &rtcRAM.LoRa_Settings, sizeof(rtcRAM.LoRa_Settings));
memcpy(&counter, &rtcRAM.counter, sizeof(rtcRAM.counter));
}

#if defined(ESP8266)
uint32_t magicBytes; // if previous data save on rtc, this equal 'magi' (183510009)
void loadMagicByte()
{
ESP.rtcUserMemoryRead(127, &magicBytes, sizeof(magicBytes));
}

void saveMagicByte()
{
magicBytes = 183510009;
ESP.rtcUserMemoryWrite(127, &magicBytes, 4);
}
#endif

void setup()
{
// Setup loraid access
Serial.begin(9600);
while (!Serial)
;
if (!lora.init())
{
Serial.println("RFM95 not detected");
delay(5000);
deepsleep(10000000);
}

// Join procedure
bool isJoined = true;
#if defined(ESP8266)
loadMagicByte();
if (magicBytes != 183510009)
#else
if (rtcRAM.counter == 0)
#endif
{
Serial.println("Cold boot Join procedure needs to be performed");
isJoined = false;
}

if (!isJoined)
{
// Set LoRaWAN Class change CLASS_A or CLASS_C
lora.setDeviceClass(CLASS_A);
// Set Data Rate
lora.setDataRate(SF9BW125);
// set channel to random
lora.setChannel(MULTI);

// Put OTAA Key and DevAddress here
lora.setDevEUI(devEui);
lora.setAppEUI(appEui);
lora.setAppKey(appKey);
while (!isJoined)
{
Serial.println("Joining...");
isJoined = lora.join();

// wait for 10s to try again if not join
if (!isJoined)
delay(10000);
}
Serial.println("Joined to network!\nWe now save LoRaWAN information");
delay(100); // Necessary for ESP32 in order to properly save data on RTC ram
saveVariableRTC();
#if defined(ESP8266)
saveMagicByte();
#endif
}
else
{
Serial.println("Previously joined network, we applied the save parameters");
loadVariableRTC();
}

// Send a upling
sprintf(myStr, "Counter-%d", counter);
Serial.print("Sending: ");
Serial.println(myStr);
lora.sendUplink(myStr, strlen(myStr), 0, 1);
counter++;

// cycle over send and receive data with LoRa update
lora.update();
recvStatus = lora.readData(outStr);
if (recvStatus)
{
Serial.println(outStr);
}
delay(100); // Necessary for ESP32 in order to properly save data on RTC ram
// Save pertinent information on RTC ram
saveVariableRTC();

// Deep sleep for 10 s
deepsleep(10000000);
}

void loop()
{
// We never get here
Serial.print("Oups, you use this example without an ESP device");
delay(10000);
}
27 changes: 13 additions & 14 deletions src/arduino-rfm/lorawan-arduino-rfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ class LoRaWANClass
unsigned int getFrameCounter();
void setFrameCounter(unsigned int FrameCounter);

// Declare public instead of private so they can be save on RTC ram in the main script before deep sleep for ESP
unsigned char DevEUI[8];
unsigned char AppEUI[8];
unsigned char AppKey[16];
unsigned char DevNonce[2];
unsigned char AppNonce[3];
unsigned char NetID[3];
unsigned char Address_Tx[4];
unsigned char NwkSKey[16];
unsigned char AppSKey[16];
unsigned int Frame_Counter_Tx;
sSettings LoRa_Settings;

private:
void randomChannel();

Expand All @@ -106,25 +119,11 @@ class LoRaWANClass
void(*messageCallback)(sBuffer *Data_Rx, bool isConfirmed, uint8_t fPort) = NULL;

// Declare ABP session
unsigned char Address_Tx[4];
unsigned char NwkSKey[16];
unsigned char AppSKey[16];
unsigned int Frame_Counter_Tx;
sLoRa_Session Session_Data;

// Declare OTAA data struct
unsigned char DevEUI[8];
unsigned char AppEUI[8];
unsigned char AppKey[16];
unsigned char DevNonce[2];
unsigned char AppNonce[3];
unsigned char NetID[3];
sLoRa_OTAA OTAA_Data;

// Declare LoRA settings struct
sSettings LoRa_Settings;
sRFM_pins LoRa_Pins;
Copy link
Contributor Author

@sacua sacua Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 126 was remove since this vairable was not used at all at any place in the code.


unsigned char drate_common;

// Lora Setting Class
Expand Down