Hello all,
I'm programming a countdown timmer, I founded a old tuto that I modified to include a pedal with buttons. I also changed SPIFFS to littleFS because i read that SPIFFS were not longer supported.
I'm done with the hardware but i still have a situation with the wifi http server.
It works, i can uploading data, and viewing them but when I connect the webpages are not fully loaded.
The webpage helps me to trigger and start a countdown without pedal.
Here is my ESP8266 configuration :
- NODE MCU ESP 12E
- Upload speed : 921600
- CPU: 80Mhz
- FS: 2MB OTA 1019
- IwIP : V2ipv6
- Vtables : Flash
- C++ disabled
- stack protect : disabled
- Erase Flash : Sketch
- MMU : 32kb cache + 32 Kb Iram
- non 32bit : Use PGM_read macros for Iram_PROGMEM
Ino code (full page) :
#include <Wire.h>
#include <RtcDS3231.h> // Include RTC library by Makuna: https://github.com/Makuna/Rtc
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <FastLED.h>
#include <LittleFS.h>
#include <FS.h> // Please read the instructions on http://arduino.esp8266.com/Arduino/versions/2.3.0/doc/filesystem.html#uploading-files-to-file-system
#include <ezButton.h>
#define countof(a) (sizeof(a) / sizeof(a[0]))
#define NUM_LEDS 86 // Total of 86 LED's
#define DATA_PIN D6 // Change this if you are using another type of ESP board than a WeMos D1 Mini
#define MILLI_AMPS 2400
#define COUNTDOWN_OUTPUT D5
#define WIFIMODE 0 // 0 = Only Soft Access Point, 1 = Only connect to local WiFi network with UN/PW, 2 = Both
#include <ezButton.h>
ezButton button(D7); // create ezButton object that attach to ESP8266 pin D7
#if defined(WIFIMODE) && (WIFIMODE == 0 || WIFIMODE == 2)
const char* APssid = "*****";
const char* APpassword = "*****";
#endif
#if defined(WIFIMODE) && (WIFIMODE == 1 || WIFIMODE == 2)
#include "Credentials.h" // Create this file in the same directory as the .ino file and add your credentials (#define SID YOURSSID and on the second line #define PW YOURPASSWORD)
const char *ssid = SID;
const char *password = PW;
#endif
RtcDS3231<TwoWire> Rtc(Wire);
ESP8266WebServer server(80);
ESP8266HTTPUpdateServer httpUpdateServer;
CRGB LEDs[NUM_LEDS];
// Settings
unsigned long prevTime = 0;
byte r_val = 255;
byte g_val = 255;
byte b_val = 255;
bool dotsOn = true;
byte brightness = 255;
float temperatureCorrection = -3.0;
byte temperatureSymbol = 12; // 12=Celcius, 13=Fahrenheit check 'numbers'
byte clockMode = 1; // Clock modes: 0=Clock, 1=Countdown, 2=Temperature, 3=Scoreboard
unsigned long countdownMilliSeconds;
unsigned long endCountDownMillis;
byte hourFormat = 24; // Change this to 12 if you want default 12 hours format instead of 24
CRGB countdownColor = CRGB(255, 255, 255);
byte scoreboardLeft = 0;
byte scoreboardRight = 0;
CRGB scoreboardColorLeft = CRGB::Green;
CRGB scoreboardColorRight = CRGB::Red;
CRGB alternateColor = CRGB::Black;
long numbers[] = {
0b000111111111111111111, // [0] 0
0b000111000000000000111, // [1] 1
0b111111111000111111000, // [2] 2
0b111111111000000111111, // [3] 3
0b111111000111000000111, // [4] 4
0b111000111111000111111, // [5] 5
0b111000111111111111111, // [6] 6
0b000111111000000000111, // [7] 7
0b111111111111111111111, // [8] 8
0b111111111111000111111, // [9] 9
0b000000000000000000000, // [10] off
0b111111111111000000000, // [11] degrees symbol
0b000000111111111111000, // [12] C(elsius)
0b111000111111111000000, // [13] F(ahrenheit)
};
void setup() {
button.setDebounceTime(50); // set debounce time to 50 milliseconds
pinMode(COUNTDOWN_OUTPUT, OUTPUT);
Serial.begin(115200);
delay(200);
// RTC DS3231 Setup
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
if (!Rtc.IsDateTimeValid()) {
if (Rtc.LastError() != 0) {
// we have a communications error see https://www.arduino.cc/en/Reference/WireEndTransmission for what the number means
Serial.print("RTC communications error = ");
Serial.println(Rtc.LastError());
} else {
// Common Causes:
// 1) first time you ran and the device wasn't running yet
// 2) the battery on the device is low or even missing
Serial.println("RTC lost confidence in the DateTime!");
// following line sets the RTC to the date & time this sketch was compiled
// it will also reset the valid flag internally unless the Rtc device is
// having an issue
Rtc.SetDateTime(compiled);
}
}
WiFi.setSleepMode(WIFI_NONE_SLEEP);
delay(200);
//Serial.setDebugOutput(true);
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(LEDs, NUM_LEDS);
FastLED.setDither(false);
FastLED.setCorrection(TypicalLEDStrip);
FastLED.setMaxPowerInVoltsAndMilliamps(5, MILLI_AMPS);
fill_solid(LEDs, NUM_LEDS, CRGB::Black);
FastLED.show();
// WiFi - AP Mode or both
#if defined(WIFIMODE) && (WIFIMODE == 0 || WIFIMODE == 2)
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(APssid, APpassword); // IP is usually 192.168.4.1
Serial.println();
Serial.print("SoftAP IP: ");
Serial.println(WiFi.softAPIP());
#endif
// WiFi - Local network Mode or both
#if defined(WIFIMODE) && (WIFIMODE == 1 || WIFIMODE == 2)
byte count = 0;
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
// Stop if cannot connect
if (count >= 60) {
Serial.println("Could not connect to local WiFi.");
return;
}
delay(500);
Serial.print(".");
LEDs[count] = CRGB::Green;
FastLED.show();
count++;
}
Serial.print("Local IP: ");
Serial.println(WiFi.localIP());
IPAddress ip = WiFi.localIP();
Serial.println(ip[3]);
#endif
httpUpdateServer.setup(&server);
// Handlers
server.on("/color", HTTP_POST, []() {
r_val = server.arg("r").toInt();
g_val = server.arg("g").toInt();
b_val = server.arg("b").toInt();
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
server.on("/setdate", HTTP_POST, []() {
// Sample input: date = "Dec 06 2009", time = "12:34:56"
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
String datearg = server.arg("date");
String timearg = server.arg("time");
Serial.println(datearg);
Serial.println(timearg);
char d[12];
char t[9];
datearg.toCharArray(d, 12);
timearg.toCharArray(t, 9);
RtcDateTime compiled = RtcDateTime(d, t);
Rtc.SetDateTime(compiled);
clockMode = 0;
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
server.on("/brightness", HTTP_POST, []() {
brightness = server.arg("brightness").toInt();
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
server.on("/countdown", HTTP_POST, []() {
//countdownMilliSeconds = server.arg("ms").toInt();
countdownMilliSeconds = server.arg("ms").toInt();
digitalWrite(COUNTDOWN_OUTPUT, LOW);
countdownColor = CRGB(255, 255, 0);
endCountDownMillis = millis() + countdownMilliSeconds;
allBlank();
clockMode = 1;
server.send(5, "text/json", "{\"result\":\"ok\"}");
});
server.on("/temperature", HTTP_POST, []() {
temperatureCorrection = server.arg("correction").toInt();
temperatureSymbol = server.arg("symbol").toInt();
clockMode = 2;
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
server.on("/scoreboard", HTTP_POST, []() {
scoreboardLeft = server.arg("left").toInt();
scoreboardRight = server.arg("right").toInt();
scoreboardColorLeft = CRGB(server.arg("rl").toInt(),server.arg("gl").toInt(),server.arg("bl").toInt());
scoreboardColorRight = CRGB(server.arg("rr").toInt(),server.arg("gr").toInt(),server.arg("br").toInt());
clockMode = 3;
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
server.on("/hourformat", HTTP_POST, []() {
hourFormat = server.arg("hourformat").toInt();
clockMode = 0;
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
server.on("/clock", HTTP_POST, []() {
clockMode = 0;
server.send(200, "text/json", "{\"result\":\"ok\"}");
});
// Before uploading the files with the "ESP8266 Sketch Data Upload" tool, zip the files with the command "gzip -r ./data/" (on Windows I do this with a Git Bash)
// *.gz files are automatically unpacked and served from your ESP (so you don't need to create a handler for each file).
server.serveStatic("/", LittleFS, "/");
server.begin();
/*
SPIFFS.begin();
Serial.println("SPIFFS contents:");
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), String(fileSize).c_str());
}
Serial.println();
*/
LittleFS.begin();
Serial.begin(115200);
Serial.println("LittleFS contents:");
Dir dir = LittleFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), String(fileSize).c_str());
}
Serial.println();
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
digitalWrite(COUNTDOWN_OUTPUT, LOW);
}
void loop(){
button.loop(); // MUST call the loop() function first
if (button.isPressed()) {
Serial.println("The switch: OFF -> ON");
Serial.println("Countdown timer ended.");
countdownMilliSeconds = 32000;
digitalWrite(COUNTDOWN_OUTPUT, HIGH);
countdownColor = CRGB(255, 255, 255);
endCountDownMillis = millis() + countdownMilliSeconds;
allBlank();
clockMode = 1;
}
if (button.isReleased())
Serial.println("The switch: ON -> OFF");
int state = button.getState();
if (state == HIGH)
{
//Serial.println("The switch: OFF");
}
else
{
//Serial.println("The switch: ON");
}
server.handleClient();
unsigned long currentMillis = millis();
if (currentMillis - prevTime >= 1000) {
prevTime = currentMillis;
if (clockMode == 1) {
updateCountdown();
}
FastLED.setBrightness(brightness);
FastLED.show();
}
}
void displayNumber(byte number, byte segment, CRGB color) {
/*
*
__ __ __ __ __ __ __ __ __ 12 13 14
__ __ __ __ __ __ 11 15
__ __ __ __ __ __ 10 16
__ __ __ __ 42 __ __ _9 17
__ __ __ __ __ __ __ __ __ 20 19 18
__ 67 __ 46 43 __ 21 _8 _0
__ __ __ __ __ __ _7 _1
__ __ __ __ __ __ _6 _2
__ __ __ __ __ __ __ __ __ _5 _4 _3
*/
// segment from left to right: 3, 2, 1, 0
byte startindex = 0;
switch (segment) {
case 0:
startindex = 0;
break;
case 1:
startindex = 21;
break;
case 2:
startindex = 46;
break;
case 3:
startindex = 67;
break;
}
for (byte i=0; i<21; i++){
yield();
LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? color : alternateColor;
}
}
void allBlank() {
for (int i=0; i<NUM_LEDS; i++) {
LEDs[i] = CRGB::Black;
}
FastLED.show();
}
void updateCountdown() {
if (countdownMilliSeconds == 0 && endCountDownMillis == 0)
return;
unsigned long restMillis = endCountDownMillis - millis();
unsigned long hours = ((restMillis / 1000) / 60) / 60;
unsigned long minutes = (restMillis / 1000) / 60;
unsigned long seconds = restMillis / 1000;
int remSeconds = seconds - (minutes * 60);
int remMinutes = minutes - (hours * 60);
Serial.print(restMillis);
Serial.print(" ");
Serial.print(hours);
Serial.print(" ");
Serial.print(minutes);
Serial.print(" ");
Serial.print(seconds);
Serial.print(" | ");
Serial.print(remMinutes);
Serial.print(" ");
Serial.println(remSeconds);
byte h1 = hours / 10;
byte h2 = hours % 10;
byte m1 = remMinutes / 10;
byte m2 = remMinutes % 10;
byte s1 = remSeconds / 10;
byte s2 = remSeconds % 10;
CRGB color = countdownColor;
if (restMillis <= 30000) {
color = CRGB::Red;
}
if (hours > 0) {
// hh:mm
displayNumber(h1,3,color);
displayNumber(h2,2,color);
displayNumber(m1,1,color);
displayNumber(m2,0,color);
} else {
// mm:ss
displayNumber(m1,3,color);
displayNumber(m2,2,color);
displayNumber(s1,1,color);
displayNumber(s2,0,color);
}
displayDots(color);
if (hours <= 0 && remMinutes <= 0 && remSeconds <= 0) {
Serial.println("Countdown timer ended.");
//endCountdown();
countdownMilliSeconds = 0;
endCountDownMillis = 0;
digitalWrite(COUNTDOWN_OUTPUT, HIGH);
return;
}
}
void endCountdown() {
allBlank();
for (int i=0; i<NUM_LEDS; i++) {
if (i>0)
LEDs[i-1] = CRGB::Black;
LEDs[i] = CRGB::Red;
FastLED.show();
delay(25);
}
}
void displayDots(CRGB color) {
if (dotsOn) {
LEDs[42] = color;
LEDs[43] = color;
LEDs[44] = CRGB::Black;
LEDs[45] = CRGB::Black;
} else {
LEDs[42] = CRGB::Black;
LEDs[43] = CRGB::Black;
LEDs[44] = color;
LEDs[45] = color;
}
dotsOn = !dotsOn;
}
void hideDots() {
LEDs[42] = CRGB::Black;
LEDs[43] = CRGB::Black;
LEDs[44] = CRGB::Black;
LEDs[45] = CRGB::Black;
}
Example of original webpage to read :
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>7 Segment Clock</title>
</head>
<body>
<body>
<div class="row" style="margin: 10px 10px;">
<div class="col-12">
<div class="card">
<div class="card-body">
<form method="POST">
<label>Time</label>
<div class="form-row">
<div class="col input-group mb-3">
<input type="text" class="form-control" value="00" id="hours">
<div class="input-group-append">
<span class="input-group-text">h</span>
</div>
</div>
<div class="col input-group mb-3">
<input type="text" class="form-control" value="15" id="minutes">
<div class="input-group-append">
<span class="input-group-text">m</span>
</div>
</div>
<div class="col input-group mb-3">
<input type="text" class="form-control" value="00" id="seconds">
<div class="input-group-append">
<span class="input-group-text">s</span>
</div>
</div>
</div>
<div>
<div>
<button type="button" class="btn btn-primary" onclick="startCountdown()">Start Countdown
Timer</button>
</div>
</div>
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript" src="moment-with-locales.js"></script>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
What the esp read :
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>7 Segment Clock</title>
</head>
<body>
<body>
<div class="row" style="margin: 10px 10px;">
<div class="col-12">
<div class="card">
<div class="card-body">
<form method="POST">
<label>Time</label>
<div class="form-row">