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

  • 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..

  • 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..!!!

  • Hello,

    I believe that the challenge you are facing is that the voltage measured on the battery is dependent on how much current you are currently drawing. I think you should consider adding a capacitor on your battery, as described in this blog post. (The voltage divider is probably not necessary).

    Read through the guide. It may contain other useful information for you as well.

    Best regards,

    Edvin

  • Thanks for your fast response...

    As you said by adding capacitor on your battery will improve read accuracy but our hardware part is completed and also manufactured PCB. I think in our product we are using WiFi module for sending data to server due to WIFI the battery voltage fluctuate is this correct. Because WiFi is high current consumption.

    Is any way to improve in software side.

    One another question is today we done some measurements multi-meter and compare this value with software read battery milivolt. It almost same if subtract 270mV from read value.

    Question is What is the use of DIODE_FWD_VOLT_DROP_MILLIVOLTS?

    In our circuitry we are not added any diode for battery read level, simply read battery as a VDD.

    Can i remove this (DIODE_FWD_VOLT_DROP_MILLIVOLTS) from my program?

    Thank you so much...

  • I am not too familiar with current consumption together with WiFi.

    I assume that it looks a bit like BLE (except higher power), i.e. short bursts of high current consumption. Do you know if this is correct?

    If so, it is possible to use something called oversampling in our ADC (SAADC). What this does is that it takes several measurements. If you check out the SDK\examples\peripheral\saadc example, and look in the sdk_config.h file on line 232, there is a define:

    #define NRFX_SAADC_CONFIG_OVERSAMPLE 0 

    which is set to 0 by default, which means that you do not use oversampling.

    // <o> NRFX_SAADC_CONFIG_OVERSAMPLE  - Sample period
     
    // <0=> Disabled 
    // <1=> 2x 
    // <2=> 4x 
    // <3=> 8x 
    // <4=> 16x 
    // <5=> 32x 
    // <6=> 64x 
    // <7=> 128x 
    // <8=> 256x 
    
    #ifndef NRFX_SAADC_CONFIG_OVERSAMPLE
    #define NRFX_SAADC_CONFIG_OVERSAMPLE 0
    #endif

    You can try to define this to something higher, 8x (=3), or even 128x(=7) or 256x(=8) to see if this improves the results. This will do n samples, and average the measurements. 

    This will if course not guarantee that not all of the measurements hit the WiFi spikes, or none of them for that matter, but overall, it should even out the differences and give a more accurate result.

    If that turns out to not be sufficient, maybe it is possible to do the measurements when you are not using WiFi. If you have some way of knowing when the wifi is on "a break". Then you can use these interrupts to trigger a sample using nrf_drv_saadc_sample();

    Best regards,

    Edvin

  • Thanks Edvin for this information,

    We will try this and lets see what results outcome?

    Before that now the important for us battery life calculations for 1.5V * 2 3.3V AA size battery. Will you please help for the same.

    We know the following function used for coin cell CR2032:--->

    /*   - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV)
     *   - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV)
     *   - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV)
     *   - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV)*/
    
    static uint8_t battery_level_in_percentage(const uint16_t mvolts) {
      uint8_t battery_level;
    
      if (mvolts >= 3000) {
        battery_level = 100;
      } else if (mvolts > 2900) {
        battery_level = 100 - ((3000 - mvolts) * 58) / 100;
      } else if (mvolts > 2740) {
        battery_level = 42 - ((2900 - mvolts) * 24) / 160;
      } else if (mvolts > 2440) {
        battery_level = 18 - ((2740 - mvolts) * 12) / 300;
      } else if (mvolts > 2100) {
        battery_level = 6 - ((2440 - mvolts) * 6) / 340;
      } else {
        battery_level = 0;
      }
      return battery_level;
    }

    Instead of this calculation how i can replaced for 2 AA batteries if lowest minimum voltage for proper working device is 2800mV. 

    How i can decided the percentage level between less than 3000mV and up to 2800mV  with dropping voltage.

    Thanks for your great supporting.....!!!

Reply
  • Thanks Edvin for this information,

    We will try this and lets see what results outcome?

    Before that now the important for us battery life calculations for 1.5V * 2 3.3V AA size battery. Will you please help for the same.

    We know the following function used for coin cell CR2032:--->

    /*   - Section 1: 3.0V - 2.9V = 100% - 42% (58% drop on 100 mV)
     *   - Section 2: 2.9V - 2.74V = 42% - 18% (24% drop on 160 mV)
     *   - Section 3: 2.74V - 2.44V = 18% - 6% (12% drop on 300 mV)
     *   - Section 4: 2.44V - 2.1V = 6% - 0% (6% drop on 340 mV)*/
    
    static uint8_t battery_level_in_percentage(const uint16_t mvolts) {
      uint8_t battery_level;
    
      if (mvolts >= 3000) {
        battery_level = 100;
      } else if (mvolts > 2900) {
        battery_level = 100 - ((3000 - mvolts) * 58) / 100;
      } else if (mvolts > 2740) {
        battery_level = 42 - ((2900 - mvolts) * 24) / 160;
      } else if (mvolts > 2440) {
        battery_level = 18 - ((2740 - mvolts) * 12) / 300;
      } else if (mvolts > 2100) {
        battery_level = 6 - ((2440 - mvolts) * 6) / 340;
      } else {
        battery_level = 0;
      }
      return battery_level;
    }

    Instead of this calculation how i can replaced for 2 AA batteries if lowest minimum voltage for proper working device is 2800mV. 

    How i can decided the percentage level between less than 3000mV and up to 2800mV  with dropping voltage.

    Thanks for your great supporting.....!!!

Children
Related