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.

CC2630: Intelligent retry behavior when network lost

Part Number: CC2630

Using ZStack 1.2.2a with a CC2630, with the goal of very low power consumption.

Our use-case:

  • We have a portable, battery powered sleeping end device
  • A user could trigger an AF transmission anytime. If the transmission is not successful a fast feedback is required
  • The device regularly sends status information every ca. 4h. When the network is not available, it should not do exhaustive scan on all channels
  • The device is battery powered and the battery should not be changed for at least 2 years.

How can I avoid exhaustive channel scans and allow it only for certain conditions?  Example:

On user-triggered transmissions,

  • a complete channel scan is performed only every 3rd try
  • otherwise a rejoin on the same old, known channel is performed once

On automatic status messages:

  • On automatic status messages a complete channel scan is never performed. Only try once on the same old, known channel

I already applied the patch described in

https://e2e.ti.com/support/wireless_connectivity/zigbee_6lowpan_802-15-4_mac/f/158/t/498387

This also allows to reduce the DEV_NWK_DISC state after a DEV_NWK_BACKOFF to perform only one complete scan of all channels, which is desirable for our use-case. But I want to avoid the single scan in certain circumstances (as described above), too.

  • Hi Simeon,

    I made some changes in the ZDO_StartDevice() function and I obtained what I think that you are looking for, to try it I just joined the endDevice to a coordinator, waited some time and power cycle the coordinator and restart the EZ-mode in the End device to obtain a rejoin :

    if (startMode == MODE_REJOIN && scanCnt++ >= 2 )
    {
    // When ApsUseExtendedPanID is commissioned to a non zero value via
    // application specific means, the device shall conduct an active scan
    // on the Default Channel list and join the PAN with the same
    // ExtendedPanID. If the PAN is not found, an scan should be completed
    // on all channels.
    // When devices rejoin the network and the PAN is not found from
    if (runtimeChannel == MAX_CHANNELS_24GHZ )
    {
    scanCnt = 0;
    runtimeChannel = _NIB.nwkLogicalChannel;
    ZDApp_StopJoiningCycle( );
    }
    runtimeChannel = MAX_CHANNELS_24GHZ;
    }

    Replace the condition that is in the line 343 of the ZDObject.c.

    Try it an tell me what you think.

    Regards.
  • Hi Jose,

    many thanks to your suggestion, it sounds promising. However I have difficulties in reproducing the behavior.

    If I understood right then changing

    if (startMode == MODE_REJOIN && scanCnt++ >= 5 )

    to

    if (startMode == MODE_REJOIN && scanCnt++ >= 2 )

    should reduce the amount of retires on the same channel. But I could not see any change with a sniffer (yes I recompiled the EndDevice project).

    How exactly do I restart the EZMode? From the SampleSwitch original code this was done with the key right press:

        if(keys == KEY_RIGHT)
        {
    #if defined (ZCL_EZMODE)
            // Start EZMode Commissioning
            {
                zclEZMode_InvokeData_t ezModeData;
                // only bind on the on/off cluster
                static uint16_t clusterIDs[] =
                {   ZCL_CLUSTER_ID_GEN_ON_OFF};
    
                // Invoke EZ-Mode
                ezModeData.endpoint = SWITCH_EP; // endpoint on which to invoke
                                                 // EZ-Mode
                if( (savedState == zstack_DevState_DEV_ZB_COORD)
                    || (savedState == zstack_DevState_DEV_ROUTER)
                    || (savedState == zstack_DevState_DEV_END_DEVICE) )
                {
                    ezModeData.onNetwork = true;   // node is already on the
                                                   // network
                }
                else
                {
                    ezModeData.onNetwork = false;  // node is not yet on the
                                                   // network
                }
                ezModeData.initiator = true;        // OnOffSwitch is an initiator
                ezModeData.numActiveOutClusters = 1; // active output cluster
                ezModeData.pActiveOutClusterIDs = clusterIDs;
                ezModeData.numActiveInClusters = 0; // no active input clusters
                ezModeData.pActiveInClusterIDs = NULL;
                zcl_InvokeEZMode(&ezModeData);
    
                LCD_WRITE_STRING("EZMode", LCD_PAGE2);
            }
    #elif defined (ZSTACK_MANUAL_START)
            Zstart_discovery();
    #endif // ZCL_EZMODE
        }
    
        // update the display
        Switch_updateLcdDisplay();
    }
    

    So I added something like this in our code:

                if (hdrStatus == zstack_ZStatusValues_ZSuccess && reqStatus == 0)
                {
                // OK
                }
                else {
                    // we already made 3 attempts for user notification, see APSC_MAX_FRAME_RETRIES in f8wConfig.cfg
                    sos_state = sos_state_SEND_FAILED;
                    // avoid exhaustiv channel scans
    
                    zclEZMode_InvokeData_t ezModeData;
    
                  ezModeData.endpoint = RB4_ENDPOINT_SOS;
                  ezModeData.onNetwork = true; // node is already part of a network
                  ezModeData.initiator = true;
                  ezModeData.numActiveOutClusters = 2;
                  ezModeData.pActiveOutClusterIDs = rb4_g_outputClusters;
                  ezModeData.numActiveInClusters = 2;
                  ezModeData.pActiveInClusterIDs = rb4_g_inputClusters;
                  zcl_InvokeEZMode(&ezModeData);
                }

    But I could not see any change in the behavior regarding beacon requests in different or the original channel. So, how do I restart the EZMode?

  • Hi Simeon,

    The changes I posted are only visible when the node is in rejoin mode (had a network before) and I leave the buttons ins the application like in the default sample application. Try to just use a clean fresh project and just add the changes, then start a network with a coordinator and join the end device. If you perform a power cycle in the coordinator and then press the right button to run the EZ mode again. That's what I did, please tell me if works for you. After that we can work on other changes that you want to include.

    Regards,

  • Hi Jose,

    OK, my setup now:
    Clean SampleSwitch on SmartRF06 as EndDevice
    Clean ZNP project on SmartRF06 as Coordinator, controlled by Z-Tool
    The coordinator is in auto-hold, that means after a reset I must send a start request

    On SampleSwitch I modified only the ZNWK_DEFAULT_CHANLIST to ZSTART_MAX_CHANNELS_24GHZ

    1: started coordinator
    2: start EZMode on SampleSwitch
    3: SampleSwitch joined Coordinator
    3: reset coordinator
    4: restart EZMode on SampleSwitch (press RIGHT once)


    Without the modifications I could see that SampleSwitch sent many beacon requests on the original channel and many beacon requests on different channels.

    With the modifications I could see that SampleSwitch only did 3 beacon requests on the original channel, and no beacon requests on different channels. This is exactly what I'm looking for.

    The next steps would be intresting: How do I achieve this after an AF transmission?
  • Can you elaborate what you want to achieve after an AF transmission?
  • We have two kinds of AF transmissions:

    * status messages every 4 hours
    * User-triggered messages (button-press event)

    We want to achieve a very long battery live: ca. 3 years with a coin cell.

    We calculate that the user-triggered transmission is done once a day, where in 1 out of 10 cases the transmission might fail.

    For status messages we calculate that the transmission fails 2 out of 7 times (two days out of reach due to weekend travels).

    Thus we want to achieve following behavior to save battery live:

    After a status message no channel scan should be performed, as this drains the battery too much.
    After a user-triggered message a channel scan is allowed. This should increase reliability of the user-triggered transmission.

    Our tests showed that we can easily reach 3 years battery live even in a 0°C environment, but only on happy paths, where no channel scans are done. When channel scans are performed the battery live decreases well below 3 years.
  • Hi Simeon,

    To achieve this you can use the ZDO_RegisterForZdoCB() function in order to register a callback for the application that sends the required message and start a 4 hour timer for the automatic resend of the messages:

    ZDO_RegisterForZdoCB( ZDO_JOIN_CNF_CBID, &Your_App_Callback);

    Register the callback during the application initialization and for the callback you can do something similar to the MT_ZdoJoinCnfCB() and just send the message and start the timer there. You will only need to run the Ez-mode with the right button as before and when the device joins to a network the registered callback will be triggered by the stack.

    I hope this helps.

    Regards.

  • If I understand correct this would stop the status message interval until the ZDO_JOIN_CNF_CBID gets executed. So after a parent loss (out-of-reach), it would stop the status messages until the enddevice re-joined the network again (realignment?). This would require the user to trigger the button. However we need the status message to be sent every 4 hours, whether the device lost its parent or not in previous transmissions. In case the parent is in-reach again, the status message should "just work".

    We have an application running behind the receiver of the status messages. In case the status message is missing for 72 hours an alarm is generated. Therefore the status messages must be continued without user intervention.

    I will try  your suggestion with ZDO_RegisterForZdoCB( ZDO_JOIN_CNF_CBID, &Your_App_Callback); on the clean SamplSwitch project. Maybe it does exactly what we want. If not, please assist me further. Thank you in advance!

  • Hi,

    to be honest I don't understand at all how ZDO_RegisterForZdoCB( ZDO_JOIN_CNF_CBID, &Your_App_Callback); will help me with the problem of channel scans. This just provides a mechanism to issue regular status messages. We already have such a mechanism implemented. How does this circumvent the channel scans we want to avoid?

  • Hi Simeon,

    If I understand correctly your requirement is to send the status message every 4 hour even if the EndDevice doesn't have a parent. That behavior is not compliant with the Zigbee specification, an EndDevice cannot broadcast messages to the network as a routers does, an End device can only talk to other devices in the network through his parent including the broadcast messages, so to send the status message you must search for a parent first.

    Regards,

  • Hi,

    This callback is to trigger the status message sending only after a parent was found and the device is connected to the network. This callback doesn't modify the behavior of the code added in ZDObject.c file, so you need to keep the last changes that I gave you and also register the ZDO_JOIN_CNF_CBID callback and to start sending messages just move the 4 hour timer start instructions that you have inside the callback.