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

DIO0 and DIO1 optional and deep sleep for ESP device #184

Closed
wants to merge 10 commits into from
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,73 @@ For example, this could look like this:
.DIO2 = RFM_DIO2,
.DIO5 = RFM_DIO5
};
All unused pin should be set to -1. All DIO pins are optional. RST could be set to -1 if connected to the reset pin of ESP8266.
Using DIO0 and DIO1 makes the sending and receiving packet slighly faster.

Deep sleep
-----------
For ESP device, when deep sleep is called, all the memory is flush execpt the memory explicitly put in RTC memory.
In order to not loose LoRa session information and thus having to rejoin the LoRaWAN network after deep sleep, the following
variable needs save on RTC RAM:

lora.DevEUI
lora.AppEUI
lora.AppKey
lora.DevNonce
lora.AppNonce
lora.NetID
lora.Address_Tx
lora.NwkSKey
lora.AppSKey
lora.Frame_Counter_Tx
lora.LoRa_Settings

Different strategies could be used to save those variables. It is suggested to create a struct as follows and to save that structure
on RTC memory:

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;
};
RTCRAM rtcRAM;

Once the RTC memory are loaded after deep sleep, the variable can be parse to the LoRaWANClass as follow:

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));

The same strategy is used before calling deep sleep in order to save the updated LoRaWAN session on the RTCRAM structure:

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));

API
--------
Expand Down
57 changes: 48 additions & 9 deletions src/arduino-rfm/RFM95.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,10 @@ void RFM_Set_Tx_Power(int level, int outputPin)
}
}

bool RFM_isRxDone()
{
return (RFM_Read(RFM_REG_IRQ_FLAGS & 0x7f) & IRQ_RX_DONE_MASK) != 0;
}

void RFM_Set_OCP(uint8_t mA)
{
Expand Down Expand Up @@ -642,7 +646,8 @@ void RFM_Send_Package(sBuffer *RFM_Tx_Package, sSettings *LoRa_Settings)
RFM_Change_Channel(LoRa_Settings->Channel_Tx);

//Switch DIO0 to TxDone
RFM_Write(RFM_REG_DIO_MAPPING1, 0x40);
if (RFM_pins.DIO0 != -1)
RFM_Write(RFM_REG_DIO_MAPPING1, 0x40);

//Set IQ to normal values
RFM_Write(RFM_REG_INVERT_IQ,0x27);
Expand All @@ -667,7 +672,12 @@ void RFM_Send_Package(sBuffer *RFM_Tx_Package, sSettings *LoRa_Settings)
RFM_Write(RFM_REG_OP_MODE,0x83);

//Wait for TxDone
while(digitalRead(RFM_pins.DIO0) == LOW);
if (RFM_pins.DIO0 != -1)
while(digitalRead(RFM_pins.DIO0) == LOW);
else
{
while ((RFM_Read(RFM_REG_IRQ_FLAGS & 0x7f) & IRQ_TX_DONE_MASK) == 0);
}

//Clear interrupt
RFM_Write(RFM_REG_IRQ_FLAGS,0x08);
Expand All @@ -688,7 +698,8 @@ message_t RFM_Single_Receive(sSettings *LoRa_Settings)
message_t Message_Status = NO_MESSAGE;

//Change DIO 0 back to RxDone
RFM_Write(RFM_REG_DIO_MAPPING1, 0x00);
if (RFM_pins.DIO0 != -1)
RFM_Write(RFM_REG_DIO_MAPPING1, 0x00);

//Invert IQ Back
RFM_Write(RFM_REG_INVERT_IQ, 0x67);
Expand All @@ -705,26 +716,53 @@ message_t RFM_Single_Receive(sSettings *LoRa_Settings)

//Wait until RxDone or Timeout
//Wait until timeout or RxDone interrupt
while((digitalRead(RFM_pins.DIO0) == LOW) && (digitalRead(RFM_pins.DIO1) == LOW));

byte RegIrqFlags;
if (RFM_pins.DIO0 != -1)
while((digitalRead(RFM_pins.DIO0) == LOW) && (digitalRead(RFM_pins.DIO1) == LOW));
else
{
RegIrqFlags = RFM_Read(RFM_REG_IRQ_FLAGS & 0x7f);
while ((RegIrqFlags & (IRQ_RX_DONE_MASK | IRQ_RX_TIMEOUT_MASK)) == 0)
{
RegIrqFlags = RFM_Read(RFM_REG_IRQ_FLAGS & 0x7f);
}
}

//Check for Timeout
if(digitalRead(RFM_pins.DIO1) == HIGH)
bool isTimeout;
if (RFM_pins.DIO0 != -1)
{
isTimeout = digitalRead(RFM_pins.DIO1) == HIGH;
}
else
{
isTimeout = (RegIrqFlags & IRQ_RX_TIMEOUT_MASK) != 0;
}
if(isTimeout)
{
//Clear interrupt register
RFM_Write(RFM_REG_IRQ_FLAGS,0xE0);
Message_Status = TIMEOUT;
}

//Check for RxDone
if(digitalRead(RFM_pins.DIO0) == HIGH)
bool isRxDone;
if (RFM_pins.DIO0 != -1)
{
isRxDone = digitalRead(RFM_pins.DIO0) == HIGH;
}
else
{
isRxDone = (RegIrqFlags & IRQ_RX_DONE_MASK) != 0;
}
if(isRxDone)
{
Message_Status = NEW_MESSAGE;
}

return Message_Status;
}


/*
*****************************************************************************************
* Description : Function to switch RFM to continuous receive mode, used for Class C motes
Expand All @@ -735,7 +773,8 @@ message_t RFM_Single_Receive(sSettings *LoRa_Settings)
void RFM_Continuous_Receive(sSettings *LoRa_Settings)
{
//Change DIO 0 back to RxDone and DIO 1 to rx timeout
RFM_Write(RFM_REG_DIO_MAPPING1,0x00);
if (RFM_pins.DIO0 != -1)
RFM_Write(RFM_REG_DIO_MAPPING1,0x00);

//Invert IQ Back
RFM_Write(RFM_REG_INVERT_IQ, 0x67);
Expand Down
6 changes: 6 additions & 0 deletions src/arduino-rfm/RFM95.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ typedef enum {
RFM_MODE_LORA = 0b10000000
} frm_mode_t;

typedef enum {
IRQ_RX_TIMEOUT_MASK = 0b10000000,
IRQ_RX_DONE_MASK = 0b01000000,
IRQ_TX_DONE_MASK = 0b00001000
} irq_mask;

/*
*****************************************************************************************
Expand All @@ -109,6 +114,7 @@ message_t RFM_Get_Package(sBuffer *RFM_Rx_Package);
void RFM_Write(unsigned char RFM_Address, unsigned char RFM_Data);
void RFM_Switch_Mode(unsigned char Mode);
void RFM_Set_Tx_Power(int level, int outputPin);
bool RFM_isRxDone();
void RFM_Set_OCP(unsigned char mA);

unsigned char RFM_Get_Rssi();
Expand Down
36 changes: 26 additions & 10 deletions src/arduino-rfm/lorawan-arduino-rfm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,23 +122,30 @@ bool LoRaWANClass::init(void)
Message_Rx.Direction = 0x01; //Set down direction for Rx message

//Initialize I/O pins
pinMode(RFM_pins.DIO0, INPUT);
pinMode(RFM_pins.DIO1, INPUT);
if (RFM_pins.DIO0 != -1)
pinMode(RFM_pins.DIO0, INPUT);
if (RFM_pins.DIO1 != -1)
pinMode(RFM_pins.DIO1, INPUT);
if (RFM_pins.DIO2 != -1)
pinMode(RFM_pins.DIO2, INPUT);
if (RFM_pins.RST != -1)
pinMode(RFM_pins.RST, OUTPUT);
#ifdef BOARD_DRAGINO_SHIELD
pinMode(RFM_pins.DIO5, INPUT);
#endif
pinMode(RFM_pins.DIO2, INPUT);
pinMode(RFM_pins.CS, OUTPUT);
pinMode(RFM_pins.RST, OUTPUT);

digitalWrite(RFM_pins.CS, HIGH);

// Reset
digitalWrite(RFM_pins.RST, HIGH);
delay(10);
digitalWrite(RFM_pins.RST, LOW);
delay(10);
digitalWrite(RFM_pins.RST, HIGH);
if (RFM_pins.RST != -1)
{
digitalWrite(RFM_pins.RST, HIGH);
delay(10);
digitalWrite(RFM_pins.RST, LOW);
delay(10);
digitalWrite(RFM_pins.RST, HIGH);
}

//Initialise the SPI port
SPI.begin();
Expand Down Expand Up @@ -495,7 +502,16 @@ void LoRaWANClass::update(void)
}

//Receive in Class C mode
if (digitalRead(RFM_pins.DIO0) == HIGH )
bool isRxDone;
if (RFM_pins.DIO0 != -1)
{
isRxDone = digitalRead(RFM_pins.DIO0) == HIGH;
}
else
{
isRxDone = RFM_isRxDone();
}
if (isRxDone)
{
LORA_Receive_Data(&Buffer_Rx, &Session_Data, &OTAA_Data, &Message_Rx, &LoRa_Settings);
if (Buffer_Rx.Counter != 0x00)
Expand Down
29 changes: 14 additions & 15 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 variable to be save on RTC RAM before deep sleep for ESP device
REGIOIGER marked this conversation as resolved.
Show resolved Hide resolved
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;

unsigned char drate_common;

// Lora Setting Class
Expand Down
2 changes: 1 addition & 1 deletion src/lorawan.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef _LORAWAN_H_
#define _LORAWAN_H_

#include "arduino-rfm/lorawan-arduino-rfm.h"
#include <arduino-rfm/lorawan-arduino-rfm.h>

extern LoRaWANClass lora;

Expand Down