I am programming a RAK4631 Board, which is of course based on the nrf52840 SoC. The BaseLine Device tree has no detail in the ADC Node so I have created an overlay. The RAK4631 documentation indicates that AIN2 (P0.04) is directly connected to the battery for voltage measurement. There are many Arduino examples out there but not many C code examples. Here is my overlay file contents:
/ {
zephyr,user {
io-channels = <&adc 2>, <&adc 7>;
};
};
&adc {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
channel@2 {
reg = <2>;
zephyr,gain = "ADC_GAIN_1_6";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN2>; /* Corresponds to P0.04 */
zephyr,resolution = <12>;
};
channel@7 {
reg = <7>;
zephyr,gain = "ADC_GAIN_1_6";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN7>; /* Corresponds to P0.31 */
zephyr,resolution = <12>;
};
};
Here is my setup code:
//
// ADC Defines
//
#define BATT_ADC_NODE DT_NODELABEL(adc) // ADC peripheral node
#define ADC_RESOLUTION 12 // 12-bit ADC resolution
#define ADC_GAIN ADC_GAIN_1_6 // Gain setting for ADC
#define ADC_REFERENCE ADC_REF_INTERNAL // Internal reference voltage
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10) // Acquisition time
#define BATTERY_CHANNEL_ID 2 // ADC channel ID for the battery AIN2
#define ADC_MAX_VOLTAGE 3.6 // Maximum ADC input voltage (V)
#define ADC_FULL_SCALE (1 << ADC_RESOLUTION) // Full-scale value for 12-bit ADC
#define VOLTAGE_DIVIDER_RATIO 2.0f
const struct device *batt_adc_dev = DEVICE_DT_GET(BATT_ADC_NODE);
// Define ADC channel configuration
static const struct adc_channel_cfg battery_channel_cfg = {
.gain = ADC_GAIN_1_6,
.reference = ADC_REF_INTERNAL,
.acquisition_time = ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10),
.channel_id = BATTERY_CHANNEL_ID, // Specify the channel ID for AIN2
.differential = 0 // Single-ended input
};
// Define ADC sequence
static struct adc_sequence battery_adc_seq = {
.channels = BIT(BATTERY_CHANNEL_ID),
.buffer = NULL, // Buffer will be set dynamically
.buffer_size = 0,
.resolution = ADC_RESOLUTION,
};
I am calling this for setup:
//
// Check AIN Ready for Battery Voltage Read
//
if (!device_is_ready(batt_adc_dev))
{
LOG_ERR("AIN2 Device not ready");
return;
}
else
{
LOG_ERR("AIN2 Device Ready!!");
}
ret = adc_channel_setup(batt_adc_dev, &battery_channel_cfg);
if (ret != 0) {
LOG_ERR("Failed to configure ADC channel: %d", ret);
}else
{
LOG_INF("ADC channel configured for battery voltage measurement");
}
These calls are all successful.
However, when I call this:
int ret = adc_read(batt_adc_dev, &battery_adc_seq);
if (ret < 0) {
LOG_ERR("Failed to read ADC: %d", ret);
return -1.0f;
}
I always get this log message:
00> [00:30:35.901,824] <err> adc_nrfx_saadc: Channel 2 not configured
00> [00:30:36.002,075] <err> ublox_gps: Failed to read ADC: -22
00> [00:30:36.002,075] <err> ublox_gps: Failed to read ADC: -22
The project builds successfully without warnings or errors. Any help letting me know where I am going wrong would be appreciated. I am using Zephyr v2.9.0 which I believe is the latest and the RAK4631 dev board.
Thank you.