This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/LAUNCHXL-CC1310: Frequency hopping: Activation of RX_on_when_idle before async message was send

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310

Tool/software: Code Composer Studio

hey guys,

we are currently adapting the frequency hopping code from the newest CC1310 15.4 Stack SDK sensor example. We'd like to lower the power consumption for sleepy sensor nodes before association and we have some questions, though the first one is the one relating to the title.

1. I was now wondering, in jdllc_join() or jdllc_rejoin() before the Ssf_setTrickleClock() is set, RX is activated ApiMac_mlmeSetReqBool(ApiMac_attribute_RxOnWhenIdle, true);. But that doesn't make sense to me, since the sensor has not yet send its PAS or PCS asynchronous message. These messages are send when the trickle clock expires. I understand, that since in the example even for sleepy devices RXOnWhenIdle is always true, this is not a big issue, but there is no drawback by setting RxOnWhenIdle after calling sendAsyncReq(), right?

2. I see that if the sensor restarts or if handleMaxDataFail() is called, it starts the TrickleClock() again and waits for a new PC message, but what if the collector has been exchanged and has a new PAN_ID. Than the sensor would have to eventually call Jdllc_sendDisassociationRequest(); to start from the beginning, right? However, I if FH is enabled sensor goes into orphan state only updateState(Jdllc_states_orphan); and waits for a new PC message. (and again ApiMac_mlmeSetReqBool(ApiMac_attribute_RxOnWhenIdle, true); is called before the TrickleClock() is set.)

3. Our dwell time is set to 250ms, according to https://software-dl.ti.com/simplelink/esd/simplelink_cc13x2_26x2_sdk/3.30.00.03/exports/docs/ti154stack/html/ti154stack/frequency-hopping-mode.html

we should send a message each 25min to ensure sync, however, we only send data messages or poll once an hour and only have sleepy end nodes. Is it necessary, to reduce the interval?

best wishes and stay healthy

Slev1n

  • Hey Slev1n,

    Slev1n said:
    there is no drawback by setting RxOnWhenIdle after calling sendAsyncReq(), right?

    I would probably set RxOnWhenIdle true before calling sendAsyncReq(). This way your receiver is on before it sends the request and does not miss the PA/PAC response from the collector. I believe this is why it was set before the trickle timer clocks are turned on.

    Slev1n said:
    Than the sensor would have to eventually call Jdllc_sendDisassociationRequest(); to start from the beginning, right?

    The intended operation of the out of box examples is for orphaned sensors to rejoin it's original collector. If the collector configuration has changed, I would suggest going this route. You'll need to make sure the NV is cleared of old network data, and the disassociation process should cover this.

    Slev1n said:
    we should send a message each 25min to ensure sync, however, we only send data messages or poll once an hour and only have sleepy end nodes. Is it necessary, to reduce the interval?

    This answer depends on a few factors. How big is your packet size and which data rate are you operating at? Additionally, how many channels are set in your channel mask? Dwell time is the time the sensor stays on a particular channel. You'll want to ensure enough time to exchange necessary data (in your case the data messages). I would also add some buffer in case the devices lose sync, otherwise you may not receive the entire packet of data you're looking for. For this reason, we generally set the dwell time to 250ms.

  • Thank you for your help.

    Ammar N said:
    I would probably set RxOnWhenIdle true before calling sendAsyncReq().

    I set it within processFHevent() right before sendAsyncReq()

    Ammar N said:
    This answer depends on a few factors. How big is your packet size and which data rate are you operating at? Additionally, how many channels are set in your channel mask? Dwell time is the time the sensor stays on a particular channel. You'll want to ensure enough time to exchange necessary data (in your case the data messages). I would also add some buffer in case the devices lose sync, otherwise you may not receive the entire packet of data you're looking for. For this reason, we generally set the dwell time to 250ms.

    The packet size is usually max. at 130 bytes for data and polling is standard around 80 bytes. However, in worst case the message length for data could go beyond 300 bytes. With the Long Range Mode (5kbps) this would certainly exceed the 250ms dwell time. So, we either split the messages or increase the dwell time.

    Regarding the channels. We have two scenarios in one, we can think about using all channels. In the other Scenario, we think about using only channels from 915 MHz onwards. So either 129 or 64 channels. Since channel spacing is below 250 kHz we have to use at least 50 channels and occupation time of a channel shall not be longer than 0.4s within 20s. This means dwell time cannot exceed 0.4s and depending on the amount of channels chosen can vary. To my understanding, using a dwell time of 350ms for more than 60 channels should be fine?! this could give us some buffer and reduce the number of messages to be send if a long message has to be split.

    1. To sum it up, if we use 5kbps, a dwell time of 350ms and ca. 64 channels and keep the message transmission duration below 300ms, than we should be fine, right?

    2. What is the benefit of lowering the dwell time except for less interference probability with other hopping nodes?

    3. Will the FH stack handle any changes of transmission intervals by itself? Meaning, if I change the data interval of a sensor from 3600s to 3422s or another random number during runtime, will the collector still know on which channel this specific sensor node will transmit?!

    4. Is there a reason, why for example in wsAsyncIndCb() after reception of a PA message from the collector, the sensor sets the trickle timer first and not just set the event for triggering a sendAsyncReq(). I do have the same question for jdllc_join() or jdllc_rejoin(), can I directly trigger the PCS event or why do I have to set the trickle timer?

    5. Why are the trickle times only 6s for some PHY_IDs and for our Long Range Mode phy ID it is 60s?

    best wishes

    Slev1n

  • Slev1n said:
    1. To sum it up, if we use 5kbps, a dwell time of 350ms and ca. 64 channels and keep the message transmission duration below 300ms, than we should be fine, right?

    This should be ok, our out of box dwell time does not change based on PHY mode. We cannot test each use case, so I'd advise testing your specific use case to make sure it is optimal.

    Slev1n said:
    2. What is the benefit of lowering the dwell time except for less interference probability with other hopping nodes?

    Another benefit I can think of is power savings, as you're using the radio less.

    Slev1n said:
    3. Will the FH stack handle any changes of transmission intervals by itself? Meaning, if I change the data interval of a sensor from 3600s to 3422s or another random number during runtime, will the collector still know on which channel this specific sensor node will transmit?!

    I know our latest CC13x2 projects on SDK 3.40 have this capability. I would very with that sensor project if you want to take a look there. You should send a new config request to the collector each time a change like that is made, so that the collector is made aware.

    Please allow me some time to look into your last two questions in more depth. I will post back when I have those answers.

  • Hi Ammar,

    thank you for your help, looking forward for your next post.

    Meanwhile, I am proceeding with my code adaptions and I am facing a rejoin issue. I am using a lot of UART prints for debugging, which I will post to describe my issue. Sorry for the long message in advance, but I want to provide as much info as possible.

    I only have one collector and one sensor (both launchpads) and sensor is a sleepy device. When both have been factory reset, the prints look like this:

    Sensor:

    Start FH
    TI Sensor
    Sensor Start EVT without INFO
    State Changed: 1
    FH-join
    Send PAS and set timer
    Set RX active
    PAS send
    Entered wsAsync
    wsAsync: status 0
    wsAsync: ieID 1
    wsAsync: ieID 4
    wsAsync: ieID 5
    PA received
    Send PCS and set timer
    Set RX active
    PCS send
    Entered wsAsync
    wsAsync: status 0
    wsAsync: ieID 1
    wsAsync: ieID 2
    wsAsync: ieID 6
    wsAsync: ieID 7
    PC received
    dataCnf: 19
    dataCnf: 19
    dataCnf: 19
    Enter assocCnfCb, status: 0
    Device Started
    Frequency Hopping
    State Changed: 3
    DataMsg Ack
    Polling Ack
    dataIndCb entered
    dataIndCb cmdID = 1
    ProcessCOnfigRequest
    cmdID= 1
    DataMsg Ack
    Polling Ack

    Collector:

    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    entered wsAsyncIndCb
    processIncASYNC
    processIncomingFHframe
    newD: 0x03 | 40:b6:a4:13:00:4b:12:00 <--- sensor has been associated
    MAC: 40:b6:a4:13:00:4b:12:00
    data = 10
    ConfigRsp: 0x3
    data = 13
    

    If I do now factory reset the collector or unplug the collector until the sensor disconnects in HandleMaxDataFail calling Jdllc_sendDisassociationRequest(); this is what is printed in the sensor console after factory resetting the collector.

    DataMsg noAck
    DataMsg noAck
    FH_MaxDataFail <--- Sensor send disconnection request
    Disc entered! <--- Disconnection Callback entered
    State Changed: 0
    Sensor Start EVT without INFO
    State Changed: 1
    FH-join
    dataCnf: 64
    Disc entered!
    State Changed: 0
    Sensor Start EVT without INFO
    State Changed: 1
    FH-join
    Entered wsAsync <--- wsAsyncCbInd entered
    wsAsync: status 0
    wsAsync: ieID 1
    wsAsync: ieID 4
    wsAsync: ieID 5
    PA received
    Send PCS and set timer
    Set RX active
    PCS send
    Entered wsAsync
    wsAsync: status 0
    wsAsync: ieID 1
    wsAsync: ieID 2
    wsAsync: ieID 6
    wsAsync: ieID 7
    PC received
    dataCnf: 64
    dataCnf: 64
    dataCnf: 64
    dataCnf: 19
    Enter assocCnfCb, status: 0
    Device Started
    Frequency Hopping
    State Changed: 3
    DataMsg Ack
    Polling Ack
    dataIndCb entered
    dataIndCb cmdID = 1
    ProcessCOnfigRequest
    cmdID= 1
    dataCnf: 64
    Polling Ack
    dataIndCb entered
    dataIndCb cmdID = 1
    ProcessCOnfigRequest
    cmdID= 1
    dataCnf: 64
    dataCnf: 64
    dataCnf: 64
    dataCnf: 64
    dataCnf: 64
    dataCnf: 64

    From here on the sensor never sends data messages, but repeatedly processes config requests followed by 6 dataCnf: 64 (meaning the destination is not in the neighbour hopping table). On the collector side the only one data message is received and nothing else happens though I guess the collector sends configRequests as a response to the sensor poll repeatedly.

    My questions are now:

    1. Why is the collector receiving so many (up to 10, sometimes less) async messages from the sensor before joining?!

    2. Why am receiving so many dataCnf: 64? In the user guide it is stated that this occurs If a data request is issued to a node whose entry is not in the neighbor table. Why is the collector not in the table?! This only happens if the sensor disconnects and then rejoins! I use the normal disassocCnfCb() and add a Util_setEvent(&Sensor_events, SENSOR_START_EVT); at the end.

    3. Why is the sensor receiving a PA message before transmitting a PAS message during reconnection?

    4. Although the sensor transmitts a PAS and a PCS frame prior to association during the rejoin process, the collector does not enter wsAsyncIndCb nor process any incoming frames.How is that possible?

    Further questions:

    5. Regarding the dwell time, I get a warning during compilation if I set the dwell time to 350ms. Here the corresponding code from jdllc_init()

            ApiMac_mlmeSetFhReqUint8(ApiMac_FHAttribute_unicastDwellInterval,
                                     CONFIG_DWELL_TIME);
            ApiMac_mlmeSetFhReqUint8(ApiMac_FHAttribute_broadcastDwellInterval,
                                     CONFIG_DWELL_TIME);

    Why is that Mac Api a Uint8 when the dwell time can be higher than 255ms? And why is the CONFIG_DWELL_TIME also used for the broadcast interval?! I though only collector can transmit a broadcast msg? Btw. I deactivated broadcast on the collector side.

    So far that is where I currently stuck. Thanks in advance.

    Slev1n

  • Hey Slev1n,

    Here's my follow up to the prior questions.

    Slev1n said:
    4. Is there a reason, why for example in wsAsyncIndCb() after reception of a PA message from the collector, the sensor sets the trickle timer first and not just set the event for triggering a sendAsyncReq(). I do have the same question for jdllc_join() or jdllc_rejoin(), can I directly trigger the PCS event or why do I have to set the trickle timer?

    Note that once the sensor receives one of these async frames, the collector may still be sending that frame to more channels. If you send the sync request too soon, the collector may not receive it. The trickle timer accounts for the time it takes the collector to finish sending a PA to the other channels in its channel mask. For this reason, it's important to set the trickle timer especially in the cases where you would require retries.

    Slev1n said:
    5. Why are the trickle times only 6s for some PHY_IDs and for our Long Range Mode phy ID it is 60s?

    The reason the trickle time for LRM is 10x greater is because in this mode, data takes ~10x longer to transmit. You're transmitting less data per second, so if you don't modify the packet size then the same transmission done on a 5kbps PHY will take longer. These timers can be optimized based on the number of channels selected in your channel mask. You can measure how long it takes the collector to do send it's PAs and calculate how long it takes per channel and modify the trickle timer to your use case.

  • Hey Ammar,

    I've been working over the weekend and I've been able to solve few issues, however, some new occur and I have many open questions needed to be answered to be able to adequately tackle them. Besides, I wanted to note, that the collector board is not a CC1310 launchpad but a CC1352R1 launchpad and we use SDK 3.3. Note, that the devices are lying very close like 15cm (6inch) from each other.

    Regarding my last questions:

    1. I understand now, that collector and sensor can receive multiple asynchtonous messages since e.g. even when listen on channel 100 and an async message is transmitted on 101 oer 102 the stack will accept and parse them in the callbacks.

    2. I still receive them occasionally during association. I think they are due to "data requests" or "data request Ack" send from collector to sensor prior to association. The disconnection and rejoin works now, however, it is CRUCIAL to set devInfoBlock.coordShortAddr = FH_COORD_SHORT_ADDR; and not to 0xFFFF like in non-beacon mode! Besides, the network info should be deleted before triggering the start event.

    3. and 4. I am not sure if I can actually reproduce this, maybe there was some UART overflow or whatsoever, I guess it does actually behave the way it should now.

    5. I still need an answer to that and some of the following questions are related to the dwell time.

    Trickle Timer and Association Questions:

    6. Related to question 1, I can see in the sniffer, which is set to a certain channel (90) that, the boards are able receive asynchronous messages transmitted on different channels than the own RX channel, of course with very different RSSI values. This might be due to the short distance and LRM, however, is this conform with FCC standards? We will come back later on this issue on another matter.

    7. I still have a question regarding the trickle timer. I checked the length of the async messages using the sniffer (PC = 153 byte, PA = 98 byte, PCS = 93 byte and PAS 94 byte) and I have set 64 channels active. With a transmission rate of 5kbps the transmission duration is 16.5s for the PC and 10.5s for the other messages. The frequency hopping guide states a worst case of 4s for though the transmission the PC with 50kbps over 129 channels would take 3s, I assume 1s latency comes from internal overhead. Hence, adding this second we are still below 20s for each async transmission. Now, I still dont know how to correctly set the trickle timer length?

    8. Besides, shouldn't the trickle timer set in the collector account for the async transmission time of the sensor and vice versa? Meaning that if the collector receives a PAS, the trickle timer of the collector should be long enough to wait for the sensor to finish its "transmission sweep", right?

    9. Hence, I understand, that trickle timers should be set upon reception of an async message, however, when being powered up, I dont understand why a sensor entering the join() or rejoin() function should set the trickle timer first, before transmitting its async message? Or can a sensor use the received PA or PC message from a collector, who has been triggered by another sensor before? I meanSensor 1 starts sending a PAS messages, 10s later Sensor 2 comes into the network and receives the PA from the collector, is that possible? Than it would make sense to first wait.

    10. What does the association status 0xEB (=235) and 0xE9 (=233) mean? My sensor sometimes receives this during association and then another association try is necessary.

    Dwell Time, Channel and Transmission Questions:

    11. Should the dwell time be the same on collector and sensor?

    12. Assuming a dwell time of 250ms and the 5kbps transmission rate. How is it possible, that a 300byte message (takes 480ms) can be successfully transmitted from sensor to collector? (it looks like it can)

    13. When a sensor transmits a message to the collector, on which channel is the ack returned? On the same channel or the sensors hopping sequence channel?

    14. Will the transmitter change the channel according to the receivers hopping list also during data retries?

    15. What happens if e.g. the reporting interval expires and when the sensor wants to send the message it notices that 200ms of the 250ms dwell time of the collectors current channel has already past, will the MAC wait until the collector hops on the next channel or just try to transmit?

    16. Since our devices are all sleepy, unicast messages will be transmitted to the sensor on a fixed channel (according to the user guide) is this channel randomly chosen from the channel mask or is it the same for all sensors?

    17. Our sensors send each hour, however, if a transmission fails, it will try a few minutes later again. Since the sensor knows the hopping sequence of the collector, the collector should be able to receive this message, right?

    Network testing questions:

    18. I've tested with 1 Sensor and 1 Collector, actually, everything works fine (join, data transmission, disconnect and rejoin), however, when I change the PAN_ID of the collector to something other than "1", the sensor disconnects and rejoins. This works fine, but now the collector sends config requests with the message type 1 (I checked the message buffer content in send_Msg()), however, the sensor parses a message ID 20, which is unknown and does not acknowledge the message, thus the collector proceeds to think it has to update the sensor each time the sensor transmits its polling data request. Everything else works fine. Have you any idea why this happens (only if PAN_ID is other than "1)?

    19. Can I stop the polling clock also in FH mode within disassocCb()? Currently this is only done in beacon or non-beacon mode.

    20. Is the "neighbour valid time" comparably to a tracking request?

    21. When I add 10 more sensors to the network, the network performance is quite bad. The collector receives many data messages with a very low RSSI (-70 or -100) even though the sensors are very close. Sometimes although not changing anything, the next message of the same sensor has an accepatable RSSI around -25dBm. I see many rejoining sensors (a consequence of entering HandleMaxDataFail()) and many not acknowledged messages on both sides (collector and sensor). All looks like the devices in the network are out of sync and the transmissions are mostly not on the correct channel. (Dwell time 250ms on both sides and message length not longer than 150 bytes). Any idea what the problem could be and how to improve performance?

    These are a lot of questions but I guess they won't just help me but also others in the future. If I find solutions on my own, I will post them, but currently I am in need for some more info to improve stability and performance of our FH network.

    best wishes and stay healthy

    Slev1n

  • Hey Slev1n,

    I think this is a good time to split this thread into different questions so that your questions and answers are more easily searchable.

    Can you split the questions up and hit the "Ask a related question"? It's OK to ask multiple related questions, so please split the questions up as appropriate into new threads.

    In the meantime, please allow me some time to look into your questions and respond.

  • I though about just the same. Too long threads decrease readability and later posted wisdom stays hidden :)

    I have created 3 single posts all using the "Ask a related question" button and marked the post answering my initial questions as the answer.

    I am looking forward to your answers.