feat(valve): Implement virtual valve control

- Add Modbus registers for valve control according to the documentation.
- Implement a virtual valve logic that simulates the opening and closing process.
- The state of the valve can be read and controlled via Modbus.
- This serves as a software-only placeholder until the hardware is ready.
This commit is contained in:
Eduard Iten 2025-07-01 18:02:59 +02:00
parent 8cab3eecc1
commit e0007a9bd8
1 changed files with 56 additions and 2 deletions

View File

@ -22,6 +22,8 @@ LOG_MODULE_REGISTER(mbs_sample, LOG_LEVEL_INF);
#define APP_VERSION_PATCH 0 #define APP_VERSION_PATCH 0
enum { enum {
REG_INPUT_VALVE_STATE_MOVEMENT = 0x0000,
REG_INPUT_MOTOR_CURRENT_MA = 0x0001,
REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0, REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0,
REG_INPUT_FIRMWARE_VERSION_PATCH = 0x00F1, REG_INPUT_FIRMWARE_VERSION_PATCH = 0x00F1,
REG_INPUT_DEVICE_STATUS = 0x00F2, REG_INPUT_DEVICE_STATUS = 0x00F2,
@ -30,10 +32,28 @@ enum {
}; };
enum { enum {
REG_HOLDING_WATCHDOG_TIMEOUT_S = 0x00F0, REG_HOLDING_VALVE_COMMAND = 0x0000,
REG_HOLDING_MAX_OPENING_TIME_S = 0x0001,
REG_HOLDING_MAX_CLOSING_TIME_S = 0x0002,
REG_HOLDING_WATCHDOG_TIMEOUT_S = 0x00F0,
}; };
enum valve_state {
VALVE_STATE_CLOSED,
VALVE_STATE_OPEN,
};
enum valve_movement {
VALVE_MOVEMENT_IDLE,
VALVE_MOVEMENT_OPENING,
VALVE_MOVEMENT_CLOSING,
VALVE_MOVEMENT_ERROR,
};
static enum valve_state current_state = VALVE_STATE_CLOSED;
static enum valve_movement current_movement = VALVE_MOVEMENT_IDLE;
static uint16_t max_opening_time_s = 60;
static uint16_t max_closing_time_s = 60;
static uint16_t watchdog_timeout_s; static uint16_t watchdog_timeout_s;
static int modbus_iface; static int modbus_iface;
@ -66,6 +86,12 @@ static int coil_wr(uint16_t addr, bool state)
static int holding_reg_rd(uint16_t addr, uint16_t *reg) static int holding_reg_rd(uint16_t addr, uint16_t *reg)
{ {
switch (addr) { switch (addr) {
case REG_HOLDING_MAX_OPENING_TIME_S:
*reg = max_opening_time_s;
break;
case REG_HOLDING_MAX_CLOSING_TIME_S:
*reg = max_closing_time_s;
break;
case REG_HOLDING_WATCHDOG_TIMEOUT_S: case REG_HOLDING_WATCHDOG_TIMEOUT_S:
*reg = watchdog_timeout_s; *reg = watchdog_timeout_s;
break; break;
@ -81,6 +107,28 @@ static int holding_reg_rd(uint16_t addr, uint16_t *reg)
static int holding_reg_wr(uint16_t addr, uint16_t reg) static int holding_reg_wr(uint16_t addr, uint16_t reg)
{ {
switch (addr) { switch (addr) {
case REG_HOLDING_VALVE_COMMAND:
if (reg == 1) { /* Open */
current_movement = VALVE_MOVEMENT_OPENING;
LOG_INF("Virtual valve opening...");
current_state = VALVE_STATE_OPEN;
current_movement = VALVE_MOVEMENT_IDLE;
} else if (reg == 2) { /* Close */
current_movement = VALVE_MOVEMENT_CLOSING;
LOG_INF("Virtual valve closing...");
current_state = VALVE_STATE_CLOSED;
current_movement = VALVE_MOVEMENT_IDLE;
} else if (reg == 0) { /* Stop */
current_movement = VALVE_MOVEMENT_IDLE;
LOG_INF("Virtual valve movement stopped");
}
break;
case REG_HOLDING_MAX_OPENING_TIME_S:
max_opening_time_s = reg;
break;
case REG_HOLDING_MAX_CLOSING_TIME_S:
max_closing_time_s = reg;
break;
case REG_HOLDING_WATCHDOG_TIMEOUT_S: case REG_HOLDING_WATCHDOG_TIMEOUT_S:
watchdog_timeout_s = reg; watchdog_timeout_s = reg;
break; break;
@ -97,6 +145,12 @@ static int input_reg_rd(uint16_t addr, uint16_t *reg)
uint32_t uptime_s = k_uptime_get_32() / 1000; uint32_t uptime_s = k_uptime_get_32() / 1000;
switch (addr) { switch (addr) {
case REG_INPUT_VALVE_STATE_MOVEMENT:
*reg = (current_movement << 8) | (current_state & 0xFF);
break;
case REG_INPUT_MOTOR_CURRENT_MA:
*reg = 50; /* Dummy value */
break;
case REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR: case REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR:
*reg = (APP_VERSION_MAJOR << 8) | (APP_VERSION_MINOR & 0xFF); *reg = (APP_VERSION_MAJOR << 8) | (APP_VERSION_MINOR & 0xFF);
break; break;