RAK4631 LoRAWAN Low Power example doesn't works

Hello Friends,

I need help because i have problems with the LoRAWan Low Power Examples.
I have a server with Chirpstack V4 running, it’s works ok with the same hardware and others software coding, but the same hardware with two low power examples doesnt works and the Serial monitor says the following the first time that i run the code:

09:41:27.526 → =====================================
09:41:27.526 → RAK4631 LoRaWan Deep Sleep Test
09:41:27.526 → =====================================
09:41:27.624 → Start network join request
09:41:28.041 → LoRaWan init success
09:42:49.387 → OVER_THE_AIR_ACTIVATION failed!
09:42:49.387 → Check your EUI’s and Keys’s!
09:42:49.387 → Check if a Gateway is in range!

In the same first time that i run the code, chirpstack recieves the following frames:


In the next times that i reset the module, chirpstack doesn’t recieve any frame.

I’m using the following example: WisBlock/examples/RAK4630/communications/LoRa/LoRaWAN/RAK4631-DeepSleep-LoRaWan at master · RAKWireless/WisBlock · GitHub

I tried to change the port (200), ADR configuration (off), Daterate(DR_0), Tx power (TX_POWER_5) and region (LORAMAC_REGION_AU915) that are the configurations that works in other working codes that i have but doesn’t help.
This it’s the original code that i used in my wisblock hardware:

RAK4631-DeepSleep-LoRaWan.ino

/**

  • @file RAK4631-DeepSleep-LoRaWan.ino
  • @author Bernd Giesecke ([email protected])
  • @brief LoRaWan deep sleep example
  • Device goes into sleep after successful OTAA/ABP network join.
  • Wake up every SLEEP_TIME seconds. Set time in main.h
  • @version 0.1
  • @date 2020-09-05
  • @copyright Copyright (c) 2020
  • @note RAK4631 GPIO mapping to nRF52840 GPIO ports
    RAK4631 ↔ nRF52840
    WB_IO1 ↔ P0.17 (GPIO 17)
    WB_IO2 ↔ P1.02 (GPIO 34)
    WB_IO3 ↔ P0.21 (GPIO 21)
    WB_IO4 ↔ P0.04 (GPIO 4)
    WB_IO5 ↔ P0.09 (GPIO 9)
    WB_IO6 ↔ P0.10 (GPIO 10)
    WB_SW1 ↔ P0.01 (GPIO 1)
    WB_A0 ↔ P0.04/AIN2 (AnalogIn A2)
    WB_A1 ↔ P0.31/AIN7 (AnalogIn A7)
    */
    #include “main.h”

/** Semaphore used by events to wake up loop task */
SemaphoreHandle_t taskEvent = NULL;

/** Timer to wakeup task frequently and send message */
SoftwareTimer taskWakeupTimer;

/** Buffer for received LoRaWan data /
uint8_t rcvdLoRaData[256];
/
* Length of received data */
uint8_t rcvdDataLen = 0;

/**

  • @brief Flag for the event type
  • -1 => no event
  • 0 => LoRaWan data received
  • 1 => Timer wakeup
  • 2 => tbd

  • */
    uint8_t eventType = -1;

/**

  • @brief Timer event that wakes up the loop task frequently
  • @param unused
    */
    void periodicWakeup(TimerHandle_t unused)
    {
    // Switch on blue LED to show we are awake
    digitalWrite(LED_BUILTIN, HIGH);
    eventType = 1;
    // Give the semaphore, so the loop task will wake up
    xSemaphoreGiveFromISR(taskEvent, pdFALSE);
    }

/**

  • @brief Arduino setup function. Called once after power-up or reset

*/
void setup(void)
{
// Create the LoRaWan event semaphore
taskEvent = xSemaphoreCreateBinary();
// Initialize semaphore
xSemaphoreGive(taskEvent);

// Initialize the built in LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);

// Initialize the connection status LED
pinMode(LED_CONN, OUTPUT);
digitalWrite(LED_CONN, HIGH);

#ifndef MAX_SAVE
// Initialize Serial for debug output
Serial.begin(115200);

time_t timeout = millis();
// On nRF52840 the USB serial is not available immediately
while (!Serial)
{
if ((millis() - timeout) < 5000)
{
delay(100);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
else
{
break;
}
}
#endif

digitalWrite(LED_BUILTIN, LOW);

#ifndef MAX_SAVE
Serial.println(“=====================================”);
Serial.println(“RAK4631 LoRaWan Deep Sleep Test”);
Serial.println(“=====================================”);
#endif

// Initialize LoRaWan and start join request
int8_t loraInitResult = initLoRaWan();

#ifndef MAX_SAVE
if (loraInitResult != 0)
{
switch (loraInitResult)
{
case -1:
Serial.println(“SX126x init failed”);
break;
case -2:
Serial.println(“LoRaWan init failed”);
break;
case -3:
Serial.println(“Subband init error”);
break;
case -4:
Serial.println(“LoRa Task init error”);
break;
default:
Serial.println(“LoRa init unknown error”);
break;
}

  // Without working LoRa we just stop here
  while (1)
  {
  	Serial.println("Nothing I can do, just loving you");
  	delay(5000);
  }

}
Serial.println(“LoRaWan init success”);
#endif

// Take the semaphore so the loop will go to sleep until an event happens
xSemaphoreTake(taskEvent, 10);
}

/**

  • @brief Arduino loop task. Called in a loop from the FreeRTOS task handler

*/
void loop(void)
{
// Switch off blue LED to show we go to sleep
digitalWrite(LED_BUILTIN, LOW);

// Sleep until we are woken up by an event
if (xSemaphoreTake(taskEvent, portMAX_DELAY) == pdTRUE)
{
// Switch on blue LED to show we are awake
digitalWrite(LED_BUILTIN, HIGH);
delay(500); // Only so we can see the blue LED

  // Check the wake up reason
  switch (eventType)
  {
  case 0: // Wakeup reason is package downlink arrived

#ifndef MAX_SAVE
Serial.println(“Received package over LoRaWan”);
#endif
if (rcvdLoRaData[0] > 0x1F)
{
#ifndef MAX_SAVE
Serial.printf(“%s\n”, (char *)rcvdLoRaData);
#endif
}
else
{
#ifndef MAX_SAVE
for (int idx = 0; idx < rcvdDataLen; idx++)
{
Serial.printf(“%X “, rcvdLoRaData[idx]);
}
Serial.println(””);
#endif
}

  	break;
  case 1: // Wakeup reason is timer

#ifndef MAX_SAVE
Serial.println(“Timer wakeup”);
#endif
/// \todo read sensor or whatever you need to do frequently

  	// Send the data package
  	if (sendLoRaFrame())
  	{

#ifndef MAX_SAVE
Serial.println(“LoRaWan package sent successfully”);
#endif
}
else
{
#ifndef MAX_SAVE
Serial.println(“LoRaWan package send failed”);
/// \todo maybe you need to retry here?
#endif
}

  	break;
  default:

#ifndef MAX_SAVE
Serial.println(“This should never happen ;-)”);
#endif
break;
}
digitalWrite(LED_BUILTIN, LOW);
// Go back to sleep
xSemaphoreTake(taskEvent, 10);
}
}

main.h

/**

  • @file main.h

  • @author Bernd Giesecke ([email protected])

  • @brief Includes, definitions and global declarations for DeepSleep example

  • @version 0.1

  • @date 2020-08-15

  • @copyright Copyright (c) 2020

*/

#include <Arduino.h>

#include <SPI.h>

#include <LoRaWan-RAK4630.h>

// Comment the next line if you want DEBUG output. But the power savings are not as good then!!!

// #define MAX_SAVE

/* Time the device is sleeping in milliseconds = 2 minutes * 60 seconds * 1000 milliseconds */

// #define SLEEP_TIME 2 * 60 * 1000

#define SLEEP_TIME 1 * 30 * 1000 //30 segundos

// LoRaWan stuff

int8_t initLoRaWan(void);

bool sendLoRaFrame(void);

extern SemaphoreHandle_t loraEvent;

// Main loop stuff

void periodicWakeup(TimerHandle_t unused);

extern SemaphoreHandle_t taskEvent;

extern uint8_t rcvdLoRaData;

extern uint8_t rcvdDataLen;

extern uint8_t eventType;

extern SoftwareTimer taskWakeupTimer;

lora_handler.cpp

/**
@file lora_handler.cpp
@author Bernd Giesecke ([email protected])
@brief Initialization, event handlers and task for LoRaWan
@version 0.1
@date 2020-08-15

@copyright Copyright (c) 2020

*/
#include “main.h”

/** Gabriel: DEFINE MIOS /
bool doOTAA = true; // OTAA is used by default.
#define LORAWAN_DATERATE DR_0 // /LoRaMac datarates definition, from DR_0 to DR_5/
#define LORAWAN_TX_POWER TX_POWER_5 /LoRaMac tx power definition, from TX_POWER_0 to TX_POWER_15/
#define JOINREQ_NBTRIALS 3 /**< Number of trials for the join request. /
DeviceClass_t gCurrentClass = CLASS_A; /
class definition
/
LoRaMacRegion_t gCurrentRegion = LORAMAC_REGION_AU915; /* Region:EU868*/
// lmh_confirm gCurrentConfirm = LMH_CONFIRMED_MSG; /* confirm/unconfirm packet definition*/
#define LORAWAN_APP_PORT 200

