This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Proper use of the nrf_mesh_disable() & nrf_mesh_enable() functions (nRF5 SDK for Mesh 2.0.1)

Hi there,

I was hoping you guys could point me in the right direction with regards to the use of the nrf_mesh_disable() & nrf_mesh_enable() functions. Since the "friend node" and "low power node" features are not yet implemented in the SDK, I was thinking of a work around to get lower power consumption.

Would this work: I have an app timer constantly running, and use the power manager - I want to disable the mesh when in system-ON "sleep".  Then when a certain amount of time has elapsed, I want to re-enable the mesh, transmit a packet and then disable the mesh again.  I think this is possible because the nodes are able to drop in and out of the mesh (ie when power was cycled etc).

Also, how long do you need to allow after calling nrf_mesh_disable() before calling nrf_mesh_enable() again?

I am using SDK for Mesh 2.0.1, SDK15 and the nrf52840, my software is based on the light switch examples.

Regards,

Gord

Parents
  • Hi Gord, 

    I don't see a problem doing that. According to Mesh spec this is requried: 

    If a node in Normal Operation receives a Secure Network beacon with an IV index less than the last known IV Index or greater than the last known IV Index + 42, the Secure Network beacon shall be ignored.
    Note: This above requirement allows a node to be away from the network for 48 weeks. A node that is away from a network for longer than 48 weeks must be reprovisioned.

     

    But 48 weeks sleeping is not something we talking about here.

    The only limitation I can think of is that when the node is sleeping, you can't send command to the node. And it won't aware of the missing packets. 

    Also it won't be able to act as a relay node. You will need a group of backbone nodes to handle the relay task and never sleep.

     

    But if you just need a node to wake up occasionally and send some data then sleep again, I think it should work. 

  • Thanks for the reply! Yes, so what I have set up at the moment is some sensor nodes ("servers") and one client. The sensor nodes have the mesh enabled on power up. They then wait for a command from the client to say "start transmitting with x sleep interval". Ideally I would like them to then transmit, data and as soon as that is done -> call nrf_mesh_disable... then some time passes and I call nrf_mesh_enable again -> then transmit -> disable mesh. The issues arise when disabling the mesh and then restarting it. Am I missing something here? Maybe I am doing the call to disable the mesh too early?

  • Forgot to mention, I am using the app scheduler/running in thread priority.

    main loop looks like this:

        
        for(;;){
          app_sched_execute();
          bool done = nrf_mesh_process();
          if (done)
          {
              PowerManager_Task();
          }
        }

    Will this have any effect on the nrf_mesh_enable() & nrf_mesh_disable() functions?

  • Hi Gord,

    Could you let me now what exactly the problem you have when disable and enabling mesh again ? 

    I don't see a problem using app scheduler can cause an issue here.

  • Hi again Hung, sorry I should have described what was happening a bit better. Every time I called nrf_mesh_disable() it would hit the error handler and the device would assert -> then restart. I've figured out more or less why that was happening, I think I was calling nrf_mesh_disable() a bit too quickly after transmitting. What I ended up doing was to find the handler and event that occurs after a transmission, and call nrf_mesh_disable() jn the  "NRF_MESH_EVT_TX_COMPLETE" case statement (in config_server.c):

    static void mesh_event_cb(const nrf_mesh_evt_t * p_evt)
    {
        switch (p_evt->type)
        {
            case NRF_MESH_EVT_TX_COMPLETE:
                if (p_evt->params.tx_complete.token == m_reset_token &&
                    NODE_RESET_PENDING == m_node_reset_pending)
                {
                    /* Clear all the state. */
                    mesh_stack_config_clear();
                    if (flash_manager_is_stable())
                    {
                        const config_server_evt_t evt = { .type = CONFIG_SERVER_EVT_NODE_RESET };
                        app_evt_send(&evt);
                        m_node_reset_pending = NODE_RESET_IDLE;
                    }
                    else
                    {
                        m_node_reset_pending = NODE_RESET_FLASHING;
                    }
                }
    
                /* Here */
                nrf_mesh_disable(); 
    
                break;
    
            case NRF_MESH_EVT_FLASH_STABLE:
                if (NODE_RESET_FLASHING == m_node_reset_pending)
                {
                    const config_server_evt_t evt = { .type = CONFIG_SERVER_EVT_NODE_RESET };
                    app_evt_send(&evt);
                    m_node_reset_pending = NODE_RESET_IDLE;
                }
                break;
    
            default:
                break;
        }
    }

    This seems to work just fine, the mesh gets disabled right after a transmission, and the current draw goes way down. I can then call nrf_mesh_enable() just before I want to transmit again, and it all works. 

    What I would like to know is your thoughts on doing it this way? Is there possibly a better way of doing it? - Like maybe adding a similar callback handler like this one to the existing light switch server model / example code ( I don't think there is a handler like this in the current example, I could be wrong).

Reply
  • Hi again Hung, sorry I should have described what was happening a bit better. Every time I called nrf_mesh_disable() it would hit the error handler and the device would assert -> then restart. I've figured out more or less why that was happening, I think I was calling nrf_mesh_disable() a bit too quickly after transmitting. What I ended up doing was to find the handler and event that occurs after a transmission, and call nrf_mesh_disable() jn the  "NRF_MESH_EVT_TX_COMPLETE" case statement (in config_server.c):

    static void mesh_event_cb(const nrf_mesh_evt_t * p_evt)
    {
        switch (p_evt->type)
        {
            case NRF_MESH_EVT_TX_COMPLETE:
                if (p_evt->params.tx_complete.token == m_reset_token &&
                    NODE_RESET_PENDING == m_node_reset_pending)
                {
                    /* Clear all the state. */
                    mesh_stack_config_clear();
                    if (flash_manager_is_stable())
                    {
                        const config_server_evt_t evt = { .type = CONFIG_SERVER_EVT_NODE_RESET };
                        app_evt_send(&evt);
                        m_node_reset_pending = NODE_RESET_IDLE;
                    }
                    else
                    {
                        m_node_reset_pending = NODE_RESET_FLASHING;
                    }
                }
    
                /* Here */
                nrf_mesh_disable(); 
    
                break;
    
            case NRF_MESH_EVT_FLASH_STABLE:
                if (NODE_RESET_FLASHING == m_node_reset_pending)
                {
                    const config_server_evt_t evt = { .type = CONFIG_SERVER_EVT_NODE_RESET };
                    app_evt_send(&evt);
                    m_node_reset_pending = NODE_RESET_IDLE;
                }
                break;
    
            default:
                break;
        }
    }

    This seems to work just fine, the mesh gets disabled right after a transmission, and the current draw goes way down. I can then call nrf_mesh_enable() just before I want to transmit again, and it all works. 

    What I would like to know is your thoughts on doing it this way? Is there possibly a better way of doing it? - Like maybe adding a similar callback handler like this one to the existing light switch server model / example code ( I don't think there is a handler like this in the current example, I could be wrong).

Children
  • Hi Gord, 

    I don't think putting nrf_mesh_disable() inside mesh_event_cb() of config_server.c would be a proper way of using it. This basically mean you will disable the mesh stack whenever you have sent anything. 

     

    If you want to wait for a particular packet to be sent, you would need to register your own call back by using nrf_mesh_evt_handler_add() and then add a token into your message and check for the token when you receive NRF_MESH_EVT_TX_COMPLETE. 

    Could you let me now what exactly the assertion you receive ? What throwing that and which error code ? Note that you should always check for return code after you call a function, for example nrf_mesh_disable().

  • Hi Hung, see my reply below:

    "I don't think putting nrf_mesh_disable() inside mesh_event_cb() of config_server.c would be a proper way of using it. This basically mean you will disable the mesh stack whenever you have sent anything."  

    Agreed.

    "If you want to wait for a particular packet to be sent, you would need to register your own call back by using nrf_mesh_evt_handler_add() and then add a token into your message and check for the token when you receive NRF_MESH_EVT_TX_COMPLETE. "

    I like this idea, that is a much nicer way of doing it!

    "Could you let me now what exactly the assertion you receive? What throwing that and which error code?"

    I was getting error code 8 on nrf_mesh_enable() (I was running it in a timer). But it seems to work fine if I instead call nrf_mesh_disable() from the NRF_MESH_EVT_TX_COMPLETE case statement.

    "Note that you should always check for return code after you call a function, for example nrf_mesh_disable()."

    I usually do. It is a good habit, I was just showing where I would call it, that is not my actual code.

  • You will receive NRF_ERROR_INVALID_STATE from nrf_mesh_enable() if the mesh stack is either not initialized or is already enabled. 
    I guess it's the second case, maybe the disable function earlier didn't take effect ? 

  • Hi Hung, yes it would seem that was the case. Either way, It might be worthwhile waiting until the friend and low power features have been added to the mesh SDK. Thanks for the help!

Related