ADC Battery Voltage Sample

Last updated on: December 31, 2019

Introduction

The ADC battery voltage sample sets up the ADC on the Icarus board, reads the ADC value from pin A0, converts it into battery voltage and prints it.

Download sample from Icarus - ADC Battery Voltage Sample

Project configuration

In order to use the ADC the sample enables the following setting in the prj.conf file:

CONFIG_ADC=y

These include and enable the ADC driver.

Code explanation

The sample initializes the ADC, gets and converts the ADC values to a battery voltage in a loop and prints them. The following code shows the initialization of the ADC by getting the ADC device handle from the Icarus device tree and setting up the ADC channel:

struct device* adc_dev = device_get_binding("ADC_0");
adc_channel_setup(adc_dev, &m_1st_channel_cfg);

with m_1st_channel_cfg being a structure of type struct adc_channel_cfg:

static const struct adc_channel_cfg m_1st_channel_cfg = {
.gain = ADC_GAIN,
.reference = ADC_REFERENCE,
.acquisition_time = ADC_ACQUISITION_TIME,
.channel_id = ADC_1ST_CHANNEL_ID,
.input_positive = ADC_1ST_CHANNEL_INPUT,
};

In this sample, the ADC_REFERENCE is set to ADC_REF_INTERNAL which is 0.6V, ADC_GAIN is set up as 1/6 so the resulting input voltage range is: 0.6/(1/6) = 3.6V and for the Icarus the value is read from ADC_1ST_CHANNEL_INPUT which is actually NRF_SAADC_INPUT_AIN0 (Analog input pin 0)

To read the value from the ADC the sample calls:

adc_read(adc_dev, &sequence)

with sequence being a structure of type struct adc_sequence:

const struct adc_sequence sequence = {
.channels = BIT(ADC_1ST_CHANNEL_ID),
.buffer = m_sample_buffer,
.buffer_size = sizeof(m_sample_buffer),
.resolution = ADC_RESOLUTION,
};

This structure sets up the buffer where the values are stored and sets up the ADC read resolution ADC_RESOLUTION which is set to 10 bit in this sample (values from 0 to 1023).

After this call the buffer contains a sample value that can be used to compute the battery voltage value. The calculation, for the Icarus board goes as follows:

sample_value * (INPUT_VOLT_RANGE / VALUE_RANGE_10_BIT) * ((BATVOLT_R1 + BATVOLT_R2) / BATVOLT_R2));

with:

INPUT_VOLTAGE_RANGE = 3.6V (check previous paragraphs)

VALUE_RANGE_10_BIT = 1.023 (max value for a 10 bit output divided by 1000 as the voltage is expressed in V instead of mV)

BATVOLT_R1 = 4.7 MOhm (see also Battery Voltage Measurement in Peripherals)

BATVOLT_R2 = 10.0 MOhm (see also Battery Voltage Measurement in Peripherals)