122 lines
4.4 KiB
C
122 lines
4.4 KiB
C
/**
|
|
* @file valve.c
|
|
* @brief Implementation of the motorized valve control library.
|
|
*
|
|
* This file contains the logic for controlling a motorized valve using a
|
|
* VND7050AJ high-side driver. It uses a delayed work item to handle the
|
|
* safety timeouts for opening and closing operations.
|
|
*/
|
|
|
|
#include <lib/valve.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/drivers/gpio.h>
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/logging/log.h>
|
|
#include <zephyr/settings/settings.h>
|
|
|
|
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_movement current_movement = VALVE_MOVEMENT_IDLE;
|
|
static uint16_t max_opening_time_s = 60;
|
|
static uint16_t max_closing_time_s = 60;
|
|
static struct k_work_delayable
|
|
valve_work; // Work item for scheduling valve movement timeouts
|
|
|
|
/**
|
|
* @brief Work handler for valve movement timeouts.
|
|
*
|
|
* This function is executed when the valve's movement timer expires.
|
|
* It stops the motor to prevent damage and updates the valve's state.
|
|
*
|
|
* @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);
|
|
|
|
if (current_movement == VALVE_MOVEMENT_OPENING) {
|
|
LOG_INF("Valve finished opening");
|
|
} else if (current_movement == VALVE_MOVEMENT_CLOSING) {
|
|
current_state = VALVE_STATE_CLOSED;
|
|
LOG_INF("Valve finished closing");
|
|
}
|
|
current_movement = VALVE_MOVEMENT_IDLE;
|
|
}
|
|
|
|
void valve_init(void) {
|
|
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);
|
|
}
|
|
|
|
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);
|
|
current_state = VALVE_STATE_OPEN;
|
|
current_movement = VALVE_MOVEMENT_OPENING;
|
|
k_work_schedule(&valve_work, K_MSEC(max_opening_time_s * 1000 * 0.9));
|
|
}
|
|
}
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
void valve_stop(void) {
|
|
k_work_cancel_delayable(&valve_work);
|
|
current_movement = VALVE_MOVEMENT_IDLE;
|
|
}
|
|
|
|
enum valve_state valve_get_state(void) { return current_state; }
|
|
enum valve_movement valve_get_movement(void) { return current_movement; }
|
|
uint16_t valve_get_motor_current(void) {
|
|
return (current_movement != VALVE_MOVEMENT_IDLE) ? 150 : 10;
|
|
}
|
|
|
|
void valve_set_max_open_time(uint16_t seconds) {
|
|
max_opening_time_s = seconds;
|
|
settings_save_one("valve/max_open_time", &max_opening_time_s,
|
|
sizeof(max_opening_time_s));
|
|
}
|
|
void valve_set_max_close_time(uint16_t seconds) {
|
|
max_closing_time_s = seconds;
|
|
settings_save_one("valve/max_close_time", &max_closing_time_s,
|
|
sizeof(max_closing_time_s));
|
|
}
|
|
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; }
|