SX126x-Arduino
LoRaWanPio\src\main.cpp

LoRaWAN application example.

#include <Arduino.h>
#include <SPI.h>
#define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE
#define SCHED_QUEUE_SIZE 60
#define LORAWAN_APP_DATA_BUFF_SIZE 64
#define LORAWAN_APP_TX_DUTYCYCLE 10000
#define APP_TX_DUTYCYCLE_RND 1000
#define JOINREQ_NBTRIALS 3
hw_config hwConfig;
#ifdef ESP32
// ESP32 - SX126x pin configuration
int PIN_LORA_RESET = 4; // LORA RESET
int PIN_LORA_NSS = 5; // LORA SPI CS
int PIN_LORA_SCLK = 18; // LORA SPI CLK
int PIN_LORA_MISO = 19; // LORA SPI MISO
int PIN_LORA_DIO_1 = 21; // LORA DIO_1
int PIN_LORA_BUSY = 22; // LORA SPI BUSY
int PIN_LORA_MOSI = 23; // LORA SPI MOSI
int RADIO_TXEN = -1; // LORA ANTENNA TX ENABLE
int RADIO_RXEN = -1; // LORA ANTENNA RX ENABLE
#endif
#ifdef ESP8266
// ESP32 - SX126x pin configuration
int PIN_LORA_RESET = 0; // LORA RESET
int PIN_LORA_NSS = 2; // LORA SPI CS
int PIN_LORA_DIO_1 = 15; // LORA DIO_1
int PIN_LORA_BUSY = 16; // LORA SPI BUSY
int PIN_LORA_SCLK = SCK; // LORA SPI CLK
int PIN_LORA_MISO = MISO; // LORA SPI MISO
int PIN_LORA_MOSI = MOSI; // LORA SPI MOSI
int RADIO_TXEN = -1; // LORA ANTENNA TX ENABLE
int RADIO_RXEN = -1; // LORA ANTENNA RX ENABLE
#endif
#ifdef NRF52_SERIES
// nRF52832 - SX126x pin configuration
int PIN_LORA_RESET = 4; // LORA RESET
int PIN_LORA_NSS = 28; // LORA SPI CS
int PIN_LORA_SCLK = 12; // LORA SPI CLK
int PIN_LORA_MISO = 14; // LORA SPI MISO
int PIN_LORA_DIO_1 = 11; // LORA DIO_1
int PIN_LORA_BUSY = 29; // LORA SPI BUSY
int PIN_LORA_MOSI = 13; // LORA SPI MOSI
int RADIO_TXEN = -1; // LORA ANTENNA TX ENABLE
int RADIO_RXEN = -1; // LORA ANTENNA RX ENABLE
// Replace PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI with your
SPIClass SPI_LORA(NRF_SPIM2, 14, 12, 13);
#endif
// Foward declaration
static void lorawan_has_joined_handler(void);
static void lorawan_rx_handler(lmh_app_data_t *app_data);
static void lorawan_confirm_class_handler(DeviceClass_t Class);
static void send_lora_frame(void);
static uint32_t timers_init(void);
// APP_TIMER_DEF(lora_tx_timer_id); ///< LoRa tranfer timer instance.
TimerEvent_t appTimer;
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE];
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0};
lorawan_rx_handler, lorawan_has_joined_handler, lorawan_confirm_class_handler};
#ifdef NRF52_SERIES
// Start BLE if we compile for nRF52
#include <bluefruit.h>
void initBLE();
extern bool bleUARTisConnected;
extern BLEUart bleuart;
#endif
// Check if the board has an LED port defined
#ifndef LED_BUILTIN
#ifdef ESP32
#define LED_BUILTIN 2
#endif
#ifdef NRF52_SERIES
#define LED_BUILTIN 17
#endif
#endif
uint8_t nodeDeviceEUI[8] = {0x00, 0x95, 0x64, 0x1F, 0xDA, 0x91, 0x19, 0x0B};
uint8_t nodeAppEUI[8] = {0x70, 0xB3, 0xD5, 0x7E, 0xD0, 0x02, 0x01, 0xE1};
uint8_t nodeAppKey[16] = {0x07, 0xC0, 0x82, 0x0C, 0x30, 0xB9, 0x08, 0x70, 0x0C, 0x0F, 0x70, 0x06, 0x00, 0xB0, 0xBE, 0x09};
uint32_t nodeDevAddr = 0x260116F8;
uint8_t nodeNwsKey[16] = {0x7E, 0xAC, 0xE2, 0x55, 0xB8, 0xA5, 0xE2, 0x69, 0x91, 0x51, 0x96, 0x06, 0x47, 0x56, 0x9D, 0x23};
uint8_t nodeAppsKey[16] = {0xFB, 0xAC, 0xB6, 0x47, 0xF3, 0x58, 0x45, 0xC7, 0x50, 0x7D, 0xBF, 0x16, 0x8B, 0xA8, 0xC1, 0x7C};
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// Define the HW configuration between MCU and SX126x
hwConfig.CHIP_TYPE = SX1262_CHIP; // Example uses an 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 CircuitRocks Alora RFM1262 which uses DIO2 pins as antenna control
hwConfig.USE_DIO3_TCXO = true; // Example uses an CircuitRocks Alora RFM1262 which uses DIO3 to control oscillator voltage
hwConfig.USE_DIO3_ANT_SWITCH = false; // Only Insight ISP4520 module uses DIO3 as antenna control
// Initialize Serial for debug output
Serial.begin(115200);
Serial.println("=====================================");
Serial.println("SX126x LoRaWan test");
Serial.println("=====================================");
#ifdef NRF52_SERIES
pinMode(30, OUTPUT);
digitalWrite(30, HIGH);
// Start BLE if we compile for nRF52
initBLE();
#endif
// Initialize Scheduler and timer
uint32_t err_code = timers_init();
if (err_code != 0)
{
Serial.printf("timers_init failed - %d\n", err_code);
}
// Initialize LoRa chip.
err_code = lora_hardware_init(hwConfig);
if (err_code != 0)
{
Serial.printf("lora_hardware_init failed - %d\n", err_code);
}
// Setup the EUIs and Keys
lmh_setDevEui(nodeDeviceEUI);
lmh_setAppEui(nodeAppEUI);
lmh_setAppKey(nodeAppKey);
lmh_setNwkSKey(nodeNwsKey);
lmh_setAppSKey(nodeAppsKey);
lmh_setDevAddr(nodeDevAddr);
// Initialize LoRaWan
err_code = lmh_init(&lora_callbacks, lora_param_init, false);
if (err_code != 0)
{
Serial.printf("lmh_init failed - %d\n", err_code);
}
// Use either
// lmh_setSingleChannelGateway
// or
// lmh_setSubBandChannels
//
// DO NOT USE BOTH OR YOUR COMMUNICATION WILL MOST LIKELY NEVER WORK
// Setup connection to a single channel gateway
// lmh_setSingleChannelGateway(0, DR_3);
// For some regions we might need to define the sub band the gateway is listening to
// This must be called AFTER lmh_init()
{
Serial.println("lmh_setSubBandChannels failed. Wrong sub band requested?");
}
// Start Join procedure
}
void loop()
{
// Handle Radio events
// We are on FreeRTOS, give other tasks a chance to run
// delay(100);
}
static void lorawan_has_joined_handler(void)
{
#if (OVER_THE_AIR_ACTIVATION != 0)
Serial.println("Network Joined");
#else
Serial.println("OVER_THE_AIR_ACTIVATION != 0");
#endif
TimerSetValue(&appTimer, LORAWAN_APP_TX_DUTYCYCLE);
TimerStart(&appTimer);
// app_timer_start(lora_tx_timer_id, APP_TIMER_TICKS(LORAWAN_APP_TX_DUTYCYCLE), NULL);
}
static void lorawan_rx_handler(lmh_app_data_t *app_data)
{
Serial.printf("LoRa Packet received on port %d, size:%d, rssi:%d, snr:%d\n",
app_data->port, app_data->buffsize, app_data->rssi, app_data->snr);
switch (app_data->port)
{
case 3:
// Port 3 switches the class
if (app_data->buffsize == 1)
{
switch (app_data->buffer[0])
{
case 0:
break;
case 1:
break;
case 2:
break;
default:
break;
}
}
break;
// YOUR_JOB: Take action on received data
break;
default:
break;
}
}
static void lorawan_confirm_class_handler(DeviceClass_t Class)
{
Serial.printf("switch to class %c done\n", "ABC"[Class]);
// Informs the server that switch has occurred ASAP
m_lora_app_data.buffsize = 0;
m_lora_app_data.port = LORAWAN_APP_PORT;
lmh_send(&m_lora_app_data, LMH_UNCONFIRMED_MSG);
}
static void send_lora_frame(void)
{
{
//Not joined, try again later
Serial.println("Did not join network, skip sending frame");
return;
}
uint32_t i = 0;
m_lora_app_data.port = LORAWAN_APP_PORT;
m_lora_app_data.buffer[i++] = 'H';
m_lora_app_data.buffer[i++] = 'e';
m_lora_app_data.buffer[i++] = 'l';
m_lora_app_data.buffer[i++] = 'l';
m_lora_app_data.buffer[i++] = 'o';
m_lora_app_data.buffer[i++] = ' ';
m_lora_app_data.buffer[i++] = 'w';
m_lora_app_data.buffer[i++] = 'o';
m_lora_app_data.buffer[i++] = 'r';
m_lora_app_data.buffer[i++] = 'l';
m_lora_app_data.buffer[i++] = 'd';
m_lora_app_data.buffer[i++] = '!';
m_lora_app_data.buffsize = i;
lmh_error_status error = lmh_send(&m_lora_app_data, LMH_UNCONFIRMED_MSG);
if (error == LMH_SUCCESS)
{
}
Serial.printf("lmh_send result %d\n", error);
}
static void tx_lora_periodic_handler(void)
{
TimerSetValue(&appTimer, LORAWAN_APP_TX_DUTYCYCLE);
TimerStart(&appTimer);
Serial.println("Sending frame");
send_lora_frame();
}
static uint32_t timers_init(void)
{
appTimer.timerNum = 3;
TimerInit(&appTimer, tx_lora_periodic_handler);
// ret_code_t err_code;
// APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
// // Initialize timer module.
// err_code = app_timer_init();
// VERIFY_SUCCESS(err_code);
// // Initialize timers
// err_code = app_timer_create(&lora_tx_timer_id, APP_TIMER_MODE_REPEATED, tx_lora_periodic_handler);
// VERIFY_SUCCESS(err_code);
return 0;
}
lmh_app_data_t::buffer
uint8_t * buffer
Definition: LoRaMacHelper.h:73
LORAWAN_DEFAULT_DATARATE
#define LORAWAN_DEFAULT_DATARATE
Definition: LoRaMacHelper.h:38
BoardGetRandomSeed
uint32_t BoardGetRandomSeed(void)
lmh_send
lmh_error_status lmh_send(lmh_app_data_t *app_data, lmh_confirm is_tx_confirmed)
Send data.
Definition: LoRaMacHelper.cpp:963
SPI_LORA
SPIClass SPI_LORA
lmh_join_status_get
lmh_join_status lmh_join_status_get(void)
Check whether the Device is joined to the network.
Definition: LoRaMacHelper.cpp:947
lmh_app_data_t
Application Data structure.
Definition: LoRaMacHelper.h:72
lmh_join
void lmh_join(void)
Join a Lora Network in class A.
Definition: LoRaMacHelper.cpp:905
lmh_init
lmh_error_status lmh_init(lmh_callback_t *callbacks, lmh_param_t lora_param, bool otaa)
Lora Initialisation.
Definition: LoRaMacHelper.cpp:738
TimerSetValue
void TimerSetValue(TimerEvent_t *obj, uint32_t value)
Set timer new timeout value.
CLASS_C
@ CLASS_C
Definition: LoRaMac.h:104
TimerInit
void TimerInit(TimerEvent_t *obj, void(*callback)(void))
Initializes the timer object.
TimerStart
void TimerStart(TimerEvent_t *obj)
Starts and adds the timer object to the list of timer events.
TimerEvent_s::timerNum
uint8_t timerNum
Definition: timer.h:56
lmh_app_data_t::buffsize
uint8_t buffsize
Definition: LoRaMacHelper.h:74
lmh_callback_s
LoRaMac Helper Callbacks.
Definition: LoRaMacHelper.h:83
lmh_setAppSKey
void lmh_setAppSKey(uint8_t *userAppSKey)
Set Application Session Key AES encryption/decryption cipher application session key.
Definition: LoRaMacHelper.cpp:121
lmh_app_data_t::snr
uint8_t snr
Definition: LoRaMacHelper.h:77
lmh_class_request
lmh_error_status lmh_class_request(DeviceClass_t newClass)
change Lora Class
Definition: LoRaMacHelper.cpp:1017
BoardGetUniqueId
void BoardGetUniqueId(uint8_t *id)
LMH_UNCONFIRMED_MSG
@ LMH_UNCONFIRMED_MSG
Definition: LoRaMacHelper.h:65
lora_hardware_init
uint32_t lora_hardware_init(hw_config hwConfig)
Initializes the target board peripherals.
Definition: board.cpp:47
LORAWAN_ADR_ON
#define LORAWAN_ADR_ON
Enable or disable LoRaWAN Adaptive Data Rate enabled (the end-device should be static here).
Definition: Commissioning.h:58
LORAWAN_PUBLIC_NETWORK
#define LORAWAN_PUBLIC_NETWORK
Indicates if the end-device is to be connected to a private or public network.
Definition: Commissioning.h:53
DeviceClass_t
enum eDeviceClass DeviceClass_t
Radio
const struct Radio_s Radio
Radio driver.
Definition: radio.cpp:358
lmh_setAppKey
void lmh_setAppKey(uint8_t *userAppKey)
Set Application Key AES encryption/decryption cipher application key.
Definition: LoRaMacHelper.cpp:111
lmh_app_data_t::rssi
int16_t rssi
Definition: LoRaMacHelper.h:76
CLASS_A
@ CLASS_A
Definition: LoRaMac.h:92
lmh_app_data_t::port
uint8_t port
Definition: LoRaMacHelper.h:75
BoardGetBatteryLevel
uint8_t BoardGetBatteryLevel(void)
lmh_setNwkSKey
void lmh_setNwkSKey(uint8_t *userNwkSKey)
Set Network Session Key AES encryption/decryption cipher network session key.
Definition: LoRaMacHelper.cpp:116
SX1262_CHIP
#define SX1262_CHIP
Definition: board.h:55
lmh_setDevAddr
void lmh_setDevAddr(uint32_t userDevAddr)
Set Device address on the network (big endian)
Definition: LoRaMacHelper.cpp:126
LORAWAN_DUTYCYCLE_OFF
#define LORAWAN_DUTYCYCLE_OFF
Definition: Commissioning.h:49
Radio_s::IrqProcess
void(* IrqProcess)(void)
Process radio irq.
Definition: radio.h:358
TimerEvent_s
Timer object description.
Definition: timer.h:55
lmh_setAppEui
void lmh_setAppEui(uint8_t *userAppEui)
Set Application IEEE EUI.
Definition: LoRaMacHelper.cpp:106
CLASS_B
@ CLASS_B
Definition: LoRaMac.h:98
lmh_setSubBandChannels
bool lmh_setSubBandChannels(uint8_t subBand)
Set custom channel mask.
Definition: LoRaMacHelper.cpp:138
lmh_setDevEui
void lmh_setDevEui(uint8_t userDevEui[])
Definition: LoRaMacHelper.cpp:101
lmh_param_s
Definition: LoRaMacHelper.h:42
LORAWAN_DEFAULT_TX_POWER
#define LORAWAN_DEFAULT_TX_POWER
Definition: LoRaMacHelper.h:39
LoRaWan-Arduino.h
LMH_SET
@ LMH_SET
Definition: LoRaMacHelper.h:54
LMH_SUCCESS
@ LMH_SUCCESS
Definition: LoRaMacHelper.h:60
LORAWAN_APP_PORT
#define LORAWAN_APP_PORT
Definition: LoRaMacHelper.h:36
lmh_error_status
lmh_error_status
Definition: LoRaMacHelper.h:58