Closed Ganesh-Shanbhag-face closed 3 years ago
In case 0:
you are using xSemaphoreTake(taskEvent, 10);
, which waits only 10 ticks to get the semaphore and then returns, whether it got the semaphore or not.
If you want to wait here until the join procedure was successful, you need to use here xSemaphoreTake(taskEvent, portMAX_DELAY)
as well.
Hi I tried in multiple ways and still its not working. Is there any other way to achieve sleep in nRF modules to save power. Don't they have sleep modes as found on other controllers. The problem may be I am not that much known to freeRTOS.
While working I noticed that if the gateway which is running Network Server if turned off then in the lmh_send function it will return LMH_SUCCESS and continuously displays like below.
19:34:06.403 -> <LM> OnRadioTxDone
19:34:06.403 -> <LM> OnRadioTxDone => RX Windows #1 995 #2 2002
19:34:11.379 -> <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
19:34:11.379 -> <LM> OnRadioRxTimeout
19:34:11.645 -> <LM> OnRadioTxDone
19:34:11.645 -> <LM> OnRadioTxDone => RX Windows #1 995 #2 2002
19:34:16.621 -> <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
19:34:16.621 -> <LM> OnRadioRxTimeout
19:34:17.118 -> <LM> OnRadioTxDone
19:34:17.118 -> <LM> OnRadioTxDone => RX Windows #1 1002 #2 2002
19:34:22.097 -> <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
19:34:22.097 -> <LM> OnRadioRxTimeout
19:34:22.628 -> <LM> OnRadioTxDone
19:34:22.628 -> <LM> OnRadioTxDone => RX Windows #1 1002 #2 2002
19:34:27.636 -> <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
19:34:27.636 -> <LM> OnRadioRxTimeout
19:34:28.563 -> <LM> OnRadioTxDone
How to stop sending if it fails to send after some intervals.
If you send the packet as LMH_CONFIRMED_MSG
, the node is waiting for an ACK
from the LoRaWAN server. If the server (or gateway) is down, it retries 8 times resending the packet and waiting for the ACK
before it gives up.
If you send the packet as LMH_UNCONFIRMED_MSG
, the packet is sent once and there is no check if the packet was received by a gateway or server.
The type of message is selected with the second parameter in lmh_send()
/**@brief Send data
*
* @param app_data Pointer to data structure to be sent
* @param is_txconfirmed do we need confirmation?
*
* @retval error status
*/
lmh_error_status lmh_send(lmh_app_data_t *app_data, lmh_confirm is_txconfirmed);
About your code, I do not understand why you make it so difficult. Here is my approach:
/**
* Type of event
* 0 = Join success
* 1 = Join fail
* 2 = Timer wakeup
*/
int eventNum = 0;
/* Semaphore used by events to wake up loop task */
SemaphoreHandle_t taskEvent = NULL;
/* Timer to wakeup task frequently and send message */
SoftwareTimer taskWakeupTimer;
void periodicWakeup(TimerHandle_t unused)
{
// Set eventNum to 2 ==> Timer wakeup
eventNum = 2;
// Give the semaphore, so the loop task will wake up
xSemaphoreGiveFromISR(taskEvent, pdFALSE);
}
void setup()
{
// Create the LoRaWan event semaphore
taskEvent = xSemaphoreCreateBinary();
// Initialize semaphore
xSemaphoreGive(taskEvent);
// Initialize timer
taskWakeupTimer.begin(60000, periodicWakeup);
/************************************************************/
// Don't start timer here. Start it after JOIN was successful
/************************************************************/
// taskWakeupTimer.start();
// Please assume these things are properly done
// Initialize LoRa chip.
// Initialize LoRaWAN in OTAA mode
// Take the semaphore at the end of setup() makes sure the loop() goes to sleep
xSemaphoreTake(taskEvent, 1);
}
void loop()
{
// Sleep here till wake up by timer or other events
xSemaphoreTake(taskEvent, portMAX_DELAY);
Serial.println("Loop woke up, time to do something");
switch (eventNum)
{
case 0:
Serial.println("Join successfull, start your work");
break;
case 1:
Serial.println("Join failed. You can retry or blink a LED or ...");
break;
case 2:
Serial.println("Loop woke up, time to do something");
break;
default:
Serial.println("This should never happen");
}
}
/* I am providing only two handlers here please assume other handlers also present */
void lorawan_has_joined_handler(void)
{
// Set eventNum to 0 ==> Successful joined
eventNum = 0;
// Give the semaphore, so the loop task will continue
xSemaphoreGiveFromISR(taskEvent, pdFALSE);
/************************************************************/
// Start timer here after JOIN was successful
/************************************************************/
taskWakeupTimer.start();
}
void lorawan_has_join_failed(void)
{
// Set eventNum to 1 ==> Join failed
eventNum = 1;
// Give the semaphore, so the loop task will continue
xSemaphoreGiveFromISR(taskEvent, pdFALSE);
}
@beegee-tokyo That helped me a lot. I noticed while sending using LMH_CONFIRMED_MSG although it fails to send it returns LMH_SUCCESS and then it will show IRQ_RX_TX_TIMEOUT 8 times on the terminal. Why it returns success if it fails?
lmh_send()
is not blocking. It only gives the data packet to the LoRaMAC state machine, which is processing the sending (and retries). In the current version of the library there is no feedback if the packet was actually sent.
I am testing right now the next version of the library which has 2 additional callbacks for confirmed and unconfirmed packet sending finished.
@beegee-tokyo Thanks for the clarification. It would be better if we know is the transmission a success or a failure in LMH_CONFIRMED_MSG with a callbacks or by any flags.
Callback for confirmed message will have a flag which reports success (ACK received) or failure (No ACK received).
For the unconfirmed message the callback is triggered when the TX - RX1 window - RX2 window
sequence is finished. For unconfirmed message it is not possible to tell if it was successful or not.
@beegee-tokyo That's a good idea. But I am not sure for unconfirmed message why we need a callback because the application is not bothered about send success or failures. Its like just send and forget.
You need it for example in this case when you need to send multiple packets, you need to know when the transceiver is ready to send the next packet.
Yes got it.
@beegee-tokyo I noticed once it successfully joins in OTAA and then by chance the gateway is turned off lmh_join_status_get() is returning LMH_SET by which it is getting difficulty in checking if it is connected to the gateway properly before sending the payload. And it tries to send the payload and fails. So is there any way to know before sending it is connected to the gateway properly?
No, LoRaWAN does not support such a connection check when using unconfirmed packets. The only option you have is to use confirmed packets and if transmission fails (no ACK received), assume you lost connection to the gateway or LoRaWAN server.
Okay in the present version of the library if I use confirmed packets then how can I get the status of ACK or No ACK?
With the next version of the library I add callbacks for both confirmed and unconfirmed TX finished. These new features are in testing right now.
Callbacks for TX-RX cycle finished and result in case of confirmed message added with library version 2.0.2.
Examples how to use will be added soon. Until then, you can see usage here:
@beegee-tokyo Good to have this feature. Thanks for adding it for better handling in the code.
Hi I am working on low power application firmware on RAK4630 by making use of semaphores I am following the examples given. I am using only one semaphore for all the tasks my aim is to hold the execution until some other task got finished and returns success or failure. But I am not getting the expected output.
I have given a sample code from my work