Skip to content

Instantly share code, notes, and snippets.

@ubergesundheit
Created October 23, 2016 19:32
Show Gist options
  • Save ubergesundheit/299c1373f7470e848a11905b16dc8156 to your computer and use it in GitHub Desktop.
Save ubergesundheit/299c1373f7470e848a11905b16dc8156 to your computer and use it in GitHub Desktop.
#include <rn2483.h>
#include <SoftwareSerial.h>
#define APP_EUI "70B3D57ED000042A"
#define APP_KEY "20FA476202AABBD1FCD1B91EFAEC7B98"
#define RESET D7
#define PIN_SERIAL1_TX D5
#define PIN_SERIAL1_RX D6
SoftwareSerial mySerial(PIN_SERIAL1_RX, PIN_SERIAL1_TX); // RX, TX !! labels on relay board is swapped !!
//create an instance of the rn2483 library,
//giving the software UART as stream to use,
//and using LoRa WAN
rn2483 myLora(mySerial);
// CRC function used to ensure data validity
uint32_t calculateCRC32(const uint8_t *data, size_t length);
struct {
uint32_t crc32;
byte data[50];
} rtcData;
bool readLoRaConfig() {
// Read struct from RTC memory
if (ESP.rtcUserMemoryRead(0, (uint32_t*) &rtcData, sizeof(rtcData))) {
uint32_t crcOfData = calculateCRC32(((uint8_t*) &rtcData) + 4, sizeof(rtcData) - 4);
if (crcOfData != rtcData.crc32) {
Serial.println("CRC32 in RTC memory doesn't match CRC32 of data. Data is probably invalid!");
return false;
}
else {
Serial.println("CRC32 check ok, data is probably valid.");
return true;
}
}
return false;
}
bool checkLoRaConfigChanged() {
Serial.println("check Lora config changed");
if (readLoRaConfig()) { // read the data and check crc32
// compare to APP_EUI and APP_KEY
int memIndex = 0;
for (int i = 0, len = sizeof(APP_EUI); i < len; i++) {
if (rtcData.data[memIndex] != APP_EUI[i]) {
return true;
}
memIndex = memIndex + 1;
}
for (int i = 0, len = sizeof(APP_KEY); i < len; i++) {
if (rtcData.data[memIndex] != APP_KEY[i]) {
return true;
}
memIndex = memIndex + 1;
}
return false;
} else { // since the data was invalid, we cannot say if the config has changed. return true to reconnect
return true;
}
}
void writeLoRaConfig() {
int memIndex = 0;
for (int i = 0, len = sizeof(APP_EUI); i < len; i++) {
rtcData.data[memIndex] = APP_EUI[i];
memIndex = memIndex + 1;
}
for (int i = 0, len = sizeof(APP_KEY); i < len; i++) {
rtcData.data[memIndex] = APP_KEY[i];
memIndex = memIndex + 1;
}
// Update CRC32 of data
rtcData.crc32 = calculateCRC32(((uint8_t*) &rtcData) + 4, sizeof(rtcData) - 4);
// Write struct to RTC memory
ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData));
}
uint32_t calculateCRC32(const uint8_t *data, size_t length)
{
uint32_t crc = 0xffffffff;
while (length--) {
uint8_t c = *data++;
for (uint32_t i = 0x80; i > 0; i >>= 1) {
bool bit = crc & 0x80000000;
if (c & i) {
bit = !bit;
}
crc <<= 1;
if (bit) {
crc ^= 0x04c11db7;
}
}
}
return crc;
}
void doTx() {
myLora.tx("!");
Serial.println("Packet sent");
}
// the setup routine runs once when you press reset:
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
mySerial.begin(57600);
delay(1000); //wait for the arduino ide's serial console to open
Serial.println("Startup");
initialize_radio();
doTx();
delay(500);
Serial.println("Going into deep sleep for 5 seconds");
Serial.println("ping");
myLora.sleep(5000);
Serial.println("pong");
ESP.deepSleep(5e6);
}
void wakeUP_RN2483() {
mySerial.end();
pinMode(PIN_SERIAL1_TX, OUTPUT);
digitalWrite(PIN_SERIAL1_TX, LOW);
delay(5);
digitalWrite(PIN_SERIAL1_TX, HIGH);
mySerial.begin(57600);
mySerial.write(0x55);
}
void initialize_radio()
{
wakeUP_RN2483();
if (checkLoRaConfigChanged()) {
Serial.println("LoRa config changed.. Resetting RN2483");
//reset RN2483
pinMode(RESET, OUTPUT);
digitalWrite(RESET, LOW);
delay(100);
digitalWrite(RESET, HIGH);
delay(100); //wait for the RN2483's startup message
mySerial.flush();
//check communication with radio
String hweui = myLora.hweui();
while (hweui.length() != 16)
{
Serial.println("Communication with RN2483 unsuccesful. Power cycle the board.");
Serial.println(hweui);
delay(10000);
hweui = myLora.hweui();
}
//print out the HWEUI so that we can register it via ttnctl
Serial.println("When using OTAA, register this DevEUI: ");
Serial.println(hweui);
Serial.println("RN2483 firmware version:");
Serial.println(myLora.sysver());
//configure your keys and join the network
Serial.println("Trying to join TTN");
bool join_result = false;
//ABP: initABP(String addr, String AppSKey, String NwkSKey);
//join_result = myLora.initABP("02017201", "8D7FFEF938589D95AAD928C2E2E7E48F", "AE17E567AECC8787F749A62F5541D522");
//OTAA: initOTAA(String AppEUI, String AppKey);
join_result = myLora.initOTAA(APP_EUI, APP_KEY);
while (!join_result)
{
Serial.println("Unable to join. Are your keys correct, and do you have TTN coverage?");
delay(60000); //delay a minute before retry
join_result = myLora.init();
}
Serial.println("Successfully joined TTN");
writeLoRaConfig();
} else {
Serial.println("LoRa settings unchanged. Doing nothing");
}
}
void loop() {
// doing nothing
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment