I am losing sleep. SLEEP issue solved. I went to bed and slept on it. And woke with a solution. Ignore my issue

OK comming from TTGO esp32 lora boards . I am trying out the Solar cubcell . As at the moment November 2022. the links for github and arduino are a mess. So have put my big boy pants on and coded using visual studio code( actually easier in the end than arduino). However sleep is a pain on this board. Either it won’t sleep or it will sleep and never wake up.From what i can gather from here ,it’s something to do with the lowPowerHandler(); . The principle to my code, stolen mostly from the pingpong example is. i have cube cells that sync themselves together and sleep for 20 minutes and wake for 60 seconds to mesh repeat relay reading and then sleep. while i have a esp32 lora wifi board in constant receive. sending the messages to Thingspeak. If this mesh repeater thing has already been done and all i am doing is reinventing the wheel. Put me out my misery and show me the code. Else can anyone give reliable solutions to why the code in this form just locks up. I have honestly wasted days and nights getting this far and need a solution before the cubecells will be transmitting from the rubbish bin.

#include “LoRaWan_APP.h”

#include “Arduino.h”

#include “time.h”

#include <Wire.h>

#include <string.h>

#include “SHT3x.h”

SHT3x Sensor;

#ifndef LoraWan_RGB

#define LoraWan_RGB = 0 //set both to 1 for led to work

#endif

#define RF_FREQUENCY 868000000 // Hz

#define TX_OUTPUT_POWER 5 // dBm

#define LORA_BANDWIDTH 0 // [0: 125 kHz,

                                                          //  1: 250 kHz,

                                                          //  2: 500 kHz,

                                                          //  3: Reserved]

#define LORA_SPREADING_FACTOR 7 // [SF7…SF12]

#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 900

#define BUFFER_SIZE 255 // Define the payload size here

byte RXcount=0;

uint64_t TxLastTimne ; // timestamp last TX

uint64_t TXinterval; // time until next TX

uint64_t ThisAwake; // time spent awake

byte txpacket[BUFFER_SIZE];

byte rxpacket[BUFFER_SIZE];

byte packetList[255]; // store packets

byte pointer;

float Temp=0;

float Humid=0;

byte TXsize=0;

uint64_t TXchipID=getID();

uint16_t volts;

int SleepTime =1; //minutes

int awakeTime =50; //second

byte RecieveSync=0; //

static TimerEvent_t sleep;

static TimerEvent_t wakeUp;

bool BatteryLow;

bool debug=false; ///**** debug with print statements

RadioEvents_t RadioEvents;

void OnTxDone( void );

void OnTxTimeout( void );

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );

typedef enum

{

LOWPOWER,

RX,

TX

}States_t;

int16_t txNumber;

States_t state;

bool sleepMode = false;

int16_t Rssi,rxSize;

void setup() {

boardInitMcu( );

Serial.begin(115200);

txNumber=0;

Rssi=0;

RadioEvents.TxDone = OnTxDone;

RadioEvents.TxTimeout = OnTxTimeout;

RadioEvents.RxDone = OnRxDone;

Radio.Init( &RadioEvents );



Radio.SetChannel( RF_FREQUENCY );

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

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

 Radio.SetSyncWord(0xF2);                        

volts = getBatteryVoltage();

TXpacketInsert();



state=RX;

TimerInit( &sleep, onSleep );

TimerInit( &wakeUp, onWakeUp );

SetAwakeTime();

TimerSetValue( &wakeUp, (SleepTime *60000));

TxLastTimne = millis(); // timestamp the message

TXinterval =2000; //between 2.5 and 7.5 seconds next T

}

void loop()

{

if (RecieveSync==0) { // not sycned so TX interval 20 seconds

TXinterval =20000;

}

if ((millis() - TxLastTimne> TXinterval)&&(state==RX)){

  TxLastTimne = millis();            // timestamp the message

  TXinterval =8000;    //between 1 and 7 seconds next TX

  state=TX;

}

switch(state)

{

case TX:

    TXPacket();

    state=RX;

    break;

case RX:

    Radio.Rx( 0 );

 

    break;

case LOWPOWER:

  //SetAwakeTime();

  lowPowerHandler();

  //StopTimers();

    break;

    default:

        break;

}

Radio.IrqProcess( );

}

void TXPacket(){

if (debug==true){

Serial.println("Get a TX packet.");

}

   TXpacketGet();

   

    if (TXsize!=0){

      TXPacketPrint();

      if (debug==true){

      turnOnRGB(0x000050,0);// blue help shine through case

    }

      //turnOnRGB(COLOR_SEND,0);

      Radio.Send( (uint8_t *)txpacket,TXsize); // *** remember to change the packet length to send

    }

}

void OnTxDone( void )

