Battery Sample - runtime error "voltage: setup: -134"

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 from
int 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. 


Parents Reply
  • Hi Hieu, 

    I'm not runing a Thingy:52, but a custom board with a voltage divider, and therefore using the vbatt in devicetree as it's here for that.

    It's just not normal to have a error at runtime in a sample provided by Nordic, that's just that...
    I could work around it with the ADC, but the aim of my post was to understand the error and document it.
    If it's the wrong place and need to be done somewhere else (github), let me know.

Children
Related