/** DIO1 GPIO pin for RAK4631 */
#define PIN_LORA_DIO_1 47

/** Max size of the data to be transmitted. /
#define LORAWAN_APP_DATA_BUFF_SIZE 64
/
* Number of trials for the join request. */
#define JOINREQ_NBTRIALS 3

/** Lora application data buffer. /
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE];
/
* Lora application data structure. */
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0};

// LoRaWan event handlers
/** LoRaWan callback when join network finished /
static void lorawan_has_joined_handler(void);
/
* LoRaWan callback when join failed /
static void lorawan_join_failed_handler(void);
/
* LoRaWan callback when data arrived /
static void lorawan_rx_handler(lmh_app_data_t app_data);
/
LoRaWan callback after class change request finished /
static void lorawan_confirm_class_handler(DeviceClass_t Class);
/
* LoRaWan Function to send a package */
bool sendLoRaFrame(void);

/**@brief Structure containing LoRaWan parameters, needed for lmh_init()

Set structure members to
LORAWAN_ADR_ON or LORAWAN_ADR_OFF to enable or disable adaptive data rate
LORAWAN_DEFAULT_DATARATE OR DR_0 … DR_5 for default data rate or specific data rate selection
LORAWAN_PUBLIC_NETWORK or LORAWAN_PRIVATE_NETWORK to select the use of a public or private network
JOINREQ_NBTRIALS or a specific number to set the number of trials to join the network
LORAWAN_DEFAULT_TX_POWER or a specific number to set the TX power used
LORAWAN_DUTYCYCLE_ON or LORAWAN_DUTYCYCLE_OFF to enable or disable duty cycles
Please note that ETSI mandates duty cycled transmissions.
*/
static lmh_param_t lora_param_init = {LORAWAN_ADR_OFF, LORAWAN_DATERATE, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_TX_POWER, LORAWAN_DUTYCYCLE_OFF};

/** Structure containing LoRaWan callback functions, needed for lmh_init() /
static lmh_callback_t lora_callbacks = {BoardGetBatteryLevel, BoardGetUniqueId, BoardGetRandomSeed,
lorawan_rx_handler, lorawan_has_joined_handler, lorawan_confirm_class_handler, lorawan_join_failed_handler
};
// !!! KEYS ARE MSB !!!
/
* Device EUI required for OTAA network join */
// uint8_t nodeDeviceEUI[8] = {0x06, 0xFF, 0x3D, 0x47, 0x30, 0x08, 0x50, 0x90}; ////Mi deveui del RAK_001
// uint8_t nodeAppEUI[8] = {0xB8, 0x27, 0xEB, 0xFF, 0xFE, 0x39, 0x00, 0x00}; //Mi appeui del RAK_001
// uint8_t nodeAppKey[16] = {0xB5, 0xAB, 0x9E, 0x1B, 0x76, 0xC2, 0x3F, 0xE0, 0x3C, 0xEF, 0xEE, 0x3E, 0x5C, 0x78, 0x45, 0x1B}; //Mi appkey del RAK_001

uint8_t nodeDeviceEUI[8] = {0x06, 0xFF, 0x3D, 0x47, 0x30, 0x08, 0x50, 0x91}; ////Mi deveui del RAK_001_LowPower
uint8_t nodeAppEUI[8] = {0xB8, 0x27, 0xEB, 0xFF, 0xFE, 0x39, 0x00, 0x00}; //Mi appeui del RAK_001_LowPower
uint8_t nodeAppKey[16] = {0xB5, 0xAB, 0x9E, 0x1B, 0x76, 0xC2, 0x3F, 0xE0, 0x3C, 0xEF, 0xEE, 0x3E, 0x5C, 0x78, 0x45, 0x1C}; //Mi appkey del RAK_001_LowPower

/** Device address required for ABP network join /
uint32_t nodeDevAddr = 0x26021FB6;
/
* Network session key required for ABP network join /
uint8_t nodeNwsKey[16] = {0x32, 0x3D, 0x15, 0x5A, 0x00, 0x0D, 0xF3, 0x35, 0x30, 0x7A, 0x16, 0xDA, 0x0C, 0x9D, 0xF5, 0x3F};
/
* Application session key required for ABP network join */
uint8_t nodeAppsKey[16] = {0x3F, 0x6A, 0x66, 0x45, 0x9D, 0x5E, 0xDC, 0xA6, 0x3C, 0xBC, 0x46, 0x19, 0xCD, 0x61, 0xA1, 0x1E};

/** Flag whether to use OTAA or ABP network join method */
// doOTAA = true;

// DeviceClass_t gCurrentClass = CLASS_A; /* class definition*/
// LoRaMacRegion_t gCurrentRegion = LORAMAC_REGION_EU868; /* Region:EU868*/

/**
@brief Initialize LoRa HW and LoRaWan MAC layer

@return int8_t result
0 => OK
-1 => SX126x HW init failure
-2 => LoRaWan MAC initialization failure
-3 => Subband selection failure
*/
int8_t initLoRaWan(void)
{
// Initialize LoRa chip.
if (lora_rak4630_init() != 0)
{
return -1;
}

// Setup the EUIs and Keys
if (doOTAA)
{
lmh_setDevEui(nodeDeviceEUI);
lmh_setAppEui(nodeAppEUI);
lmh_setAppKey(nodeAppKey);
}
else
{
lmh_setNwkSKey(nodeNwsKey);
lmh_setAppSKey(nodeAppsKey);
lmh_setDevAddr(nodeDevAddr);
}

// Initialize LoRaWan
if (lmh_init(&lora_callbacks, lora_param_init, doOTAA, gCurrentClass, gCurrentRegion) != 0)
{
return -2;
}

// For some regions we might need to define the sub band the gateway is listening to
// This must be called AFTER lmh_init()
if (!lmh_setSubBandChannels(1))
{
return -3;
}

// Start Join procedure
#ifndef MAX_SAVE
Serial.println(“Start network join request”);
#endif
lmh_join();

return 0;
}

/**
@brief LoRa function for handling HasJoined event.
*/
static void lorawan_has_joined_handler(void)
{
if (doOTAA)
{
uint32_t otaaDevAddr = lmh_getDevAddr();
#ifndef MAX_SAVE
Serial.printf(“OTAA joined and got dev address %08X\n”, otaaDevAddr);
#endif
}
else
{
#ifndef MAX_SAVE
Serial.println(“ABP joined”);
#endif
}

// Default is Class A, where the SX1262 transceiver is in sleep mode unless a package is sent
// If switched to Class C the power consumption is higher because the SX1262 chip remains in RX mode

// lmh_class_request(CLASS_C);

digitalWrite(LED_CONN, LOW);

// Now we are connected, start the timer that will wakeup the loop frequently
taskWakeupTimer.begin(SLEEP_TIME, periodicWakeup);
taskWakeupTimer.start();
}
/*@brief LoRa function for handling OTAA join failed
/
static void lorawan_join_failed_handler(void)
{
Serial.println(“OVER_THE_AIR_ACTIVATION failed!”);
Serial.println(“Check your EUI’s and Keys’s!”);
Serial.println(“Check if a Gateway is in range!”);
}
/

@brief Function for handling LoRaWan received data from Gateway

@param app_data Pointer to rx data
*/
static void lorawan_rx_handler(lmh_app_data_t *app_data)
{
#ifndef MAX_SAVE
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);
#endif
switch (app_data->port)
{
case 3:
// Port 3 switches the class
if (app_data->buffsize == 1)
{
switch (app_data->buffer[0])
{
case 0:
lmh_class_request(CLASS_A);
#ifndef MAX_SAVE
Serial.println(“Request to switch to class A”);
#endif
break;

      case 1:
        lmh_class_request(CLASS_B);

#ifndef MAX_SAVE
Serial.println(“Request to switch to class B”);
#endif
break;

      case 2:
        lmh_class_request(CLASS_C);

#ifndef MAX_SAVE
Serial.println(“Request to switch to class C”);
#endif
break;

      default:
        break;
    }
  }
  break;
case LORAWAN_APP_PORT:
  // Copy the data into loop data buffer
  memcpy(rcvdLoRaData, app_data->buffer, app_data->buffsize);
  rcvdDataLen = app_data->buffsize;
  eventType = 0;
  // Notify task about the event
  if (taskEvent != NULL)
  {

#ifndef MAX_SAVE
Serial.println(“Waking up loop task”);
#endif
xSemaphoreGive(taskEvent);
}
}
}

