#include <FastLED.h> //https://github.com/FastLED/FastLED
#include <LEDMatrix.h> //https://github.com/Jorgen-VikingGod/LEDMatrix
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "RTClib.h"
#define DATA_PIN 2
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
// initial matrix layout (to get led strip index by x/y)
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
#define MATRIX_TYPE VERTICAL_MATRIX
#define MATRIX_SIZE (MATRIX_WIDTH * MATRIX_HEIGHT)
#define NUMPIXELS MATRIX_SIZE
cLEDMatrix<MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_TYPE> leds;
#include <ESP8266WebServer.h> //pour pouvoir changer les couleurs des leds à partir d'une page web
ESP8266WebServer server(80); //déclare le webserver
RTC_DS3231 rtc; //déclare le module RTC
WiFiUDP ntpUDP; //déclare le serveur de temps externe
NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000); //7200 pour le fuseau horaire + 2h
int S, M, H;
int hueH = 0; //valeur hue des leds affichant l'heure , hue max avec fast led 255
int hueM = 160; //valeur hue des leds affichant les minutes
int hueS = 96; //valeur hue des leds affichant les secondes
int saturation = 255; //saturation
int bright = 130; //luminosité des leds
const char* ssid = "xxxxxxxxxxx"; //nom du wifi
const char* password = "yyyyyyyyyyyyy"; //mdp du wifi
uint16_t miseAjourHeure = 0; //pour mettre à jour l'heure par le serveur de temps toutes les heures
void setup() {
Serial.begin(57600);
WiFi.begin(ssid, password); //initialise wifi
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Imprime l'adresse IP sur la console série
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: " + WiFi.localIP().toString());
if (!rtc.begin()) { //initialise module RTC
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
timeClient.begin(); //initialise le serveur de temps
updateHeure(); //void pour mettre à jour l'heure avec le serveur de temps
server.on("/", HTTP_GET, handleRoot); //initialise le web server
server.on("/values", HTTP_GET, handleValues);
server.begin();
FastLED.addLeds<CHIPSET, DATA_PIN, COLOR_ORDER>(leds[0], leds.Size()).setCorrection(TypicalSMD5050);
FastLED.setCorrection(TypicalLEDStrip);
//FastLED.setBrightness(100);
FastLED.clear(true); // on éteint toutes les LEDs
}
void loop() {
delay(1000);
miseAjourHeure += 1;
if (miseAjourHeure == 3600) { //remet à jour l'heure par le serveur de temps à intervalle régulier, ici toutes les heures
miseAjourHeure = 0;
updateHeure();
}
/*pour DEBUG
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();*/
server.handleClient(); //pour lire couleurs envoyées au serveur web par la page web d'un navigateur
FastLED.clear(true); // on éteint toutes les LEDs
DateTime now = rtc.now();
H = now.hour();
M = now.minute();
S = now.second();
//procédure pour mettre chaque valeur sur 2 digits
int Hd = (H / 10U) % 10; //premier digit des heures
int Hu = (H / 1U) % 10; //deuxieme digit des heures
int Md = (M / 10U) % 10; //premier digit des minutes
int Mu = (M / 1U) % 10; //deuxieme digit des minutes
int Sd = (S / 10U) % 10; //premier digit des secondes
int Su = (S / 1U) % 10; //deuxieme digit des secondes
switch (Hu) {
case 0:
leds.DrawPixel(1, 0, CHSV(0, 0, 0));
leds.DrawPixel(1, 2, CHSV(0, 0, 0));
leds.DrawPixel(1, 4, CHSV(0, 0, 0));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 1:
leds.DrawPixel(1, 0, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 2, CHSV(0, 0, 0));
leds.DrawPixel(1, 4, CHSV(0, 0, 0));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 2:
leds.DrawPixel(1, 0, CHSV(0, 0, 0));
leds.DrawPixel(1, 2, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 4, CHSV(0, 0, 0));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 3:
leds.DrawPixel(1, 0, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 2, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 4, CHSV(0, 0, 0));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 4:
leds.DrawPixel(1, 0, CHSV(0, 0, 0));
leds.DrawPixel(1, 2, CHSV(0, 0, 0));
leds.DrawPixel(1, 4, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 5:
leds.DrawPixel(1, 0, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 2, CHSV(0, 0, 0));
leds.DrawPixel(1, 4, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 6:
leds.DrawPixel(1, 0, CHSV(0, 0, 0));
leds.DrawPixel(1, 2, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 4, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 7:
leds.DrawPixel(1, 0, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 2, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 4, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 6, CHSV(0, 0, 0));
break;
case 8:
leds.DrawPixel(1, 0, CHSV(0, 0, 0));
leds.DrawPixel(1, 2, CHSV(0, 0, 0));
leds.DrawPixel(1, 4, CHSV(0, 0, 0));
leds.DrawPixel(1, 6, CHSV(hueH, saturation, bright));
break;
case 9:
leds.DrawPixel(1, 0, CHSV(hueH, saturation, bright));
leds.DrawPixel(1, 2, CHSV(0, 0, 0));
leds.DrawPixel(1, 4, CHSV(0, 0, 0));
leds.DrawPixel(1, 6, CHSV(hueH, saturation, bright));
break;
}
switch (Hd) {
case 0:
leds.DrawPixel(0, 0, CHSV(0, 0, 0));
leds.DrawPixel(0, 2, CHSV(0, 0, 0));
break;
case 1:
leds.DrawPixel(0, 0, CHSV(hueH, saturation, bright));
leds.DrawPixel(0, 2, CHSV(0, 0, 0));
break;
case 2:
leds.DrawPixel(0, 0, CHSV(0, 0, 0));
leds.DrawPixel(0, 2, CHSV(hueH, saturation, bright));
break;
}
switch (Mu) {
case 0:
leds.DrawPixel(4, 0, CHSV(0, 0, 0));
leds.DrawPixel(4, 2, CHSV(0, 0, 0));
leds.DrawPixel(4, 4, CHSV(0, 0, 0));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 1:
leds.DrawPixel(4, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 2, CHSV(0, 0, 0));
leds.DrawPixel(4, 4, CHSV(0, 0, 0));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 2:
leds.DrawPixel(4, 0, CHSV(0, 0, 0));
leds.DrawPixel(4, 2, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 4, CHSV(0, 0, 0));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 3:
leds.DrawPixel(4, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 2, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 4, CHSV(0, 0, 0));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 4:
leds.DrawPixel(4, 0, CHSV(0, 0, 0));
leds.DrawPixel(4, 2, CHSV(0, 0, 0));
leds.DrawPixel(4, 4, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 5:
leds.DrawPixel(4, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 2, CHSV(0, 0, 0));
leds.DrawPixel(4, 4, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 6:
leds.DrawPixel(4, 0, CHSV(0, 0, 0));
leds.DrawPixel(4, 2, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 4, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 7:
leds.DrawPixel(4, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 2, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 4, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 6, CHSV(0, 0, 0));
break;
case 8:
leds.DrawPixel(4, 0, CHSV(0, 0, 0));
leds.DrawPixel(4, 2, CHSV(0, 0, 0));
leds.DrawPixel(4, 4, CHSV(0, 0, 0));
leds.DrawPixel(4, 6, CHSV(hueM, saturation, bright));
break;
case 9:
leds.DrawPixel(4, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(4, 2, CHSV(0, 0, 0));
leds.DrawPixel(4, 4, CHSV(0, 0, 0));
leds.DrawPixel(4, 6, CHSV(hueM, saturation, bright));
break;
}
switch (Md) {
case 0:
leds.DrawPixel(3, 0, CHSV(0, 0, 0));
leds.DrawPixel(3, 2, CHSV(0, 0, 0));
leds.DrawPixel(3, 4, CHSV(0, 0, 0));
break;
case 1:
leds.DrawPixel(3, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(3, 2, CHSV(0, 0, 0));
leds.DrawPixel(3, 4, CHSV(0, 0, 0));
break;
case 2:
leds.DrawPixel(3, 0, CHSV(0, 0, 0));
leds.DrawPixel(3, 2, CHSV(hueM, saturation, bright));
leds.DrawPixel(3, 4, CHSV(0, 0, 0));
break;
case 3:
leds.DrawPixel(3, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(3, 2, CHSV(hueM, saturation, bright));
leds.DrawPixel(3, 4, CHSV(0, 0, 0));
break;
case 4:
leds.DrawPixel(3, 0, CHSV(0, 0, 0));
leds.DrawPixel(3, 2, CHSV(0, 0, 0));
leds.DrawPixel(3, 4, CHSV(hueM, saturation, bright));
break;
case 5:
leds.DrawPixel(3, 0, CHSV(hueM, saturation, bright));
leds.DrawPixel(3, 2, CHSV(0, 0, 0));
leds.DrawPixel(3, 4, CHSV(hueM, saturation, bright));
break;
}
switch (Su) {
case 0:
leds.DrawPixel(7, 0, CHSV(0, 0, 0));
leds.DrawPixel(7, 2, CHSV(0, 0, 0));
leds.DrawPixel(7, 4, CHSV(0, 0, 0));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 1:
leds.DrawPixel(7, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 2, CHSV(0, 0, 0));
leds.DrawPixel(7, 4, CHSV(0, 0, 0));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 2:
leds.DrawPixel(7, 0, CHSV(0, 0, 0));
leds.DrawPixel(7, 2, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 4, CHSV(0, 0, 0));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 3:
leds.DrawPixel(7, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 2, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 4, CHSV(0, 0, 0));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 4:
leds.DrawPixel(7, 0, CHSV(0, 0, 0));
leds.DrawPixel(7, 2, CHSV(0, 0, 0));
leds.DrawPixel(7, 4, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 5:
leds.DrawPixel(7, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 2, CHSV(0, 0, 0));
leds.DrawPixel(7, 4, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 6:
leds.DrawPixel(7, 0, CHSV(0, 0, 0));
leds.DrawPixel(7, 2, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 4, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 7:
leds.DrawPixel(7, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 2, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 4, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 6, CHSV(0, 0, 0));
break;
case 8:
leds.DrawPixel(7, 0, CHSV(0, 0, 0));
leds.DrawPixel(7, 2, CHSV(0, 0, 0));
leds.DrawPixel(7, 4, CHSV(0, 0, 0));
leds.DrawPixel(7, 6, CHSV(hueS, saturation, bright));
break;
case 9:
leds.DrawPixel(7, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(7, 2, CHSV(0, 0, 0));
leds.DrawPixel(7, 4, CHSV(0, 0, 0));
leds.DrawPixel(7, 6, CHSV(hueS, saturation, bright));
break;
}
switch (Sd) {
case 0:
leds.DrawPixel(6, 0, CHSV(0, 0, 0));
leds.DrawPixel(6, 2, CHSV(0, 0, 0));
leds.DrawPixel(6, 4, CHSV(0, 0, 0));
break;
case 1:
leds.DrawPixel(6, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(6, 2, CHSV(0, 0, 0));
leds.DrawPixel(6, 4, CHSV(0, 0, 0));
break;
case 2:
leds.DrawPixel(6, 0, CHSV(0, 0, 0));
leds.DrawPixel(6, 2, CHSV(hueS, saturation, bright));
leds.DrawPixel(6, 4, CHSV(0, 0, 0));
break;
case 3:
leds.DrawPixel(6, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(6, 2, CHSV(hueS, saturation, bright));
leds.DrawPixel(6, 4, CHSV(0, 0, 0));
break;
case 4:
leds.DrawPixel(6, 0, CHSV(0, 0, 0));
leds.DrawPixel(6, 2, CHSV(0, 0, 0));
leds.DrawPixel(6, 4, CHSV(hueS, saturation, bright));
break;
case 5:
leds.DrawPixel(6, 0, CHSV(hueS, saturation, bright));
leds.DrawPixel(6, 2, CHSV(0, 0, 0));
leds.DrawPixel(6, 4, CHSV(hueS, saturation, bright));
break;
}
FastLED.show();
}
void handleRoot() { //landing page quand on entre uniquement l'IP de la carte sur une page web
String phrase = "<html><head><title>Horloge binaire server</title><style>body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background-color:#121212;color: #eee;line-height:1.5;}";
phrase += "button { width: 100%; padding: 7px; background-color: #007BFF; color: #eeeeee; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; }";
phrase += "button:hover { background-color: #0056b3; }";
phrase += "form { max-width: 250px; margin: auto; padding: 20px; background-color: #1e1e1e; border-radius: 8px;}";
phrase += "h1 { text-align: center; }";
phrase += "</style></head><body>";
phrase += "<h1>Bienvenue sur le serveur web de l'horloge binaire (Wemos D1 Mini)</h1>";
phrase += "<form id='urlForm'><button type='button' onclick='rediriger()'>Paramètres</button></form>";
phrase += "<script type='text/javascript'>";
phrase += "function rediriger() {window.location.href = 'http://" + WiFi.localIP().toString() + "/values?hueH=70&hueM=170&hueS=250&saturation=255&bright=180';}";
phrase += "</script></body></html>";
server.send(200, "text/html", phrase); //si on met "text/plain" ça écrit litéralement le texte sans mise en forme html
}
void handleValues() {
// Récupérer les paramètres de l'URL
hueH = server.arg("hueH").toInt();
hueM = server.arg("hueM").toInt();
hueS = server.arg("hueS").toInt();
saturation = server.arg("saturation").toInt();
bright = server.arg("bright").toInt();
// Répondre à la requête
String response = "<html><head><title>Horloge binaire server</title><style>body {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;background-color:#121212;color: #eee;line-height:1.1;}";
response += "form{ max-width: 230px; margin: auto; padding: 20px; background-color: #1e1e1e; border-radius: 8px;}";
response += "input[type='text'] {width:100%; padding: 5px; margin-bottom: 5px; border: 1px solid #444;background-color: #2c2c2c; color: #eeeeee; border-radius: 4px; box-sizing: border-box; font-size: 16px;}";
response += "button { width: 100%; padding: 10px; background-color: #007BFF; color: #eeeeee; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; }";
response += "button:hover { background-color: #0056b3; }";
response += "h1,h2,p{ text-align: center; }";
response += "label { display: block; margin-bottom: 5px; font-weight: bold;color: #eeeeee; }";
response += ".center {display:block;margin:auto;}";
response += "</style></head><body>";
response += "<h1>Bienvenue sur le serveur web de la Wemos D1 Mini</h1>";
response += "<form id='urlForm'>";
response += "<label for='IP'>IP de la carte </label>";
response += "<input type='text' id='IP' name='IP' placeholder='" + WiFi.localIP().toString() + "' required>";
response += "<label for='hueH'>Couleur des heures </label>";
response += "<input type='text' id='hueH' name='hueH' placeholder='0 -> 255' required>";
response += "<label for='hueM'>Couleur des minutes </label>";
response += "<input type='text' id='hueM' name='hueM' placeholder='0 -> 255' required>";
response += "<label for='hueS'>Couleur des secondes </label>";
response += "<input type='text' id='hueS' name='hueS' placeholder='0 -> 255' required>";
response += "<label for='saturation'>Saturation </label>";
response += "<input type='text' id='saturation' name='saturation' placeholder='0 -> 255' required>";
response += "<label for='bright'>Luminosité </label>";
response += "<input type='text' id='bright' name='bright' placeholder='0 -> 255' required>";
response += "<button type='button' onclick='generateURL()'>Confirmer</button>";
response += "</form>";
response += "<script>";
response += "function generateURL() {";
response += " var IP = document.getElementById('IP').value;";
response += " var hueH = document.getElementById('hueH').value;";
response += " var hueM = document.getElementById('hueM').value;";
response += " var hueS = document.getElementById('hueS').value;";
response += " var saturation = document.getElementById('saturation').value;";
response += " var bright = document.getElementById('bright').value;";
response += " if (!IP || !hueH || !hueM || !hueS || !saturation || !bright) {alert('Veuillez remplir toutes les cases.');return;}";
response += " var url = 'http://' + IP + '/values?hueH=' + hueH + '&hueM=' + hueM + '&hueS=' + hueS + '&saturation=' + saturation + '&bright=' + bright;";
response += " window.location.href = url;}";
response += "window.onload = function() {"; //pour pré-remplir les cases
response += " document.getElementById('IP').value = '" + WiFi.localIP().toString() + "';";
response += " document.getElementById('hueH').value = '" + String(hueH) + "';";
response += " document.getElementById('hueM').value = '" + String(hueM) + "';";
response += " document.getElementById('hueS').value = '" + String(hueS) + "';";
response += " document.getElementById('saturation').value = '" + String(saturation) + "';";
response += " document.getElementById('bright').value = '" + String(bright) + "';}";
response += "</script>";
response += "<h2>Quelques informations :</h2>";
response += "<p>Heure actuelle : " + timeClient.getFormattedTime() + "</p>";
response += "<p>Nom de la carte : Wemos D1 mini ESP-60A572</p>";
response += "<p>SSID connecté : " + WiFi.SSID() + "</p>";
response += "<p>Adresse IP : " + WiFi.localIP().toString() + "</p>";
response += "<p>Version du SDK : " + String(ESP.getSdkVersion()) + "</p>";
response += "<h2>Palette des couleurs Fastled</h2>";
response += "<img src=https://i.goopics.net/paklx5.jpg class='center'>"; //image
response += "</body></html>";
server.send(200, "text/html", response);
}
void updateHeure() {
timeClient.update();
rtc.adjust(DateTime(2024, 2, 8, timeClient.getHours(), timeClient.getMinutes(), timeClient.getSeconds()));
}