Refactor VND7050AJ sensor configuration to eliminate redundancy

- Create centralized sensor multiplexer node (vnd7050aj_mux) with shared configuration
- Consolidate ADC channel, GPIO pins, and reference voltage in single location
- Update sensor bindings to reference centralized mux via sensor-mux property
- Add channel-based sensor selection using mux-channel property (0-3)
- Refactor ADC sensor library to use centralized GPIO and channel control
- Update valve library to use new vnd7050aj_mux node reference
- Eliminate duplicate ADC/GPIO definitions between voltage and current sensors
- Ensure configuration consistency and prevent mismatched settings

Benefits:
- Single source of truth for VND7050AJ hardware configuration
- Impossible to have inconsistent GPIO/ADC settings between sensors
- Simplified maintenance and scalability for additional sensors
- Clean channel-based multiplexer selection interface
This commit is contained in:
2025-07-08 17:05:34 +02:00
parent a9a0626913
commit 222ffea568
6 changed files with 185 additions and 240 deletions

View File

@@ -23,16 +23,30 @@ LOG_MODULE_REGISTER(adc_sensor, LOG_LEVEL_INF);
// Devicetree node checks
#define VOLTAGE_SENSOR_NODE DT_NODELABEL(supply_voltage)
#define CURRENT_SENSOR_NODE DT_NODELABEL(motor_current)
#define SENSOR_MUX_NODE DT_NODELABEL(vnd7050aj_mux)
#ifndef CONFIG_ADC_SENSOR_SIMULATED
// ADC device reference
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
#define ADC_NODE DT_PHANDLE(VOLTAGE_SENSOR_NODE, io_channels)
#define ADC_CHANNEL DT_PHA(VOLTAGE_SENSOR_NODE, io_channels, input)
// ADC device reference from centralized mux node
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
#define ADC_NODE DT_PHANDLE(SENSOR_MUX_NODE, io_channels)
#define ADC_CHANNEL DT_PHA(SENSOR_MUX_NODE, io_channels, input)
#define ADC_RESOLUTION 12
#define ADC_REFERENCE_MV DT_PROP(VOLTAGE_SENSOR_NODE, reference_mv)
#define ADC_REFERENCE_MV DT_PROP(SENSOR_MUX_NODE, reference_mv)
// Sensor-specific properties
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
#define VOLTAGE_DIVIDER_RATIO \
DT_PROP(VOLTAGE_SENSOR_NODE, voltage_divider_ratio)
#define VOLTAGE_MUX_CHANNEL DT_PROP(VOLTAGE_SENSOR_NODE, mux_channel)
#define VOLTAGE_DELAY_MS DT_PROP(VOLTAGE_SENSOR_NODE, measurement_delay_ms)
#endif
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
#define CURRENT_SENSE_RESISTOR_MOHM \
DT_PROP(CURRENT_SENSOR_NODE, current_sense_resistor_mohm)
#define CURRENT_MUX_CHANNEL DT_PROP(CURRENT_SENSOR_NODE, mux_channel)
#define CURRENT_DELAY_MS DT_PROP(CURRENT_SENSOR_NODE, measurement_delay_ms)
#endif
static const struct device *adc_dev;
static struct adc_channel_cfg adc_channel_cfg = {
@@ -55,81 +69,44 @@ static uint16_t adc_buffer;
static bool initialized = false;
#ifndef CONFIG_ADC_SENSOR_SIMULATED
// GPIO specs for voltage sensor (if devicetree nodes exist)
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
static const struct gpio_dt_spec voltage_sen_gpio =
GPIO_DT_SPEC_GET(VOLTAGE_SENSOR_NODE, sen_gpios);
static const struct gpio_dt_spec voltage_s0_gpio =
GPIO_DT_SPEC_GET(VOLTAGE_SENSOR_NODE, s0_gpios);
static const struct gpio_dt_spec voltage_s1_gpio =
GPIO_DT_SPEC_GET(VOLTAGE_SENSOR_NODE, s1_gpios);
#endif
// GPIO specs for current sensor (if devicetree nodes exist)
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
static const struct gpio_dt_spec current_sen_gpio =
GPIO_DT_SPEC_GET(CURRENT_SENSOR_NODE, sen_gpios);
static const struct gpio_dt_spec current_s0_gpio =
GPIO_DT_SPEC_GET(CURRENT_SENSOR_NODE, s0_gpios);
static const struct gpio_dt_spec current_s1_gpio =
GPIO_DT_SPEC_GET(CURRENT_SENSOR_NODE, s1_gpios);
// GPIO specs from centralized mux node
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
static const struct gpio_dt_spec sen_gpio =
GPIO_DT_SPEC_GET(SENSOR_MUX_NODE, sen_gpios);
static const struct gpio_dt_spec s0_gpio =
GPIO_DT_SPEC_GET(SENSOR_MUX_NODE, s0_gpios);
static const struct gpio_dt_spec s1_gpio =
GPIO_DT_SPEC_GET(SENSOR_MUX_NODE, s1_gpios);
#endif
/**
* @brief Configure GPIO pins for ADC sensor control
* @brief Configure GPIO pins for ADC sensor multiplexer control
*/
static int configure_sensor_gpios(void) {
int ret = 0;
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
// Configure voltage sensor GPIOs
if (gpio_is_ready_dt(&voltage_sen_gpio)) {
ret = gpio_pin_configure_dt(&voltage_sen_gpio, GPIO_OUTPUT_INACTIVE);
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
// Configure sensor multiplexer GPIOs
if (gpio_is_ready_dt(&sen_gpio)) {
ret = gpio_pin_configure_dt(&sen_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure voltage sen GPIO: %d", ret);
LOG_ERR("Failed to configure SEN GPIO: %d", ret);
return ret;
}
}
if (gpio_is_ready_dt(&voltage_s0_gpio)) {
ret = gpio_pin_configure_dt(&voltage_s0_gpio, GPIO_OUTPUT_INACTIVE);
if (gpio_is_ready_dt(&s0_gpio)) {
ret = gpio_pin_configure_dt(&s0_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure voltage s0 GPIO: %d", ret);
LOG_ERR("Failed to configure S0 GPIO: %d", ret);
return ret;
}
}
if (gpio_is_ready_dt(&voltage_s1_gpio)) {
ret = gpio_pin_configure_dt(&voltage_s1_gpio, GPIO_OUTPUT_INACTIVE);
if (gpio_is_ready_dt(&s1_gpio)) {
ret = gpio_pin_configure_dt(&s1_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure voltage s1 GPIO: %d", ret);
return ret;
}
}
#endif
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
// Configure current sensor GPIOs
if (gpio_is_ready_dt(&current_sen_gpio)) {
ret = gpio_pin_configure_dt(&current_sen_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure current sen GPIO: %d", ret);
return ret;
}
}
if (gpio_is_ready_dt(&current_s0_gpio)) {
ret = gpio_pin_configure_dt(&current_s0_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure current s0 GPIO: %d", ret);
return ret;
}
}
if (gpio_is_ready_dt(&current_s1_gpio)) {
ret = gpio_pin_configure_dt(&current_s1_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure current s1 GPIO: %d", ret);
LOG_ERR("Failed to configure S1 GPIO: %d", ret);
return ret;
}
}
@@ -139,55 +116,27 @@ static int configure_sensor_gpios(void) {
}
/**
* @brief Set GPIO pins for voltage measurement
* @param s0_state State for S0 pin (multiplexer bit 0)
* @param s1_state State for S1 pin (multiplexer bit 1)
* @brief Set multiplexer channel for sensor selection
* @param enable Enable/disable the sensor
* @param channel Multiplexer channel (0-3)
* @param delay_ms Delay after setting GPIOs
*/
static int set_voltage_sensor_gpios(bool enable, bool s0_state, bool s1_state) {
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
if (gpio_is_ready_dt(&voltage_sen_gpio)) {
gpio_pin_set_dt(&voltage_sen_gpio, enable ? 1 : 0);
static int set_mux_channel(bool enable, uint8_t channel, uint32_t delay_ms) {
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
if (gpio_is_ready_dt(&sen_gpio)) {
gpio_pin_set_dt(&sen_gpio, enable ? 1 : 0);
}
if (gpio_is_ready_dt(&voltage_s0_gpio)) {
gpio_pin_set_dt(&voltage_s0_gpio, s0_state ? 1 : 0);
if (gpio_is_ready_dt(&s0_gpio)) {
gpio_pin_set_dt(&s0_gpio, (channel & 0x01) ? 1 : 0);
}
if (gpio_is_ready_dt(&voltage_s1_gpio)) {
gpio_pin_set_dt(&voltage_s1_gpio, s1_state ? 1 : 0);
if (gpio_is_ready_dt(&s1_gpio)) {
gpio_pin_set_dt(&s1_gpio, (channel & 0x02) ? 1 : 0);
}
// Delay for GPIO settling (from devicetree or default)
#if DT_NODE_HAS_PROP(VOLTAGE_SENSOR_NODE, measurement_delay_ms)
k_msleep(DT_PROP(VOLTAGE_SENSOR_NODE, measurement_delay_ms));
#else
k_msleep(5); // Default 5ms delay
#endif
#endif
return 0;
}
/**
* @brief Set GPIO pins for current measurement
* @param s0_state State for S0 pin (multiplexer bit 0)
* @param s1_state State for S1 pin (multiplexer bit 1)
*/
static int set_current_sensor_gpios(bool enable, bool s0_state, bool s1_state) {
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
if (gpio_is_ready_dt(&current_sen_gpio)) {
gpio_pin_set_dt(&current_sen_gpio, enable ? 1 : 0);
// Delay for GPIO settling
if (delay_ms > 0) {
k_msleep(delay_ms);
}
if (gpio_is_ready_dt(&current_s0_gpio)) {
gpio_pin_set_dt(&current_s0_gpio, s0_state ? 1 : 0);
}
if (gpio_is_ready_dt(&current_s1_gpio)) {
gpio_pin_set_dt(&current_s1_gpio, s1_state ? 1 : 0);
}
// Delay for GPIO settling (from devicetree or default)
#if DT_NODE_HAS_PROP(CURRENT_SENSOR_NODE, measurement_delay_ms)
k_msleep(DT_PROP(CURRENT_SENSOR_NODE, measurement_delay_ms));
#else
k_msleep(10); // Default 10ms delay
#endif
#endif
return 0;
}
@@ -195,11 +144,11 @@ static int set_current_sensor_gpios(bool enable, bool s0_state, bool s1_state) {
#ifndef CONFIG_ADC_SENSOR_SIMULATED
/**
* @brief Read ADC value and convert to millivolts
* @brief Read ADC value and convert to millivolts (for voltage sensor)
* @return ADC reading in millivolts, or 0 on error
*/
static uint16_t read_adc_voltage_mv(void) {
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
#if DT_NODE_EXISTS(SENSOR_MUX_NODE) && DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
int ret = adc_read(adc_dev, &adc_sequence);
if (ret < 0) {
LOG_ERR("ADC read failed: %d", ret);
@@ -227,7 +176,7 @@ static uint16_t read_adc_voltage_mv(void) {
* @return ADC reading in milliamps, or 0 on error
*/
static uint16_t read_adc_current_ma(void) {
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
#if DT_NODE_EXISTS(SENSOR_MUX_NODE) && DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
int ret = adc_read(adc_dev, &adc_sequence);
if (ret < 0) {
LOG_ERR("ADC read failed: %d", ret);
@@ -238,10 +187,10 @@ static uint16_t read_adc_current_ma(void) {
uint32_t adc_value = adc_buffer;
uint32_t voltage_mv = (adc_value * ADC_REFERENCE_MV) / 4095;
// Convert voltage to current based on current sensor characteristics
// Assuming a linear current sensor with specific mV/mA ratio
// This will need to be calibrated for your specific current sensor
uint32_t current_ma = voltage_mv / 10; // Example: 10mV per mA
// Convert voltage to current based on sense resistor
// I = V / R, where R is in milliohms and V is in millivolts
// Result is in milliamps
uint32_t current_ma = (voltage_mv * 1000) / CURRENT_SENSE_RESISTOR_MOHM;
LOG_DBG("ADC raw: %u, current: %u mA", adc_value, (uint16_t)current_ma);
@@ -270,7 +219,7 @@ int adc_sensor_init(void) {
}
// Initialize ADC hardware
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
adc_dev = DEVICE_DT_GET(ADC_NODE);
if (!device_is_ready(adc_dev)) {
LOG_ERR("ADC device not ready");
@@ -288,13 +237,15 @@ int adc_sensor_init(void) {
LOG_INF("ADC device ready: %s", adc_dev->name);
#endif
LOG_INF("ADC sensor initialized (real ADC mode with GPIO control)");
LOG_INF("ADC sensor initialized (real ADC mode with centralized mux)");
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
LOG_INF("Voltage sensor found in devicetree");
LOG_INF("Voltage sensor: channel %d, divider ratio %d", VOLTAGE_MUX_CHANNEL,
VOLTAGE_DIVIDER_RATIO);
#endif
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
LOG_INF("Current sensor found in devicetree");
LOG_INF("Current sensor: channel %d, sense resistor %d mOhm",
CURRENT_MUX_CHANNEL, CURRENT_SENSE_RESISTOR_MOHM);
#endif
#endif
@@ -311,16 +262,20 @@ uint16_t adc_sensor_get_voltage_mv(void) {
#ifdef CONFIG_ADC_SENSOR_SIMULATED
return SIMULATED_VOLTAGE_MV;
#else
// Set GPIOs for voltage measurement (example: s0=0, s1=0 for channel 0)
set_voltage_sensor_gpios(true, false, false);
// Set multiplexer to voltage channel
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
set_mux_channel(true, VOLTAGE_MUX_CHANNEL, VOLTAGE_DELAY_MS);
// Read real ADC value for voltage
uint16_t voltage = read_adc_voltage_mv();
// Disable sensor after measurement to save power
set_voltage_sensor_gpios(false, false, false);
set_mux_channel(false, 0, 0);
return voltage;
#else
return 0;
#endif
#endif
}
@@ -333,15 +288,19 @@ uint16_t adc_sensor_get_current_ma(void) {
#ifdef CONFIG_ADC_SENSOR_SIMULATED
return SIMULATED_CURRENT_MA;
#else
// Set GPIOs for current measurement (example: s0=1, s1=0 for channel 1)
set_current_sensor_gpios(true, true, false);
// Set multiplexer to current channel
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
set_mux_channel(true, CURRENT_MUX_CHANNEL, CURRENT_DELAY_MS);
// Read real ADC value for current
uint16_t current = read_adc_current_ma();
// Disable sensor after measurement to save power
set_current_sensor_gpios(false, false, false);
set_mux_channel(false, 0, 0);
return current;
#else
return 0;
#endif
#endif
}