/**
@brief Callback for class switch confirmation

@param Class The new class
*/
static void lorawan_confirm_class_handler(DeviceClass_t Class)
{
#ifndef MAX_SAVE
Serial.printf(“switch to class %c done\n”, “ABC”[Class]);
#endif

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

/**
@brief Send a LoRaWan package

@return result of send request
*/
bool sendLoRaFrame(void)
{
if (lmh_join_status_get() != LMH_SET)
{
//Not joined, try again later
#ifndef MAX_SAVE
Serial.println(“Did not join network, skip sending frame”);
#endif
return false;
}

m_lora_app_data.port = LORAWAN_APP_PORT;

//******************************************************************
/// \todo here some more usefull data should be put into the package
//******************************************************************

uint8_t buffSize = 0;
m_lora_app_data_buffer[buffSize++] = ‘H’;
m_lora_app_data_buffer[buffSize++] = ‘e’;
m_lora_app_data_buffer[buffSize++] = ‘l’;
m_lora_app_data_buffer[buffSize++] = ‘l’;
m_lora_app_data_buffer[buffSize++] = ‘o’;

m_lora_app_data.buffsize = buffSize;

lmh_error_status error = lmh_send(&m_lora_app_data, LMH_UNCONFIRMED_MSG);

return (error == 0);
}

Continues in the next post because the forum text limits.

I tought that the examples was broke so i tried other example that i found in this forum, in this link but the results are the same.

The code that i modified using this example it’s the following, i deleted all the SDIO lines and added the lorawan config that i said early about port, region, tx power, adr off and daterate:

#include <Arduino.h>
#include <SPI.h>

#include <LoRaWan-RAK4630.h>

// #include “RAK13010_SDI12.h”

// #define TX_PIN WB_IO6 // The pin of the SDI-12 data bus.
// #define RX_PIN WB_IO5 // The pin of the SDI-12 data bus.
// #define OE WB_IO4 // Output enable pin, active low.

// #define SENSOR_ADDRESS ‘a’

// RAK_SDI12 mySDI12(RX_PIN, TX_PIN, OE);

// String sdiResponse = “”;
// int sdiCommandIndex = 1;
// String sdiCommand = “M1!”;

float batteryVoltage, ecBulk;

#define LORAWAN_DATERATE DR_0 // /LoRaMac datarates definition, from DR_0 to DR_5/
#define LORAWAN_TX_POWER TX_POWER_5 /LoRaMac tx power definition, from TX_POWER_0 to TX_POWER_15/

#define PIN_VBAT WB_A0
uint32_t vbat_pin = PIN_VBAT;
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12 - bit ADC resolution = 3000mV / 4096
#define VBAT_DIVIDER_COMP (1.73) // Compensation factor for the VBAT divider, depend on the board
#define PIN_LORA_DIO_1 47 // DIO1 GPIO pin for RAK4631
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
#define LORAWAN_APP_DATA_BUFF_SIZE 64 // Max size of the data to be transmitted.
#define JOINREQ_NBTRIALS 8 // Number of trials for the join request.
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE]; // Lora application data buffer.
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0}; // Lora application data structure.
// LoRaWan event handlers
static void lorawan_has_joined_handler(void);
static void lorawan_join_failed_handler(void);
static void lorawan_rx_handler(lmh_app_data_t *app_data);
static void lorawan_confirm_class_handler(DeviceClass_t Class);
bool sendLoRaFrame(void);
#define LORAWAN_APP_PORT 200

// bool doOTAA = true; // OTAA is used by default.
// #define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /< Maximum size of scheduler events. */
// #define SCHED_QUEUE_SIZE 60 /
< Maximum number of events in the scheduler queue. /
// #define LORAWAN_DATERATE DR_0 //ERA DR_0 /LoRaMac datarates definition, from DR_0 to DR_5/
// #define LORAWAN_TX_POWER TX_POWER_5 /LoRaMac tx power definition, from TX_POWER_0 to TX_POWER_15/
// #define JOINREQ_NBTRIALS 3 /**< Number of trials for the join request. /
// DeviceClass_t gCurrentClass = CLASS_A; /
class definition
/
// LoRaMacRegion_t gCurrentRegion = LORAMAC_REGION_AU915; /* Region:EU868*/
// lmh_confirm gCurrentConfirm = LMH_CONFIRMED_MSG; /* confirm/unconfirm packet definition*/

/**

  • @brief Structure containing LoRaWan parameters, needed for lmh_init()
    Set structure members to
    LORAWAN_ADR_ON or LORAWAN_ADR_OFF to enable or disable adaptive data rate
    LORAWAN_DEFAULT_DATARATE OR DR_0 … DR_5 for default data rate or specific data rate selection
    LORAWAN_PUBLIC_NETWORK or LORAWAN_PRIVATE_NETWORK to select the use of a public or private network
    JOINREQ_NBTRIALS or a specific number to set the number of trials to join the network
    LORAWAN_DEFAULT_TX_POWER or a specific number to set the TX power used
    LORAWAN_DUTYCYCLE_ON or LORAWAN_DUTYCYCLE_OFF to enable or disable duty cycles
    Please note that ETSI mandates duty cycled transmissions.
    */
    // static lmh_param_t lora_param_init = {LORAWAN_ADR_ON, DR_3, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_DEFAULT_TX_POWER, LORAWAN_DUTYCYCLE_ON}; //Gabriel: Viene del ejemplo
    static lmh_param_t lora_param_init = {LORAWAN_ADR_OFF, LORAWAN_DATERATE, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_TX_POWER, LORAWAN_DUTYCYCLE_OFF};

