Skip to content

Instantly share code, notes, and snippets.

@stritti
Forked from gjlawran/Template_ESP8266.ino
Created October 31, 2017 18:36
Show Gist options
  • Save stritti/1906271449afb7ee9e089ee6bbd585cd to your computer and use it in GitHub Desktop.
Save stritti/1906271449afb7ee9e089ee6bbd585cd to your computer and use it in GitHub Desktop.
ESP8266 Arduino project template with optional OTA firmware update
/**
* ESP8266 project template with optional:
* - WiFi config portal - auto or manual trigger
* - OTA update - Arduino or web server
* - Deep sleep
* - Process timeout watchdog
*
* Copyright (c) 2016 Dean Cording <dean@cording.id.au>
*
* 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.
*/
/**
* ESP8266 Pin Connections
*
* GPIO0/SPI-CS2/_FLASH_ - Pull low for Flash download by UART
* GPIO1/TXD0/SPI-CS1 - _LED_
* GPIO2/TXD1/I2C-SDA/I2SO-WS -
* GPIO3/RXD0/I2SO-DATA -
* GPIO4 -
* GPIO5/IR-Rx -
* GPIO6/SPI-CLK - Flash CLK
* GPIO7/SPI-MISO - Flash DI
* GPIO8/SPI-MOSI/RXD1 - Flash DO
* GPIO9/SPI-HD - Flash _HD_
* GPIO10/SPI-WP - Flash _WP_
* GPIO11/SPI-CS0 - Flash _CS_
* GPIO12/MTDI/HSPI-MISO/I2SI-DATA/IR-Tx -
* GPIO13/MTCK/CTS0/RXD2/HSPI-MOSI/I2S-BCK -
* GPIO14/MTMS/HSPI-CLK/I2C-SCL/I2SI_WS -
* GPIO15/MTDO/RTS0/TXD2/HSPI-CS/SD-BOOT/I2SO-BCK - Pull low for Flash boot
* GPIO16/WAKE -
* ADC -
* EN -
* RST -
* GND -
* VCC -
*/
#include <Arduino.h>
// Optional functionality. Comment out defines to disable feature
#define WIFI_PORTAL // Enable WiFi config portal
//#define ARDUINO_OTA // Enable Arduino IDE OTA updates
#define HTTP_OTA // Enable OTA updates from http server
#define LED_STATUS_FLASH // Enable flashing LED status
//#define DEEP_SLEEP_SECONDS 5 // Define for sleep period between process repeats. No sleep if not defined
#define STATUS_LED 2 // Built-in blue LED on pin 2
#include <ESP8266WiFi.h>
#ifdef WIFI_PORTAL
#include <DNSServer.h> // Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h> // Local WebServer used to serve the configuration portal
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager WiFi Configuration Magic
WiFiManager wifiManager;
#define WIFI_PORTAL_TRIGGER_PIN 4 // A low input on this pin will trigger the Wifi Manager Console at boot. Comment out to disable.
#else
#define WIFI_SSID "SSID"
#define WIFI_PASSWORD "password"
#endif
#ifdef ARDUINO_OTA
/* Over The Air updates directly from Arduino IDE */
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#define ARDUINO_OTA_PORT 8266
#define ARDUINO_OTA_HOSTNAME "esp8266"
#define ARDUINO_OTA_PASSWD "123"
#endif
#ifdef HTTP_OTA
/* Over The Air automatic firmware update from a web server. ESP8266 will contact the
* server on every boot and check for a firmware update. If available, the update will
* be downloaded and installed. Server can determine the appropriate firmware for this
* device from any combination of HTTP_OTA_VERSION, MAC address, and firmware MD5 checksums.
*/
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#define HTTP_OTA_ADDRESS F("iot.cording.id.au") // Address of OTA update server
#define HTTP_OTA_PATH F("/esp8266-ota/update") // Path to update firmware
#define HTTP_OTA_PORT 1880 // Port of update server
// Name of firmware
#define HTTP_OTA_VERSION String(__FILE__).substring(String(__FILE__).lastIndexOf('/')+1) + ".generic"
#endif
const char* SSID = (String("ESP") + String(ESP.getChipId())).c_str();
/* Watchdog to guard against the ESP8266 wasting battery power looking for
* non-responsive wifi networks and servers. Expiry of the watchdog will trigger
* either a deep sleep cycle or a delayed reboot. The ESP8266 OS has another built-in
* watchdog to protect against infinite loops and hangups in user code.
*/
#include <Ticker.h>
Ticker watchdog;
#define WATCHDOG_SETUP_SECONDS 30 // Setup should complete well within this time limit
#define WATCHDOG_LOOP_SECONDS 20 // Loop should complete well within this time limit
void timeout_cb() {
// This sleep happened because of timeout. Do a restart after a sleep
Serial.println(F("Watchdog timeout..."));
#ifdef DEEP_SLEEP_SECONDS
// Enter DeepSleep so that we don't exhaust our batteries by countinuously trying to
// connect to a network that isn't there.
ESP.deepSleep(DEEP_SLEEP_SECONDS * 1000, WAKE_RF_DEFAULT);
// Do nothing while we wait for sleep to overcome us
while(true){};
#else
delay(1000);
ESP.restart();
#endif
}
#ifdef LED_STATUS_FLASH
Ticker flasher;
void flash() {
digitalWrite(STATUS_LED, !digitalRead(STATUS_LED));
}
#endif
#ifdef WIFI_PORTAL
// Callback for entering config mode
void configModeCallback (WiFiManager *myWiFiManager) {
// Config mode has its own timeout
watchdog.detach();
#ifdef LED_STATUS_FLASH
flasher.attach(0.2, flash);
#endif
}
#endif
// Put any project specific initialisation here
void setup() {
Serial.begin(115200);
Serial.println(F("Booting"));
#ifdef LED_STATUS_FLASH
pinMode(STATUS_LED, OUTPUT);
flasher.attach(0.6, flash);
#endif
// Watchdog timer - resets if setup takes longer than allocated time
watchdog.once(WATCHDOG_SETUP_SECONDS, &timeout_cb);
// Set up WiFi connection
// Previous connection details stored in eeprom
#ifdef WIFI_PORTAL
#ifdef WIFI_PORTAL_TRIGGER_PIN
pinMode(WIFI_PORTAL_TRIGGER_PIN, INPUT_PULLUP);
delay(100);
if ( digitalRead(WIFI_PORTAL_TRIGGER_PIN) == LOW ) {
watchdog.detach();
if (!wifiManager.startConfigPortal(SSID, NULL)) {
Serial.println(F("Config Portal Failed!"));
timeout_cb();
}
} else {
#endif
wifiManager.setConfigPortalTimeout(180);
wifiManager.setAPCallback(configModeCallback);
if (!wifiManager.autoConnect()) {
Serial.println(F("Connection Failed!"));
timeout_cb();
}
#ifdef WIFI_PORTAL_TRIGGER_PIN
}
#endif
#else
// Save boot up time by not configuring them if they haven't changed
if (WiFi.SSID() != WIFI_SSID) {
Serial.println(F("Initialising Wifi..."));
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.persistent(true);
WiFi.setAutoConnect(true);
WiFi.setAutoReconnect(true);
}
#endif
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println(F("Connection Failed!"));
timeout_cb();
}
Serial.print(F("IP address: "));
Serial.println(WiFi.localIP());
#ifdef LED_STATUS_FLASH
flasher.detach();
digitalWrite(STATUS_LED, HIGH);
#endif
#ifdef HTTP_OTA
// Check server for firmware updates
Serial.print("Checking for firmware updates from server http://");
Serial.print(HTTP_OTA_ADDRESS);
Serial.print(":");
Serial.print(HTTP_OTA_PORT);
Serial.println(HTTP_OTA_PATH);
switch(ESPhttpUpdate.update(HTTP_OTA_ADDRESS, HTTP_OTA_PORT, HTTP_OTA_PATH, HTTP_OTA_VERSION)) {
case HTTP_UPDATE_FAILED:
Serial.printf("HTTP update failed: Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
break;
case HTTP_UPDATE_NO_UPDATES:
Serial.println(F("No updates"));
break;
case HTTP_UPDATE_OK:
Serial.println(F("Update OK"));
break;
}
#endif
#ifdef ARDUINO_OTA
// Arduino OTA Initalisation
ArduinoOTA.setPort(ARDUINO_OTA_PORT);
ArduinoOTA.setHostname(SSID);
ArduinoOTA.setPassword(ARDUINO_OTA_PASSWD);
ArduinoOTA.onStart([]() {
watchdog.detach();
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("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();
#endif
// Put your initialisation code here
Serial.println(F("Ready"));
watchdog.detach();
}
void loop() {
// Watchdog timer - resets if setup takes longer than allocated time
watchdog.once(WATCHDOG_LOOP_SECONDS, &timeout_cb);
// put your main code here, to run repeatedly:
delay(10000);
watchdog.detach();
#ifdef ARDUINO_OTA
// Handle any OTA upgrade
ArduinoOTA.handle();
#endif
#ifdef DEEP_SLEEP_SECONDS
// Enter DeepSleep
Serial.println(F("Sleeping..."));
ESP.deepSleep(DEEP_SLEEP_SECONDS * 1000000, WAKE_RF_DEFAULT);
// Do nothing while we wait for sleep to overcome us
while(true){};
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment