Skip to content

Instantly share code, notes, and snippets.

@timurnurutdinov
Created March 29, 2025 19:11
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