Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Read multiple ADC samples on single channel

Hi,

I'm trying to read the battery voltage of a custom board from the VDDHDIV5  channel. I'm using FreeRTOS in my project. I would like to read trigger the ADC to read 5 samples(non-blocking) once every hour. I tried the below pseudo code to trigger the read but I noticed that only one reading is present in the buffer.

nrf_saadc_value_t raw_value[5] = {0};

void saadc_handler(nrf_drv_saadc_evt_t const * p_event)
{
    if(p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        raw_val = *(p_event->data.done.p_buffer);
        test = (raw_val*10/1024);
        
        //Notify saadc_thread
    }

}

void saadc_init()
{
    uint32_t err_code;

    //SAADC peripheral configuration
    nrf_drv_saadc_config_t m_saadc_config = 
    {
        .interrupt_priority = APP_IRQ_PRIORITY_LOW,
        .low_power_mode = false,
        .oversample = NRF_SAADC_OVERSAMPLE_DISABLED,
        .resolution = NRF_SAADC_RESOLUTION_10BIT
    };

    // Channel configuration
    //Internal reference is 0.6V
    nrf_saadc_channel_config_t m_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDDHDIV5);
    m_channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
    m_channel_config.gain = NRF_SAADC_GAIN1_6;

    err_code = nrf_drv_saadc_init(&m_saadc_config, saadc_handler);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &m_channel_config);
    APP_ERROR_CHECK(err_code);
}

void saadc_sample()
{
    nrf_drv_saadc_buffer_convert(raw_value, 5);
    
    for(uint8_t i=0; i<5; ++i)
        nrf_drv_saadc_sample();
}

static void saadc_thread(void * arg)
{
    // Call saadc_sample and wait for a notification. And then delay for 1 hour
}


I tried two more things and noticed different output

  • The SAADC example in the SDK. The code was running fine and the ADC values were correct.
  • Call saadc_sample in the SAADC handler on NRF_DRV_SAADC_EVT_DONE. The ADC values were correct but this is not a desirable situation as I don't need the SAADC to constantly sample
  • Change the size of raw_value to 1. The ADC value was wrong. I tried this with and without oversampling.

MCU - nRF52833-QDAAA0

SDK - nRF5 SDK 17.1.0

With FreeRTOS

Parents Reply Children
  • Hi Vidar,

    I checked the value of MAINREGSTATUS and it is High when I tried both the projects.

    Additionally, please don't check the value using a breakpoint and instead use the Watch window as I've noticed that I get the correct value sometimes when the code execution stops. And usually the first or second time it hits the breakpoint, it reads the correct value.

    Thanks,

    Gowtham

  • Hi Gowtham,

    Thanks for confirming. The problem is that I am consistently measuring 291 here with minor deviation, both with breakpoints and watchpoints. Also don't see why this should have made any difference. 

    Have you tried to see if it behaves differently with different build configurations (i.e. Debug vs Release) and would you mind recording a short screencast of when you are monitoring the sample buffer?

    Best regards,

    Vidar

  • Hey Vidar,

    Sorry for the delay in replying. I was able to make a recording of this issue. The battery voltage at the time of recording was around 3.97V.  You can notice that the first sample had a value close to the expected value while the next sample onwards it's completely wrong.

  • Hi,

    Do you see the same if you comment the 'raw_value = *(p_event->data.done.p_buffer);' line in your saadc_handler() callback, and does it make any difference if you use the 'Debug' build configuration instead of 'Release'?

  • Hi Vidar,

    I've tried commenting the line you have mentioned and I'm still facing the same issue. I tried the Debug variant and the issue is still seen.

Related