sensor: voltage_divider: delay sampling after power-on

Enforce some minimum delay between enabling the voltage divider with a
GPIO and sampling the analog voltage. Without this delay the ADC can
easily sample the transient power up curve instead of the steady state
output.

Signed-off-by: Jordan Yates <jordan@embeint.com>
This commit is contained in:
Jordan Yates 2024-08-23 17:19:31 +10:00 committed by Anas Nashif
parent acbc14e767
commit 8f4cf7f6af
2 changed files with 21 additions and 0 deletions

View file

@ -18,10 +18,12 @@ LOG_MODULE_REGISTER(voltage, CONFIG_SENSOR_LOG_LEVEL);
struct voltage_config {
struct voltage_divider_dt_spec voltage;
struct gpio_dt_spec gpio_power;
uint32_t sample_delay_us;
};
struct voltage_data {
struct adc_sequence sequence;
k_timeout_t earliest_sample;
uint16_t raw;
};
@ -35,6 +37,9 @@ static int fetch(const struct device *dev, enum sensor_channel chan)
return -ENOTSUP;
}
/* Wait until sampling is valid */
k_sleep(data->earliest_sample);
ret = adc_read(config->voltage.port.dev, &data->sequence);
if (ret != 0) {
LOG_ERR("adc_read: %d", ret);
@ -90,6 +95,7 @@ static const struct sensor_driver_api voltage_api = {
static int pm_action(const struct device *dev, enum pm_device_action action)
{
const struct voltage_config *config = dev->config;
struct voltage_data *data = dev->data;
int ret = 0;
if (config->gpio_power.port == NULL) {
@ -109,6 +115,8 @@ static int pm_action(const struct device *dev, enum pm_device_action action)
if (ret != 0) {
LOG_ERR("failed to set GPIO for PM resume");
}
data->earliest_sample = K_TIMEOUT_ABS_TICKS(
k_uptime_ticks() + k_us_to_ticks_ceil32(config->sample_delay_us));
break;
#ifdef CONFIG_PM_DEVICE
case PM_DEVICE_ACTION_SUSPEND:
@ -133,6 +141,9 @@ static int voltage_init(const struct device *dev)
struct voltage_data *data = dev->data;
int ret;
/* Default value to use if `power-gpios` does not exist */
data->earliest_sample = K_TIMEOUT_ABS_TICKS(0);
if (!adc_is_ready_dt(&config->voltage.port)) {
LOG_ERR("ADC is not ready");
return -ENODEV;
@ -169,6 +180,7 @@ static int voltage_init(const struct device *dev)
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}), \
.sample_delay_us = DT_INST_PROP(inst, power_on_sample_delay_us), \
}; \
\
PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \

View file

@ -36,3 +36,12 @@ properties:
If present the corresponding GPIO must be set to an active level
to enable the divider input.
power-on-sample-delay-us:
type: int
default: 100
description: |
Duration to delay sampling after enabling the circuitry with
`power-gpios`. In most cases the switched voltage rail will
require some non-zero time to settle to its final value. The
default value of 100us should be sufficient in most situations.