Just saving

This commit is contained in:
Eduard Iten 2025-07-10 17:23:22 +02:00
parent 222ffea568
commit c1622bb01c
11 changed files with 352 additions and 104 deletions

View File

@ -1,23 +1,17 @@
#include <zephyr/dt-bindings/gpio/gpio.h>
/ {
/* VND7050AJ Sensor Multiplexer - Centralized configuration */
vnd7050aj_mux: sensor-multiplexer {
compatible = "vnd7050aj,sensor-mux";
vnd7050aj: vnd7050aj {
compatible = "vnd7050aj-valve-controller";
status = "okay";
/* Shared ADC configuration */
io-channels = <&adc1 1>; /* ADC1 channel 1 (PA0) */
io-channel-names = "sensor-input";
reference-mv = <3300>;
/* VND7050AJ GPIO pin definitions - shared by all sensors */
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - Sense Enable */
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - Mux select bit 0 */
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - Mux select bit 1 */
/* Valve control pins (separate from sensor mux) */
in0-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>; /* IN0 (PB7) - Valve input 0 */
in1-gpios = <&gpiob 9 GPIO_ACTIVE_HIGH>; /* IN1 (PB9) - Valve input 1 */
rst-gpios = <&gpiob 3 GPIO_ACTIVE_HIGH>; /* RST (PB3) - Reset pin */
// VND7050AJ GPIO pin definitions
in0-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>; // IN0 (PB7) - Input 0 control signal
in1-gpios = <&gpiob 9 GPIO_ACTIVE_HIGH>; // IN1 (PB9) - Input 1 control signal
rst-gpios = <&gpiob 3 GPIO_ACTIVE_HIGH>; // RST (PB3) - Reset pin for VND7050AJ
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; // SEN (PB4) - Sense Enable for current monitoring
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; // S0 (PB6) - Status/Select 0 output from VND7050AJ
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; // S1 (PB5) - Status/Select 1 output from VND7050AJ
};
adc_sensors {
@ -25,21 +19,48 @@
supply_voltage: supply-voltage {
compatible = "custom,supply-voltage";
sensor-mux = <&vnd7050aj_mux>; /* Reference to shared mux config */
/* Sensor-specific configuration */
io-channels = <&adc1 1>; /* ADC1 channel 1 (PA0) */
io-channel-names = "voltage";
reference-mv = <3300>;
voltage-divider-ratio = <4>; /* Adjust based on your voltage divider */
mux-channel = <0>; /* Channel 0: s1=0, s0=0 */
/* GPIO control pins using VND7050AJ pins */
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */
measurement-delay-ms = <5>; /* 5ms delay after GPIO setup */
};
motor_current: motor-current {
motor_current_open: motor-current-open {
compatible = "custom,motor-current";
sensor-mux = <&vnd7050aj_mux>; /* Reference to shared mux config */
io-channels = <&adc1 1>; /* Same ADC channel, different mux setting */
io-channel-names = "current";
reference-mv = <3300>;
current-sense-resistor-mohm = <1500000>; /* 1.5kΩ sense resistor in mΩ */
k-factor = <10>; /* Current sense amplification factor */
/* GPIO control pins using VND7050AJ pins */
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */
measurement-delay-ms = <10>; /* 10ms delay for current settling */
};
motor_current_close: motor-current-close {
compatible = "custom,motor-current";
io-channels = <&adc1 1>; /* Same ADC channel, different mux setting */
io-channel-names = "current";
reference-mv = <3300>;
current-sense-resistor-mohm = <1500000>; /* 1.5kΩ sense resistor in mΩ */
k-factor = <10>; /* Current sense amplification factor */
/* GPIO control pins using VND7050AJ pins */
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */
/* Sensor-specific configuration */
current-sense-resistor-mohm = <100>; /* 100mΩ sense resistor */
mux-channel = <1>; /* Channel 1: s1=0, s0=1 */
measurement-delay-ms = <10>; /* 10ms delay for current settling */
};
};

View File

@ -1,3 +1,78 @@
#include <zephyr/dt-bindings/gpio/gpio.h>
/ {
vnd7050aj: vnd7050aj {
compatible = "vnd7050aj-valve-controller";
status = "okay";
// VND7050AJ GPIO pin definitions
in0-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>; // IN0 (PB7) - Input 0 control signal
in1-gpios = <&gpiob 9 GPIO_ACTIVE_HIGH>; // IN1 (PB9) - Input 1 control signal
rst-gpios = <&gpiob 3 GPIO_ACTIVE_HIGH>; // RST (PB3) - Reset pin for VND7050AJ
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; // SEN (PB4) - Sense Enable for current monitoring
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; // S0 (PB6) - Status/Select 0 output from VND7050AJ
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; // S1 (PB5) - Status/Select 1 output from VND7050AJ
};
adc_sensors {
compatible = "adc-sensors";
supply_voltage: supply-voltage {
compatible = "custom,supply-voltage";
io-channels = <&adc1 1>; /* ADC1 channel 1 (PA0) */
io-channel-names = "voltage";
reference-mv = <3300>;
voltage-divider-ratio = <4>; /* Adjust based on your voltage divider */
sensor-mux = <&vnd7050aj>; /* Reference to VND7050AJ mux */
mux-channel = <3>; /* VCC sense channel */
measurement-delay-ms = <5>; /* 5ms delay after GPIO setup */
};
motor_current_open: motor-current-open {
compatible = "custom,motor-current";
io-channels = <&adc1 1>; /* Same ADC channel, different mux setting */
io-channel-names = "current";
reference-mv = <3300>;
current-sense-resistor-mohm = <1500000>; /* 1.5kΩ sense resistor in mΩ */
k-factor = <10>; /* Current sense amplification factor */
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */
measurement-delay-ms = <10>; /* 10ms delay for current settling */
};
motor_current_close: motor-current-close {
compatible = "custom,motor-current";
io-channels = <&adc1 1>; /* Same ADC channel, different mux setting */
io-channel-names = "current";
reference-mv = <3300>;
current-sense-resistor-mohm = <1500000>; /* 1.5kΩ sense resistor in mΩ */
k-factor = <10>; /* Current sense amplification factor */
sen-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>; /* SEN (PB4) - enable sensor */
s0-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; /* S0 (PB6) - mux select bit 0 */
s1-gpios = <&gpiob 5 GPIO_ACTIVE_HIGH>; /* S1 (PB5) - mux select bit 1 */
measurement-delay-ms = <10>; /* 10ms delay for current settling */
};
};
};
&adc1 { // ADC1 wird für PA0 verwendet
status = "okay"; // ADC1 aktivieren
pinctrl-0 = <&adc1_in1_pa0>; // Pinmux für PA0 als ADC1_IN1
pinctrl-names = "default";
st,adc-clock-source = "SYNC";
st,adc-prescaler = <4>;
#address-cells = <1>;
#size-cells = <0>;
};
&pinctrl {
// Pinmux für PA0 als ADC1_IN1 (Analogmodus)
adc1_in1_pa0: adc1_in1_pa0 {
pinmux = <STM32_PINMUX('A', 0, ANALOG)>; // PA0 in den Analogmodus setzen
};
};
&zephyr_udc0 {
cdc_acm_uart0: cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";

View File

@ -4,29 +4,48 @@ description: Motor current sensor using VND7050AJ multiplexer
compatible: "custom,motor-current"
properties:
sensor-mux:
type: phandle
io-channels:
type: phandle-array
required: true
description: Reference to the VND7050AJ sensor multiplexer node
description: ADC channel phandle and specifier
io-channel-names:
type: string-array
required: true
description: Names for the ADC channels
reference-mv:
type: int
required: true
description: ADC reference voltage in millivolts
current-sense-resistor-mohm:
type: int
required: true
description: Current sense resistor value in milliohms
amplifier-gain:
type: int
required: false
default: 1
description: Current sense amplifier gain
mux-channel:
k-factor:
type: int
required: true
description: Multiplexer channel number (0-3) for this sensor
description: Current sense amplification factor for VND7050AJ
sen-gpios:
type: phandle-array
required: true
description: GPIO for sensor enable (SEN pin)
s0-gpios:
type: phandle-array
required: true
description: GPIO for multiplexer select bit 0 (S0 pin)
s1-gpios:
type: phandle-array
required: true
description: GPIO for multiplexer select bit 1 (S1 pin)
measurement-delay-ms:
type: int
required: false
default: 10
description: Delay in milliseconds after GPIO setup before measurement
description: Delay in milliseconds after setting GPIO pins before reading ADC

View File

@ -4,6 +4,21 @@ description: Supply voltage sensor using VND7050AJ multiplexer
compatible: "custom,supply-voltage"
properties:
io-channels:
type: phandle-array
required: true
description: ADC channel phandle and specifier
io-channel-names:
type: string-array
required: true
description: Names for the ADC channels
reference-mv:
type: int
required: true
description: ADC reference voltage in millivolts
sensor-mux:
type: phandle
required: true

View File

@ -48,3 +48,13 @@ properties:
type: phandle-array
required: false
description: GPIO for reset control (RST pin)
sense-resistor-ohm:
type: int
required: true
description: Current sense resistor value in ohms
k-factor:
type: int
required: true
description: Current sense ratio for VND7050AJ (typical ~1200:1)

View File

@ -34,13 +34,34 @@ int adc_sensor_init(void);
uint16_t adc_sensor_get_voltage_mv(void);
/**
* @brief Gets the current motor current reading.
* @brief Gets the current motor current reading (legacy function).
*
* This function reads the value from the motor driver's sense pin via ADC
* and converts it to milliamps. This is used for end-stop detection.
* This function reads the current from the opening channel (IN0).
* For backward compatibility only. Use adc_sensor_get_current_open_ma()
* instead.
*
* @return The motor current in milliamps (mA).
*/
uint16_t adc_sensor_get_current_ma(void);
/**
* @brief Gets the motor opening current reading (IN0 current sense).
*
* This function reads the current from the VND7050AJ IN0 current sense channel.
* Used for monitoring valve opening current.
*
* @return The motor opening current in milliamps (mA).
*/
uint16_t adc_sensor_get_current_open_ma(void);
/**
* @brief Gets the motor closing current reading (IN1 current sense).
*
* This function reads the current from the VND7050AJ IN1 current sense channel.
* Used for monitoring valve closing current.
*
* @return The motor closing current in milliamps (mA).
*/
uint16_t adc_sensor_get_current_close_ma(void);
#endif /* ADC_SENSOR_H */

View File

@ -23,9 +23,13 @@ enum {
*/
REG_INPUT_VALVE_STATE_MOVEMENT = 0x0000,
/**
* @brief Aktueller Motorstrom in Milliampere (mA).
* @brief Motorstrom beim Öffnen in Milliampere (mA) - IN0 current sense.
*/
REG_INPUT_MOTOR_CURRENT_MA = 0x0001,
REG_INPUT_MOTOR_OPEN_CURRENT_MA = 0x0001,
/**
* @brief Motorstrom beim Schließen in Milliampere (mA) - IN1 current sense.
*/
REG_INPUT_MOTOR_CLOSE_CURRENT_MA = 0x0002,
/**
* @brief Bitmaske der digitalen Eingänge. Bit 0: Eingang 1, Bit 1: Eingang 2.
* 1=Aktiv.

View File

@ -22,30 +22,40 @@ 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)
#define CURRENT_OPEN_SENSOR_NODE DT_NODELABEL(motor_current_open)
#define CURRENT_CLOSE_SENSOR_NODE DT_NODELABEL(motor_current_close)
#define VND7050AJ_NODE DT_NODELABEL(vnd7050aj)
#ifndef CONFIG_ADC_SENSOR_SIMULATED
// 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(SENSOR_MUX_NODE, reference_mv)
// ADC device reference from voltage sensor node (all sensors use same ADC)
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
#define ADC_NODE DT_PHANDLE(VOLTAGE_SENSOR_NODE, io_channels)
#define ADC_REFERENCE_MV DT_PROP(VOLTAGE_SENSOR_NODE, reference_mv)
#endif
#define ADC_CHANNEL 1 /* ADC1 channel 1 as defined in overlay */
// 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)
#if DT_NODE_EXISTS(CURRENT_OPEN_SENSOR_NODE)
#define CURRENT_OPEN_SENSE_RESISTOR_MOHM \
DT_PROP(CURRENT_OPEN_SENSOR_NODE, current_sense_resistor_mohm)
#define CURRENT_OPEN_K_FACTOR DT_PROP(CURRENT_OPEN_SENSOR_NODE, k_factor)
#define CURRENT_OPEN_DELAY_MS \
DT_PROP(CURRENT_OPEN_SENSOR_NODE, measurement_delay_ms)
#endif
#if DT_NODE_EXISTS(CURRENT_CLOSE_SENSOR_NODE)
#define CURRENT_CLOSE_SENSE_RESISTOR_MOHM \
DT_PROP(CURRENT_CLOSE_SENSOR_NODE, current_sense_resistor_mohm)
#define CURRENT_CLOSE_K_FACTOR DT_PROP(CURRENT_CLOSE_SENSOR_NODE, k_factor)
#define CURRENT_CLOSE_DELAY_MS \
DT_PROP(CURRENT_CLOSE_SENSOR_NODE, measurement_delay_ms)
#endif
static const struct device *adc_dev;
@ -59,24 +69,23 @@ static struct adc_channel_cfg adc_channel_cfg = {
static struct adc_sequence adc_sequence = {
.channels = BIT(ADC_CHANNEL),
.buffer_size = sizeof(uint16_t),
.resolution = ADC_RESOLUTION,
.resolution = 12,
};
static uint16_t adc_buffer;
#endif
#endif
static bool initialized = false;
#ifndef CONFIG_ADC_SENSOR_SIMULATED
// GPIO specs from centralized mux node
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
// GPIO specs from VND7050AJ node
#if DT_NODE_EXISTS(VND7050AJ_NODE)
static const struct gpio_dt_spec sen_gpio =
GPIO_DT_SPEC_GET(SENSOR_MUX_NODE, sen_gpios);
GPIO_DT_SPEC_GET(VND7050AJ_NODE, sen_gpios);
static const struct gpio_dt_spec s0_gpio =
GPIO_DT_SPEC_GET(SENSOR_MUX_NODE, s0_gpios);
GPIO_DT_SPEC_GET(VND7050AJ_NODE, s0_gpios);
static const struct gpio_dt_spec s1_gpio =
GPIO_DT_SPEC_GET(SENSOR_MUX_NODE, s1_gpios);
GPIO_DT_SPEC_GET(VND7050AJ_NODE, s1_gpios);
#endif
/**
@ -85,7 +94,7 @@ static const struct gpio_dt_spec s1_gpio =
static int configure_sensor_gpios(void) {
int ret = 0;
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
#if DT_NODE_EXISTS(VND7050AJ_NODE)
// Configure sensor multiplexer GPIOs
if (gpio_is_ready_dt(&sen_gpio)) {
ret = gpio_pin_configure_dt(&sen_gpio, GPIO_OUTPUT_INACTIVE);
@ -122,7 +131,7 @@ static int configure_sensor_gpios(void) {
* @param delay_ms Delay after setting GPIOs
*/
static int set_mux_channel(bool enable, uint8_t channel, uint32_t delay_ms) {
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
#if DT_NODE_EXISTS(VND7050AJ_NODE)
if (gpio_is_ready_dt(&sen_gpio)) {
gpio_pin_set_dt(&sen_gpio, enable ? 1 : 0);
}
@ -148,7 +157,7 @@ static int set_mux_channel(bool enable, uint8_t channel, uint32_t delay_ms) {
* @return ADC reading in millivolts, or 0 on error
*/
static uint16_t read_adc_voltage_mv(void) {
#if DT_NODE_EXISTS(SENSOR_MUX_NODE) && DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
int ret = adc_read(adc_dev, &adc_sequence);
if (ret < 0) {
LOG_ERR("ADC read failed: %d", ret);
@ -172,11 +181,11 @@ static uint16_t read_adc_voltage_mv(void) {
}
/**
* @brief Read ADC value and convert to milliamps (for current sensor)
* @brief Read ADC value and convert to milliamps for opening current
* @return ADC reading in milliamps, or 0 on error
*/
static uint16_t read_adc_current_ma(void) {
#if DT_NODE_EXISTS(SENSOR_MUX_NODE) && DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
static uint16_t read_adc_current_open_ma(void) {
#if DT_NODE_EXISTS(CURRENT_OPEN_SENSOR_NODE)
int ret = adc_read(adc_dev, &adc_sequence);
if (ret < 0) {
LOG_ERR("ADC read failed: %d", ret);
@ -187,12 +196,45 @@ 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 sense resistor
// I = V / R, where R is in milliohms and V is in millivolts
// VND7050AJ current calculation: I = V_sense * K / R_sense
// Where: V_sense in mV, K is the current sense factor, R_sense in mΩ
// Result is in milliamps
uint32_t current_ma = (voltage_mv * 1000) / CURRENT_SENSE_RESISTOR_MOHM;
uint32_t current_ma = (voltage_mv * CURRENT_OPEN_K_FACTOR * 1000) /
CURRENT_OPEN_SENSE_RESISTOR_MOHM;
LOG_DBG("ADC raw: %u, current: %u mA", adc_value, (uint16_t)current_ma);
LOG_DBG("Open current - ADC raw: %u, voltage: %u mV, current: %u mA",
adc_value, voltage_mv, (uint16_t)current_ma);
return (uint16_t)current_ma;
#else
return 0;
#endif
}
/**
* @brief Read ADC value and convert to milliamps for closing current
* @return ADC reading in milliamps, or 0 on error
*/
static uint16_t read_adc_current_close_ma(void) {
#if DT_NODE_EXISTS(CURRENT_CLOSE_SENSOR_NODE)
int ret = adc_read(adc_dev, &adc_sequence);
if (ret < 0) {
LOG_ERR("ADC read failed: %d", ret);
return 0;
}
// Convert ADC reading to millivolts first
uint32_t adc_value = adc_buffer;
uint32_t voltage_mv = (adc_value * ADC_REFERENCE_MV) / 4095;
// VND7050AJ current calculation: I = V_sense * K / R_sense
// Where: V_sense in mV, K is the current sense factor, R_sense in mΩ
// Result is in milliamps
uint32_t current_ma = (voltage_mv * CURRENT_CLOSE_K_FACTOR * 1000) /
CURRENT_CLOSE_SENSE_RESISTOR_MOHM;
LOG_DBG("Close current - ADC raw: %u, voltage: %u mV, current: %u mA",
adc_value, voltage_mv, (uint16_t)current_ma);
return (uint16_t)current_ma;
#else
@ -219,7 +261,7 @@ int adc_sensor_init(void) {
}
// Initialize ADC hardware
#if DT_NODE_EXISTS(SENSOR_MUX_NODE)
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
adc_dev = DEVICE_DT_GET(ADC_NODE);
if (!device_is_ready(adc_dev)) {
LOG_ERR("ADC device not ready");
@ -237,15 +279,18 @@ int adc_sensor_init(void) {
LOG_INF("ADC device ready: %s", adc_dev->name);
#endif
LOG_INF("ADC sensor initialized (real ADC mode with centralized mux)");
LOG_INF("ADC sensor initialized (real ADC mode)");
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
LOG_INF("Voltage sensor: channel %d, divider ratio %d", VOLTAGE_MUX_CHANNEL,
VOLTAGE_DIVIDER_RATIO);
LOG_INF("Voltage sensor: divider ratio %d", VOLTAGE_DIVIDER_RATIO);
#endif
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
LOG_INF("Current sensor: channel %d, sense resistor %d mOhm",
CURRENT_MUX_CHANNEL, CURRENT_SENSE_RESISTOR_MOHM);
#if DT_NODE_EXISTS(CURRENT_OPEN_SENSOR_NODE)
LOG_INF("Open current sensor: K-factor %d, sense resistor %d mΩ",
CURRENT_OPEN_K_FACTOR, CURRENT_OPEN_SENSE_RESISTOR_MOHM);
#endif
#if DT_NODE_EXISTS(CURRENT_CLOSE_SENSOR_NODE)
LOG_INF("Close current sensor: K-factor %d, sense resistor %d mΩ",
CURRENT_CLOSE_K_FACTOR, CURRENT_CLOSE_SENSE_RESISTOR_MOHM);
#endif
#endif
@ -262,9 +307,9 @@ uint16_t adc_sensor_get_voltage_mv(void) {
#ifdef CONFIG_ADC_SENSOR_SIMULATED
return SIMULATED_VOLTAGE_MV;
#else
// Set multiplexer to voltage channel
// Set multiplexer to voltage channel (channel 3: VCC sense)
#if DT_NODE_EXISTS(VOLTAGE_SENSOR_NODE)
set_mux_channel(true, VOLTAGE_MUX_CHANNEL, VOLTAGE_DELAY_MS);
set_mux_channel(true, 3, VOLTAGE_DELAY_MS);
// Read real ADC value for voltage
uint16_t voltage = read_adc_voltage_mv();
@ -280,6 +325,11 @@ uint16_t adc_sensor_get_voltage_mv(void) {
}
uint16_t adc_sensor_get_current_ma(void) {
// Legacy function - redirect to opening current for backward compatibility
return adc_sensor_get_current_open_ma();
}
uint16_t adc_sensor_get_current_open_ma(void) {
if (!initialized) {
LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()");
adc_sensor_init();
@ -288,12 +338,38 @@ uint16_t adc_sensor_get_current_ma(void) {
#ifdef CONFIG_ADC_SENSOR_SIMULATED
return SIMULATED_CURRENT_MA;
#else
// Set multiplexer to current channel
#if DT_NODE_EXISTS(CURRENT_SENSOR_NODE)
set_mux_channel(true, CURRENT_MUX_CHANNEL, CURRENT_DELAY_MS);
// Set multiplexer to IN0 current sense channel (channel 0)
#if DT_NODE_EXISTS(CURRENT_OPEN_SENSOR_NODE)
set_mux_channel(true, 0, CURRENT_OPEN_DELAY_MS);
// Read real ADC value for current
uint16_t current = read_adc_current_ma();
uint16_t current = read_adc_current_open_ma();
// Disable sensor after measurement to save power
set_mux_channel(false, 0, 0);
return current;
#else
return 0;
#endif
#endif
}
uint16_t adc_sensor_get_current_close_ma(void) {
if (!initialized) {
LOG_WRN("ADC sensor not initialized, calling adc_sensor_init()");
adc_sensor_init();
}
#ifdef CONFIG_ADC_SENSOR_SIMULATED
return SIMULATED_CURRENT_MA;
#else
// Set multiplexer to IN1 current sense channel (channel 1)
#if DT_NODE_EXISTS(CURRENT_CLOSE_SENSOR_NODE)
set_mux_channel(true, 1, CURRENT_CLOSE_DELAY_MS);
// Read real ADC value for current
uint16_t current = read_adc_current_close_ma();
// Disable sensor after measurement to save power
set_mux_channel(false, 0, 0);

View File

@ -147,8 +147,11 @@ static int input_reg_rd(uint16_t addr, uint16_t *reg) {
case REG_INPUT_VALVE_STATE_MOVEMENT:
*reg = (valve_get_movement() << 8) | (valve_get_state() & 0xFF);
break;
case REG_INPUT_MOTOR_CURRENT_MA:
*reg = adc_sensor_get_current_ma();
case REG_INPUT_MOTOR_OPEN_CURRENT_MA:
*reg = adc_sensor_get_current_open_ma();
break;
case REG_INPUT_MOTOR_CLOSE_CURRENT_MA:
*reg = adc_sensor_get_current_close_ma();
break;
case REG_INPUT_UPTIME_SECONDS_LOW:
*reg = (uint16_t)(uptime_s & 0xFFFF);

View File

@ -17,12 +17,12 @@
LOG_MODULE_REGISTER(valve, LOG_LEVEL_INF);
static const struct valve_gpios valve_gpios = {
.in0 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj_mux), in0_gpios),
.in1 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj_mux), in1_gpios),
.rst = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj_mux), rst_gpios),
.sen = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj_mux), sen_gpios),
.s0 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj_mux), s0_gpios),
.s1 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj_mux), s1_gpios),
.in0 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj), in0_gpios),
.in1 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj), in1_gpios),
.rst = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj), rst_gpios),
.sen = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj), sen_gpios),
.s0 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj), s0_gpios),
.s1 = GPIO_DT_SPEC_GET(DT_NODELABEL(vnd7050aj), s1_gpios),
};
static enum valve_state current_state = VALVE_STATE_CLOSED;
@ -78,8 +78,8 @@ void valve_init(void) {
void valve_open(void) {
if (current_state == VALVE_STATE_CLOSED) {
gpio_pin_set_dt(&valve_gpios.rst, 1);
gpio_pin_set_dt(&valve_gpios.in1, 0);
gpio_pin_set_dt(&valve_gpios.in0, 1);
gpio_pin_set_dt(&valve_gpios.in1, 0);
current_state = VALVE_STATE_OPEN;
current_movement = VALVE_MOVEMENT_OPENING;
k_work_schedule(&valve_work, K_MSEC(max_opening_time_s * 1000 * 0.9));

View File

@ -11,7 +11,8 @@ from pymodbus.exceptions import ModbusException
# --- Register Definitions ---
# (omitted for brevity, no changes here)
REG_INPUT_VALVE_STATE_MOVEMENT = 0x0000
REG_INPUT_MOTOR_CURRENT_MA = 0x0001
REG_INPUT_MOTOR_OPEN_CURRENT_MA = 0x0001
REG_INPUT_MOTOR_CLOSE_CURRENT_MA = 0x0002
REG_INPUT_DIGITAL_INPUTS_STATE = 0x0020
REG_INPUT_BUTTON_EVENTS = 0x0021
REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0
@ -83,14 +84,15 @@ def poll_status(slave_id, interval):
continue
# If connected, try to read data
ir_valve = client.read_input_registers(REG_INPUT_VALVE_STATE_MOVEMENT, count=2, slave=slave_id)
ir_valve = client.read_input_registers(REG_INPUT_VALVE_STATE_MOVEMENT, count=1, slave=slave_id)
ir_current = client.read_input_registers(REG_INPUT_MOTOR_OPEN_CURRENT_MA, count=2, slave=slave_id)
ir_dig = client.read_input_registers(REG_INPUT_DIGITAL_INPUTS_STATE, count=2, slave=slave_id)
ir_sys = client.read_input_registers(REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR, count=6, slave=slave_id)
hr_valve = client.read_holding_registers(REG_HOLDING_MAX_OPENING_TIME_S, count=2, slave=slave_id)
hr_dig = client.read_holding_registers(REG_HOLDING_DIGITAL_OUTPUTS_STATE, count=1, slave=slave_id)
hr_sys = client.read_holding_registers(REG_HOLDING_WATCHDOG_TIMEOUT_S, count=1, slave=slave_id)
for res in [ir_valve, ir_dig, ir_sys, hr_valve, hr_dig, hr_sys]:
for res in [ir_valve, ir_current, ir_dig, ir_sys, hr_valve, hr_dig, hr_sys]:
if res.isError():
raise ModbusException(str(res))
@ -99,7 +101,8 @@ def poll_status(slave_id, interval):
state_map = {0: "Closed", 1: "Open"}
new_data["movement"] = movement_map.get(valve_state_raw >> 8, 'Unknown')
new_data["state"] = state_map.get(valve_state_raw & 0xFF, 'Unknown')
new_data["motor_current"] = f"{ir_valve.registers[1]} mA"
new_data["motor_current_open"] = f"{ir_current.registers[0]} mA"
new_data["motor_current_close"] = f"{ir_current.registers[1]} mA"
new_data["open_time"] = f"{hr_valve.registers[0]}s"
new_data["close_time"] = f"{hr_valve.registers[1]}s"
new_data["digital_inputs"] = f"0x{ir_dig.registers[0]:04X}"
@ -295,7 +298,8 @@ def main_menu(stdscr, slave_id):
col1, col2, col3, col4 = 2, 30, 58, 88
stdscr.addstr(1, col1, "State:", bold); stdscr.addstr(1, col1 + 18, str(current_data.get('state', 'N/A')), normal)
stdscr.addstr(2, col1, "Movement:", bold); stdscr.addstr(2, col1 + 18, str(current_data.get('movement', 'N/A')), normal)
stdscr.addstr(3, col1, "Motor Current:", bold); stdscr.addstr(3, col1 + 18, str(current_data.get('motor_current', 'N/A')), normal)
stdscr.addstr(3, col1, "Open Current:", bold); stdscr.addstr(3, col1 + 18, str(current_data.get('motor_current_open', 'N/A')), normal)
stdscr.addstr(4, col1, "Close Current:", bold); stdscr.addstr(4, col1 + 18, str(current_data.get('motor_current_close', 'N/A')), normal)
stdscr.addstr(1, col2, "Digital Inputs:", bold); stdscr.addstr(1, col2 + 18, str(current_data.get('digital_inputs', 'N/A')), normal)
stdscr.addstr(2, col2, "Digital Outputs:", bold); stdscr.addstr(2, col2 + 18, str(current_data.get('digital_outputs', 'N/A')), normal)
stdscr.addstr(3, col2, "Button Events:", bold); stdscr.addstr(3, col2 + 18, str(current_data.get('button_events', 'N/A')), normal)
@ -306,7 +310,7 @@ def main_menu(stdscr, slave_id):
stdscr.addstr(2, col4, "Uptime:", bold); stdscr.addstr(2, col4 + 14, str(current_data.get('uptime', 'N/A')), normal)
stdscr.addstr(3, col4, "Dev. Status:", bold); stdscr.addstr(3, col4 + 14, str(current_data.get('device_status', 'N/A')), normal)
stdscr.addstr(4, col4, "Supply V:", bold); stdscr.addstr(4, col4 + 14, str(current_data.get('supply_voltage', 'N/A')), normal)
stdscr.addstr(5, 0, "" * (w - 1), normal)
stdscr.addstr(6, 0, "" * (w - 1), normal)
for idx, row in enumerate(menu):
draw_button(stdscr, h // 2 - len(menu) + (idx * 2), w // 2 - len(row) // 2, row, idx == current_row_idx)
if time.time() - message_time < 2.0: stdscr.addstr(h - 2, 0, message.ljust(w - 1), curses.color_pair(1) | curses.A_BOLD)