Created
March 9, 2018 15:25
-
-
Save ilyushchenko/f583c59ec87e2d046383cd8ab2f13694 to your computer and use it in GitHub Desktop.
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
//#include <ESP8266WiFi.h> | |
//#include <WiFiClient.h> | |
#include <ESP8266WebServer.h> | |
#include <ESP8266mDNS.h> | |
#include <ESP8266HTTPUpdateServer.h> | |
#include <Ticker.h> | |
const char* host = "master"; | |
const char* ssid = "unnamed"; | |
const char* password = "answer61"; | |
ESP8266WebServer httpServer(80); | |
ESP8266HTTPUpdateServer httpUpdater; | |
Ticker buttonChecker; | |
Ticker longPressTicker; | |
#define DEBUG true | |
// Конфигурация входов и выходов | |
#if DEBUG | |
#define RELAY1 13 | |
#define RELAY2 15 | |
#define BUTTON 2 | |
#else | |
#define RELAY1 12 | |
#define RELAY2 14 | |
#define BUTTON 0 | |
#endif | |
// Задержки | |
#define LONG_PRESS_DELAY 1000 // Задержка, для длинного нажатия | |
#define SHORT_PRESS_DELAY 25 // Задержка, для проверки нажатия кнопки | |
#define BUTTON_CD_TIME 250 // Задержка, для защиты от повторного нажатия | |
volatile bool IsActive = false; | |
volatile bool buttonPressEnd = false; | |
volatile unsigned long pushTime = 0; | |
volatile unsigned long buttonCountdownTime = 0; | |
volatile int statePosition = 0; | |
const int relay_1_state[] = {HIGH, LOW, HIGH }; | |
const int relay_2_state[] = {LOW, HIGH, HIGH }; | |
enum ButtonState { NotPressed = 1, UnhandledShortPress, ShortPress, UnhandledLongPress, LongPress }; | |
enum OutTransition { Initial = 1, OnToOff, OffToOn }; | |
volatile ButtonState buttonState = NotPressed; | |
volatile OutTransition outState = Initial; | |
void setup() { | |
pinMode(RELAY1, OUTPUT); | |
pinMode(RELAY2, OUTPUT); | |
Off(); | |
Serial.begin(115200); | |
Serial.println(); | |
Serial.println("Booting Sketch..."); | |
Serial.print("Debug mode: "); | |
Serial.println((DEBUG) ? "ON" : "OFF"); | |
Serial.println("Setup input's"); | |
pinMode(BUTTON, INPUT); | |
Serial.println("Setup Interrupt"); | |
attachInterrupt(BUTTON, ButtonOneInt, FALLING); | |
Serial.println("Setup WIFI connection"); | |
WiFi.mode(WIFI_AP_STA); | |
WiFi.begin(ssid, password); | |
while (WiFi.waitForConnectResult() != WL_CONNECTED) { | |
WiFi.begin(ssid, password); | |
Serial.println("WiFi failed, retrying."); | |
} | |
MDNS.begin(host); | |
httpUpdater.setup(&httpServer); | |
httpServer.on ( "/switch", handleRoot ); | |
httpServer.on ( "/", handleRoot ); | |
httpServer.onNotFound ( handleNotFound ); | |
httpServer.begin(); | |
MDNS.addService("http", "tcp", 80); | |
Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", host); | |
Serial.println(WiFi.localIP()); | |
Serial.println("Done"); | |
Serial.println(); | |
} | |
void handleNotFound() { | |
String message = "File Not Found\n\n"; | |
message += "URI: "; | |
message += httpServer.uri(); | |
message += "\nMethod: "; | |
message += ( httpServer.method() == HTTP_GET ) ? "GET" : "POST"; | |
message += "\nArguments: "; | |
message += httpServer.args(); | |
message += "\n"; | |
for ( uint8_t i = 0; i < httpServer.args(); i++ ) { | |
message += " " + httpServer.argName ( i ) + ": " + httpServer.arg ( i ) + "\n"; | |
} | |
httpServer.send ( 404, "text/plain", message ); | |
} | |
void handleRoot() { | |
if (httpServer.method() == HTTP_POST) | |
SwitchState(); | |
char temp[400]; | |
int sec = millis() / 1000; | |
int min = sec / 60; | |
int hr = min / 60; | |
snprintf ( temp, 400, | |
"<html>\ | |
<head>\ | |
<meta http-equiv='refresh' content='5'/>\ | |
<title>ESP8266 Demo</title>\ | |
<style>\ | |
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\ | |
</style>\ | |
</head>\ | |
<body>\ | |
<form method='post'>\ | |
<button type='submit'>Switch</button>\ | |
</form>\ | |
<p>Uptime: %02d:%02d:%02d</p>\ | |
</body>\ | |
</html>", | |
hr, min % 60, sec % 60 | |
); | |
httpServer.send ( 200, "text/html", temp ); | |
} | |
void pin_ISR_long_check(int buttonPin) { | |
noInterrupts(); | |
unsigned long currentTime = millis(); | |
unsigned long delta = currentTime - pushTime; | |
if (IsButtonPressed(buttonPin)) { | |
// Обработка UnhandledLongPress | |
if (buttonState == ShortPress && delta > LONG_PRESS_DELAY && currentTime > buttonCountdownTime) { | |
OnUnhandledLongPress(); | |
buttonState = LongPress; | |
} | |
// Обработка LongPress | |
if (buttonState == LongPress && delta > LONG_PRESS_DELAY && currentTime > buttonCountdownTime) { | |
buttonCountdownTime = currentTime + LONG_PRESS_DELAY; | |
OnLongPress(); | |
} | |
} | |
else { | |
longPressTicker.detach(); | |
OnEndPress(); | |
buttonCountdownTime = currentTime + BUTTON_CD_TIME; // Задержка, для предотвращения случайного повторного нажатия | |
buttonPressEnd = true; // Флаг, для дебага | |
} | |
interrupts(); | |
} | |
// Блок методов-обработчиков событий нажатия | |
// Обработчик короткого нажатия | |
void OnShortPress() | |
{ | |
if (outState == OffToOn) { | |
On(); | |
} | |
} | |
// Обработчик длинного нажатия, срабатывающий единожды | |
void OnUnhandledLongPress() | |
{ | |
outState = Initial; | |
} | |
// Обработчик длинного нажатия | |
void OnLongPress() | |
{ | |
if (IsActive && buttonState == LongPress) { | |
SwitchMode(); | |
On(); | |
} | |
} | |
// Обработчик конца нажатия | |
void OnEndPress() | |
{ | |
if (outState == OnToOff) { | |
Off(); | |
} | |
} | |
void CheckButtonPosition(int buttonPin) { | |
noInterrupts(); | |
// Если кнопка все еще нажата, то начинаем анализ состояния кнопки | |
if (IsButtonPressed(buttonPin)) { | |
pushTime = millis(); // Фикисруем время нажитя кнопки | |
buttonState = ShortPress; // Задаем состояние кнопки - короткое нажатие | |
outState = (IsActive) ? OnToOff : OffToOn; // Указываем, как происходит нажатие. С выключенного на включенное состояние или наоборот | |
buttonCountdownTime = pushTime + LONG_PRESS_DELAY; // Задаем задержку, для длинного нажатия | |
OnShortPress(); // Вызов обработчика первого нажатия на кнопку | |
longPressTicker.attach_ms(10, pin_ISR_long_check, buttonPin); // Запускаем таймер проверки нажатия | |
} | |
//TODO: Если придется отключать прерывание на пин, то здесь надо будет его включить заново | |
interrupts(); | |
} | |
void ButtonOneInt() { | |
noInterrupts(); | |
unsigned long currentTime = millis(); | |
// Проверяем, прошло ли время задержки нажатия | |
if (currentTime > buttonCountdownTime) { | |
// Запуск таймера на проверку нажатия через 50 мс | |
buttonChecker.once_ms(50, CheckButtonPosition, BUTTON); | |
} | |
interrupts(); | |
} | |
void SwitchState() { | |
if (IsActive) | |
Off(); | |
else | |
On(); | |
} | |
void SwitchMode() { | |
statePosition++; | |
if (statePosition > 2) | |
statePosition = 0; | |
} | |
void On() { | |
IsActive = true; | |
digitalWrite(RELAY1, relay_1_state[statePosition]); | |
digitalWrite(RELAY2, relay_2_state[statePosition]); | |
} | |
void Off() { | |
IsActive = false; | |
digitalWrite(RELAY1, LOW); | |
digitalWrite(RELAY2, LOW); | |
} | |
bool IsButtonPressed(int button) { | |
return digitalRead(button) ? false : true; | |
} | |
void loop() { | |
httpServer.handleClient(); | |
if (buttonPressEnd) | |
{ | |
unsigned long currentTime = millis(); | |
unsigned long delta = currentTime - pushTime; | |
Serial.println("--------------------"); | |
Serial.println("Button Press End"); | |
Serial.println("--------------------"); | |
Serial.println(); | |
Serial.print("Push time: "); | |
Serial.print(pushTime); | |
Serial.println(" ms"); | |
Serial.print("Cuttent Time: "); | |
Serial.print(currentTime); | |
Serial.println(" ms"); | |
Serial.print("Pushing time: "); | |
Serial.print(delta); | |
Serial.println(" ms"); | |
Serial.print("Button end state: "); | |
switch (buttonState) { | |
case NotPressed: | |
Serial.println("NotPressed"); | |
break; | |
case UnhandledShortPress: | |
Serial.println("UnhandledShortPress"); | |
break; | |
case ShortPress: | |
Serial.println("ShortPress"); | |
break; | |
case LongPress: | |
Serial.println("LongPress"); | |
break; | |
default: | |
Serial.println("ERROR"); | |
break; | |
} | |
Serial.println(); | |
buttonPressEnd = false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment