// Пины светодиодов
const int ledOpenPin = 2; // Светодиод открытия ворот (D2)
const int ledClosePin = 3; // Светодиод закрытия ворот (D3)
// Пины кнопок управления
const int modeSwitchPin = 4; // Переключатель режима: LOW — авто, HIGH — ручной (D4)
const int buttonOpenPin = 5; // Кнопка открытия ворот (D5)
const int buttonClosePin = 6; // Кнопка закрытия ворот (D6)
// Пины концевиков
const int limitOpenPin = 7; // Концевик открытых ворот (D7)
const int limitClosedPin = 8; // Концевик закрытых ворот (D8)
// Параметры для обработки нажатий
const unsigned long holdThreshold = 700; // Порог удержания в мс (3 с)
const unsigned long doubleClickTime = 300; // Макс. время между кликами для двойного нажатия (мс)
const unsigned long debounceDelay = 50; // Задержка антидребезга в мс
const unsigned long autoCloseDelay = 5000; // Задержка автоматического закрытия (5 с)
// Переменные для кнопки открытия
int buttonOpenState = 0;
int lastButtonOpenState = 0;
unsigned long buttonOpenPressStartTime = 0;
unsigned long lastButtonOpenReleaseTime = 0;
unsigned long lastButtonOpenDebounceTime = 0;
int buttonOpenClickCount = 0;
bool buttonOpenFixed = false; // Флаг фиксации состояния кнопки открытия
// Переменные для кнопки закрытия
int buttonCloseState = 0;
int lastButtonCloseState = 0;
unsigned long buttonClosePressStartTime = 0;
unsigned long lastButtonCloseReleaseTime = 0;
unsigned long lastButtonCloseDebounceTime = 0;
int buttonCloseClickCount = 0;
bool buttonCloseFixed = false; // Флаг фиксации состояния кнопки закрытия
// Переменные для концевиков
int limitOpenState = 0;
int limitClosedState = 0;
// Переменная для режима работы
int modeState = 0;
// Переменные для автоматического закрытия
bool autoCloseTriggered = false;
bool pressButton = false;
unsigned long autoCloseStartTime = 0;
void setup() {
// Настройка пинов светодиодов как выходы
pinMode(ledOpenPin, OUTPUT);
pinMode(ledClosePin, OUTPUT);
// Выключаем светодиоды при старте
digitalWrite(ledOpenPin, LOW);
digitalWrite(ledClosePin, LOW);
// Настройка пинов кнопок с подтяжкой к питанию
pinMode(modeSwitchPin, INPUT_PULLUP);
pinMode(buttonOpenPin, INPUT_PULLUP);
pinMode(buttonClosePin, INPUT_PULLUP);
// Настройка пинов концевиков с подтяжкой к питанию
pinMode(limitOpenPin, INPUT_PULLUP);
pinMode(limitClosedPin, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("Программа запущена. Ожидание нажатий...");
}
// Проверка состояния концевиков и управление светодиодами
void checkLimitSwitches() {
limitOpenState = digitalRead(limitOpenPin);
limitClosedState = digitalRead(limitClosedPin);
// Если любой из концевиков активен (нажат), гасим оба светодиода и блокируем соответствующие кнопки
if (limitOpenState == LOW || limitClosedState == LOW) {
digitalWrite(ledOpenPin, LOW);
digitalWrite(ledClosePin, LOW);
// buttonOpenFixed = false;
// buttonCloseFixed = false;
}
if (limitOpenState == LOW) {
buttonOpenFixed = false;
Serial.println("Концевик открытых ворот активен — светодиоды погашены, кнопка открытия заблокирована");
}
if (limitClosedState == LOW) {
buttonCloseFixed = false;
Serial.println("Концевик закрытых ворот активен — светодиоды погашены, кнопка закрытия заблокирована");
}
}
// Проверка условий автоматического закрытия
void checkAutoClose() {
// Если оба концевика не нажаты (ворота ни открыты, ни закрыты)
// И кнопки не активны и не зафиксированы
if (limitOpenState == HIGH && limitClosedState == HIGH
&& !buttonOpenFixed && !buttonCloseFixed && !pressButton) {
if (!autoCloseTriggered) {
autoCloseTriggered = true;
autoCloseStartTime = millis();
Serial.println("Оба концевика не нажаты — запускается автоматическое закрытие через 5 с");
} else if (millis() - autoCloseStartTime >= autoCloseDelay) {
// Автоматически активируем закрытие ворот
if (!buttonCloseFixed) {
buttonCloseFixed = true;
digitalWrite(ledClosePin, HIGH);
digitalWrite(ledOpenPin, LOW);
buttonOpenFixed = false;
Serial.println("Автоматическое закрытие: LED Close зафиксирован");
}
autoCloseTriggered = false;
}
} else {
autoCloseTriggered = false;
pressButton = false;
}
}
// Обработка кнопки открытия ворот
void handleButtonOpen() {
int reading = digitalRead(buttonOpenPin);
// Антидребезг
if (reading != lastButtonOpenState) {
lastButtonOpenDebounceTime = millis();
pressButton = true;
Serial.println("Была нажата кнопка открытия");
}
if ((millis() - lastButtonOpenDebounceTime) > debounceDelay) {
if (reading != buttonOpenState) {
buttonOpenState = reading;
if (buttonOpenState == LOW) { // Кнопка нажата
buttonOpenPressStartTime = millis();
// Проверка на двойной клик
if (millis() - lastButtonOpenReleaseTime < doubleClickTime) {
buttonOpenClickCount++;
} else {
buttonOpenClickCount = 1;
}
// Если уже зафиксирован — снимаем фиксацию при нажатии
if (buttonOpenFixed) {
buttonOpenFixed = false;
digitalWrite(ledOpenPin, LOW);
Serial.println("Кнопка открытия: снято фиксирование");
} else {
// Одиночное нажатие — включаем светодиод временно
digitalWrite(ledOpenPin, HIGH);
digitalWrite(ledClosePin, LOW); // Гасим светодиод закрытия
buttonCloseFixed = false; // Снимаем фиксацию с кнопки закрытия
}
} else { // Кнопка отпущена
lastButtonOpenReleaseTime = millis();
// Обработка двойного клика — фиксируем состояние
if (buttonOpenClickCount == 2) {
buttonOpenFixed = true;
digitalWrite(ledOpenPin, HIGH);
digitalWrite(ledClosePin, LOW);
buttonCloseFixed = false; // Снимаем фиксацию с кнопки закрытия
Serial.println("Двойной клик — LED Open зафиксирован");
buttonOpenClickCount = 0;
}
// Проверка удержания — фиксируем состояние
else if (millis() - buttonOpenPressStartTime >= holdThreshold) {
buttonOpenFixed = true;
digitalWrite(ledOpenPin, HIGH);
digitalWrite(ledClosePin, LOW);
buttonCloseFixed = false; // Снимаем фиксацию с кнопки закрытия
Serial.println("Удержание — LED Open зафиксирован");
}
// При одиночном нажатии и отпускании гасим светодиод (если не зафиксировали)
else if (!buttonOpenFixed) {
digitalWrite(ledOpenPin, LOW);
}
}
}
}
lastButtonOpenState = reading;
}
// Обработка кнопки закрытия ворот
void handleButtonClose() {
int reading = digitalRead(buttonClosePin);
// Антидребезг
if (reading != lastButtonCloseState) {
lastButtonCloseDebounceTime = millis();
pressButton = true;
Serial.println("Была нажата кнопка закрытия");
}
if ((millis() - lastButtonCloseDebounceTime) > debounceDelay) {
if (reading != buttonCloseState) {
buttonCloseState = reading;
if (buttonCloseState == LOW) { // Кнопка нажата
buttonClosePressStartTime = millis();
// Проверка на двойной клик
if (millis() - lastButtonCloseReleaseTime < doubleClickTime) {
buttonCloseClickCount++;
} else {
buttonCloseClickCount = 1;
}
// Если уже зафиксирован — снимаем фиксацию при нажатии
if (buttonCloseFixed) {
buttonCloseFixed = false;
digitalWrite(ledClosePin, LOW);
Serial.println("Кнопка закрытия: снято фиксирование");
} else {
// Одиночное нажатие — включаем светодиод временно
digitalWrite(ledClosePin, HIGH);
digitalWrite(ledOpenPin, LOW); // Гасим светодиод открытия
buttonOpenFixed = false; // Снимаем фиксацию с кнопки открытия
}
} else { // Кнопка отпущена
lastButtonCloseReleaseTime = millis();
// Обработка двойного клика — фиксируем состояние
if (buttonCloseClickCount == 2) {
buttonCloseFixed = true;
digitalWrite(ledClosePin, HIGH);
digitalWrite(ledOpenPin, LOW);
buttonOpenFixed = false; // Снимаем фиксацию с кнопки открытия
Serial.println("Двойной клик — LED Close зафиксирован");
buttonCloseClickCount = 0;
}
// Проверка удержания — фиксируем состояние
else if (millis() - buttonClosePressStartTime >= holdThreshold) {
buttonCloseFixed = true;
digitalWrite(ledClosePin, HIGH);
digitalWrite(ledOpenPin, LOW);
buttonOpenFixed = false; // Снимаем фиксацию с кнопки открытия
Serial.println("Удержание — LED Close зафиксирован");
}
// При одиночном нажатии и отпускании гасим светодиод (если не зафиксировали)
else if (!buttonCloseFixed) {
digitalWrite(ledClosePin, LOW);
}
}
}
}
lastButtonCloseState = reading;
}
// Вспомогательная функция для сброса всех состояний
void resetAll() {
digitalWrite(ledOpenPin, LOW);
digitalWrite(ledClosePin, LOW);
buttonOpenFixed = false;
buttonCloseFixed = false;
autoCloseTriggered = false;
}
void loop() {
// Читаем состояние переключателя режима
modeState = digitalRead(modeSwitchPin);
// Проверяем состояние концевиков
checkLimitSwitches();
// Если любой из концевиков активен, сбрасываем все состояния
if (limitOpenState == LOW || limitClosedState == LOW) {
resetAll();
} else {
// Если автоматический режим (LOW) — проверяем автоматическое закрытие
if (modeState == LOW) {
checkAutoClose();
} else {
// В ручном режиме сбрасываем таймер автоматического закрытия
autoCloseTriggered = false;
}
}
handleButtonOpen();
handleButtonClose();
}