Bonjour à tous, je reprends quasiment à zéro un serveur synchrone multitâche, essentiellement autour d'un contrôle de tension de batterie solaire 12v avec alarme (petite installation de balcon avec régulateur et onduleur 220v). La conversion du CAN en volts est modérée par une variable moderVolt que je voudrais pouvoir modifier à la volée, ainsi que les niveaux de déclenchement d'alarme par la suite. Je passe par un enregistrement/lecture data SPIFF de cette variable, mémorisé dans la SRAM RTC (essai pour économiser la mémoire flash en écriture plus tard).
Ce qui est simple quand on veut allumer ou éteindre une led l'est moins pour des actions ponctuelles car la fonction est rappelée à chaque tour de serveur. Par exemple ici j'appelle ma fonction buzzA qui excite le buzzer. Il se lançait à chaque tour.
Quelle est la méthode rationnelle pour que l'action n'ait lieu qu'une seule fois ? J'ai trouvé une solution fonctionnelle mais est-ce acceptable ? Merci d'avance :
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
buzzA(20);
//XXXXXXXXXXXXXXXXXX Redirection HTTP vers une autre URL
client.println("HTTP/1.1 303 See Other");
client.println("Location: 192.168.1.27"); // URL vers laquelle rediriger (racine dans cet exemple)
client.println();
---------------------------------------------------- code complet :
/*
cf bas de pasge
230708 Intégrer SPIFF pour initier moderVolt à partir de la mémoire Flash (répertoire data)
POR-004 : init moderVar par SPIFF // retour aux essais SPIFFS pour ligne (pas tt le fichier)
fonction ligne OK, lecture float première ligne ok, affectation à la variable moderVolt si on est au premier boot (RTC)
-----
20:05 08/07/2023
PROBLEME DE BOUCLAGE FOU
ça se passe dans la partie SPIFF, probablement le cast .. :(
005 ok avec ess mais il faut trouver comment le caster
OK reste à implémenter les input GET pour modifier moderVolt
*/
#include <WiFi.h>
//void buzzA(int tim=10);
// *************************** SPIFF
#include "SPIFFS.h"
const char* ssid = "nanonex";
const char* password = "avocatier@bizarretyuC1901";
const char* adresseFichierSource = __FILE__;
String moderVoltR = ""; // lecture String pour cast float
//****************************************************************
//float moderVolt=18.8; // pour facteur de moderation CAN mesure volts
//char ess="";
// ******************************************************************
WiFiServer server(80);
#define LED_PIN 12
#define BUZ_PIN 27
// DEEP SLEEP --------
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 4 /* Time ESP32 will go to sleep (in seconds) */
//************************
RTC_DATA_ATTR int bootCount = 0; // compteur en mémoire RTC (SRAM)
RTC_DATA_ATTR float moderVolt=0; // moderVolt en mémoire RTC (SRAM)
// Undeclock --------
uint32_t Freq = 0; // pour underclocking
//------>
// RAFRAICHISSEMENT : retrouver comment rafraichir seulement la donnée
unsigned long refreshInterval = 5000; // Rafraîchissement toutes les n secondes
//----- CAN INIT
const int anaPin = 34;
int anaValue = 0;
float tension =0;
float moy=0;
float moyF=0; // moyenne finale
// -------->
void setup(){ // ============= SETUP ========================================================
// ----- Underclocking -----------------------------------
setCpuFrequencyMhz(240); // setup fréquence cpu de départ
//-------------------------------------------------------
Freq = getCpuFrequencyMhz(); // lecture des fréquences (ici on s'intéressera au CPU)
Serial.begin(115200);
delay(1000);
// ****** SPIFF ************************************************************************
// seulement au premier tour pour ne pas user la mémoire et perdre du temps et du cpu:
Serial.println("Boot number: " + String(bootCount));
if (bootCount==0){
Serial.println("XXXXXXXXXXXXXXX PREMIER TOUR XXXXXXXXXXXXXXXXXX");
if(!SPIFFS.begin(true)){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
//---------- Lecture et CAST de moderVolt --------------
Serial.println(" ------ Récup moderVolt sur SPIFF : -------->");
moderVoltR=read_lineB (1);
moderVolt = moderVoltR.toFloat();
Serial.println(moderVoltR);
Serial.println(moderVolt);
}
// *********** SPIFF **************************** >
Serial.print("CPU Freq = ");
Serial.print(Freq);
Serial.println(" MHz");
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Boot number: " + String(bootCount));
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // Setup réveil
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
" Seconds");
//----- CAN, BUZ, LED SETUP
pinMode(anaPin,INPUT_PULLUP);
pinMode(BUZ_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
delay(20);
digitalWrite(LED_PIN, LOW);
// path fichier source
Serial.print("AdresseFichierSource: ");
Serial.println(adresseFichierSource);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
//esp_wifi_start();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
// int value = 0;
// ================================= LOOP =====================================================================
void loop(){
//------------ PARTIE CAN DE LOOP --------
for(int i=1; i<=5; i++) {
anaValue = analogRead(anaPin);
// ****************************************************************************************
// Conversion mesure CAN to Volts avec facteur de modération moderVolt casté, lu par SPIFF.
tension = anaValue * (moderVolt / 4096.0);
//*****************************************************************************************
Serial.println(anaValue);
Serial.println(tension);
moy=moy+tension;
// --------- LISSAGE -------
if (i==5) {
moy = moy/5;
moyF= moy;
Serial.print(" ");
Serial.println(moyF);
if (moyF < 12.15){
digitalWrite(LED_PIN, HIGH);
buzzA(20);
}
else{
digitalWrite(LED_PIN, LOW);
}
if (moyF < 12.05){
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZ_PIN,HIGH);
delay(30);//wait for 1ms
digitalWrite(BUZ_PIN,LOW);
}
moy=0;
}
delay(200);
}
// -------------->
// ============ SERVEUR ===============================================
Serial.println("");
Serial.println("<<<<<<<<<<< SERVEUR IN <<<<<<<<<");
for(int ii=1; ii<=5; ii++) { // sous-boucle serveur pour qu'il dure un peu
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// ----------- rafraîchissement ----------------------
client.println("<html>");
client.println("<head>");
client.println("<meta http-equiv=\"refresh\" content=\"" + String(refreshInterval / 1000) + "\">");
client.println("</head>");
client.println("<body>");
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> turn the LED on pin 2 ON<br>");
client.print("Click <a href=\"/L\">here</a> turn the LED on pin 2 OFF<br>");
//======================================= CH ==========================================================
client.print(WiFi.localIP());
client.print("<br>");
client.print(moyF);
client.print("<br>");
//=================================================>
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(LED_PIN, HIGH); // GET /H turns the LED on
buzzA(20);
//XXXXXXXXXXXXXXXXXX Redirection HTTP vers une autre URL
client.println("HTTP/1.1 303 See Other");
client.println("Location: 192.168.1.27"); // URL vers laquelle rediriger (racine dans cet exemple)
client.println();
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(LED_PIN, LOW); // GET /L turns the LED off
buzzA(100);
//XXXXXXXXXXXXXXXXXX Redirection HTTP vers une autre URL
client.println("HTTP/1.1 303 See Other");
client.println("Location: 192.168.1.27"); // URL vers laquelle rediriger (racine dans cet exemple)
client.println();
}
}
}
// close the connection:
client.stop();
Serial.println("client disconnected");
} // end of 'if client'
delay(1000);
}// fin sous boucle serveur
Serial.println(">>>>>>>>>>>>>>> OUT >>>>>>>>>>>>");
// XXXXXXXXXXXXXXXX
Serial.println("Going to sleep now");
// Serial.flush();
// esp_deep_sleep_start();
} // LOOP -->
void buzzA(int tim){
unsigned char i;
//output a frequency
for(i=0;i<1;i++)
{
digitalWrite(BUZ_PIN,HIGH);
delay(tim);//wait for 1ms
digitalWrite(BUZ_PIN,LOW);
}
}
// ============================= read_lineB ============== <
String read_lineB (int lineNum){
File file = SPIFFS.open("/test.txt", "r");
int i = 1;
char buffer[64];
char* lineR;
while (file.available()) {
int l = file.readBytesUntil('\n', buffer, sizeof(buffer));
buffer[l] = 0;
if (lineNum == i) {
lineR = buffer;
Serial.println("WWWWWWWWWWWWWW");
Serial.println(lineR);
file.close();
break;
}
i++;
}
return (lineR); // XXXXXXXXXXXXXXXXXXXXX
}
// ============= readlineB >
/*
L’ADC n’est pas un point fort de l’ESP32 car il possède de nombreux défauts. Préférez celui de l’Arduino ou utiliser un ADC externe si vous voulez faire des mesures précises.
Avertissement
Même si cela semble étrange, l’ADC de l’Arduino sur 10 bits (1024 valeurs) est plus précis et plus fiable que celui de l’ESP32 sur 12 bits (4096 valeurs).
https://www.upesy.fr/blogs/tutorials/measure-voltage-on-esp32-with-adc-with-arduino-code
Le calibrage se fait en trichant sur la valeur d'entrée (par ex 19.5v au lieu de 11.3)on est en 12 bits / 4096
*/
/*
* ON PART DU SERVEUR ON Y INTEGRE LE CAN
* Tout de suite le besoin de faire un thread pour le serveur se ressent (besoin de delay pour le CAN)
* essai pourl'instant avec delay 1 sec : serveur ok ?
* AF améliorer buzzer: fonction avec arg temps selon gravité
* contrôler valeurs alarme
* ----------
* float moderVolt : mettre à jour la modération 'à chaud' (dans la boucle avec BOUTONS - +)
* MAIS il faut après intégrer ça en fichier config sur flash SPIFF
* MIEUX sera requête extérieure pour pouvoir varier de l'extérieur, ou BOUTON - + sera suffisant ?
* >> requête http important à connaître
* --------
* 230703 Sous boucle serveur (sinon il dure 1 seconde !! (on se dmeande comment il pouvait accrocher
* + diminue le delay du CAN (qui bloque lle début du serveur)
*/