RAK3172 Not Sending After Waking Up from Deep Sleep

Exact same code is working fine when I use the delay.

As soon as I replace delay with api.system.sleep.all(3000); I do not get data on receiving node. I tried re-initialing the Lora parameters after waking up but that didn’t worked as well.

uint8_t counter = 1;
unsigned int previousTxDuration = 0;  // Stores TX duration from previous loop

void send_cb(void) {
  // Optional: callback after sending
}


void setup() {
  // No Serial
  api.lora.nwm.set();             // Set to P2P mode
  api.lora.pfreq.set(923200000);  // Match receiver frequency
  api.lora.psf.set(12);           // Spreading Factor
  api.lora.pbw.set(125);          // Bandwidth
  api.lora.pcr.set(0);            // Coding Rate
  api.lora.ppl.set(8);            // Preamble Length
  api.lora.ptp.set(10);           // TX Power

  api.lora.registerPSendCallback(send_cb);
  delay(1000);
}

void loop() {
  uint8_t payload[3];  // 1 byte for counter + 2 bytes for txDuration

  unsigned long startTime = millis();  // Start time before transmission
  api.lora.precv(0);  // Clear RX buffer

  // Transmit payload
  payload[0] = counter;
  payload[1] = previousTxDuration & 0xFF;          // Low byte (from previous iteration)
  payload[2] = (previousTxDuration >> 8) & 0xFF;   // High byte (from previous iteration)

  api.lora.psend(sizeof(payload), payload);

  unsigned long endTime = millis();  // End time after transmission

  // Calculate transmission duration for the next iteration
  previousTxDuration = (endTime - startTime);  // Duration taken to transmit

  counter++;
  if (counter > 50) counter = 1;

  delay(3000);

}

Re-Initialized using this function

void reinitLoRa() {
api.lora.nwm.set(); // P2P mode
api.lora.pfreq.set(923200000);
api.lora.psf.set(12);
api.lora.pbw.set(125);
api.lora.pcr.set(0);
api.lora.ppl.set(8);
api.lora.ptp.set(10);
api.lora.registerPSendCallback(send_cb);
}
and calling it after wake up condition.
Please let me know if I am over looking anything. Thanks.

api.lora.psend(sizeof(payload), payload);

is not a blocking call. It does not wait for the transmission to be finished, just sends it to the underlaying RUI3 system for sending and comes back immediately.

api.system.sleep.all(3000);

Puts the LoRa transceiver and the MCU into sleep mode, most likely before it even started sending.

Improved code (but not the best solution imho):
Use the TX callback to know when the TX is finished, then call api.system.sleep.all(3000);

#include <Arduino.h>

uint8_t counter = 1;
unsigned int previousTxDuration = 0; // Stores TX duration from previous loop

// Flag for TX finished
bool tx_finished = false;

void send_cb(void)
{
	// Set TX finished flag
	tx_finished = true;
}

void setup()
{
	// No Serial
	api.lora.nwm.set();			   // Set to P2P mode
	api.lora.pfreq.set(916000000); // Match receiver frequency
	api.lora.psf.set(7);		   // Spreading Factor
	api.lora.pbw.set(250);		   // Bandwidth
	api.lora.pcr.set(0);		   // Coding Rate
	api.lora.ppl.set(8);		   // Preamble Length
	api.lora.ptp.set(10);		   // TX Power

	api.lora.registerPSendCallback(send_cb);
	delay(1000);
}

void loop()
{
	uint8_t payload[3]; // 1 byte for counter + 2 bytes for txDuration

	unsigned long startTime = millis(); // Start time before transmission
	api.lora.precv(0);					// Clear RX buffer

	// Transmit payload
	payload[0] = counter;
	payload[1] = previousTxDuration & 0xFF;		   // Low byte (from previous iteration)
	payload[2] = (previousTxDuration >> 8) & 0xFF; // High byte (from previous iteration)

	api.lora.psend(sizeof(payload), payload);

	unsigned long endTime = millis(); // End time after transmission

	// Calculate transmission duration for the next iteration
	previousTxDuration = (endTime - startTime); // Duration taken to transmit

	counter++;
	if (counter > 50)
		counter = 1;

	// delay(3000);
	while (!tx_finished)
	{
		delay(100);
	}
	tx_finished = false;
	api.system.sleep.all(3000);
}

That works:

Personally, I would not use the loop() at all if I want to send every three seconds and instead use a timer.
With api.system.lpm(1); you enable automatic power save mode and the module will go into sleep whenever possible.
With api.system.sleep.all(); in the loop, the loop is disabled and doesn’t consume power.
The send routine will wake up by a timer and initiate the sending. Once the transmission is finished, the system goes into sleep mode by itself.

My code

#include <Arduino.h>

uint8_t counter = 1;
unsigned int previousTxDuration = 0; // Stores TX duration from previous loop

bool tx_finished = true;

void send_handler(void *);

void send_cb(void)
{
	// Set TX finished flag
	tx_finished = true;
}

void setup()
{
	// No Serial
	api.lora.nwm.set();			   // Set to P2P mode
	api.lora.pfreq.set(916000000); // Match receiver frequency
	api.lora.psf.set(7);		   // Spreading Factor
	api.lora.pbw.set(250);		   // Bandwidth
	api.lora.pcr.set(0);		   // Coding Rate
	api.lora.ppl.set(8);		   // Preamble Length
	api.lora.ptp.set(10);		   // TX Power

	api.lora.registerPSendCallback(send_cb);
	delay(1000);

	// Enable power saving
	api.system.lpm(1);
	
	// Create a timer.
	api.system.timer.create(RAK_TIMER_0, send_handler, RAK_TIMER_PERIODIC);
	// Start a timer.
	api.system.timer.start(RAK_TIMER_0, 3000, NULL);
}

void loop(void)
{
	api.system.sleep.all();
}

void send_handler(void *)
{
	// Check if last transmission is finished
	if (!tx_finished)
	{
		return;
	}

	uint8_t payload[3]; // 1 byte for counter + 2 bytes for txDuration

	unsigned long startTime = millis(); // Start time before transmission
	api.lora.precv(0);					// Clear RX buffer

	// Transmit payload
	payload[0] = counter;
	payload[1] = previousTxDuration & 0xFF;		   // Low byte (from previous iteration)
	payload[2] = (previousTxDuration >> 8) & 0xFF; // High byte (from previous iteration)

	tx_finished = false;
	api.lora.psend(sizeof(payload), payload);

	unsigned long endTime = millis(); // End time after transmission

	// Calculate transmission duration for the next iteration
	previousTxDuration = (endTime - startTime); // Duration taken to transmit

	counter++;
	if (counter > 50)
		counter = 1;
}
1 Like

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