Hi!
I use the Heltec AB02S dev board with the onboard Air530z GPS on a sheep tracking application in a mountainous area in Norway, Europe. I’m using the LoRaWan_OnBoardGPS example code as a starting point for my code. The nodes can connect to two gateways, one HT-M01 with rpi zero on ethernet placed at spot1 and one HT-M01S on 4G placed at spot2. Update interval is every second hour in may-august and every 30min in sept-oct (I use month from GPS clock). The nodes have good contact with the gateways when testing the setup. Due to a lot of hills I expect the nodes to loose contact with the gateway at spot1 during the time the sheep is out and gain access to the gateway at spot2 some time later. For the nodes not to drain the battery I need to be able to set a timeout on send and join device_states. If the node loose contact with the gateway, it should timeout after i.e 30sec, then go to join to see if it can connect to a different gateway on another channel. When in join the node should timeout after 30sec and go to sleep (2 hours in may-aug) if it can’t connect to a gateway. I don’t care if I loose some position updates, the important part is that the battery last as long as possible. I am currently using 3,7V 2600mAh LiPo batteries and I will be testing 12 nodes this season.
So far I have done the following to achieve this (note: this is just a small part/ bottom part of the modified example code)
void loop()
{
//when in join, timer start tf1 is set. if joining takes more than 30 sec, go to sleep (gateway out of reach)
if(flag1==true && (millis()-tf1) > 30000){
deviceState = DEVICE_STATE_SLEEP;
flag1=false;
flag2=false;
}
//when in sending mode, timer start tf2 is set. if sending takes more than 30 sec, go to init (new gateway or gateway out of reach)
//this seems to be working ok
if(flag2 == true && (millis()-tf2) > 30000){
deviceState = DEVICE_STATE_INIT;
flag1=false;
flag2=false;
}
switch( deviceState )
{
case DEVICE_STATE_INIT:
{
#if(AT_SUPPORT)
getDevParam();
#endif
//printDevParam();
LoRaWAN.init(loraWanClass,loraWanRegion);
deviceState = DEVICE_STATE_JOIN;
break;
}
case DEVICE_STATE_JOIN:
{
if(flag1==false){
flag1=true;
tf1 = millis();
}
LoRaWAN.displayJoining();
LoRaWAN.join();
break;
}
case DEVICE_STATE_SEND:
{
if(flag2==false){
flag2=true;
tf2 = millis();
}
prepareTxFrame( appPort );
LoRaWAN.displaySending();
LoRaWAN.send();
deviceState = DEVICE_STATE_CYCLE;
break;
}
case DEVICE_STATE_CYCLE:
{
// Schedule next packet transmission
txDutyCycleTime = appTxDutyCycle + randr( 0, APP_TX_DUTYCYCLE_RND );
LoRaWAN.cycle(txDutyCycleTime);
deviceState = DEVICE_STATE_SLEEP;
break;
}
case DEVICE_STATE_SLEEP:
{
LoRaWAN.displayAck();
LoRaWAN.sleep();
break;
}
default:
{
deviceState = DEVICE_STATE_INIT;
break;
}
}
}
The code seems to be working ok for the sending part. If I turn off the gateway after joining, the device state “SEND” timeouts to init and starts joining again. However, in join it just keeps hanging. To come around this I have started to look at the LoRaWan_APP.cpp code. Would it be possible to add a timeout functionality on the “static void OnTxNextPacketTimerEvent( void )”? It seems that if it receives a “LORAMAC_STATUS_OK” it goes to sleep. if not, it keeps on cycling. I was thinking to add a timeout here and have it go to sleep instead of trying to rejoin. Cpp is not really my cup of tea, so far I’ve found that chrono and time.h give some functionality to create similar to millis() functionality, but chrono fails with an error when trying to verify from the arduino ide.
Any ideas on how to do this properly? I don’t really want to mess with the LoRaWAN_APP.cpp code, the best is if this can be achieved from the arduino ide. Any comment/ help is greatly appreciated!
Best regards,
Bendik