Decawave / uwb-apps

Apache License 2.0
34 stars 31 forks source link

Sleep during twr_nranges_tdma #9

Open stephenmasih opened 4 years ago

stephenmasih commented 4 years ago

i am trying to add sleep just like in the example of tdoa_tag / Enter sleep / uwb_phy_forcetrxoff(udev); uwb_phy_rx_reset(udev); uwb_sleep_config(udev); uwb_enter_sleep(udev);

after nrng_complete_cb(struct dpl_event *ev) is called. The code is able get the pan slot_id and compute the distance only for once, after that it shows slot_timercb....start_tx_error

please help me resolve this issue. Thanks

ncasaril commented 4 years ago

If you're adding sleep you will need to add wakeup before the next operation. But, as the timing of the next range exchange depends on the timer in the decawave running continously it will fail. The timer is stopped during sleep and thus the application will need to resync to the network.

stephenmasih commented 4 years ago

Thanks for your comment. Please let me know if I am understanding it wrong. I have called uwb_wakeup(Udev) if sleeping; In the beginning of slot_cb() in main.c

But the same happens slot_timer_cb....start_tx_error

You mentioned that I should resync to the network upon wake up. Does the timer also automatically activates upon wake up ? Please let me know how should I resync back with master anchor time. Probably after resync I should call nrng_request_delay_start()

ncasaril commented 4 years ago

The ntwr example sends out a blink every 1s. Every time a node/tag needs to resync you need to receive two of these blinks. So, it'll take about 2s after each sleep to resync to the network. So, unless you're sleeping for 2+s you're actually wasting more energy by sleeping than by not sleeping. What I'm saying is that sleeping is not really a good thing to try to do with this example.

stephenmasih commented 4 years ago

Okay I get it. Can you recommend me an example. I am actually trying to add sleep for 5 seconds using os_time_delay(OS_TICKS_PER_SEC*5) after calling nrng_delay_start() and, uwb_enter_sleep(udev) in slot_cb() itself.

In the beginning of the slot_cb() i have added uwb_wakeup(udev).

Will the resync happen automatically after call of this function ?

If not how to do so ? How can I keep nrng_delay_start() in hold until resync is completely done ?

Thank you for your support.

ncasaril commented 4 years ago

You need to do a bit more work to tear down the tdma and ccp stacks and then restart them. Something like this:

static void
low_battery_mode(void)
{
        tdma = (tdma_instance_t*)uwb_mac_find_cb_inst_ptr(inst, UWBEXT_TDMA);
        uwb_ccp_stop(tdma->ccp);
        uwb_phy_forcetrxoff(inst);

        /* Force timeout */
        uwb_set_rx_timeout(inst, 1);
        uwb_phy_forcetrxoff(inst);
        os_time_delay(1);

        uwb_sleep_config(inst);
        uwb_enter_sleep(inst);
}

void
resume_uwb(struct uwb_dev *inst)
{
        uwb_wakeup(inst);
        uwb_mac_config(inst, NULL);
        uwb_txrf_config(inst, &inst->config.txrf);

        uwb_phy_forcetrxoff(inst);
        os_time_delay(1);
        tdma = (tdma_instance_t*)uwb_mac_find_cb_inst_ptr(inst, UWBEXT_TDMA);
        uwb_ccp_start(tdma->ccp, CCP_ROLE_SLAVE);
}
stephenmasih commented 4 years ago

i tried working out with your functions, but it still shows up slot_timercb:start_tx_error

Please look into this code i used in main.c

static void slot_cb(struct dpl_event ev){ assert(ev); tdma_slot_t slot = (tdma_slot_t ) dpl_event_get_arg(ev); tdma_instance_t tdma = slot->parent; struct uwb_ccp_instance ccp = tdma->ccp; struct uwb_dev udev = tdma->dev_inst; uint16_t idx = slot->idx; struct nrng_instance nrng = (struct nrng_instance )slot->arg;

if (udev->status.sleeping) {
    printf("sleeping\n");
    resume_uwb(udev);

}
/* Avoid colliding with the ccp in case we've got out of sync */
if (dpl_sem_get_count(&ccp->sem) == 0) {
    return;
}

/* Update config if needed */
if (uwb_config_updated) {
    uwb_config_updated = false;
    uwb_phy_forcetrxoff(udev);
    uwb_mac_config(udev, NULL);
    uwb_txrf_config(udev, &udev->config.txrf);
    return;
}

if (ccp->local_epoch==0 || udev->slot_id == 0xffff) return;

/* Process any newtmgr packages queued up */
if (idx > 6 && idx < (tdma->nslots-6) && (idx%4)==0) {
    nmgr_uwb_instance_t *nmgruwb = (nmgr_uwb_instance_t *)uwb_mac_find_cb_inst_ptr(udev, UWBEXT_NMGR_UWB);
    assert(nmgruwb);
    if (uwb_nmgr_process_tx_queue(nmgruwb, tdma_tx_slot_start(tdma, idx))) {
        return;
    }
}

if (udev->role&UWB_ROLE_ANCHOR) {
    /* Listen for a ranging tag */
    uwb_set_delay_start(udev, tdma_rx_slot_start(tdma, idx));
    uint16_t timeout = uwb_phy_frame_duration(udev, sizeof(nrng_request_frame_t))
        + nrng->config.rx_timeout_delay;

    /* Padded timeout to allow us to receive any nmgr packets too */
    uwb_set_rx_timeout(udev, timeout + 0x1000);
    nrng_listen(nrng, UWB_BLOCKING);
} else {
    /* Range with the anchors */
    if (idx%MYNEWT_VAL(NRNG_NTAGS) != udev->slot_id) {
        return;
    }
    /* Range with the anchors */
    uint64_t dx_time = tdma_tx_slot_start(tdma, idx) & 0xFFFFFFFFFE00UL;
    uint32_t slot_mask = 0;
    for (uint16_t i = MYNEWT_VAL(NODE_START_SLOT_ID);
         i <= MYNEWT_VAL(NODE_END_SLOT_ID); i++) {
        slot_mask |= 1UL << i;
    }

    if(nrng_request_delay_start(
           nrng, UWB_BROADCAST_ADDRESS, dx_time,
           DWT_SS_TWR_NRNG, slot_mask, 0).start_tx_error) {
        uint32_t utime = os_cputime_ticks_to_usecs(os_cputime_get32());
        printf("{\"utime\": %lu,\"msg\": \"slot_timer_cb_%d:start_tx_error\"}\n",
               utime,idx);
    }
    low_battery_mode();   
    os_time_delay(OS_TICKS_PER_SEC*5);
      }

} I have called low_battery_mode() and a delay of 5 seconds exact after nrng_request_delay _start() which is SUCCESS only once. resume_uwb(udev) is called when checked if sleeping. After sometime in the UART Console even the printf stops showing "sleeping" I am also attaching a screenshot for your reference..

Screenshot from 2020-09-22 04-29-22

Please help.