{

if (debug==true){

Serial.print(“TX done…\r\n”);

turnOnRGB(0,0);

}

//Radio.Sleep( );

//lowPowerHandler();

//StopTimers();

state=RX;

if (RecieveSync!=0){ // sycned with other devices so do exchanges and go to sleep in 10 seconds

awakeTime=30; // seconds

}

SetAwakeTime();

}

void OnTxTimeout( void )

{

Radio.Sleep( );

if (debug==true){

Serial.print("TX Timeout......");

}

state=TX;

}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )

{

Rssi=rssi;

rxSize=size;

memcpy(rxpacket, payload, size );

//turnOnRGB(COLOR_RECEIVED,0);

if (rxSize==18){  // found another of my nodes

RXpacketApend();

 

  Radio.Rx( 0 );

  //lowPowerHandler();

  //StopTimers();

  RecieveSync=3;  // reset sycn to keep trying for 2 attempts so could lose contact for 3 hours

  SleepTime=20;   // sycned so sleep and wake together every 20 minutes

  awakeTime=20;    // just stay awake for another 10 seconds to see if any other node joins or transmits

  SetAwakeTime();

  state=RX;

 

}

}

void TXpacketInsert(){

pointer=1; // start at position 1 to insert packet length at 0

volts = getBatteryVoltage();

if (debug==true){

Serial.printf("ChipID:%04X%08X\r\n",(uint32_t)(TXchipID>>32),(uint32_t)TXchipID);

Serial.printf("Battery:");

Serial.println((float)volts/1000);

}

SHT30();



byte *aStr = new byte[8];

byte *bStr =  new byte[8];

byte *cStr =  new byte[8];

packetList[pointer]=0; // transmit recieve counter

pointer++;

int64ToChar(aStr, TXchipID);

for (int i=0;i<8;++i) {

packetList[pointer]=aStr[i];

pointer++;

}

int16ToChar(bStr, volts);

for (int i=0;i<2;++i) {

packetList[pointer]=bStr[i];

pointer++;

}

floatToChar(cStr,Temp);  // pack in temperature in packet

for (int i=0;i<4;++i) {

packetList[pointer]=cStr[i];

pointer++;

}

floatToChar(cStr,Humid);

for (int i=0;i<4;++i) {

packetList[pointer]=cStr[i];

pointer++;

}

packetList[pointer]=0; // End terminated ready for appending

packetList[0]=pointer; // put the packet length at the start.

}

void TXpacketGet(){

byte BasePoint=0;

pointer=0;

TXsize=0;

while (packetList[BasePoint+pointer]!=0) {

TXsize=packetList[BasePoint+pointer]-2;

pointer++;

if (packetList[BasePoint+pointer]<2){

  packetList[BasePoint+pointer]++;  // increment it as going to transmit this one

 

  pointer++; // incement to point at packet data

   for (int i=0;i<TXsize;++i) {

  txpacket[i]=packetList[BasePoint+pointer];

  pointer++;

}

return;

}

BasePoint+=20;

pointer=0;

}

TXsize=0;

if (debug==true){

Serial.println(“Nothing to send”);

}

if ((RecieveSync != 0)&& (RXcount>10)) {

awakeTime=1; // seconds

Radio.Sleep( );

state=LOWPOWER;

}

RXcount++;

Radio.Rx( 0 );

state=RX;

}

void RXpacketApend(){

byte BasePoint=0;

pointer=0;

while (packetList[BasePoint+pointer]!=0){ // look for end zero

bool match=true;

pointer++; // Now pointing at TX RX count

pointer++; // Now pointing at Data

for (int i=0;i<rxSize;++i) {

if (packetList[BasePoint+pointer]!=rxpacket[i]){

  match=false;

}

pointer++;

}

if (match==true) { // packet already in list don’t append just add recieved count and return

if (debug==true){

Serial.println("RX-packet matched already");

}

packetList[BasePoint+1]++;

return;

}

//BasePoint+=packetList[BasePoint]; // point to start of next packet and test match again

BasePoint+=20;

pointer=0;

}

if (BasePoint+rxSize>254){

Serial.print("Append packet full");

return;        // if buffer full do not append

}

packetList[BasePoint+pointer]= rxSize+2;

pointer++;

packetList[BasePoint+pointer]=0; // transmit recieve counter

pointer++;

for (int i=0;i<rxSize;++i) {// check for matching ID and payload

packetList[BasePoint+pointer]=rxpacket[i];

pointer++;

}

packetList[BasePoint+pointer]=0; // End terminated ready for appending

if (debug==true){

Serial.println(“New Packet appended at”);

Serial.println( BasePoint);

}

packetList[1]=1; // Send this Device again to confirm new recieved device has it.

}

