Cubecell stops after a random amount of wakes and sleeps. looked and edited my code as suggested in other posts. But they still stop working after a couple of hours. Could it be a memory leak or Stack pointer not being reset on wake? Is there a way to test this theory?
2022-12-09T00:00:00Z
#include “LoRaWan_APP.h”
#include “Arduino.h”
#include “time.h”
#include <Wire.h>
#include <string.h>
#include “SHT3x.h”
#ifdef asr650x
#include “innerWdt.h”
#endif
/*
-
For asr650x, the max feed time is 2.8 seconds.
-
For asr6601, the max feed time is 24 seconds.
*/
#ifdef asr650x
#define MAX_FEEDTIME 2800// ms // was 2800
#else
#define MAX_FEEDTIME 24000// ms
#endif
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 // WAS 5
#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
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];
bool AllTXdone =false;
byte packetList[255]; // store packets
byte pointer;
float Temp=0;
float Humid=0;
byte TXsize=0;
uint64_t TXchipID=getID();
byte groupID =0; // set group ID to your mesh group. Only matching ID nodes will repeat
byte action =1; // Action 0 is following bytes are Voltage, Temperature,Humidity values
uint16_t volts;
int SleepTime ; //minutes to sleep
int awakeTime =70; //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
{
WAIT_TX_DONE,
LOWPOWER,
RX,
TX
}States_t;
int16_t txNumber;
States_t state;
bool sleepMode = false;
int16_t Rssi,rxSize;
void setup() {
boardInitMcu( );
CommonBoot();
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);
if (debug==true){
Serial.println(MAX_FEEDTIME);
Serial.println("Booting from SetUp");
}
}
void loop()
{
feedInnerWdt(); // feed watchdog timer
if ((millis() - TxLastTimne> TXinterval)&&(state==RX)){
TxLastTimne = millis(); // timestamp the message
state=TX;
}
switch(state)
{
case TX:
TXPacket();
break;
case RX:
break;
case LOWPOWER:
if (debug==true){
Serial.println("LOW POWER MODE");
}
CySysWdtDisable();
Serial.println();
Serial.flush();
lowPowerHandler();
break;
default:
break;
Radio.IrqProcess( );
}
}
void TXPacket(){
if (AllTXdone==true){
awakeTime=5; // All done, go into lowpower and sleep in 5 seconds
SetAwakeTime();
state=LOWPOWER;
}
else
{
if (debug==true){
Serial.println("Get a TX packet.");
}
TXpacketGet();
if (AllTXdone==false){
//turnOnRGB(COLOR_SEND,0);
//turnOnRGB(0x000050,0);// blue help shine through case
Radio.Send( (uint8_t *)txpacket,TXsize); // *** remember to change the packet length to send
TXPacketPrint();
state=WAIT_TX_DONE;
}
}
}
void OnTxDone( void )
{
if (debug==true){
Serial.print("TX done......\r\n");
}
turnOnRGB(0,0);
awakeTime=60; // just stay awake for another 10 seconds to see if any other node joins or transmits
SetAwakeTime();
delay(1000);
Radio.Rx( 0 );
state=RX;
}
void OnTxTimeout( void )
{
delay(1000);
Radio.Sleep();
if (debug==true){
Serial.print("TX Timeout......");
}
delay(1000);
Radio.Rx( 0 );
state=RX;
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
Rssi=rssi;
rxSize=size;
//turnOnRGB(COLOR_RECEIVED,0);
delay(1000);
Radio.Sleep();
if (rxSize==18){ // found a potential node packet
memcpy(rxpacket, payload, size );
if (rxpacket[6]==groupID){ // group ID matches to add the packet to the repeat que
RXpacketApend();
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=10; // just stay awake for another 10 seconds to see if any other node joins or transmits
SetAwakeTime();
}
}
delay(1000);
Radio.Rx( 0 );
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<6;++i) {
packetList[pointer]=aStr[i];
pointer++;
}
packetList[pointer]=groupID; // Group ID location 6
pointer++;
packetList[pointer]=action; // action location 7
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++;
}
awakeTime=60; // seconds
SetAwakeTime();
return;
}
BasePoint+=20;
pointer=0;
}
TXsize=0;
if (debug==true){
Serial.println(“Nothing to send”);
}
AllTXdone=true;
delay(1000);
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])&&(i<8)){ // Compare ID's only
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(){
delay(1000);
Radio.Sleep( );
turnOnRGB(0,0);
if (debug==true){
Serial.printf("Going to sleep for %d Minutes....\r\n",SleepTime);
}
Serial.println();
Serial.flush();
state=LOWPOWER;
//TimerStop(&wakeUp);
TimerInit( &wakeUp, onWakeUp );
TimerSetValue( &wakeUp, (SleepTime *60000));
TimerStart( &wakeUp );
}
void SetAwakeTime(){
if (debug==true){
Serial.printf(“Awake for %d Seconds…\r\n”,awakeTime);
}
//TimerStop(&sleep);
TimerSetValue( &sleep, awakeTime*1000);
TimerStart( &sleep );
}
void onWakeUp(){
CommonBoot();
if (debug==true){
Serial.println(“Just Woke Up”);
}
}
void CommonBoot(){
CySysWdtEnable();
//innerWdtEnable(true);
Sensor.Begin();
Serial.begin(115200);
volts = getBatteryVoltage();
if (RecieveSync==0){ // lost sync or no nodes so go into long listen short sleep mode.
SleepTime=constrain(map(volts,3500,3000,2,90),2,90); // sleep for longer to charge from solar
//SleepTime=2;
}
else
{
SleepTime=30; // sycnd , so wake every 30 minutes to exchange data
}
awakeTime=60;
if(RecieveSync>0){
RecieveSync--;
}
TXpacketInsert();
TxLastTimne = millis(); // timestamp the message
TXinterval =20000; //between 2.5 and 7.5 seconds next T
TimerSetValue( &wakeUp, (SleepTime *60000));
TimerInit( &sleep, onSleep );
SetAwakeTime();
delay(1000);
Radio.Rx( 0 );
state=RX;
AllTXdone=false;
if (debug==true){
Serial.println("");
}
TxLastTimne = millis(); // timestamp the message
TXinterval =20000; //between 2.5 and 7.5 seconds next TX
if ((volts)<3000){
BatteryLow=true;
}
if ((volts)>3100){
BatteryLow=false;
}
if (BatteryLow==true){
SleepTime=240; // battery is flat and risks a brownout WDT trigger so sleep for 4 hours to charge
awakeTime=5; // seconds
RecieveSync=0; // no chance we will wake from recharge with sync so wake as lost sync
state=LOWPOWER; // Just go lowpower mode and sleep ASAP
}
}
void SHT30() {
// Vext ON
digitalWrite(Vext, LOW);
delay(500);
Sensor.UpdateData();
if (Humid==0){ // error reading so try again
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("%");
}
Wire.end();
delay(50);
// Vext OFF
digitalWrite(Vext, HIGH);
}
// 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;
}