/*********************************
pour acceder à la page web, taper jauge.local dans une barre de recherche ou 192.168.4.1
connection de l'ecran lcd 16*02 en I2C
vcc 5v
gnd
SDA GPIO 21
SCL GPIO 22
CAPTEUR DE PRESSION AU GPIO 34
*********************************/
#include <WiFi.h>
#include <WebServer.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#include <ESPmDNS.h>
const char *ssid = "jauge";
const char *password = "";
WebServer server(80);
int numValues = 2;
int *inValues;
int *outValues;
const int windowSize = 50;
int sensorValues[windowSize];
int currentIndex = 0;
int runningTotal = 0;
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int bufferSize = 1200; // tableau pour stocker la valeur de niveau d'eau, la nouvelle ajoutée chasse la derniere , si previousmillis de 600s mettre 1200 car on ajoute 1 valeur toutes les 500ms
int remappedBuffer[bufferSize];
unsigned long previousMillis = 0;
float flowRate = 0.0;
void loadValuesFromEEPROM() {
EEPROM.get(0, numValues);
inValues = new int[numValues];
outValues = new int[numValues];
for (int i = 0; i < numValues; i++) {
EEPROM.get(sizeof(int) + i * sizeof(int), inValues[i]);
EEPROM.get(sizeof(int) + (numValues + i) * sizeof(int), outValues[i]);
}
}
void saveValuesToEEPROM() {
EEPROM.put(0, numValues);
for (int i = 0; i < numValues; i++) {
EEPROM.put(sizeof(int) + i * sizeof(int), inValues[i]);
EEPROM.put(sizeof(int) + (numValues + i) * sizeof(int), outValues[i]);
}
EEPROM.commit();
}
void handleRoot() {
String valuesHtml = "<!DOCTYPE html><html lang='fr'><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'><title>Tableaux de valeurs de remappage</title><style>table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid black; padding: 8px; text-align: center; } th { background-color: #f2f2f2; } .submit-btns { text-align: center; margin-top: 10px; } .reset-btn { background-color: #ff6666; width: 25%; } .reset-btn:hover { background-color: #ff3333; } .save-btn { background-color: #66ff66; width: 72%; } .save-btn:hover { background-color: #33ff33; } input[type='text'] { width: 100%; box-sizing: border-box; } </style></head><body><h1>Tableaux de valeurs de remappage</h1><form action='/update' method='post'><label for='numValues'>Nombre de valeurs (numValues): </label><input type='number' id='numValues' name='numValues' value='" + String(numValues) + "' min='1' max='10'><br><br><table><tr><th>Index</th><th>Entrée</th><th>Sortie</th></tr>";
for (int i = 0; i < numValues; i++) {
valuesHtml += "<tr><td>" + String(i) + "</td><td><input type='text' name='entrée" + String(i) + "' value='" + String(inValues[i]) + "'></td><td><input type='text' name='sortie" + String(i) + "' value='" + String(outValues[i]) + "'></td></tr>";
}
valuesHtml += "</table><div class='submit-btns'><form action='/reset' method='post' style='display: inline-block; margin-right: 10px;'><input type='submit' value='Reset EEPROM' class='reset-btn'></form><input type='submit' value='Save' class='save-btn'></div></form></body></html>";
server.send(200, "text/html", valuesHtml);
}
void handleUpdate() {
numValues = server.arg("numValues").toInt(); // Mettre à jour le nombre de valeurs
// Supprimer les anciens tableaux
delete[] inValues;
delete[] outValues;
// Allouer de nouveaux tableaux avec la taille mise à jour
inValues = new int[numValues];
outValues = new int[numValues];
// Récupérer et mettre à jour les valeurs du formulaire
for (int i = 0; i < numValues; i++) {
inValues[i] = server.arg("entrée" + String(i)).toInt();
outValues[i] = server.arg("sortie" + String(i)).toInt();
}
// Enregistrer les nouvelles valeurs dans la mémoire EEPROM
saveValuesToEEPROM();
// Rediriger vers la page principale après la mise à jour
server.sendHeader("Location", String("/"), true);
server.send(302, "text/plain", "");
}
void handleReset() {
for (int i = 0; i < 512; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
server.sendHeader("Location", String("/"), true);
server.send(302, "text/plain", "");
}
void setup() {
Serial.begin(115200);
WiFi.softAP(ssid, password);
Serial.println("ESP32 AP Started");
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
EEPROM.begin(512);
inValues = new int[numValues];
outValues = new int[numValues];
loadValuesFromEEPROM();
if (!MDNS.begin("jauge")) {
Serial.println("Erreur lors de l'initialisation mDNS");
while (1);
}
Serial.println("mDNS a été initialisé");
MDNS.addService("http", "tcp", 80);
server.on("/", HTTP_GET, handleRoot);
server.on("/update", HTTP_POST, handleUpdate);
server.on("/reset", HTTP_POST, handleReset);
server.begin();
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("**jauge pulve**");
delay(3000);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("WIFI ACCESS POINT");
delay(3000);
lcd.clear();
}
void updateFlowRate(int remappedValue) {
for (int i = bufferSize - 1; i > 0; i--) {
remappedBuffer[i] = remappedBuffer[i - 1];
}
remappedBuffer[0] = remappedValue;
int diff = remappedBuffer[bufferSize - 1] - remappedBuffer[0]; // pour calculer le debit valeur la plus ancienne du buffer - valeur actuelle
if (millis() - previousMillis >= 600000) { // ici 600s soit 10 mn , donc le volume perdu en 10mn
flowRate = float(diff) / 10; // diviser par 10 pour trouver le debit / mn
previousMillis = millis();
}
}
float calculateFlowRate() {
return flowRate;
}
void loop() {
// Variable statique pour mesurer le temps écoulé
static unsigned long chrono = 0;
// Traitement des clients
server.handleClient();
// Vérifie si le temps écoulé est supérieur ou égal à 500 millisecondes
if (millis() - chrono >= 500) {
// Met à jour le chrono avec le temps actuel
chrono = millis();
// Lit la valeur analogique du capteur connecté à la broche 34
int sensorValue = analogRead(34);
// Calcul de la moyenne mobile pondérée
runningTotal -= sensorValues[currentIndex]; // Soustrait la valeur précédente
sensorValues[currentIndex] = sensorValue; // Met à jour la valeur actuelle
runningTotal += sensorValue; // Ajoute la nouvelle valeur
int movingAverage = runningTotal / windowSize; // Calcule la moyenne mobile
// Remappage de la valeur lue à un autre ensemble de valeurs
int remappedValue = movingAverage;
int selectedInValue = -1;
// Parcours des valeurs d'entrée
for (int i = 0; i < numValues - 1; i++) {
// Vérifie si la moyenne mobile se situe entre deux valeurs d'entrée
if (movingAverage >= inValues[i] && movingAverage <= inValues[i + 1]) {
// Sélectionne la valeur d'entrée correspondante
selectedInValue = inValues[i];
// Remappe la moyenne mobile à l'échelle des valeurs de sortie
remappedValue = map(movingAverage, inValues[i], inValues[i + 1], outValues[i], outValues[i + 1]);
break;
}
}
updateFlowRate(remappedValue);
float currentFlowRate = calculateFlowRate();
Serial.print("Valeur brute : ");
Serial.print(sensorValue);
Serial.print(", Moyenne mobile : ");
Serial.print(movingAverage);
Serial.print(", Valeur inValue utilisée : ");
Serial.print(selectedInValue);
Serial.print(", Valeur remappée : ");
Serial.print(remappedValue);
Serial.print(", Débit : ");
Serial.println(currentFlowRate);
int roundedValue = round(remappedValue / 10.0) * 10;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(roundedValue);
lcd.setCursor(5, 0);
lcd.print("L");
lcd.setCursor(8, 0);
if (currentFlowRate >= 10) {
lcd.print(int(currentFlowRate)); // Affiche la partie entière uniquement
} else {
lcd.print(currentFlowRate, 1); // Affiche currentFlowRate avec 1 chiffre après la virgule
}
lcd.setCursor(12, 0);
lcd.print("l/mn");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(movingAverage);
lcd.setCursor(11, 1);
lcd.print(" ");
lcd.setCursor(11, 1);
lcd.print(sensorValue);
currentIndex = (currentIndex + 1) % windowSize;
}
}