Files
CCSModuleSW30Web/Core/Src/lock.c

170 lines
5.6 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* lock.c
*
* Created on: Jul 31, 2024
* Author: colorbass
*/
#include "lock.h"
#include "debug.h"
uint8_t LOCK_POLARITY = 1; // 1 for v1
uint8_t LOCK_MOTOR_POLARITY = 1;
uint16_t LOCK_DELAY = 100;
GBT_LockState_t GBT_LockState = {
.demand = 0,
.error = 0,
.action_requested = 255, // нет запрошенного действия
.motor_state = 0, // idle
.last_action_time = 0,
.retry_count = 0,
.error_tick = 0
};
void GBT_ForceLock(uint8_t state){
// Устанавливаем флаг для выполнения действия
GBT_LockState.action_requested = state ? 1 : 0;
GBT_LockState.retry_count = 0;
}
uint8_t GBT_LockGetState(){
//1 = locked
//0 = unlocked
if(LOCK_POLARITY){
return HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
}else{
return !HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
}
}
void GBT_Lock(uint8_t state){
GBT_LockState.demand = state;
}
void GBT_ManageLockSolenoid(){
static uint32_t tick;
if(HAL_GetTick() - tick < 50) return;
tick = HAL_GetTick();
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, GBT_LockState.demand ? 1 : 0);
}
void GBT_ManageLockMotor(){
static const uint8_t MAX_RETRIES = 5;
uint32_t current_tick = HAL_GetTick();
// Проверяем таймаут сброса ошибки (до проверки error, чтобы можно было сбросить)
GBT_ResetErrorTimeout();
if (GBT_LockState.error) {
return;
}
// Проверяем, нужно ли выполнить действие
bool lock_is_open = GBT_LockGetState() == 0;
bool lock_should_be_open = GBT_LockState.demand == 0;
// Если есть запрошенное действие или состояние не соответствует требуемому
if (GBT_LockState.action_requested != 255 || (lock_is_open != lock_should_be_open)) {
// Если действие еще не запрошено, запрашиваем его
if (GBT_LockState.action_requested == 255) {
GBT_LockState.action_requested = lock_should_be_open ? 0 : 1;
GBT_LockState.retry_count = 0;
}
// Управление мотором через машину состояний
switch (GBT_LockState.motor_state) {
case 0: // idle - мотор выключен
// Определяем, какой пин нужно включить
if (LOCK_MOTOR_POLARITY) {
if (GBT_LockState.action_requested == 1) { // LOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
} else { // UNLOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
}
} else {
if (GBT_LockState.action_requested == 1) { // LOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
} else { // UNLOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
}
}
GBT_LockState.motor_state = 1; // motor_on
GBT_LockState.last_action_time = current_tick;
break;
case 1: // motor_on - мотор включен, ждем LOCK_DELAY
if (current_tick - GBT_LockState.last_action_time >= LOCK_DELAY) {
// Выключаем оба пина
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
GBT_LockState.motor_state = 2; // waiting_off
GBT_LockState.last_action_time = current_tick;
}
break;
case 2: // waiting_off - ждем немного перед проверкой состояния
// Небольшая задержка перед проверкой состояния (например, 50мс)
if (current_tick - GBT_LockState.last_action_time >= 50) {
// Проверяем, достигнуто ли требуемое состояние
lock_is_open = GBT_LockGetState() == 0;
bool action_success = (lock_is_open == (GBT_LockState.action_requested == 0));
if (action_success) {
// Действие выполнено успешно
GBT_LockState.action_requested = 255; // сбрасываем флаг
GBT_LockState.motor_state = 0; // idle
GBT_LockState.retry_count = 0;
} else {
// Действие не выполнено, повторяем попытку
GBT_LockState.retry_count++;
if (GBT_LockState.retry_count >= MAX_RETRIES) {
// Превышено количество попыток
GBT_LockState.error = 1;
GBT_LockState.error_tick = current_tick; // сохраняем время установки ошибки
GBT_LockState.action_requested = 0; // пытаемся разблокировать
GBT_LockState.motor_state = 0;
GBT_LockState.retry_count = 0;
log_printf(LOG_ERR, "Lock error\n");
} else {
// Повторяем попытку
GBT_LockState.motor_state = 0; // возвращаемся к началу
}
}
}
break;
}
} else {
// Состояние соответствует требуемому, сбрасываем флаги
if (GBT_LockState.motor_state != 0) {
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
GBT_LockState.motor_state = 0;
}
GBT_LockState.action_requested = 255;
GBT_LockState.retry_count = 0;
}
}
void GBT_LockResetError(){
GBT_LockState.error = 0;
GBT_LockState.error_tick = 0;
log_printf(LOG_INFO, "Lock error reset\n");
}
void GBT_ResetErrorTimeout(){
static const uint32_t ERROR_TIMEOUT_MS = 300000; // 5 минут
if (GBT_LockState.error && GBT_LockState.error_tick != 0) {
if ((HAL_GetTick()-GBT_LockState.error_tick) >= ERROR_TIMEOUT_MS) {
// Прошло 5 минут, сбрасываем ошибку
GBT_LockResetError();
}
}
}