Hello,
I'm building the sample Measure battery voltage on a custom board, and I have an error voltage: setup: -134 at runtime.
SEGGER J-Link V7.94i - Real time terminal output SEGGER J-Link (unknown) V1.0, SN=1050264300 Process: JLink.exe [00:00:00.390,777] <err> voltage: setup: -134 *** Booting nRF Connect SDK v2.9.0-7787b2649840 *** *** Using Zephyr OS v3.7.99-1f8f3dc29142 *** [00:00:04.254,882] <inf> BATTERY: Setup AIN2 got 0 [00:00:04.254,882] <inf> BATTERY: Battery setup: 0 1 [00:00:04.262,878] <inf> BATTERY: raw 1348 ~ 296 mV => 3256 mV
The overlay file is configure as explained in the sample:
/{ vbatt { compatible = "voltage-divider"; io-channels = <&adc 2>; output-ohms = <100000>; // 100k full-ohms = <(100000 + 1000000)>; // 100k + 1M power-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; }; }; &adc { status = "okay"; };
And the code in the sample has not been changed.
I use the SDK v2.9.0
From what I can trace, the compatible = "voltage-divider"; will configure the .config with DT_HAS_VOLTAGE_DIVIDER_ENABLED, therefore enabling the "voltage_divider" folder located in <zephyr/drivers/sensors/voltage_divider>.
The error comes from the file voltage.c, more specifically the initialisation function called by the macro DT_INST_FOREACH_STATUS_OKAY(VOLTAGE_INIT)static int voltage_init(const struct device *dev)
{
const struct voltage_config *config = dev->config;
struct voltage_data *data = dev->data;
int ret;
if (!adc_is_ready_dt(&config->voltage.port)) {
LOG_ERR("ADC is not ready");
return -ENODEV;
}
if (config->gpio_power.port != NULL) {
if (!gpio_is_ready_dt(&config->gpio_power)) {
LOG_ERR("Power GPIO is not ready");
return -ENODEV;
}
}
ret = adc_channel_setup_dt(&config->voltage.port);
if (ret != 0) {
LOG_ERR("setup: %d", ret);
return ret;
}
ret = adc_sequence_init_dt(&config->voltage.port, &data->sequence);
if (ret != 0) {
LOG_ERR("sequence init: %d", ret);
return ret;
}
data->sequence.buffer = &data->raw;
data->sequence.buffer_size = sizeof(data->raw);
return pm_device_driver_init(dev, pm_action);
}
#define VOLTAGE_INIT(inst) \
static struct voltage_data voltage_##inst##_data; \
\
static const struct voltage_config voltage_##inst##_config = { \
.voltage = VOLTAGE_DIVIDER_DT_SPEC_GET(DT_DRV_INST(inst)), \
.gpio_power = GPIO_DT_SPEC_INST_GET_OR(inst, power_gpios, {0}), \
}; \
\
PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, &voltage_init, PM_DEVICE_DT_INST_GET(inst), \
&voltage_##inst##_data, &voltage_##inst##_config, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &voltage_api);
DT_INST_FOREACH_STATUS_OKAY(VOLTAGE_INIT)
The function adc_channel_setup_dt(&config->voltage.port) will fail as it is called POST_KERNEL and the parameters of the ADC are not configured yet.
The driver for adc is <zephyr/drivers/adc/adc_nrfx_saadc> and the function:/* Implementation of the ADC driver API function: adc_channel_setup. */
static int adc_nrfx_channel_setup(const struct device *dev,
const struct adc_channel_cfg *channel_cfg)
{
...
}
implement the adc_channel_setup.
I'm not sure where the error is coming from next, but I guess fromint ret = adc_convert_acq_time(channel_cfg->acquisition_time, &config.acq_time);
as the acquisition time of the ADC has never been defined, and is done at run time in the sample (therefore at APPLICATION level and not POST_KERNEL).
Could you tell me why the ADC is not configured in the overlay file for something similar as:&adc {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
channel@0 {
reg = <0>;
zephyr,gain = "ADC_GAIN_1_6";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,input-positive = <NRF_SAADC_AIN2>;
zephyr,resolution = <12>;
};
};
I checked as well the board definiton for the Nordic Thingy52 and there is not definition for the ADC, therefore I guess the error is happening as well.
Please, let me know how to get rid of that error, and correct the sample if necessay.
Thank you.