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 !

  • Try setting this value to a larger number and see if the connection lasts longer.

    Thanks for a very detailed log by the way! Not very often we see these things, so it is much appreciated.

    Best regards,

    Simon

  • It is normal that the saadc never trigger again after that.  This is because you didn't read the data out when the connection handle is invalid.  The state of the saadc was not reset.  You should read the saadc date even not connected, just don't send it.

  • No problem, you asked for it :D

    I really want this to be fixed so I try to give you as much informations as possible.

    For the CONN_SUP_TIMEOUT, I tried 8000 and even 10000 but I have the same result and behaviour.

    So I tried lower number, with 2000 same result.

    But during my manipulation I was able to reproduce the exact same issue apparently (no saadc_callback trigger) if I comment the saadc_init(); line in the DEVICE_SET case.

    So I tried to put a nrf_delay_us(100000) just after saadc_init() just in case this was because the init is not yet finish before it start advertising but without success.

    If I comment the saadc_init and saadc_uninit from the switch case (so it stay always initialized because it's init during first boot) the problem is still there.

    So I put log in every function that I call when disconnecting. Log when entering and log when exiting. Every time when it's not working, I do not see all logs. Sometimes I miss "exit saadc_uninit" or sometimes I miss "enter and exit GPIO_lowpower" and even "End DEVICE_GOtoLowpower".

    So I added nrf_delay_ms(25) between each line of DEVICE_SET case and DEVICE_GotoLowpower case. So far, I did not reproduce the issue after ~40 trials.

    Now the game is to find which one is really useful...

    EDIT : It looks like the only important one is the first one of DEVICE_GotoLowpower case to make sure the saadc_sample is finished before uninit everything. Please take a look at my other answer here.

  • Hi ,

    Thanks for your feedback, so I updated my saadc_callback to send it only if m_conn_handle is equal to zero (connected). Here is the new saadc_callback.

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
       
      NRF_LOG_INFO("u8_device_state: %d", u8_device_state);
      NRF_LOG_INFO("p_event->type: %d", p_event->type);
      NRF_LOG_PROCESS();
        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);
            send_log("nrf_drv_saadc_buffer_convert DONE");
          
            val = p_event->data.done.p_buffer[0];
            if(val > 65000 || val < 0) val=0;
    
            
            value_data[0]= (uint8_t) val;
            value_data[1]= (uint8_t) (val>>8);
    
            if(m_conn_handle == NRF_SUCCESS){
              NRF_LOG_INFO("Send it !");
              err_code = ble_service_on_value_change(m_conn_handle, &m_service, value_data);
              NRF_LOG_INFO("m_conn_handle: %d", m_conn_handle);
              NRF_LOG_INFO("err_code: %d", err_code);
              NRF_LOG_PROCESS();
              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
                 )
                {
                  NRF_LOG_INFO("ERROR CHECK");
                  NRF_LOG_PROCESS();
                  APP_ERROR_CHECK(err_code);
                }
            }
            else{
              send_log("Did not sent it because we are not connected anymore");
            }
    
        }
    }

    But it's not working. Here are the log :

    WORKING LOGS :
    [...]
    <info> app: Send it !
    <info> app: m_conn_handle: 0
    <info> app: err_code: 0
    <info> app: m_conn_handle DISCONNECTED
    <info> app:
    <info> app:
    <info> app: Start DEVICE_GOtoLowpower
    <info> app: enter stop_TimerOne
    <info> app: exit stop_TimerOne
    <info> app: enter stop_TimerTwo
    <info> app: exit stop_TimerTwo
    <info> app: Timers stopped
    <info> app: enter saadc_uninit
    <info> app: before nrf_drv_saadc_uninit
    <info> app: after nrf_drv_saadc_uninit
    <info> app: exit saadc_uninit
    <info> app: enter GPIO_lowpower
    <info> app: exit GPIO_lowpower
    <info> app: End DEVICE_GOtoLowpower
    <info> app: m_conn_handle CONNECTED : 0
    <info> app: ------------------------------------------------------
    <info> app: enter saadc_init
    <info> app: exit saadc_init
    <info> app: enter GPIO_init
    <info> app: exit GPIO_init
    <info> app: enter start_TimerTwo
    <info> app: exit start_TimerTwo
    <info> app: Device SET
    <info> app: m_conn_handle : 0
    <info> app: nrf_drv_saadc_sample
    <info> app: u8_device_state: 0
    <info> app: p_event->type: 0
    <info> app: nrf_drv_saadc_buffer_convert DONE
    <info> app: Send it !
    <info> app: m_conn_handle: 0
    [...]
    
    
    
    
    NOT WORKING LOGS :
    [...]
    <info> app: nrf_drv_saadc_sample
    <info> app: m_conn_handle DISCONNECTED
    <info> app:
    <info> app:
    <info> app: Start DEVICE_GOtoLowpower
    <info> app: enter stop_TimerOne
    <info> app: exit stop_TimerOne
    <info> app: enter stop_TimerTwo
    <info> app: exit stop_TimerTwo
    <info> app: Timers stopped
    <info> app: enter saadc_uninit
    <info> app: u8_device_state: 3
    <info> app: p_event->type: 0
    <info> app: nrf_drv_saadc_buffer_convert DONE
    <info> app: Did not sent it because we are not connected anymore
    <info> app: before nrf_drv_saadc_uninit
    <info> app: after nrf_drv_saadc_uninit
    <info> app: m_conn_handle CONNECTED : 0
    <info> app: ------------------------------------------------------
    <info> app: enter saadc_init
    <info> app: exit saadc_init
    <info> app: enter GPIO_init
    <info> app: exit GPIO_init
    <info> app: enter start_TimerTwo
    <info> app: exit start_TimerTwo
    <info> app: Device SET
    <info> app: m_conn_handle : 0
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    <info> app: nrf_drv_saadc_sample
    [...]

  • I see that there was a saadc sample started then saadc uninit before getting the result then the saadc interrupt occurs in between.  Could this be the cause of the issue ?

      

Related