| SX126x-Arduino 2.0.1

Sensor-Gateway-Deepsleep\LoRa-TempSensor\src\main.cpp
#include <Arduino.h>
#include <SX126x-Arduino.h>
#include <SPI.h>
#include "Adafruit_Si7021.h"
// Set to 1 to stop any output on Serial
#define BATT_SAVE_ON 0
#define CAD_RETRY 20
// LoRa definitions
#define RF_FREQUENCY 915600000 // Hz
#define TX_OUTPUT_POWER 22 // dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7..SF12] [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
#define LORA_CODINGRATE 1 // [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 5000
#define TX_TIMEOUT_VALUE 5000
// ESP32 Feather - Alora RFM1262 pin configuration
int PIN_LORA_RESET = 32;
int PIN_LORA_DIO_1 = 14;
int PIN_LORA_BUSY = 27;
int PIN_LORA_NSS = 33;
int PIN_LORA_SCLK = SCK;
int PIN_LORA_MISO = MISO;
int PIN_LORA_MOSI = MOSI;
int RADIO_TXEN = -1;
int RADIO_RXEN = -1;
static RadioEvents_t RadioEvents;
// LoRa callback functions
void OnTxDone(void);
void OnTxTimeout(void);
void OnCadDone(bool cadResult);
struct dataMsg
{
uint8_t startMark[4] = {0xAA, 0x55, 0x00, 0x00};
uint32_t nodeId;
int8_t tempInt;
uint8_t tempFrac;
uint8_t humidInt;
uint8_t humidFrac;
uint8_t endMark[4] = { 0x00, 0x00, 0x55, 0xAA};
} dataMsg;
uint32_t deviceID;
time_t loraTimeout;
uint8_t cadRepeat;
Adafruit_Si7021 sensor = Adafruit_Si7021();
#define uS_TO_mS_FACTOR 1000
long sleepForMillis = 30000;
time_t wakeup;
void goToSleep(void);
void setup()
{
// Record the wakeup time
wakeup = millis();
// Slowing down the ESP32 to 1/4 of its speed saves more energy
setCpuFrequencyMhz(80);
// Show we are awake
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
hw_config hwConfig;
#if BATT_SAVE_ON == 0
// Start Serial
Serial.begin(115200);
#endif
// Create node ID
uint8_t deviceMac[8];
BoardGetUniqueId(deviceMac);
deviceID += (uint32_t)deviceMac[2];
deviceID += (uint32_t)deviceMac[3] << 8;
deviceID += (uint32_t)deviceMac[4] << 16;
deviceID += (uint32_t)deviceMac[5] << 24;
#if BATT_SAVE_ON == 0
Serial.println("++++++++++++++++++++++++++++++++++++++");
Serial.printf("Sensor node ID %08X using frequency %.1f MHz\n", deviceID, (double)(RF_FREQUENCY/1000000.0));
Serial.println("++++++++++++++++++++++++++++++++++++++");
#endif
// Define the HW configuration between MCU and SX126x
hwConfig.CHIP_TYPE = SX1262_CHIP; // eByte E22 module with an SX1262
hwConfig.PIN_LORA_RESET = PIN_LORA_RESET; // LORA RESET
hwConfig.PIN_LORA_NSS = PIN_LORA_NSS; // LORA SPI CS
hwConfig.PIN_LORA_SCLK = PIN_LORA_SCLK; // LORA SPI CLK
hwConfig.PIN_LORA_MISO = PIN_LORA_MISO; // LORA SPI MISO
hwConfig.PIN_LORA_DIO_1 = PIN_LORA_DIO_1; // LORA DIO_1
hwConfig.PIN_LORA_BUSY = PIN_LORA_BUSY; // LORA SPI BUSY
hwConfig.PIN_LORA_MOSI = PIN_LORA_MOSI; // LORA SPI MOSI
hwConfig.RADIO_TXEN = RADIO_TXEN; // LORA ANTENNA TX ENABLE
hwConfig.RADIO_RXEN = RADIO_RXEN; // LORA ANTENNA RX ENABLE
hwConfig.USE_DIO2_ANT_SWITCH = true; // Example uses an eByte E22 module which uses RXEN and TXEN pins as antenna control
hwConfig.USE_DIO3_TCXO = true; // Example uses an eByte E22 module which uses DIO3 to control oscillator voltage
hwConfig.USE_DIO3_ANT_SWITCH = false; // Only Insight ISP4520 module uses DIO3 as antenna control
if (lora_hardware_init(hwConfig) != 0)
{
#if BATT_SAVE_ON == 0
Serial.println("Error in hardware init");
#endif
}
// Initialize the callbacks we need for sending
RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.CadDone = OnCadDone;
Radio.Init(&RadioEvents);
// Put LoRa into standby
Radio.Standby();
// Set Frequency
Radio.SetChannel(RF_FREQUENCY);
// Set transmit configuration
Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, TX_TIMEOUT_VALUE);
// Set receive configuration
Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, true);
// Initialize SI7021 temperature sensor
if (!sensor.begin())
{
#if BATT_SAVE_ON == 0
Serial.println("Did not find Si7021 sensor!");
#endif
goToSleep();
}
// Get the sensor values
float sensTemp = sensor.readTemperature();
float sensHumid = sensor.readHumidity();
if ((sensTemp == NAN) || (sensHumid == NAN) || (sensTemp == 255.255) || (sensHumid == 255.255))
{
// Error reading the sensor, try one more time
float sensTemp = sensor.readTemperature();
float sensHumid = sensor.readHumidity();
if ((sensTemp == NAN) || (sensHumid == NAN))
{
// Second reading failed as well, give up
#if BATT_SAVE_ON == 0
Serial.println("Could not read sensor data, skip sending");
#endif
goToSleep();
}
}
// Prepare data package
dataMsg.nodeId = deviceID;
dataMsg.tempInt = (int8_t) sensTemp;
dataMsg.tempFrac = (uint8_t)((sensTemp - dataMsg.tempInt) * 100);
dataMsg.humidInt = (uint8_t)sensHumid;
dataMsg.humidFrac = (uint8_t)((sensHumid - dataMsg.humidInt) * 100);
#if BATT_SAVE_ON == 0
Serial.printf("Finished reading sensor after %ldms\n", (millis() - wakeup));
Serial.print("Temp ");
Serial.print(dataMsg.tempInt);
Serial.print(".");
Serial.println(dataMsg.tempFrac);
Serial.print("Humid ");
Serial.print(dataMsg.humidInt);
Serial.print(".");
Serial.println(dataMsg.humidFrac);
Serial.println("Data package as HEX values:");
char *printData = (char *) &dataMsg;
for (int idx=0; idx < sizeof(dataMsg); idx++)
{
Serial.printf("%02X ", printData[idx]);
}
#endif
// Start sending
Radio.SetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
// Counter for repeated CAD in case we have many traffic
cadRepeat = 0;
Radio.StartCad();
// Make sure we detect a timeout during sending
loraTimeout = millis();
}
void loop()
{
#ifdef ESP8266
// Handle LoRa events
Radio.IrqProcess();
#endif
// Check for LoRa timeout
if ((millis() - loraTimeout) > 120000)
{
#if BATT_SAVE_ON == 0
Serial.println("LoRa loop timeout");
#endif
// LoRa failed, go back to bed
goToSleep();
}
delay(100);
}
void goToSleep(void)
{
// Send the LoRa module to sleep
Radio.Standby();
Radio.Sleep();
#if BATT_SAVE_ON == 0
Serial.printf("Sleeping after %ldms\n", (millis() - wakeup));
#endif
// Go back to bed for
time_t awakeTime = millis() - wakeup;
esp_sleep_enable_timer_wakeup((sleepForMillis - awakeTime) * uS_TO_mS_FACTOR);
esp_deep_sleep_start();
}
void OnTxDone(void)
{
#if BATT_SAVE_ON == 0
Serial.println("Transmit finished");
#endif
// LoRa failed, go back to bed
goToSleep();
}
void OnTxTimeout(void)
{
#if BATT_SAVE_ON == 0
Serial.println("Transmit timeout");
#endif
// LoRa failed, go back to bed
goToSleep();
}
void OnCadDone(bool cadResult)
{
cadRepeat++;
Radio.Standby();
if (cadResult)
{
#if BATT_SAVE_ON == 0
Serial.printf("CAD returned channel busy %d times\n", cadRepeat);
#endif
if (cadRepeat < 6)
{
// Retry CAD
Radio.Standby();
Radio.SetCadParams(LORA_CAD_08_SYMBOL, LORA_SPREADING_FACTOR + 13, 10, LORA_CAD_ONLY, 0);
Radio.StartCad();
}
else
{
// LoRa is too busy? Go to bed
goToSleep();
}
}
else
{
#if BATT_SAVE_ON == 0
Serial.printf("CAD returned channel free after %d times\n", cadRepeat);
#endif
// Send data
Radio.Send((uint8_t *) &dataMsg, sizeof(dataMsg));
}
}
RadioEvents_t::TxDone
void(* TxDone)(void)
Tx Done callback prototype.
Definition: radio.h:56
hw_config::RADIO_TXEN
int RADIO_TXEN
Definition: board.h:70
Radio_s::SetRxConfig
void(* SetRxConfig)(RadioModems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, uint16_t symbTimeout, bool fixLen, uint8_t payloadLen, bool crcOn, bool freqHopOn, uint8_t hopPeriod, bool iqInverted, bool rxContinuous)
Sets the reception parameters.
Definition: radio.h:195
RadioEvents_t::CadDone
void(* CadDone)(bool channelActivityDetected)
CAD Done callback prototype.
Definition: radio.h:96
Radio_s::Init
void(* Init)(RadioEvents_t *events)
Initializes the radio.
Definition: radio.h:109
RadioEvents_t
Radio driver callback functions.
Definition: radio.h:52
RadioEvents
static RadioEvents_t RadioEvents
Definition: LoRaMac.cpp:327
BoardGetUniqueId
void BoardGetUniqueId(uint8_t *id)
hw_config::USE_DIO2_ANT_SWITCH
bool USE_DIO2_ANT_SWITCH
Definition: board.h:72
lora_hardware_init
uint32_t lora_hardware_init(hw_config hwConfig)
Initializes the target board peripherals.
Definition: board.cpp:56
Radio_s::SetTxConfig
void(* SetTxConfig)(RadioModems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preambleLen, bool fixLen, bool crcOn, bool freqHopOn, uint8_t hopPeriod, bool iqInverted, uint32_t timeout)
Sets the transmission parameters.
Definition: radio.h:237
LORA_CAD_ONLY
@ LORA_CAD_ONLY
Definition: sx126x.h:245
hw_config::PIN_LORA_MOSI
int PIN_LORA_MOSI
Definition: board.h:69
Radio
const struct Radio_s Radio
Radio driver.
Definition: radio.cpp:364
LORA_CAD_08_SYMBOL
@ LORA_CAD_08_SYMBOL
Definition: sx126x.h:236
SX126x-Arduino.h
hw_config::CHIP_TYPE
int CHIP_TYPE
Definition: board.h:62
hw_config::PIN_LORA_NSS
int PIN_LORA_NSS
Definition: board.h:64
RadioEvents_t::TxTimeout
void(* TxTimeout)(void)
Tx Timeout callback prototype.
Definition: radio.h:60
SX1262_CHIP
#define SX1262_CHIP
Definition: board.h:56
Radio_s::Standby
void(* Standby)(void)
Sets the radio in standby mode.
Definition: radio.h:275
hw_config::USE_DIO3_ANT_SWITCH
bool USE_DIO3_ANT_SWITCH
Definition: board.h:74
Radio_s::SetCadParams
void(* SetCadParams)(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout)
Set Channel Activity Detection parameters.
Definition: radio.h:285
Radio_s::IrqProcess
void(* IrqProcess)(void)
Process radio irq.
Definition: radio.h:362
hw_config::PIN_LORA_DIO_1
int PIN_LORA_DIO_1
Definition: board.h:67
hw_config::PIN_LORA_SCLK
int PIN_LORA_SCLK
Definition: board.h:65
hw_config
Definition: board.h:61
hw_config::USE_DIO3_TCXO
bool USE_DIO3_TCXO
Definition: board.h:73
hw_config::PIN_LORA_MISO
int PIN_LORA_MISO
Definition: board.h:66
Radio_s::Send
void(* Send)(uint8_t *buffer, uint8_t size)
Sends the buffer of size. Prepares the packet to be sent and sets the radio in transmission.
Definition: radio.h:267
Radio_s::Sleep
void(* Sleep)(void)
Sets the radio in sleep mode.
Definition: radio.h:271
Radio_s::StartCad
void(* StartCad)(void)
Start a Channel Activity Detection.
Definition: radio.h:289
MODEM_LORA
@ MODEM_LORA
Definition: radio.h:34
hw_config::PIN_LORA_RESET
int PIN_LORA_RESET
Definition: board.h:63
Radio_s::SetChannel
void(* SetChannel)(uint32_t freq)
Sets the channel frequency.
Definition: radio.h:133
hw_config::RADIO_RXEN
int RADIO_RXEN
Definition: board.h:71
hw_config::PIN_LORA_BUSY
int PIN_LORA_BUSY
Definition: board.h:68