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

Update timer speed once connected

I have a custom Characteristic in my GATT that is sending data in Notify mode every 30ms.

In my firmware I use timer to do this with something like this :


#define RTC1_TICK_DURATION		31
	
#define TIMER_ONE_DURATION   		33 // 30ms																/**<(deflt:1000)[ms] sending/measurement cycle duration for 1s cycled characteristics*/
#define TIMER_ONE_TICKS_NB 		(TIMER_ONE_DURATION * 1000 / RTC1_TICK_DURATION)


err_code = app_timer_start(m_TimerOne_id, (uint32_t)TIMER_ONE_TICKS_NB, NULL);


Everything is working great but sometimes, randomly, my app using BLE or my laptop using Web BLE (so two different device with two different source code with the same behavior) are unable to retrieve value for this Characteristic. They are able to connect to my device but no Characteristic value is send.

I tried to change the interval from 30ms to 90ms and so far I am not able to reproduce this issue so it lead me to think that the speed can be the source of the issue.

How would you deal with that ? Is it possible to notify at a low pace, then one second after a connection is made, increase the speed ? Or better, when someone subscribe to the Notifying Characteristic increase speed, when it disconnect decrease speed ?

Thanks !

  • According to this post I have the same behaviour.

    The error appears when my m_conn_handle = 0xFFFF

    But I don't think this is the real error. The real error is that sometimes, even if I call nrf_drv_saadc_sample(), it never trigger the saadc_callback() function.

    Could it be because I uninit the saadc every time I do a disconnection to enter in low power ?

    Every time I disconnect I do :

    void saadc_uninit(void)
    {
        ret_code_t err_code;
        nrf_drv_saadc_abort();
    
    
        nrf_saadc_disable();
        while(NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos))
          {}
    
        err_code = nrf_drv_saadc_channel_uninit(0);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_uninit(1);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_saadc_uninit();
        NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
        NVIC_ClearPendingIRQ(SAADC_IRQn);
    
    }

    It seems more likely to be something to do with the saadc driver for me instead of the connection handler.

    Can this be related to this or this ?

    Because most of the times I can predict when an error will occurs just by checking my debug from my previous disconnection. If during a disconnection, I see a debug log from saadc_callback() showing while i'm in the DEVICE_GOtoLowpower case (or after), my next connection will not get data. I hope I make myself clear.

    Here are the log :

    case DEVICE_GOtoLowpower :
            send_log("Start DEVICE_GOtoLowpower");
            stop_TimerOne();
            stop_TimerTwo();
            send_log("Timers stopped");
            accel_deep_sleep();
            disable_spi();
            send_log("before saadc_uninit");
            //saadc_uninit();
            send_log("after saadc_uninit");
            GPIO_lowpower();
            u8_device_state=DEVICE_DISCONNECTED;
            send_log("End DEVICE_GOtoLowpower");

    <info> app: Start DEVICE_GOtoLowpower
    <info> app: Timers stopped
    <info> app: before saadc_uninit
    <info> app: after saadc_uninit
    <info> app: End DEVICE_GOtoLowpower
    <info> app: LOG FROM saadc_callback here

  • Hi

    Due to the Easter holiday you will have to expect a delay in replies, sorry for the inconvenience!

    I see that in your previous post you have made some changes to your saadc_callback function, and that you've made further changes to that function in this case as well. It seems you have removed the SAADC_EVT_DONE event, which should be generated when the buffer is filled with samples, which is why I think you are experiencing the crash. Please make sure that this snippet is in your saadc_callback function, and see if that fixes your problem.

    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            ret_code_t err_code;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
    
            int i;
            NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
            m_adc_evt_counter++;
        }

    Best regards and happy Easter,

    Simon

  • Hi ,

    No it's still here but I simplify my code for an easier reading :)

    I still have the if NRF_DRV_SAADC_EVT_DONE. It's true that the issue happens always when I try to reconnect after a disconnection while the saadc_callback was fired after the disconnection.

    For example please take a look at this log, I hope it's clear and that I didn't make mistake copy/pasting :

    uint8_t u8_device_state=0;
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
       
      	NRF_LOG_INFO("u8_device_state: %d", u8_device_state);
      	NRF_LOG_INFO("NRF_DRV_SAADC_EVT_DONE: %d", NRF_DRV_SAADC_EVT_DONE);
      	NRF_LOG_INFO("p_event->type: %d", p_event->type);
      	NRF_LOG_PROCESS();
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE &&
            m_conn_handle == NRF_SUCCESS)
        {
     
            ret_code_t err_code;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
    	    APP_ERROR_CHECK(err_code);
    
    	    val = p_event->data.done.p_buffer[0];
    
    	    value_data[0]= (uint8_t) val;
    	    value_data[1]= (uint8_t) (val>>8);
    
    		err_code = ble_service_on_value_change(m_conn_handle, &m_service, value_data);
            if (err_code != NRF_SUCCESS &&
                err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                err_code != NRF_ERROR_INVALID_STATE &&
                err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING &&
                err_code != NRF_ERROR_RESOURCES
               )
              {
                APP_ERROR_CHECK(err_code);
              }
    
        }
        else{
          if(m_conn_handle != NRF_SUCCESS){
            NRF_LOG_INFO("m_conn_handle not ready: %d", m_conn_handle);
            NRF_LOG_PROCESS();
          }
        }
    }
    
    
    
    
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code = NRF_SUCCESS;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_DISCONNECTED:
                u8_device_state=DEVICE_GOtoLowpower;
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                send_log("m_conn_handle DISCONNECTED");
                send_log("");
                send_log("");
                // LED indication will be changed when advertising starts.
                break;
    
            case BLE_GAP_EVT_CONNECTED:
               	u8_device_state=DEVICE_SET;
               	// err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
               	// APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                NRF_LOG_INFO("m_conn_handle CONNECTED : %d", m_conn_handle);
                NRF_LOG_PROCESS();
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                // SET TX POWER AFTER CONNECTING
    	    	uint32_t err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_conn_handle, TX_POWER_LEVEL); 
    	    	APP_ERROR_CHECK(err_code);
                break;
    
            // Other default cases after here not copy/pasted
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    
    
    
    int main(void)
    {
        uint8_t i=0;
        uint32_t err_code;
        bool erase_bonds;
    
        // Some initialisations before that I did not included...
      
        saadc_init();
        timers_init();
        power_management_init();
    
        // Some initialisations after here that I did not included...
       
        err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, TX_POWER_LEVEL);
        APP_ERROR_CHECK(err_code);
    
        u8_device_state=DEVICE_GOtoLowpower;
    
        // Enter main loop.
        for (;;){ 
     		switch(u8_device_state)
            {
              case DEVICE_CONNECTED :
                if(TimerTwo_IRQ && m_conn_handle == NRF_SUCCESS)
                  {
                    send_log("nrf_drv_saadc_sample");
                    nrf_drv_saadc_sample();
                    TimerTwo_IRQ = 0; 
                  }
                  else{
                    if(m_conn_handle != NRF_SUCCESS){
                      NRF_LOG_INFO("m_conn_handle not ready !!! : %d", m_conn_handle);
                      NRF_LOG_PROCESS();
                    }
                  }
                idle_state_handle();
            break; 
    
            case DEVICE_DISCONNECTED : 
            	idle_state_handle();
            break; 
    
            case DEVICE_SET :
    			send_log("------------------------------------------------------");
    			saadc_init();
    			GPIO_init();
    			accel_init();
    			start_TimerTwo();
    			send_log("Device SET");
    			NRF_LOG_INFO("m_conn_handle : %d", m_conn_handle);
    			NRF_LOG_PROCESS();
    			u8_device_state=DEVICE_CONNECTED;
    			break;
    
           	case DEVICE_GOtoLowpower :
    			send_log("Start DEVICE_GOtoLowpower");
    			stop_TimerTwo();
    			send_log("Timers stopped");
    			accel_deep_sleep();
    			disable_spi();
    			send_log("before saadc_uninit");
    			saadc_uninit();
    			send_log("after saadc_uninit");
    			GPIO_lowpower();
    			u8_device_state=DEVICE_DISCONNECTED;
    			send_log("End DEVICE_GOtoLowpower");
            	break; 
    
           	default: 
           		break; 
    
            //nrf_pwr_mgmt_run();
        }
    }
    }
    
    
    

    <info> app: m_conn_handle CONNECTED : 0       <--------------------- Start connection request
    <info> app: ------------------------------------------------------
    <info> app: Device SET
    <info> app: m_conn_handle : 0       <--------------------- Connection made
    <info> app: nrf_drv_saadc_sample       <--------------------- Perform SAADC sample
    <info> app: u8_device_state: 0       <--------------------- Device connected
    <info> app: NRF_DRV_SAADC_EVT_DONE: 0       <--------------------- Just a debug for me
    <info> app: p_event->type: 0       <--------------------- NRF_DRV_SAADC_EVT_DONE
    <info> app: m_conn_handle: 0
    <info> app: err_code: 13313       <--------------------- Waiting for the connected device receive the data
    [......]
    <info> app: nrf_drv_saadc_sample
    <info> app: u8_device_state: 0
    <info> app: NRF_DRV_SAADC_EVT_DONE: 0
    <info> app: p_event->type: 0
    <info> app: m_conn_handle: 0
    <info> app: err_code: 13313
    <info> app: nrf_drv_saadc_sample
    <info> app: u8_device_state: 0
    <info> app: NRF_DRV_SAADC_EVT_DONE: 0
    <info> app: p_event->type: 0
    <info> app: m_conn_handle: 0
    <info> app: err_code: 0       <--------------------- Now the data are received in the connected device
    [......]
    <info> app: nrf_drv_saadc_sample
    <info> app: u8_device_state: 0
    <info> app: NRF_DRV_SAADC_EVT_DONE: 0
    <info> app: p_event->type: 0
    <info> app: m_conn_handle: 0
    <info> app: err_code: 0
    <info> app: nrf_drv_saadc_sample
    <info> app: m_conn_handle DISCONNECTED       <--------------------- Disconnected by the device
    <info> app:
    <info> app:
    <info> app: Start DEVICE_GOtoLowpower
    <info> app: Timers stopped
    <info> app: before saadc_uninit
    <info> app: after saadc_uninit
    <info> app: End DEVICE_GOtoLowpower
    <info> app: u8_device_state: 1       <--------------------- /!\ WARNING : I still receive data on saadc_callback, when this happen, I know next connection will fail to send data
    <info> app: NRF_DRV_SAADC_EVT_DONE: 0
    <info> app: p_event->type: 0
    <info> app: m_conn_handle not ready: 65535
    
    
    <info> app: m_conn_handle CONNECTED : 0       <--------------------- Start a new connection request
    <info> app: ------------------------------------------------------
    <info> app: Device SET
    <info> app: m_conn_handle : 0       <--------------------- Connection made
    <info> app: nrf_drv_saadc_sample       <--------------------- Perform SAADC sample but never trigger saadc_callback
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    [.......]

    Thanks for your help and feedbacks !

    Stéphane

  • Hi

    For about how long does it take until the device disconnects? It might be that the connection times out. What have you set  #define CONN_SUP_TIMEOUT as?

    Best regards,

    Simon

  • Hi,

    I don't know how to calculate it but here it is : 

    #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)

    Sorry I'm on my phone

Related