Created
March 29, 2025 19:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const int TRANSFORMER_PIN = 8; | |
const int OPEN_COMMAND_PIN = 20; | |
const int CLOSE_COMMAND_PIN = 21; | |
const int SLOW_MODE_PIN = 9; | |
const int LIGHT_PIN = 6; // Пин для управления светом | |
const int DOOR_OPEN_SENSOR_PIN = 0; | |
const int DOOR_CLOSE_SENSOR_PIN = 19; | |
const int TRANSFORMER_BTN_PIN = 5; | |
const int OPEN_BTN_PIN = 2; | |
const int CLOSE_BTN_PIN = 3; | |
const int LIGHT_BTN_PIN = 1; // Кнопка для управления светом | |
const unsigned long NORMAL_OPENING_TIME = 18500; | |
const unsigned long NORMAL_CLOSING_TIME = 16500; | |
const unsigned long SLOW_DOWN_TIME = 3000; | |
const unsigned long TO_VENTILATION_OPEN_TIME = 5000; | |
const unsigned long FROM_VENTILATION_CLOSE_TIME = 6500; | |
const unsigned long FROM_VENTILATION_OPEN_TIME = 13000; | |
const unsigned long BRAKE_TIME = 100; | |
const unsigned long TRANSFORMER_IDLE_TIMEOUT = 10000; | |
const unsigned long VENTILATION_BUTTON_TIME = 2000; | |
const unsigned long LIGHT_TIMEOUT = 5000; | |
const unsigned long LIGHT_MANUAL_TIMEOUT = 15000; // Новый таймаут для ручного выключения света | |
enum SystemState { | |
IDLE, | |
WAITING_WHILE_OPENED, | |
WAITING_WHILE_CLOSED, | |
WAITING_WHILE_VENTILATION, | |
OPENING, | |
OPENING_SLOW, | |
OPENING_BRAKE, | |
CLOSING, | |
CLOSING_SLOW, | |
CLOSING_BRAKE, | |
VENTILATION_OPENING, | |
OPENING_FROM_VENT, | |
OPENING_FROM_VENT_SLOW, | |
OPENING_FROM_VENT_BRAKE, | |
CLOSING_FROM_VENT, | |
CLOSING_FROM_VENT_SLOW, | |
CLOSING_FROM_VENT_BRAKE | |
}; | |
unsigned long brakeStartTime = 0; | |
SystemState currentState = IDLE; | |
unsigned long operationStartTime = 0; | |
unsigned long buttonPressTime = 0; | |
bool closeButtonHeld = false; | |
// Переменные для управления светом | |
bool lightOn = false; | |
unsigned long lightStartTime = 0; | |
bool lightButtonPressed = false; | |
bool prevLightButtonState = HIGH; | |
bool doorOperationActive = false; | |
bool lightTimerStarted = false; | |
bool manualLightControl = false; // Флаг ручного управления светом | |
unsigned long manualLightStartTime = 0; // Время включения света в ручном режиме | |
bool doorOperationCompleted = false; // Флаг для отслеживания завершения операции с воротами | |
bool doorWasOperatedSinceTransformerOn = false; // Флаг для отслеживания операций после включения трансформатора | |
void setup() { | |
pinMode(TRANSFORMER_PIN, OUTPUT); | |
pinMode(OPEN_COMMAND_PIN, OUTPUT); | |
pinMode(CLOSE_COMMAND_PIN, OUTPUT); | |
pinMode(SLOW_MODE_PIN, OUTPUT); | |
pinMode(LIGHT_PIN, OUTPUT); // Инициализация пина света | |
pinMode(DOOR_OPEN_SENSOR_PIN, INPUT_PULLUP); | |
pinMode(DOOR_CLOSE_SENSOR_PIN, INPUT_PULLUP); | |
pinMode(TRANSFORMER_BTN_PIN, INPUT_PULLUP); | |
pinMode(OPEN_BTN_PIN, INPUT_PULLUP); | |
pinMode(CLOSE_BTN_PIN, INPUT_PULLUP); | |
pinMode(LIGHT_BTN_PIN, INPUT_PULLUP); // Инициализация пина кнопки света | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
void startBrakeOpening() { | |
digitalWrite(CLOSE_COMMAND_PIN, HIGH); | |
brakeStartTime = millis(); | |
switch(currentState) { | |
case OPENING: | |
case OPENING_SLOW: | |
currentState = OPENING_BRAKE; | |
break; | |
case OPENING_FROM_VENT: | |
case OPENING_FROM_VENT_SLOW: | |
currentState = OPENING_FROM_VENT_BRAKE; | |
break; | |
} | |
// Отмечаем, что операция с воротами завершается | |
doorOperationCompleted = true; | |
} | |
void startBrakeClosing() { | |
digitalWrite(OPEN_COMMAND_PIN, HIGH); | |
brakeStartTime = millis(); | |
switch(currentState) { | |
case CLOSING: | |
case CLOSING_SLOW: | |
currentState = CLOSING_BRAKE; | |
break; | |
case CLOSING_FROM_VENT: | |
case CLOSING_FROM_VENT_SLOW: | |
currentState = CLOSING_FROM_VENT_BRAKE; | |
break; | |
} | |
// Отмечаем, что операция с воротами завершается | |
doorOperationCompleted = true; | |
} | |
void turnOnTransformer() { | |
digitalWrite(TRANSFORMER_PIN, HIGH); | |
// Включаем свет только если он не был включен вручную | |
if (!manualLightControl && !lightOn) { | |
turnOnLight(); | |
} | |
doorOperationActive = false; | |
doorOperationCompleted = false; | |
doorWasOperatedSinceTransformerOn = false; // Сбрасываем флаг при включении трансформатора | |
lightTimerStarted = false; | |
} | |
void turnOffTransformer() { | |
digitalWrite(TRANSFORMER_PIN, LOW); | |
// Выключаем свет только если не было операций с воротами после включения трансформатора | |
// и свет не был включен вручную | |
if (lightOn && !doorWasOperatedSinceTransformerOn && !manualLightControl) { | |
turnOffLight(); | |
} | |
// Запускаем таймер для выключения света, если была операция с воротами | |
if (lightOn && doorWasOperatedSinceTransformerOn && !manualLightControl && !lightTimerStarted) { | |
lightStartTime = millis(); | |
lightTimerStarted = true; | |
} | |
} | |
void turnOnLight() { | |
digitalWrite(LIGHT_PIN, HIGH); | |
lightOn = true; | |
} | |
void turnOffLight() { | |
digitalWrite(LIGHT_PIN, LOW); | |
lightOn = false; | |
lightTimerStarted = false; | |
manualLightControl = false; | |
} | |
void startOpeningDoor() { | |
digitalWrite(OPEN_COMMAND_PIN, HIGH); | |
digitalWrite(CLOSE_COMMAND_PIN, LOW); | |
digitalWrite(SLOW_MODE_PIN, LOW); | |
doorOperationActive = true; | |
doorOperationCompleted = false; | |
doorWasOperatedSinceTransformerOn = true; // Устанавливаем флаг при операции с воротами | |
} | |
void startClosingDoor() { | |
digitalWrite(OPEN_COMMAND_PIN, LOW); | |
digitalWrite(CLOSE_COMMAND_PIN, HIGH); | |
digitalWrite(SLOW_MODE_PIN, LOW); | |
doorOperationActive = true; | |
doorOperationCompleted = false; | |
doorWasOperatedSinceTransformerOn = true; // Устанавливаем флаг при операции с воротами | |
} | |
void enableSlowMode() { | |
digitalWrite(SLOW_MODE_PIN, HIGH); | |
} | |
void turnOffAll() { | |
digitalWrite(TRANSFORMER_PIN, LOW); | |
digitalWrite(OPEN_COMMAND_PIN, LOW); | |
digitalWrite(CLOSE_COMMAND_PIN, LOW); | |
digitalWrite(SLOW_MODE_PIN, LOW); | |
// После операции с воротами запускаем таймер света, если он еще не запущен | |
if (doorOperationActive && doorOperationCompleted && lightOn && !manualLightControl && !lightTimerStarted) { | |
lightStartTime = millis(); | |
lightTimerStarted = true; | |
} | |
doorOperationActive = false; | |
doorOperationCompleted = false; | |
} | |
bool isTransformerIdleTimeExpired() { | |
return (millis() - operationStartTime) >= TRANSFORMER_IDLE_TIMEOUT; | |
} | |
bool isLightTimeExpired() { | |
return lightTimerStarted && (millis() - lightStartTime) >= LIGHT_TIMEOUT; | |
} | |
bool isManualLightTimeExpired() { | |
return manualLightControl && (millis() - manualLightStartTime) >= LIGHT_MANUAL_TIMEOUT; | |
} | |
bool isDoorOperationTimeExpired() { | |
unsigned long maxTime; | |
switch(currentState) { | |
case VENTILATION_OPENING: | |
maxTime = TO_VENTILATION_OPEN_TIME; | |
break; | |
case OPENING_FROM_VENT: | |
case OPENING_FROM_VENT_SLOW: | |
maxTime = FROM_VENTILATION_OPEN_TIME + SLOW_DOWN_TIME; | |
break; | |
case CLOSING_FROM_VENT: | |
case CLOSING_FROM_VENT_SLOW: | |
maxTime = FROM_VENTILATION_CLOSE_TIME + SLOW_DOWN_TIME; | |
break; | |
case OPENING: | |
case OPENING_SLOW: | |
maxTime = NORMAL_OPENING_TIME + SLOW_DOWN_TIME; | |
break; | |
case CLOSING: | |
case CLOSING_SLOW: | |
maxTime = NORMAL_CLOSING_TIME + SLOW_DOWN_TIME; | |
break; | |
default: | |
return false; | |
} | |
bool isExpired = (millis() - operationStartTime) >= maxTime; | |
// Отмечаем, что операция завершена по таймауту, если это так | |
if (isExpired) { | |
doorOperationCompleted = true; | |
} | |
return isExpired; | |
} | |
bool shouldSlowDown() { | |
unsigned long elapsedTime = millis() - operationStartTime; | |
unsigned long fastModeTime; | |
switch(currentState) { | |
case VENTILATION_OPENING: | |
return false; | |
case OPENING_FROM_VENT: | |
fastModeTime = FROM_VENTILATION_OPEN_TIME - SLOW_DOWN_TIME; | |
break; | |
case CLOSING_FROM_VENT: | |
fastModeTime = FROM_VENTILATION_CLOSE_TIME - SLOW_DOWN_TIME; | |
break; | |
case OPENING: | |
fastModeTime = NORMAL_OPENING_TIME - SLOW_DOWN_TIME; | |
break; | |
case CLOSING: | |
fastModeTime = NORMAL_CLOSING_TIME - SLOW_DOWN_TIME; | |
break; | |
default: | |
return false; | |
} | |
return elapsedTime >= fastModeTime; | |
} | |
bool isButtonPressed(int pin) { | |
return digitalRead(pin) == LOW; | |
} | |
bool isDoorFullyOpen() { | |
return digitalRead(DOOR_OPEN_SENSOR_PIN) == LOW; | |
} | |
bool isDoorFullyClosed() { | |
return digitalRead(DOOR_CLOSE_SENSOR_PIN) == LOW; | |
} | |
void handleLightButton() { | |
bool currentButtonState = digitalRead(LIGHT_BTN_PIN); | |
// Обнаружение нажатия кнопки (по фронту сигнала) | |
if (currentButtonState == LOW && prevLightButtonState == HIGH) { | |
if (lightOn) { | |
turnOffLight(); | |
} else { | |
turnOnLight(); | |
manualLightControl = true; // Отмечаем, что свет был включен вручную | |
manualLightStartTime = millis(); // Запоминаем время включения света в ручном режиме | |
lightTimerStarted = false; // Сбрасываем таймер при ручном включении | |
} | |
} | |
prevLightButtonState = currentButtonState; | |
} | |
void handleOperation() { | |
// Обработка кнопки света | |
handleLightButton(); | |
// Проверка таймаута света - выделено в отдельный блок вначале | |
if (lightOn) { | |
if ((!manualLightControl && isLightTimeExpired()) || | |
(manualLightControl && isManualLightTimeExpired())) { | |
turnOffLight(); | |
} | |
} | |
if (isButtonPressed(TRANSFORMER_BTN_PIN)) { | |
if (currentState == IDLE || | |
currentState == WAITING_WHILE_OPENED || | |
currentState == WAITING_WHILE_CLOSED || | |
currentState == WAITING_WHILE_VENTILATION) { | |
turnOnTransformer(); | |
operationStartTime = millis(); | |
buttonPressTime = 0; | |
closeButtonHeld = false; | |
if (isDoorFullyOpen()) { | |
currentState = WAITING_WHILE_OPENED; | |
} else if (isDoorFullyClosed()) { | |
currentState = WAITING_WHILE_CLOSED; | |
} else { | |
currentState = WAITING_WHILE_VENTILATION; | |
} | |
} | |
} | |
if (currentState == WAITING_WHILE_CLOSED) { | |
if (isButtonPressed(CLOSE_BTN_PIN)) { | |
if (buttonPressTime == 0) { | |
buttonPressTime = millis(); | |
closeButtonHeld = true; | |
} | |
else if (closeButtonHeld && (millis() - buttonPressTime >= VENTILATION_BUTTON_TIME)) { | |
startOpeningDoor(); | |
operationStartTime = millis(); | |
currentState = VENTILATION_OPENING; | |
buttonPressTime = 0; | |
closeButtonHeld = false; | |
} | |
} | |
else { | |
buttonPressTime = 0; | |
closeButtonHeld = false; | |
} | |
} | |
switch (currentState) { | |
case IDLE: | |
break; | |
case WAITING_WHILE_OPENED: | |
case WAITING_WHILE_CLOSED: | |
case WAITING_WHILE_VENTILATION: | |
if (isButtonPressed(OPEN_BTN_PIN)) { | |
if (currentState != WAITING_WHILE_OPENED) { | |
startOpeningDoor(); | |
operationStartTime = millis(); | |
if (currentState == WAITING_WHILE_VENTILATION) { | |
currentState = OPENING_FROM_VENT; | |
} else { | |
currentState = OPENING; | |
} | |
} | |
} | |
else if (isButtonPressed(CLOSE_BTN_PIN) && !closeButtonHeld) { | |
if (currentState != WAITING_WHILE_CLOSED) { | |
startClosingDoor(); | |
operationStartTime = millis(); | |
if (currentState == WAITING_WHILE_VENTILATION) { | |
currentState = CLOSING_FROM_VENT; | |
} else { | |
currentState = CLOSING; | |
} | |
} | |
} | |
else if (isTransformerIdleTimeExpired()) { | |
turnOffTransformer(); | |
currentState = IDLE; | |
} | |
break; | |
case VENTILATION_OPENING: | |
if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_VENTILATION; | |
} | |
break; | |
case CLOSING_FROM_VENT: | |
if (isDoorFullyClosed()) { | |
startBrakeClosing(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
else if (shouldSlowDown()) { | |
enableSlowMode(); | |
currentState = CLOSING_FROM_VENT_SLOW; | |
} | |
break; | |
case CLOSING_FROM_VENT_SLOW: | |
if (isDoorFullyClosed()) { | |
startBrakeClosing(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
break; | |
case CLOSING_FROM_VENT_BRAKE: | |
if (millis() - brakeStartTime >= BRAKE_TIME) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
break; | |
case OPENING_FROM_VENT: | |
if (isDoorFullyOpen()) { | |
startBrakeOpening(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_OPENED; | |
} | |
else if (shouldSlowDown()) { | |
enableSlowMode(); | |
currentState = OPENING_FROM_VENT_SLOW; | |
} | |
break; | |
case OPENING_FROM_VENT_SLOW: | |
if (isDoorFullyOpen()) { | |
startBrakeOpening(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_OPENED; | |
} | |
break; | |
case OPENING_FROM_VENT_BRAKE: | |
if (millis() - brakeStartTime >= BRAKE_TIME) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_OPENED; | |
} | |
break; | |
case OPENING: | |
if (isDoorFullyOpen()) { | |
startBrakeOpening(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_OPENED; | |
} | |
else if (shouldSlowDown()) { | |
enableSlowMode(); | |
currentState = OPENING_SLOW; | |
} | |
break; | |
case OPENING_SLOW: | |
if (isDoorFullyOpen()) { | |
startBrakeOpening(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_OPENED; | |
} | |
break; | |
case OPENING_BRAKE: | |
if (millis() - brakeStartTime >= BRAKE_TIME) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_OPENED; | |
} | |
break; | |
case CLOSING: | |
if (isDoorFullyClosed()) { | |
startBrakeClosing(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
else if (shouldSlowDown()) { | |
enableSlowMode(); | |
currentState = CLOSING_SLOW; | |
} | |
break; | |
case CLOSING_SLOW: | |
if (isDoorFullyClosed()) { | |
startBrakeClosing(); | |
} | |
else if (isDoorOperationTimeExpired()) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
break; | |
case CLOSING_BRAKE: | |
if (millis() - brakeStartTime >= BRAKE_TIME) { | |
turnOffAll(); | |
currentState = WAITING_WHILE_CLOSED; | |
} | |
break; | |
} | |
} | |
void loop() { | |
handleOperation(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment