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

Understanding SAADC

Hi all,

I am trying to use the SAADC to measure battery level. I have a rechargable lithium battery connected to my customed PCB with a NRF52832. The rechargable battery has a max voltage of about 4.2V when charged.

I also have a 3.3V voltage regulator connected to the battery and the 3.3V is used to power up the NRF52032.

I am using a voltage divider to measure the battery voltage. 4M ohm to battery and a 10M ohm to ground. The point between the 4M resistor and the 10M resistor is connected to AIN1. There is also a capacitor of 10nF across the 10M resistor.

My saadc init function is as follows:

void saadc_init(void)
{
    ret_code_t err_code;

    nrf_saadc_channel_config_t channel_config =
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
    channel_config.reference = NRF_SAADC_REFERENCE_VDD4;
    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
}

And the callback function is as follows:

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
   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);

  NRF_LOG_INFO("Conversion Result: %d\r\n", p_event->data.done.p_buffer[0]);

      nrf_drv_saadc_uninit();
      NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
      NVIC_ClearPendingIRQ(SAADC_IRQn);
   }
}

I used a multimeter and measure a voltage if 2.09V at the output of the voltage divider and I am getting a measure value of about 550 for the ADC conversion.

How is this 550 value obtained? And is it the correct value? What is the reference voltage for the ADC? I am assuming it 0.6 x 6 = 3.6V?

If so, then (2.09/3.6) * 1023 = 593. This is slightly off from the measured value of 550.

Can anyone help?

Parents
  • Hi,

    In your code you are using the nRF52's VDD divided by 4 as reference voltage (NRF_SAADC_REFERENCE_VDD4) and a gain of 1/6. If we rearange the equation presentet here we can see that Vin is:

    Vin = ADCresult * Reference / (Resolution * Gain)

    In your case that should result in:

    Vin = 550 * (VDD/4) / (1024 * (1/6)) = 2.66.

    So something is wrong. Are you sure that VDD is 3.3V?

Reply
  • Hi,

    In your code you are using the nRF52's VDD divided by 4 as reference voltage (NRF_SAADC_REFERENCE_VDD4) and a gain of 1/6. If we rearange the equation presentet here we can see that Vin is:

    Vin = ADCresult * Reference / (Resolution * Gain)

    In your case that should result in:

    Vin = 550 * (VDD/4) / (1024 * (1/6)) = 2.66.

    So something is wrong. Are you sure that VDD is 3.3V?

Children
  • Hi Martin,

    I measured with a voltmeter. My VDD is 3.28V and the voltage I am feeding into AN1 now is 2.22V (after charging the battery). I am getting a converstion result of 592.

    Something still seems wrong.

  • You are measuring the voltage across the 10 MOhm resistor with your volt meter right? What is the input impedance of your meter? Could it be related to this?

  • Hi Martin, I don't know the input impedance of my meter.

    Now, instead of measuring the voltage across the 10MOhm resistor, I measured the voltage across the battery instead.

    And these are my observations: Battery Voltage/ADC Value

    • 3.95/592
    • 3.79/568
    • 3.61/541

    There seems to be a consistent pattern. At 3.95V battery voltage, the theoretical voltage at the 10MOhm resistor should be 3.95*(10/14) = 2.821V

    At 3.79V battery voltage, the theoretical voltage at the 10MOhm resistor should be 3.79*(10/14) = 2.707V

    The difference in voltage is 2.832-2.707 = 0.114V and the difference in ADC result is 592-568 = 24. Therefore the ADC resolution is about 0.114/24 = 0.00475

    Working backwards, with a ADC result of 541, this gives a ADC measured voltage of 5410.00475 =2.57V. Take this result and multiple by 2.57(14/10) = 3.598V (battery voltage). Which is quite close to what I measured.

  • I'm not sure if I understand. It sounds like your measurements and ADC results are almost spot on (3.61V vs 3.598V)?

    Have you taken into account the accuracy of your resistors and the dropout voltage of your voltage regulator? Since you are using VDD as a reference voltage your ADC readings will be useless when/if the battery voltage gets so low that the regulator cannot produce 3.3V anymore.

Related