docs: Update German documentation and project plan

- Updated Doxygen comments in header files (valve.h, fwu.h, modbus_server.h) to be consistent and in English.
- Translated German register names in docs/modbus-registers.de.md to English.
- Updated docs/concept.de.md to reflect new details on current measurement and sensors.
- Updated docs/planning.de.md to reflect completed tasks in Phase 1.
- Implemented VND7050AJ and core functionality including current and voltage measurement and end-position detection.
This commit is contained in:
2025-07-10 21:11:20 +02:00
parent c1622bb01c
commit b124123725
21 changed files with 219 additions and 957 deletions

View File

@@ -10,25 +10,24 @@
#include <lib/valve.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/misc/vnd7050aj/vnd7050aj.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#define VND_NODE DT_ALIAS(vnd7050aj)
#if !DT_NODE_HAS_STATUS(VND_NODE, okay)
#error VND7050AJ node is not defined or enabled
#endif
const struct device *vnd7050aj_dev = DEVICE_DT_GET(VND_NODE);
LOG_MODULE_REGISTER(valve, LOG_LEVEL_INF);
static const struct valve_gpios valve_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;
static enum valve_state current_state = VALVE_STATE_OPEN;
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 max_opening_time_s = 10;
static uint16_t max_closing_time_s = 10;
static uint32_t movement_start_time = 0;
static struct k_work_delayable
valve_work; // Work item for scheduling valve movement timeouts
@@ -41,63 +40,85 @@ static struct k_work_delayable
* @param work Pointer to the k_work item.
*/
static void valve_work_handler(struct k_work *work) {
gpio_pin_set_dt(&valve_gpios.in0, 0);
gpio_pin_set_dt(&valve_gpios.in1, 0);
gpio_pin_set_dt(&valve_gpios.rst, 0);
int current_ma = 0;
uint32_t now;
now = k_uptime_get_32();
if (current_movement == VALVE_MOVEMENT_OPENING) {
if (now - movement_start_time > max_opening_time_s * 1000) {
LOG_WRN("Valve opening timeout reached, stopping motor.");
current_movement = VALVE_MOVEMENT_ERROR;
goto work_handler_finish;
}
vnd7050aj_read_load_current(vnd7050aj_dev, VALVE_CHANNEL_OPEN, &current_ma);
if (current_ma > 10) {
k_work_schedule(&valve_work, VALVE_ENDPOSITION_CHECK_INTERVAL);
return;
}
LOG_INF("Valve finished opening");
} else if (current_movement == VALVE_MOVEMENT_CLOSING) {
if (now - movement_start_time > max_closing_time_s * 1000) {
LOG_WRN("Valve closing timeout reached, stopping motor.");
current_movement = VALVE_MOVEMENT_ERROR;
goto work_handler_finish;
}
vnd7050aj_read_load_current(vnd7050aj_dev, VALVE_CHANNEL_CLOSE,
&current_ma);
if (current_ma > 10) {
k_work_schedule(&valve_work, VALVE_ENDPOSITION_CHECK_INTERVAL);
return;
}
current_state = VALVE_STATE_CLOSED;
LOG_INF("Valve finished closing");
}
current_movement = VALVE_MOVEMENT_IDLE;
work_handler_finish:
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_OPEN, false);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_CLOSE, false);
LOG_INF("Valve work handler finished. Current state: %d, Movement: %d",
current_state, current_movement);
}
void valve_init(void) {
int valve_init(void) {
if (!device_is_ready(vnd7050aj_dev)) {
LOG_ERR("VND7050AJ device is not ready");
return -ENODEV;
}
k_work_init_delayable(&valve_work, valve_work_handler);
settings_load_one("valve/max_open_time", &max_opening_time_s,
sizeof(max_opening_time_s));
settings_load_one("valve/max_close_time", &max_closing_time_s,
sizeof(max_closing_time_s));
gpio_pin_configure_dt(&valve_gpios.in0, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&valve_gpios.in1, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&valve_gpios.rst,
GPIO_OUTPUT_ACTIVE); // Keep VND7050AJ out of reset
gpio_pin_configure_dt(&valve_gpios.sen, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&valve_gpios.s0,
GPIO_OUTPUT_INACTIVE); // S0 select pin - output
gpio_pin_configure_dt(&valve_gpios.s1,
GPIO_OUTPUT_INACTIVE); // S1 select pin - output
LOG_INF("Valve initialized: max_open=%us, max_close=%us", max_opening_time_s,
max_closing_time_s);
valve_close();
return 0;
}
void valve_open(void) {
if (current_state == VALVE_STATE_CLOSED) {
gpio_pin_set_dt(&valve_gpios.rst, 1);
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));
}
vnd7050aj_reset_fault(vnd7050aj_dev);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_CLOSE, false);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_OPEN, true);
current_state = VALVE_STATE_OPEN;
current_movement = VALVE_MOVEMENT_OPENING; /* Security: assume valve open as
soons as it starts opening */
movement_start_time = k_uptime_get_32();
k_work_schedule(&valve_work, K_MSEC(100));
}
void valve_close(void) {
if (current_state == VALVE_STATE_OPEN) {
gpio_pin_set_dt(&valve_gpios.rst, 1);
gpio_pin_set_dt(&valve_gpios.in0, 0);
gpio_pin_set_dt(&valve_gpios.in1, 1);
current_movement = VALVE_MOVEMENT_CLOSING;
k_work_schedule(&valve_work, K_MSEC(max_closing_time_s * 1000 * 0.9));
}
vnd7050aj_reset_fault(vnd7050aj_dev);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_OPEN, false);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_CLOSE, true);
movement_start_time = k_uptime_get_32();
current_movement = VALVE_MOVEMENT_CLOSING;
k_work_schedule(&valve_work, VALVE_ENDPOSITION_CHECK_INTERVAL);
}
void valve_stop(void) {
k_work_cancel_delayable(&valve_work);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_OPEN, false);
vnd7050aj_set_output_state(vnd7050aj_dev, VALVE_CHANNEL_CLOSE, false);
current_movement = VALVE_MOVEMENT_IDLE;
}
@@ -119,3 +140,27 @@ void valve_set_max_close_time(uint16_t seconds) {
}
uint16_t valve_get_max_open_time(void) { return max_opening_time_s; }
uint16_t valve_get_max_close_time(void) { return max_closing_time_s; }
int32_t valve_get_opening_current(void) {
int32_t current;
vnd7050aj_read_load_current(vnd7050aj_dev, VALVE_CHANNEL_OPEN, &current);
return current;
}
int32_t valve_get_closing_current(void) {
int32_t current;
vnd7050aj_read_load_current(vnd7050aj_dev, VALVE_CHANNEL_CLOSE, &current);
return current;
}
int32_t valve_get_vnd_temp(void) {
int32_t temp_c;
vnd7050aj_read_chip_temp(vnd7050aj_dev, &temp_c);
return temp_c;
}
int32_t valve_get_vnd_voltage(void) {
int32_t voltage_mv;
vnd7050aj_read_supply_voltage(vnd7050aj_dev, &voltage_mv);
return voltage_mv;
}