/** Structure containing LoRaWan callback functions, needed for lmh_init() */
static lmh_callback_t lora_callbacks = {BoardGetBatteryLevel, BoardGetUniqueId, BoardGetRandomSeed, lorawan_rx_handler, lorawan_has_joined_handler, lorawan_confirm_class_handler, lorawan_join_failed_handler};

// Comment the next line if you want DEBUG output. But the power savings are not as good then!!!
// #define MAX_SAVE
/* Time the device is sleeping in milliseconds = 2 minutes * 60 seconds * 1000 milliseconds */
#define SLEEP_TIME 20 * 60 * 1000

uint8_t nodeDeviceEUI[8] = {0x06, 0xFF, 0x3D, 0x47, 0x30, 0x08, 0x50, 0x91}; ////Mi deveui del RAK_001_LowPower
uint8_t nodeAppEUI[8] = {0xB8, 0x27, 0xEB, 0xFF, 0xFE, 0x39, 0x00, 0x00}; //Mi appeui del RAK_001_LowPower
uint8_t nodeAppKey[16] = {0xB5, 0xAB, 0x9E, 0x1B, 0x76, 0xC2, 0x3F, 0xE0, 0x3C, 0xEF, 0xEE, 0x3E, 0x5C, 0x78, 0x45, 0x1C}; //Mi appkey del RAK_001_LowPower

DeviceClass_t gCurrentClass = CLASS_A;
LoRaMacRegion_t gCurrentRegion = LORAMAC_REGION_AU915;

/** Semaphore used by events to wake up loop task /
SemaphoreHandle_t taskEvent = NULL;
/
* Timer to wakeup task frequently and send message */
SoftwareTimer taskWakeupTimer;

/** Buffer for received LoRaWan data /
uint8_t rcvdLoRaData[256];
/
* Length of received data */
uint8_t rcvdDataLen = 0;

/**

  • @brief Flag for the event type
  • -1 => no event
  • 0 => LoRaWan data received
  • 1 => Timer wakeup
  • 2 => tbd

  • */
    uint8_t eventType = -1;

/**

  • @brief Timer event that wakes up the loop task frequently
  • @param unused
    */
    void periodicWakeup(TimerHandle_t unused)
    {
    eventType = 1;
    // Give the semaphore, so the loop task will wake up
    xSemaphoreGiveFromISR(taskEvent, pdFALSE);
    }

float readVBAT(void)
{
// Set the analog reference to 3.0V (default = 3.6V)
analogReference(AR_INTERNAL_3_0);
// Set the resolution to 12-bit (0…4095)
analogReadResolution(12); // Can be 8, 10, 12 or 14
// Let the ADC settle
delay(1);
float raw;
// Get the raw 12-bit, 0…3000mV ADC value
raw = analogRead(vbat_pin);
return raw * REAL_VBAT_MV_PER_LSB;
}

/*

  • Get the response as string from the SDI-12, split by “+” sign and
  • assign the values to the variables waterContent, ecPore and temperature.
    */
    // void parseResponse(String response)
    // {
    // int index = 0;
    // int nextIndex = 0;
    // int counter = 0;
    // String value = “”;
    // while (index < response.length())
    // {
    // nextIndex = response.indexOf(‘+’, index);

// // If no other “+” sign is found, get the rest of the string.
// if (nextIndex == -1)
// {
// nextIndex = response.length();
// }

// value = response.substring(index, nextIndex);
// switch (counter)
// {
// case 0:
// // Address of the sensor
// break;
// case 1:
// waterContent = value.toFloat();
// break;
// case 2:
// ecPore = value.toFloat();
// break;
// case 3:
// temperature = value.toFloat();
// break;
// case 4:
// ecBulk = value.toFloat();
// break;
// case 5:
// permittivity = value.toFloat();
// break;
// default:
// break;
// }

// index = nextIndex + 1;
// counter = counter + 1;
// }
// }

// void setAddress()
// {
// // Power the sensor.
// pinMode(WB_IO2, OUTPUT);
// digitalWrite(WB_IO2, HIGH);
// delay(3000);
// mySDI12.begin();
// delay(500);
// mySDI12.clearBuffer();
// delay(3000);
// mySDI12.sendCommand(“0Aa!”);
// delay(30);

// mySDI12.end();
// digitalWrite(WB_IO2, LOW);
// }

// void readFromSensor()
// {
// // Power the sensor.
// pinMode(WB_IO2, OUTPUT);
// digitalWrite(WB_IO2, HIGH);
// delay(1500);
// mySDI12.begin();
// delay(500);
// mySDI12.clearBuffer();
// delay(500);
// mySDI12.sendCommand(String(SENSOR_ADDRESS) + sdiCommand);
// delay(30);