void TXPacketPrint(){

byte *aStr =  new byte[8];

byte *bStr =  new byte[8];

byte *cStr =  new byte[8];

int pointer =0;



for (int i=0;i<8;++i) {   // get Chip ID

aStr[i]=txpacket[pointer];

pointer++;

}

int64_t RXchipID = charTo64bitNum(aStr);

if (debug==true){

Serial.printf(“TX-ChipID:%04X%08X\r\n”,(uint32_t)(RXchipID>>32),(uint32_t)RXchipID);

}

for (int i=0;i<2;++i) { // get battery voltage from packet

bStr[i]=txpacket[pointer];

pointer++;

}

volts=charTo16bitNum(bStr);

if (debug==true){

Serial.printf(“TX-Battery:”);

Serial.println((float)volts/1000);

}

for (int i=0;i<4;++i) { // get temperature from packet

cStr[i]=txpacket[pointer];

pointer++;

}

Temp= charTofloatNum(cStr);

if (debug==true){

Serial.print("TX-Temperature: ");

Serial.print(Temp);

Serial.write("\xC2\xB0"); //The Degree symbol

Serial.println(“C”);

}

for (int i=0;i<4;++i) { // get Humidity from packet

cStr[i]=txpacket[pointer];

pointer++;

}

Humid= charTofloatNum(cStr);

if (debug==true){

Serial.print("TX-Humidity : ");

Serial.print(Humid);

Serial.println("%");

Serial.println("------------------------");

}

}

void onSleep()

{

Radio.Sleep( );

turnOnRGB(0,0);

if (debug==true){

Serial.printf(“Going to sleep for %d Minutes…\r\n”,SleepTime);

Serial.println();

Serial.flush();

Serial.println();

Serial.flush();

}

//TimerStop(&wakeUp);

TimerSetValue( &wakeUp, (SleepTime *60000));

TimerStart( &wakeUp );

delay(50);

//LoRaWAN.sleep();

//lowPowerHandler();

}

void SetAwakeTime(){

if (debug==true){

Serial.printf(“Awake for %d Seconds…\r\n”,awakeTime);

delay(50);

Serial.flush();

}

//TimerStop(&sleep);

TimerSetValue( &sleep, awakeTime*1000);

TimerStart( &sleep );

}

void onWakeUp()

{

//TimerStop(&wakeUp);

ThisAwake=millis();

if (debug==true){

Serial.println(“Just Woke Up”);

}

//StopTimers();

if (RecieveSync==0){ // lost sync or no nodes so go into long listen short sleep mode.

SleepTime=constrain(map(volts,2900,2500,1,120),1,120); // sleep for longer to charge from solar

awakeTime=71;// awake time 71 seconds

}

else

{

SleepTime=20; // minutes

awakeTime=55; // seconds

}

if(RecieveSync>0){

RecieveSync–;

}

volts = getBatteryVoltage();

if ((volts)<2500){

BatteryLow=true;

}

if ((volts)>3100){

BatteryLow=false;

}

if (BatteryLow==true){

SleepTime=120; // 2hours do long sleep

awakeTime=1; // seconds

RecieveSync=0; // no chance we will wake from recharge with sync so wake as lost sync

onSleep(); // just sleep to recharge

}

SetAwakeTime();

TimerSetValue( &wakeUp, (SleepTime *60000));

TXpacketInsert();

Radio.Rx( 0 );

state=RX;

if (debug==true){

Serial.println("");

}

TxLastTimne = millis(); // timestamp the message

TXinterval =8000; //between 2.5 and 7.5 seconds next TX

}

void SHT30() {

// Vext ON

digitalWrite(Vext, LOW);

delay(50);

Sensor.UpdateData();

Temp=Sensor.GetTemperature();

if (debug==true){

Serial.print("Temperature: ");

Serial.print(Temp);

Serial.write("\xC2\xB0"); //The Degree symbol

Serial.println(“C”);

}

Humid=Sensor.GetRelHumidity();

if (debug==true){

Serial.print("Humidity : ");

Serial.print(Humid);

Serial.println("%");

}

// Vext OFF

digitalWrite(Vext, HIGH);

}

void StopTimers() {

TimerStop(&sleep);

TimerStop(&wakeUp);

}

void StartTimers() {

TimerSetValue( &sleep, awakeTime*1000);

TimerSetValue( &wakeUp, SleepTime *60000);

TimerStart(&sleep);

TimerStart(&wakeUp);

}

// Service routines…

void int64ToChar(byte a[], int64_t n) {

memcpy(a, &n, 8);

}

void int16ToChar(byte a[], int16_t n) {

memcpy(a, &n, 2);

}

void floatToChar(byte a[], float f) {

memcpy(a, &f, sizeof(float));

}

int64_t charTo64bitNum(byte a[]) {

int64_t n = 0;

memcpy(&n, a, 8);

return n;

}

int16_t charTo16bitNum(byte a[]) {

int16_t n = 0;

memcpy(&n, a, 2);

return n;

}

float charTofloatNum(byte a[]) {

float n = 0;

memcpy(&n, a, sizeof(float));

return n;

}