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

ADC for read battery level the event is not trigger in second time?

We are using nRF52840 SDK 15.0 with Segger embedded studio. We have referred ble_app_proximity example only for read battery level using ADC. Now in our application used SAADC for read 3 axis sensor data for that we have configured saadc_init(); For battery level read we have configured adc_configure_battery();

Meaning there are two function used for different ADC configuration, my saadc_init() function worked properly and also their saadc_callback(..) getting. But problem coming for adc_configure_battery() function event call back is not triggering means saadc_battry_event_handler() not trigger in second time.

I have called this function like 

void saadc_battry_event_handler(nrf_drv_saadc_evt_t const *p_event) {
  if (p_event->type == NRF_DRV_SAADC_EVT_DONE) {
    nrf_saadc_value_t adc_result;
    uint32_t err_code;

    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
    APP_ERROR_CHECK(err_code);
    adc_result = p_event->data.done.p_buffer[0];
//    NRF_LOG_INFO("%d", adc_result);
    s_info.batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) +
                              DIODE_FWD_VOLT_DROP_MILLIVOLTS;
    s_info.percentage_batt_lvl = battery_level_in_percentage(s_info.batt_lvl_in_milli_volts);
    err_code = ble_bas_battery_level_update(&m_bas, s_info.percentage_batt_lvl, BLE_CONN_HANDLE_ALL);
    if (
        (err_code != NRF_SUCCESS) &&
        (err_code != NRF_ERROR_INVALID_STATE) &&
        (err_code != NRF_ERROR_RESOURCES) &&
        (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)) {
      APP_ERROR_HANDLER(err_code);
    }
  }
}

/**@brief Function for configuring ADC to do battery level conversion.
 */
static void adc_configure_battery(void) {
  ret_code_t err_code;
  nrf_saadc_value_t adc_battery_buf[2];
  NRF_LOG_DEBUG("adc_configure_battery call");
  nrf_saadc_channel_config_t config =
  NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);

  err_code = nrf_drv_saadc_init(NULL, saadc_battry_event_handler);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_channel_init(3, &config);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_buffer_convert(&adc_battery_buf[0], 1);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_drv_saadc_buffer_convert(&adc_battery_buf[1], 1);
  APP_ERROR_CHECK(err_code);
}

  adc_configure_battery();
  err_code = nrf_drv_saadc_sample();
  APP_ERROR_CHECK(err_code);

My battery level not updating when sensor device wake up then i called above functions to trigger adc_configure_battery(); event handler.

My question is any problem is i used two ADC configuration function?

2. Why battery event means saadc_battry_event_handler(); is not triggering?

Parents
  • Hello,

    I don't see that you actually trigger any readings in the snippet that you pasted. You need to trigger some samples, and the event handler will be called after N samples has been captured (where N is the size of your buffer).

    Are you triggering some ADC samples outside the snippet? The typical way to do this is to use a timer to trigger a sample every second, every minute, or whatever suits your application.

    Best regards,

    Edvin

Reply
  • Hello,

    I don't see that you actually trigger any readings in the snippet that you pasted. You need to trigger some samples, and the event handler will be called after N samples has been captured (where N is the size of your buffer).

    Are you triggering some ADC samples outside the snippet? The typical way to do this is to use a timer to trigger a sample every second, every minute, or whatever suits your application.

    Best regards,

    Edvin

Children
  • Thanks for reply,

    Now I am able to trigger ADC sample and also got event saadc_battry_event_handler(...); But in this function the read adc result is very fluctuations sometime it goes into higher value sometime goes into negative value.

    Due to fluctuations in adc result hence our battery level accuracy not getting good it changing in each readings. Sometime shows 78%, 97%, 100% like even the power of board by USB.

    Will you please suggest any solution for how i can improve the accuracy of battery level read. Because in our application battery level parameter is important features.

    Thanks..

  • Hello,

    I suggest that you take a look at the ble_app_proximity example. This has some battery readings using the saadc. Note that the way that this example is set up, it does not read the battery level until the timer times out the first time, which is 2 minutes. So if you want a reading from the start, just trigger a reading before you start the timer.

    Best regards,

    Edvin

  • Sorry for late reply,

    We were busy for implementing other functionality. But now we need to read battery level with accuracy.

    We are using 2*1.5V AA size battery for our application and also read battery level when device will wake up. But now problem getting battery level in % and also in milivolt got more fluctuations like sometime 100% sometime 80% 75% etc. Battery read accuracy is more important for us because we will notify to user when specific battery level reached and stop working functionality in device ON red LED. Here is bellow our battery saadc battery event handler function:

    void saadc_battry_event_handler(nrf_drv_saadc_evt_t const *p_event) {
      if (p_event->type == NRF_DRV_SAADC_EVT_DONE) {
        nrf_saadc_value_t adc_result;
        uint32_t err_code;
    
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
        APP_ERROR_CHECK(err_code);
        adc_result = p_event->data.done.p_buffer[0];
    //    NRF_LOG_DEBUG("battery level adc value result:%d", adc_result);
        s_info.batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) +
                                  DIODE_FWD_VOLT_DROP_MILLIVOLTS;
        s_info.percentage_batt_lvl = battery_level_in_percentage(s_info.batt_lvl_in_milli_volts);
        err_code = ble_bas_battery_level_update(&m_bas, s_info.percentage_batt_lvl, BLE_CONN_HANDLE_ALL);
        if (
            (err_code != NRF_SUCCESS) &&
            (err_code != NRF_ERROR_INVALID_STATE) &&
            (err_code != NRF_ERROR_RESOURCES) &&
            (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)) {
          APP_ERROR_HANDLER(err_code);
        }
        battery_adc_evt_counter++;
          if (battery_adc_evt_counter >= 1){
          NRF_LOG_INFO("Updated Read battery level: %d", s_info.percentage_batt_lvl);
          NRF_LOG_DEBUG("Battery milivolt: %d", s_info.batt_lvl_in_milli_volts);
          nrf_drv_saadc_uninit();
          battery_adc_evt_counter = 0;
          channel_number = 0;
          m_adc_evt_counter = 0;
          saadc_init(); /* Start measuring actual sensor data*/
        }
      }
    }

    looking forward your response..

    Thanks....!!!

  • Hello,

    What do you mean by "sometime 100% sometime 80% 75% etc."?

    What does your ADC_RESULT_IN_MILLI_VOLTS() functino look like? Does this function do what you intend? Are the adc_result values looking as expected?

    BR,

    Edvin

  • What do you mean by "sometime 100% sometime 80% 75% etc."?

    I am saying when i configure timer for sensor device to wake up every 5 minute that time in every sensor reading sending battery level. This battery level we got 80% then after 5 minute got 90%, every reading got different not getting stable sometime the difference between last and current 40%.

    here is below ADC_RESULT_IN_MILLI_VOLTS() function:

    /** Battery Measurements Macro**/
    #define ADC_REF_VOLTAGE_IN_MILLIVOLTS 600                   /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
    #define ADC_PRE_SCALING_COMPENSATION 6                      /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
    #define DIODE_FWD_VOLT_DROP_MILLIVOLTS 270                  /**< Typical forward voltage drop of the diode . */
    #define ADC_RES_10BIT 1024                                  /**< Maximum digital value for 10-bit ADC conversion. */
    #define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE) \
      ((((ADC_VALUE)*ADC_REF_VOLTAGE_IN_MILLIVOLTS) / ADC_RES_10BIT) * ADC_PRE_SCALING_COMPENSATION)

    Thanks..!!!

Related