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

BAS with SAADC - How to read ADC value periodically

Hi, I'm testing my custom PCB that uses nRF52832-QFAA and a single cell Li-Ion battery (3 ~ 4.2V).

Additionally, I use

  • SDK 12.1

  • SoftDevice S132 v3

  • HRS example and SAADC example

schematic

void saadc_init(void) {
ret_code_t err_code;
nrf_saadc_channel_config_t channel_config =
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(nrf_drv_saadc_gpio_to_ain(4)); // for AIN2

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

err_code = nrf_drv_saadc_channel_init(2, &channel_config);
APP_ERROR_CHECK(err_code);
// ...

I think the SAADC example uses an interrupt that is triggered when the buffer is filled with samples.

Whereas I want to sample the values using the timer.

My objective is to the send battery level after reading the ADC value via BAS (Battery Service) using the timer.

err_code = app_timer_create(&m_battery_timer_id,
                            APP_TIMER_MODE_REPEATED,
                            battery_level_meas_timeout_handler); // ...
static void battery_level_meas_timeout_handler(void * p_context){
UNUSED_PARAMETER(p_context);
battery_level_update(); // I want to read the ADC value here!
  1. Have I correctly configured AIN2?

    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(nrf_drv_saadc_gpio_to_ain(4)); err_code = nrf_drv_saadc_channel_init(2, &channel_config); // Are they the correct number?

// Added 2017.06.01

As you said about if you only use one SAADC channel, you can use channel 0,

yes. I use only one, so I will change it. Thanks for checking it out.

ADCResult

NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(nrf_drv_saadc_gpio_to_ain(4)); // for AIN2

I used that code, not NRF_SAADC_INPUT_AIN2.

If I use NRF_SAADC_INPUT_AIN2, different values (42, 30, 35, ...) are read.

After typing 4, the values of the battery divided voltages are read.

  1. Is there a function that reads the buffer of the ADC?

If that exists, can I use it inside the timeout handler? Or should I call it outside the handler?

-Best Regards, MANGO

Parents
  • Hi,

    If you want to get a single sample from the SAADC, you can use blocking mode with the function nrf_drv_saadc_sample_convert(). This can be called in your timer callback, and you can use the sample value to update the BAS characteristics.

    I still think it is a better solution to use non-blocking sampling and trigger the sample task from the timer callback (or connect the timer event directly to the sample task using PPI), if you will be doing regular sampling. You can set the buffer size to 1 to get a callback after each sample.

    Your channel setup looks correct, but if you only use one SAADC channel, you can use channel 0. It is also possible to use the AIN2 define from nrf_adc.h as an input directly, this depends on what you think is more easily readable:

    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    

    Best regards,

    Jørgen

  • There should not be any difference in using nrf_drv_saadc_gpio_to_ain(4) or NRF_SAADC_INPUT_AIN2 directly. The gpio_to_ain function only returns the correct index of the nrf_saadc_input_t enum, to get corresponding NRF_SAADC_INPUT_AINx value. Note that this reflects the Analog input, not the GPIO pin number, i.e., AIN2 = GPIO P0.04.

Reply Children
No Data
Related