// sdiResponse = mySDI12.readStringUntil(‘\n’);
// #ifndef MAX_SAVE
// Serial.println("Response TIME: " + sdiResponse);
// #endif

// // Should be gather from the response
// delay(2000);

// mySDI12.clearBuffer();
// mySDI12.sendCommand(String(SENSOR_ADDRESS) + “D0!”);
// sdiResponse = mySDI12.readStringUntil(‘\n’);
// #ifndef MAX_SAVE
// Serial.println("Response: " + sdiResponse);
// #endif
// parseResponse(sdiResponse);

// mySDI12.end();
// digitalWrite(WB_IO2, LOW);
// }

/**
@brief Initialize LoRa HW and LoRaWan MAC layer

@return int8_t result
0 => OK
-1 => SX126x HW init failure
-2 => LoRaWan MAC initialization failure
-3 => Subband selection failure
*/
int8_t initLoRaWan(void)
{
// Initialize LoRa chip.
if (lora_rak4630_init() != 0)
{
return -1;
}

// Setup the EUIs and Keys
lmh_setDevEui(nodeDeviceEUI);
lmh_setAppEui(nodeAppEUI);
lmh_setAppKey(nodeAppKey);

// Initialize LoRaWan
if (lmh_init(&lora_callbacks, lora_param_init, true, gCurrentClass, gCurrentRegion) != 0)
{
return -2;
}

// For some regions we might need to define the sub band the gateway is listening to
// This must be called AFTER lmh_init()
if (!lmh_setSubBandChannels(1))
{
return -3;
}

// Start Join procedure
#ifndef MAX_SAVE
Serial.println(“Start network join request”);
#endif
lmh_join();

return 0;
}

/**
@brief LoRa function for handling HasJoined event.
*/
static void lorawan_has_joined_handler(void)
{
uint32_t otaaDevAddr = lmh_getDevAddr();
#ifndef MAX_SAVE
Serial.printf(“OTAA joined and got dev address %08X\n”, otaaDevAddr);
#endif

// Default is Class A, where the SX1262 transceiver is in sleep mode unless a package is sent
// If switched to Class C the power consumption is higher because the SX1262 chip remains in RX mode
// lmh_class_request(CLASS_C);

// Now we are connected, start the timer that will wakeup the loop frequently
taskWakeupTimer.begin(SLEEP_TIME, periodicWakeup);
taskWakeupTimer.start();
}
/*@brief LoRa function for handling OTAA join failed
/
static void lorawan_join_failed_handler(void)
{
Serial.println(“OVER_THE_AIR_ACTIVATION failed!”);
Serial.println(“Check your EUI’s and Keys’s!”);
Serial.println(“Check if a Gateway is in range!”);
}
/

@brief Function for handling LoRaWan received data from Gateway

@param app_data Pointer to rx data
*/
static void lorawan_rx_handler(lmh_app_data_t *app_data)
{
#ifndef MAX_SAVE
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);
#endif
switch (app_data->port)
{
case 3:
// Port 3 changes the command for the sensor
if (app_data->buffsize == 1)
{
// sdiCommandIndex = app_data->buffer[0];
// sdiCommand = “M” + String(sdiCommandIndex) + “!”;
}
break;

case LORAWAN_APP_PORT:
// Copy the data into loop data buffer
memcpy(rcvdLoRaData, app_data->buffer, app_data->buffsize);
rcvdDataLen = app_data->buffsize;
eventType = 0;
// Notify task about the event
if (taskEvent != NULL)
{
#ifndef MAX_SAVE
Serial.println(“Waking up loop task”);
#endif
xSemaphoreGive(taskEvent);
}
}
}

