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

Simplest way to read an ADC input

Dear All, I would like a simple way to read the voltage on one ADC pin without using any "adc_event_handler"-like solution. I tried

reading=nrf_adc_convert_single(NRF_ADC_CONFIG_INPUT_2);

but without success.

Thanks

Francesco

  • The function does not check if the ADC is initialized and powered

    See: developer.nordicsemi.com/.../a00754.html

    So are you sure that you have correctly initialized and powered the ADC?

  • Let me explain better. This is my main. It is basically the adc example where I tried not to use the interrupts or the handler to have a reading.

    #include "nrf.h"
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include "nrf_drv_adc.h"
    #include "nordic_common.h"
    #include "boards.h"
    #include "nrf_log.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    
    #define ADC_BUFFER_SIZE 1 /**< Size of buffer for ADC samples. */
    
    static nrf_adc_value_t adc_buffer[ADC_BUFFER_SIZE]; /* ADC buffer. */ 
    static nrf_drv_adc_channel_t m_channel_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_2); /* Channel instance. Default configuration used. */
    
    static void adc_event_handler(nrf_drv_adc_evt_t const * p_event) 
    { 
    // if (p_event->type == NRF_DRV_ADC_EVT_DONE) 
    // { // uint32_t i; 
    // for (i = 0; i < p_event->data.done.size; i++) 
    // { 
    // NRF_LOG_PRINTF("Current sample value: %d\r\n", p_event->data.done.p_buffer[i]); // 
    // } 
    // } 
    }
    
    static void adc_config(void) 
    { 
    ret_code_t ret_code; 
    nrf_drv_adc_config_t config = NRF_DRV_ADC_DEFAULT_CONFIG;
    ret_code = nrf_drv_adc_init(&config, adc_event_handler);
        APP_ERROR_CHECK(ret_code);
    nrf_drv_adc_channel_enable(&m_channel_config);
    }
    
    int main(void)
    { 
    nrf_adc_value_t myvalue; 
    LEDS_CONFIGURE(BSP_LED_0_MASK); 
    LEDS_OFF(BSP_LED_0_MASK);
    adc_config();
    UNUSED_RETURN_VALUE(NRF_LOG_INIT());
    
    NRF_LOG_PRINTF("ADC example\r\n");
    
    while(1)
    {
    APP_ERROR_CHECK(nrf_drv_adc_buffer_convert(adc_buffer,ADC_BUFFER_SIZE));
    nrf_drv_adc_sample();
    nrf_delay_ms(100);
    LEDS_INVERT(BSP_LED_0_MASK);\
    myvalue=nrf_adc_convert_single(NRF_ADC_CONFIG_INPUT_2);
    NRF_LOG_PRINTF("Currently my value: %d\r\n",myvalue);
    }
    
    }
    

    I would like to know more details about:

    1. "APP_ERROR_CHECK(nrf_drv_adc_buffer_convert(adc_buffer,ADC_BUFFER_SIZE));": without this it does not work

    2: if I understand properly first a measurement is triggered with nrf_drv_adc_sample() while nrf_adc_convert_single makes accessible the first of the measurements. Am I correct?

    Thanks

  • First of all, event-driven ADC is recommended, so that the CPU can be turned off during inactive periods. But if you don’t want that, here is a very simple way to read the ADC without using any events, using the nrf_drv_adc_sample_convert function:

    #include "nrf.h"
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include "nrf_drv_adc.h"
    #include "nordic_common.h"
    #include "boards.h"
    #include "nrf_log.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    
    
    static nrf_adc_value_t       adc_value; /**< ADC buffer. */
    static nrf_drv_adc_channel_t m_channel_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_2); 
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        UNUSED_RETURN_VALUE(NRF_LOG_INIT());
        NRF_LOG_PRINTF("ADC example\r\n");
    
        while (true)
        {
            nrf_drv_adc_sample_convert(&m_channel_config,&adc_value);
            NRF_LOG_PRINTF("ADC buffer: %d\r\n",adc_value);
            nrf_delay_ms(100);
        }
    }
    /** @} */
    
  • Thanks Sigurd, how long does it take to have a measurement ready? Can I shorten the nrf_delay_ms() to 10ms (of course after removing the UART)?

  • How long time before the measurement is ready depend on what bit mode you use on the ADC. The default configuration uses 10-bit, and takes 68 μs to sample. If you use 8-bit mode it takes 20 μs (50K samples per second). The nrf_delay_ms() is just there to not overflow the uart.

Related