forked from achamaikin/CCSModuleSW30Web
170 lines
5.6 KiB
C
Executable File
170 lines
5.6 KiB
C
Executable File
/*
|
||
* 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();
|
||
}
|
||
}
|
||
}
|