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.

Fullscreen
1
2
3
4
5
6
7
8
9
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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


The overlay file is configure as explained in the sample:
Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
/{
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";
};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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)

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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:

Fullscreen
1
2
3
4
5
6
/* 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)
{
...
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


implement the adc_channel_setup.

I'm not sure where the error is coming from next, but I guess from
Fullscreen
1
int ret = adc_convert_acq_time(channel_cfg->acquisition_time, &config.acq_time);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
&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>;
};
};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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
  • Hi cbraissant,

    Could you please try using the adc_dt sample instead?
    https://github.com/nrfconnect/sdk-zephyr/tree/v3.7.99-ncs2/samples/drivers/adc/adc_dt

    Hieu

  • Hi Hileu, thanks for your answer.

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

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    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>;
    };
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


    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.

Reply Children
  • Hi Hieu, 

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

    Fullscreen
    1
    2
    3
    &adc {
    status = "okay";
    };
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


    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.

  • Hi cbraissant,

    My apology. I missed that ADC enable part.

    But the reason I don't think the channel configuration is necessary is because I ran a simple test with the nrf52840dk/nrf52840 target. I copy the vbatt node from thingy52_nrf52832.dts into an overlay file, and the sample runs just fine without any ADC channel configuration, as you can see in the adc node part of the compiled zephyr.dts here:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    adc: adc@40007000 {
    compatible = "nordic,nrf-saadc";
    reg = < 0x40007000 0x1000 >;
    interrupts = < 0x7 0x1 >;
    status = "okay";
    #io-channel-cells = < 0x1 >;
    phandle = < 0x1c >;
    };
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    I checked my project and it turns out that the voltage divider driver wasn't a part of the build. Instead, the ADC channel is setup in the sample's battery.c with a zero initialized configuration.

    Could you please check your project to see if voltage.c was actually used? If so, could you please share your project and custom board file? If the full files are confidential, a minimalized version to reproduce the issue would be enough.