I am trying to use the ADC on an nRF52840DK.
I have configured the two ADC channels in the overlay
&adc {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
channel@0 {
reg = <0>;
zephyr,gain = "ADC_GAIN_1_5";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN1>;
zephyr,resolution = <12>;
zephyr,oversampling = <8>;
};
channel@1 {
reg = <1>;
zephyr,gain = "ADC_GAIN_1_5";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN2>;
zephyr,resolution = <12>;
zephyr,oversampling = <8>;
};
};
I setup the channels like this
#define DT_SPEC_AND_COMMA(node_id, prop, idx) ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
static const struct adc_dt_spec adc_channels[] = {DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, DT_SPEC_AND_COMMA)};
and take readings using this code
static uint16_t read_temperature(int i)
{
int err = adc_sequence_init_dt(&adc_channels[i], &temperature_sequence);
if (err < 0)
{
LOG_ERR("Could initialise ADC%d (%d)", i, err);
return -1;
}
err = adc_read(adc_channels[i].dev, &temperature_sequence);
if (err < 0)
{
LOG_ERR("Could not read ADC%d (%d)", i, err);
return -1;
}
int32_t adc_reading = temperature_buf;
...remainder of the function...
}
I have setup a simple voltage divider. Two 10kOhm resisters between GND and VDD. When I check the divider value with a multi-meter, I see 1.5v, as expected.
When I use this divider on P0.03 (AIN1), I get a measurement of just over 2000, which I convert to 1.5v.
When I use this divider on P0.04 (AIN2), I get a measurement of around 30.
If I connect VDD directly to AIN2, I get a measurement over 4000.
If I connect GND to AIN2, I get a measurement around 8.
I am satisfied that I am reading AIN2 based on my VDD & GND tests.
Why, oh, why, doesn't a voltage of 1.5v register on AIN2?
How can I troubleshoot this? Faulty DK?