/**
@brief Callback for class switch confirmation

@param Class The new class
*/
static void lorawan_confirm_class_handler(DeviceClass_t Class)
{
#ifndef MAX_SAVE
Serial.printf(“switch to class %c done\n”, “ABC”[Class]);
#endif

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

/**
@brief Send a LoRaWan package

@return result of send request
*/
bool sendLoRaFrame(void)
{
if (lmh_join_status_get() != LMH_SET)
{
// Not joined, try again later
#ifndef MAX_SAVE
Serial.println(“Did not join network, skip sending frame”);
#endif
return false;
}

// KIND: ecp
// m_lora_app_data.port = 7;
m_lora_app_data.port = LORAWAN_APP_PORT;
batteryVoltage = readVBAT();

//******************************************************************
/// \todo here some more usefull data should be put into the package
//******************************************************************

uint8_t buffSize = 0;
// First byte is here for future use
m_lora_app_data_buffer[buffSize++] = highByte(00);
m_lora_app_data_buffer[buffSize++] = lowByte(00);
// TODO battery voltage
m_lora_app_data_buffer[buffSize++] = highByte((int)batteryVoltage);
m_lora_app_data_buffer[buffSize++] = lowByte((int)batteryVoltage);
// m_lora_app_data_buffer[buffSize++] = highByte((int)(waterContent * 100));
// m_lora_app_data_buffer[buffSize++] = lowByte((int)(waterContent * 100));
// m_lora_app_data_buffer[buffSize++] = highByte((int)(temperature * 100));
// m_lora_app_data_buffer[buffSize++] = lowByte((int)(temperature * 100));
// m_lora_app_data_buffer[buffSize++] = highByte((int)(ecPore * 10));
// m_lora_app_data_buffer[buffSize++] = lowByte((int)(ecPore * 10));
// m_lora_app_data_buffer[buffSize++] = highByte((int)(SLEEP_TIME / 1000));
// m_lora_app_data_buffer[buffSize++] = lowByte((int)(SLEEP_TIME / 1000));
// m_lora_app_data_buffer[buffSize++] = highByte((int)(sdiCommandIndex));
// m_lora_app_data_buffer[buffSize++] = lowByte((int)(sdiCommandIndex));

m_lora_app_data.buffsize = buffSize;

lmh_error_status error = lmh_send(&m_lora_app_data, LMH_UNCONFIRMED_MSG);

return (error == 0);
}

/**

  • @brief Arduino setup function. Called once after power-up or reset

*/
void setup(void)
{

#ifndef MAX_SAVE
Serial.begin(9600);

time_t serialTimeout = millis();
while (!Serial)
{
    delay(10); // for nrf52840 with native usb
    if ((millis() - serialTimeout) > 5000)
    {
        break;
    }
}
// delay(2000);
Serial.println("Serial OK!");

#endif

// setAddress(); //Address SDIO
// Create the LoRaWan event semaphore
taskEvent = xSemaphoreCreateBinary();
// Initialize semaphore
xSemaphoreGive(taskEvent);

// Initialize LoRaWan and start join request
int8_t loraInitResult = initLoRaWan();

#ifndef MAX_SAVE
if (loraInitResult != 0)
{
switch (loraInitResult)
{
case -1:
Serial.println(“SX126x init failed”);
break;
case -2:
Serial.println(“LoRaWan init failed”);
break;
case -3:
Serial.println(“Subband init error”);
break;
case -4:
Serial.println(“LoRa Task init error”);
break;
default:
Serial.println(“LoRa init unknown error”);
break;
}

// Without working LoRa we just stop here
while (1)
{
  Serial.println("Nothing I can do, just loving you");
  delay(5000);
}

}
Serial.println(“LoRaWan init success”);
#endif

// // Take the semaphore so the loop will go to sleep until an event happens
// xSemaphoreTake(taskEvent, 10);
eventType = 1;
}

/**

  • @brief Arduino loop task. Called in a loop from the FreeRTOS task handler

*/
void loop(void)
{
// Sleep until we are woken up by an event
if (xSemaphoreTake(taskEvent, portMAX_DELAY) == pdTRUE)
{
// Check the wake up reason
switch (eventType)
{
case 0: // Wakeup reason is package downlink arrived
#ifndef MAX_SAVE
Serial.println(“Received package over LoRaWan”);
#endif
if (rcvdLoRaData[0] > 0x1F)
{
#ifndef MAX_SAVE
Serial.printf(“%s\n”, (char *)rcvdLoRaData);
#endif
}
else
{
#ifndef MAX_SAVE
for (int idx = 0; idx < rcvdDataLen; idx++)
{
Serial.printf(“%X “, rcvdLoRaData[idx]);
}
Serial.println(””);
#endif
}

  break;
case 1: // Wakeup reason is timer

#ifndef MAX_SAVE
Serial.println(“Timer wakeup”);
#endif
// readFromSensor();
// Send the data package
if (sendLoRaFrame())
{
#ifndef MAX_SAVE
Serial.println(“LoRaWan package sent successfully”);
#endif
}
else
{
#ifndef MAX_SAVE
Serial.println(“LoRaWan package send failed”);
/// \todo maybe you need to retry here?
#endif
}

  break;
default:

#ifndef MAX_SAVE
Serial.println(“This should never happen ;-)”);
#endif
break;
}
// Go back to sleep
xSemaphoreTake(taskEvent, 10);
}
}

I continue to searching and i found the solution:

The problem was in subchannel band, because AU915 works in sub band 2.

Here i found the solution:

Another advice: if you comment the setsubband command, the library assign automatically the right sub channel.

// if (!lmh_setSubBandChannels(2))
// {
// return -3;
// }

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.