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 Children
  • Hi Hileu, thanks for your answer.

    The adc sample works perfectly fine as the adc channel is properly configured in the devicetree:

    	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_AIN1>; /* P0.03 */
    		zephyr,resolution = <12>;
    	};


    My issue is linked to the fact that the vbatt doesn't configure properly the ADC.

  • Hi cbraissant,

    Right, my focus was to get you something that functions so that you can progress with your work. I am not entirely clear here. Can I understand that you have a working solution to achieve your goal yet?

    As for using the vbatt device driver, I don't have a Thingy device with me this week to try it. The Development Kits I have would have the adc nodes defined, but no vbatt node, and thus would fail even from building.

    Do I understand right that you run into this issue with the Thingy:52? Or are you using a custom board and custom files?

  • 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.

  • Hi cbraissant,

    I can see how you find it unusual that a sample

    Then please try to enable the ADC node. The thingy52/nrf52832 target actually does have the adc node. See https://github.com/nrfconnect/sdk-zephyr/blob/v3.7.99-ncs2-1/boards/nordic/thingy52/thingy52_nrf52832.dts#L112-L114.

    I think DT_INST_FOREACH_STATUS_OKAY causing trouble might be because your custom board file doesn't have an ADC node yet, rather than acquisition be ran before it is configured.

    As for where to report, this is a sample in the Zephyr part of the SDK, but one that is specific to Nordic board, so I would say either DevZone or the Zephyr RTOS GitHub repository are both good places to discuss it. We can continue here.

  • Hi Hieu, 

    I think you misunderstood the issue... The ADC node is activated in all cases mentionned above.

    &adc {
    	status = "okay";
    };
    


    The issue comes from the channel not being declared in the devicetree.

    My first post explain that fairly clearly and the ADC is mentioned in my devicetree. The issue is more linked to the lack of configuration for the zephyr,acquisition-time

    Please, read again the original post for the details.

Related