No edit summary |
No edit summary |
||
(11 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
== Source == | == ESPHome == | ||
Al SonOff Basics have been flashed with [https://esphome.io/devices/sonoff_basic.html ESPHome]. | |||
For a working SonOff Basic config, see the ESPHome section on [[Jarvis]]. "buitenlamp" has a nice working config. | |||
== Old stuff == | |||
Before ESPHome, we used the firmware below. | |||
=== Source === | |||
* This uses https://github.com/Imroy/pubsubclient | * This uses https://github.com/Imroy/pubsubclient | ||
===Flashing the firmware=== | |||
==Flashing the firmware== | |||
With ESP8266 | With ESP8266 | ||
===Soldering=== | ====Soldering==== | ||
You will need to solder pin headers to the board. | You will need to solder pin headers to the board. | ||
===Setting up Arduino IDE=== | ====Setting up Arduino IDE==== | ||
Open Arduino IDE and go to File, Preferences. | * You will need the [https://www.arduino.cc/en/Main/Software latest Arduino software]. Arduino IDE from most Linux repositories is outdated. | ||
* Open Arduino IDE and install PubSubClient library. Go to Sketch, Include Library, Manage Libraries. Search for PubSubClient and install. | |||
* Next go to File, Preferences. Under Additional Boards Manager URLs field, enter http://arduino.esp8266.com/stable/package_esp8266com_index.json (separate multiple URLs by comma). Press OK. | |||
* Open Tools, Board, Boards Manager. Search for ESP8266 and install. | |||
* After installation, select the ESP8266 board under Tools, Board, Generic ESP8266 Module. | |||
The Tools menu has more options, change these settings: | |||
* Set Flash Size to 1M (64K SPIFFS) | |||
* Set Flash Mode to DIO | |||
====Connecting the hardware==== | |||
===Connecting the hardware=== | |||
[[File:Sonoff-switch-pinout.jpg|thumb|Pin headers for Sonoff switch]] | [[File:Sonoff-switch-pinout.jpg|thumb|Pin headers for Sonoff switch]] | ||
Some ESP8266 converters have a single Vcc pin with jumper to switch between 5V and 3.3V. Make sure you have it set to 3.3V. | Some ESP8266 converters have a single Vcc pin with jumper to switch between 5V and 3.3V. Make sure you have it set to 3.3V. | ||
Line 35: | Line 32: | ||
Connect the wires as follows: | Connect the wires as follows: | ||
* 3.3V → 3.3V (or Vcc) | |||
* Tx → Rx | |||
* Rx → Tx | |||
* Gnd → Gnd | |||
Afterwards, while holding the push button on the Sonoff, connect the ESP8266 to your computer with USB and release the button after several seconds. Doing that enables Flash mode on the Sonoff switch. | |||
In Arduino IDE select the device under Tools, Port. (Usually /dev/ttyUSB0) | |||
Give it more rights. sudo chmod 777 /dev/ttyUSB0 | |||
Copy the firmware below and upload to the sonoff with the Arduino IDE. (Ctrl+U) | |||
Make sure you edit MQTT_CLIENT, MQTT_TOPIC, WIFI_SSID and WIFI_PASS. | |||
=== Firmware === | |||
Mind there are 2 versions below. The first works fine. | Mind there are 2 versions below. The first works fine. | ||
==== SonOff Firmware ==== | |||
<nowiki>/* | <nowiki>/* | ||
Line 94: | Line 97: | ||
#define LED 13 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) | #define LED 13 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) | ||
#define MQTT_CLIENT "rookhok" | #define MQTT_CLIENT "rookhok" // mqtt client_id (Must be unique for each Sonoff) | ||
#define MQTT_SERVER "10.208.11.30" | #define MQTT_SERVER "10.208.11.30" // mqtt server | ||
#define MQTT_PORT 1883 // mqtt port | #define MQTT_PORT 1883 // mqtt port | ||
#define MQTT_TOPIC "space/rookhok/1" | #define MQTT_TOPIC "space/rookhok/1" // mqtt topic (Must be unique for each Sonoff) | ||
#define MQTT_USER "" | #define MQTT_USER "" // mqtt user | ||
#define MQTT_PASS "" | #define MQTT_PASS "" // mqtt password | ||
#define WIFI_SSID "SSID" | #define WIFI_SSID "SSID" // wifi ssid | ||
#define WIFI_PASS "password" // wifi password | #define WIFI_PASS "password" // wifi password | ||
Line 323: | Line 326: | ||
}</nowiki> | }</nowiki> | ||
=== SonOff (1 channel no pow) === | ==== SonOff Firmware (1 channel no pow) ==== | ||
<pre><nowiki> | <pre><nowiki> | ||
/* | /* |
Latest revision as of 18:39, 18 October 2019
ESPHome
Al SonOff Basics have been flashed with ESPHome. For a working SonOff Basic config, see the ESPHome section on Jarvis. "buitenlamp" has a nice working config.
Old stuff
Before ESPHome, we used the firmware below.
Source
- This uses https://github.com/Imroy/pubsubclient
Flashing the firmware
With ESP8266
Soldering
You will need to solder pin headers to the board.
Setting up Arduino IDE
- You will need the latest Arduino software. Arduino IDE from most Linux repositories is outdated.
- Open Arduino IDE and install PubSubClient library. Go to Sketch, Include Library, Manage Libraries. Search for PubSubClient and install.
- Next go to File, Preferences. Under Additional Boards Manager URLs field, enter http://arduino.esp8266.com/stable/package_esp8266com_index.json (separate multiple URLs by comma). Press OK.
- Open Tools, Board, Boards Manager. Search for ESP8266 and install.
- After installation, select the ESP8266 board under Tools, Board, Generic ESP8266 Module.
The Tools menu has more options, change these settings:
- Set Flash Size to 1M (64K SPIFFS)
- Set Flash Mode to DIO
Connecting the hardware
Some ESP8266 converters have a single Vcc pin with jumper to switch between 5V and 3.3V. Make sure you have it set to 3.3V.
Connect the wires as follows:
- 3.3V → 3.3V (or Vcc)
- Tx → Rx
- Rx → Tx
- Gnd → Gnd
Afterwards, while holding the push button on the Sonoff, connect the ESP8266 to your computer with USB and release the button after several seconds. Doing that enables Flash mode on the Sonoff switch.
In Arduino IDE select the device under Tools, Port. (Usually /dev/ttyUSB0)
Give it more rights. sudo chmod 777 /dev/ttyUSB0
Copy the firmware below and upload to the sonoff with the Arduino IDE. (Ctrl+U)
Make sure you edit MQTT_CLIENT, MQTT_TOPIC, WIFI_SSID and WIFI_PASS.
Firmware
Mind there are 2 versions below. The first works fine.
SonOff Firmware
/* Copyright (c) 2017 @KmanOz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================== Changes in v1.01pOTA - Relay state now stored in EEPROM and will power up with last relay state - OTA Firmware Upgradable ============================================================================== **** USE THIS Firmware for: Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Smart Socket **** */ #include <EEPROM.h> #include <ESP8266WiFi.h> #include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> #include <PubSubClient.h> #include <Ticker.h> #define BUTTON 0 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) #define RELAY 12 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) #define LED 13 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) #define MQTT_CLIENT "rookhok" // mqtt client_id (Must be unique for each Sonoff) #define MQTT_SERVER "10.208.11.30" // mqtt server #define MQTT_PORT 1883 // mqtt port #define MQTT_TOPIC "space/rookhok/1" // mqtt topic (Must be unique for each Sonoff) #define MQTT_USER "" // mqtt user #define MQTT_PASS "" // mqtt password #define WIFI_SSID "SSID" // wifi ssid #define WIFI_PASS "password" // wifi password #define VERSION "\n\n---------------- Sonoff Powerpoint v1.01pOTA -----------------" bool rememberRelayState = true; // If 'true' remembers the state of the relay before power loss. bool OTAupdate = false; // (Do not Change) bool sendStatus = false; // (Do not Change) bool requestRestart = false; // (Do not Change) int kUpdFreq = 1; // Update frequency in Mintes to check for mqtt connection int kRetries = 10; // WiFi retry count. Increase if not connecting to router. int lastRelayState; // (Do not Change) unsigned long TTasks; // (Do not Change) unsigned long count = 0; // (Do not Change) extern "C" { #include "user_interface.h" } WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); Ticker btn_timer; void callback(const char *topic, uint8_t *payload, unsigned len) { char bla[32]; memset(bla, 0x00, sizeof bla); memcpy(bla, payload, min(len, 31u)); String pub(bla); if (pub == "stat") { } else if (pub == "on") { digitalWrite(LED, LOW); digitalWrite(RELAY, HIGH); } else if (pub == "off") { digitalWrite(LED, HIGH); digitalWrite(RELAY, LOW); } else if (pub == "reset") { requestRestart = true; } sendStatus = true; } void setup() { pinMode(LED, OUTPUT); pinMode(RELAY, OUTPUT); pinMode(BUTTON, INPUT); digitalWrite(LED, HIGH); digitalWrite(RELAY, LOW); Serial.begin(115200); EEPROM.begin(8); lastRelayState = EEPROM.read(0); if (rememberRelayState && lastRelayState == 1) { digitalWrite(LED, LOW); digitalWrite(RELAY, HIGH); } btn_timer.attach(0.05, button); mqttClient.setServer(MQTT_SERVER, MQTT_PORT); mqttClient.setCallback(callback); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASS); ArduinoOTA.onStart([]() { OTAupdate = true; blinkLED(LED, 400, 2); digitalWrite(LED, HIGH); Serial.println("OTA Update Initiated . . ."); }); ArduinoOTA.onEnd([]() { Serial.println("\nOTA Update Ended . . .s"); ESP.restart(); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { digitalWrite(LED, LOW); delay(5); digitalWrite(LED, HIGH); Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { blinkLED(LED, 40, 2); OTAupdate = false; Serial.printf("OTA Error [%u] ", error); if (error == OTA_AUTH_ERROR) Serial.println(". . . . . . . . . . . . . . . Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println(". . . . . . . . . . . . . . . Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println(". . . . . . . . . . . . . . . Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println(". . . . . . . . . . . . . . . Receive Failed"); else if (error == OTA_END_ERROR) Serial.println(". . . . . . . . . . . . . . . End Failed"); }); ArduinoOTA.begin(); Serial.println(VERSION); Serial.print("\nUnit ID: "); Serial.print("esp8266-"); Serial.print(ESP.getChipId(), HEX); Serial.print("\nConnecting to "); Serial.print(WIFI_SSID); Serial.print(" Wifi"); while ((WiFi.status() != WL_CONNECTED) && kRetries --) { delay(500); Serial.print(" ."); } if (WiFi.status() == WL_CONNECTED) { Serial.println(" DONE"); Serial.print("IP Address is: "); Serial.println(WiFi.localIP()); Serial.print("Connecting to ");Serial.print(MQTT_SERVER);Serial.print(" Broker . ."); delay(500); while (!mqttClient.connect(MQTT_CLIENT) && kRetries --) { Serial.print(" ."); delay(1000); } if(mqttClient.connected()) { Serial.println(" DONE"); Serial.println("\n---------------------------- Logs ----------------------------"); Serial.println(); mqttClient.subscribe(MQTT_TOPIC); blinkLED(LED, 40, 8); if(digitalRead(RELAY) == HIGH) { digitalWrite(LED, LOW); } else { digitalWrite(LED, HIGH); } } else { Serial.println(" FAILED!"); Serial.println("\n----------------------------------------------------------------"); Serial.println(); } } else { Serial.println(" WiFi FAILED!"); Serial.println("\n----------------------------------------------------------------"); Serial.println(); } mqttClient.publish(MQTT_TOPIC"/stat", "init"); } void loop() { ArduinoOTA.handle(); if (OTAupdate == false) { mqttClient.loop(); timedTasks(); checkStatus(); } } void blinkLED(int pin, int duration, int n) { for(int i=0; i<n; i++) { digitalWrite(pin, HIGH); delay(duration); digitalWrite(pin, LOW); delay(duration); } } void button() { if (!digitalRead(BUTTON)) { count++; } else { if (count > 1 && count <= 40) { digitalWrite(LED, !digitalRead(LED)); digitalWrite(RELAY, !digitalRead(RELAY)); sendStatus = true; } else if (count >40){ Serial.println("\n\nSonoff Rebooting . . . . . . . . Please Wait"); requestRestart = true; } count=0; } } void checkConnection() { if (WiFi.status() == WL_CONNECTED) { if (mqttClient.connected()) { Serial.println("mqtt broker connection . . . . . . . . . . OK"); } else { Serial.println("mqtt broker connection . . . . . . . . . . LOST"); requestRestart = true; } } else { Serial.println("WiFi connection . . . . . . . . . . LOST"); requestRestart = true; } } void checkStatus() { if (sendStatus) { if(digitalRead(LED) == LOW) { if (rememberRelayState) { EEPROM.write(0, 1); } mqttClient.publish(MQTT_TOPIC "/stat", "on"); Serial.println("Relay . . . . . . . . . . . . . . . . . . ON"); } else { if (rememberRelayState) { EEPROM.write(0, 0); } mqttClient.publish(MQTT_TOPIC "/stat", "off"); Serial.println("Relay . . . . . . . . . . . . . . . . . . OFF"); } if (rememberRelayState) { EEPROM.commit(); } sendStatus = false; } if (requestRestart) { blinkLED(LED, 400, 4); ESP.restart(); } } void timedTasks() { if ((millis() > TTasks + (kUpdFreq*60000)) || (millis() < TTasks)) { TTasks = millis(); checkConnection(); } }
SonOff Firmware (1 channel no pow)
/* Copyright (c) 2017 @KmanOz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================== Changes in v1.01pOTA - Relay state now stored in EEPROM and will power up with last relay state - OTA Firmware Upgradable ============================================================================== **** USE THIS Firmware for: Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Smart Socket **** */ #include <EEPROM.h> #include <ESP8266WiFi.h> #include <ESP8266mDNS.h> #include <WiFiUdp.h> #include <ArduinoOTA.h> #include <PubSubClient.h> #include <Ticker.h> #define BUTTON 0 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) #define RELAY 12 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) #define LED 13 // (Don't Change for Original Sonoff, Sonoff SV, Sonoff Touch, Sonoff S20 Socket) #define MQTT_CLIENT "space_grotezaal_rechts_1" // mqtt client_id (Must be unique for each Sonoff) #define MQTT_SERVER "10.208.11.30" // mqtt server #define MQTT_PORT 1883 // mqtt port #define MQTT_TOPIC "space/grotezaal/rechts/1" // mqtt topic (Must be unique for each Sonoff) #define MQTT_USER "" // mqtt user #define MQTT_PASS "" // mqtt password #define WIFI_SSID "SSID" // wifi ssid #define WIFI_PASS "password" // wifi password #define VERSION "\n\n---------------- Sonoff Powerpoint v1.01pOTA -----------------" bool rememberRelayState = true; // If 'true' remembers the state of the relay before power loss. bool OTAupdate = false; // (Do not Change) bool sendStatus = false; // (Do not Change) bool requestRestart = false; // (Do not Change) int kUpdFreq = 1; // Update frequency in Mintes to check for mqtt connection int kRetries = 10; // WiFi retry count. Increase if not connecting to router. int lastRelayState; // (Do not Change) unsigned long TTasks; // (Do not Change) unsigned long count = 0; // (Do not Change) extern "C" { #include "user_interface.h" } WiFiClient wifiClient; PubSubClient mqttClient(wifiClient, MQTT_SERVER, MQTT_PORT); Ticker btn_timer; void callback(const MQTT::Publish& pub) { if (pub.payload_string() == "stat") { } else if (pub.payload_string() == "on") { digitalWrite(LED, LOW); digitalWrite(RELAY, HIGH); } else if (pub.payload_string() == "off") { digitalWrite(LED, HIGH); digitalWrite(RELAY, LOW); } else if (pub.payload_string() == "reset") { requestRestart = true; } sendStatus = true; } void setup() { pinMode(LED, OUTPUT); pinMode(RELAY, OUTPUT); pinMode(BUTTON, INPUT); digitalWrite(LED, HIGH); digitalWrite(RELAY, LOW); Serial.begin(115200); EEPROM.begin(8); lastRelayState = EEPROM.read(0); if (rememberRelayState && lastRelayState == 1) { digitalWrite(LED, LOW); digitalWrite(RELAY, HIGH); } btn_timer.attach(0.05, button); mqttClient.set_callback(callback); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASS); ArduinoOTA.onStart([]() { OTAupdate = true; blinkLED(LED, 400, 2); digitalWrite(LED, HIGH); Serial.println("OTA Update Initiated . . ."); }); ArduinoOTA.onEnd([]() { Serial.println("\nOTA Update Ended . . .s"); ESP.restart(); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { digitalWrite(LED, LOW); delay(5); digitalWrite(LED, HIGH); Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { blinkLED(LED, 40, 2); OTAupdate = false; Serial.printf("OTA Error [%u] ", error); if (error == OTA_AUTH_ERROR) Serial.println(". . . . . . . . . . . . . . . Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println(". . . . . . . . . . . . . . . Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println(". . . . . . . . . . . . . . . Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println(". . . . . . . . . . . . . . . Receive Failed"); else if (error == OTA_END_ERROR) Serial.println(". . . . . . . . . . . . . . . End Failed"); }); ArduinoOTA.begin(); Serial.println(VERSION); Serial.print("\nUnit ID: "); Serial.print("esp8266-"); Serial.print(ESP.getChipId(), HEX); Serial.print("\nConnecting to "); Serial.print(WIFI_SSID); Serial.print(" Wifi"); while ((WiFi.status() != WL_CONNECTED) && kRetries --) { delay(500); Serial.print(" ."); } if (WiFi.status() == WL_CONNECTED) { Serial.println(" DONE"); Serial.print("IP Address is: "); Serial.println(WiFi.localIP()); Serial.print("Connecting to ");Serial.print(MQTT_SERVER);Serial.print(" Broker . ."); delay(500); while (!mqttClient.connect(MQTT::Connect(MQTT_CLIENT).set_keepalive(90).set_auth(MQTT_USER, MQTT_PASS)) && kRetries --) { Serial.print(" ."); delay(1000); } if(mqttClient.connected()) { Serial.println(" DONE"); Serial.println("\n---------------------------- Logs ----------------------------"); Serial.println(); mqttClient.subscribe(MQTT_TOPIC); blinkLED(LED, 40, 8); if(digitalRead(RELAY) == HIGH) { digitalWrite(LED, LOW); } else { digitalWrite(LED, HIGH); } } else { Serial.println(" FAILED!"); Serial.println("\n----------------------------------------------------------------"); Serial.println(); } } else { Serial.println(" WiFi FAILED!"); Serial.println("\n----------------------------------------------------------------"); Serial.println(); } } void loop() { ArduinoOTA.handle(); if (OTAupdate == false) { mqttClient.loop(); timedTasks(); checkStatus(); } } void blinkLED(int pin, int duration, int n) { for(int i=0; i<n; i++) { digitalWrite(pin, HIGH); delay(duration); digitalWrite(pin, LOW); delay(duration); } } void button() { if (!digitalRead(BUTTON)) { count++; } else { if (count > 1 && count <= 40) { digitalWrite(LED, !digitalRead(LED)); digitalWrite(RELAY, !digitalRead(RELAY)); sendStatus = true; } else if (count >40){ Serial.println("\n\nSonoff Rebooting . . . . . . . . Please Wait"); requestRestart = true; } count=0; } } void checkConnection() { if (WiFi.status() == WL_CONNECTED) { if (mqttClient.connected()) { Serial.println("mqtt broker connection . . . . . . . . . . OK"); } else { Serial.println("mqtt broker connection . . . . . . . . . . LOST"); requestRestart = true; } } else { Serial.println("WiFi connection . . . . . . . . . . LOST"); requestRestart = true; } } void checkStatus() { if (sendStatus) { if(digitalRead(LED) == LOW) { if (rememberRelayState) { EEPROM.write(0, 1); } mqttClient.publish(MQTT::Publish(MQTT_TOPIC"/stat", "on").set_retain().set_qos(1)); Serial.println("Relay . . . . . . . . . . . . . . . . . . ON"); } else { if (rememberRelayState) { EEPROM.write(0, 0); } mqttClient.publish(MQTT::Publish(MQTT_TOPIC"/stat", "off").set_retain().set_qos(1)); Serial.println("Relay . . . . . . . . . . . . . . . . . . OFF"); } if (rememberRelayState) { EEPROM.commit(); } sendStatus = false; } if (requestRestart) { blinkLED(LED, 400, 4); ESP.restart(); } } void timedTasks() { if ((millis() > TTasks + (kUpdFreq*60000)) || (millis() < TTasks)) { TTasks = millis(); checkConnection(); } }