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

ADC result not changing

I'm trying to set up the ADC to read a battery voltage but am unable to get the adc result to change regardless of whether the input line is connected to VDD or GND. I'm using the nRF51-DK, and am configuring AIN5 for my ADC input. I'm reading the ADC on a timer interrupt. The timer works fine and I can set a breakpoint there to verify the ADC read occurs every 10 seconds. Every ADC read gives me a result of around 0xCC whether AIN5 is connected to GND or VDD (~2.9V). Looking at the nRF51422 Product Spec, it says that AIN5 is P0.04. This is the pin that I am switching between GND and VDD. I've also verified that LPCOMP is disabled so there is no contention here. I'm using SDK9 with the S110 SoftDevice. Here's my ADC configuration code - battery_init() is called from main(). Am I missing a configuration somewhere? Thanks.

#include <stdint.h>
#include "nordic_common.h"
#include "nrf.h"
#include "nrf_soc.h"
#include "nrf_adc.h"
#include "app_error.h"
#include "nrf51_bitfields.h"
#include "app_timer.h"

#define ADC_REF_VOLTAGE_IN_MILLIVOLTS   1200                                         /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define ADC_PRE_SCALING_COMPENSATION    3                                            /**< 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 BATTERY_LEVEL_MEAS_INTERVAL     APP_TIMER_TICKS(10000, APP_TIMER_PRESCALER) /**< Battery level measurement interval (ticks). This value corresponds to 10 seconds. */
#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
    ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / 255) * ADC_PRE_SCALING_COMPENSATION)

static app_timer_id_t _battery_timer_id;

static void adc_configure(void);
static void battery_level_meas_timeout_handler(void * p_context);


void battery_init(void)
{
    uint32_t err_code;

    // Create battery timer.
    err_code = app_timer_create(&_battery_timer_id,
                            APP_TIMER_MODE_REPEATED,
                            battery_level_meas_timeout_handler);
    APP_ERROR_CHECK(err_code);

    adc_configure();

    // Start battery timer
    err_code = app_timer_start(_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
    APP_ERROR_CHECK(err_code);
}

static void adc_configure(void)
{
    uint32_t err_code;
    nrf_adc_config_t adc_config = NRF_ADC_CONFIG_DEFAULT;

    // Configure ADC
    adc_config.reference  = NRF_ADC_CONFIG_REF_VBG;
    adc_config.resolution = NRF_ADC_CONFIG_RES_8BIT;
    adc_config.scaling    = NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD;
    nrf_adc_configure(&adc_config);

    // Select the battery level input
    nrf_adc_input_select(NRF_ADC_CONFIG_INPUT_5);

    // Enable ADC interrupt
    nrf_adc_int_enable(ADC_INTENSET_END_Msk);
    err_code = sd_nvic_ClearPendingIRQ(ADC_IRQn);
    APP_ERROR_CHECK(err_code);

    err_code = sd_nvic_SetPriority(ADC_IRQn, NRF_APP_PRIORITY_LOW);
    APP_ERROR_CHECK(err_code);

    err_code = sd_nvic_EnableIRQ(ADC_IRQn);
    APP_ERROR_CHECK(err_code);
}

static void battery_level_meas_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    nrf_adc_start();
}

void ADC_IRQHandler(void)
{
    if (nrf_adc_conversion_finished())
    {
        uint8_t  adc_result;
        static volatile uint16_t batt_lvl_in_milli_volts;

        nrf_adc_conversion_event_clean();

        adc_result = nrf_adc_result_get();

        batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result);
    }
}
Parents Reply Children
No Data
Related