Déclencheur de relais – Interfaces Web et Bluetooth actives simultanément

Intégration des deux interfaces dans le même programme.

Application : Déclencheur d’appareil photo et de flashs

Le relais peut être déclenché par la pression d’un interrupteur, par la coupure d’un faisceau laser, par un bruit fort ou une commande de l’interface Web ou Bluetooth.

Le programme est volumineux, il faut appliquer le partitionnement no_ota, huge_app ou min_spiffs pour s’assurer d’avoir assez d’espace mémoire pour contenir tout le code.


Téléchargement

L’application est divisée en quatre fichiers. Ils doivent être placés dans le même répertoire nommé «Declencheur_de_relais_01-01-00»

https://github.com/rcepmorel/Declencheur-de-relais_Interfaces-Web-et-Bluetooth


Détails des fichiers

connect_id_Wifi.h

Fichier dans lequel vous incorporer les paramètres réseau que vous voulez utiliser

const char* ssid     = "Le nom du réseau WiFi"; // Réseau à accéder
const char* password = "Le mot de passe du réseau WiFI";

const char* ssid_AP = "Nom donné au point d'accès"; // Point d'accès 
const char* password_AP = "Mot de passe donné au point d'accès";


// Set your Static IP address
IPAddress local_IP(192, 168, 1, 141);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);

IPAddress subnet(255, 255, 0, 0);

Declencheur_de_relais_01-01-00

/*      DÉCLENCHEUR DE RELAIS V1.1.0
* 
* Auteur : Richard Morel
*     2018-11-09
* 
* Modification
*     2018-11-17
*     - Mesure du voltage d'entrée
*     - Ajout du clignotement de la DEL bleue
*       Relié sur la broche D33
*    2018-11-30
*     - Ajout du déclencheur de relais
*       Relié sur le GPIO 32
*     - Ajout du détecteur du rayon laser pour déclencher le relais
*       sur la coupure du faisceau
*       Relié sur la GPIO 13
*     - Ajout d'un interrupteur pour déclencher le relais
*       Relié sur la GPIO 25
*     - La DEL bleue suit l'état du détecteur laser
*    2018-11-01
*     - Ajout du serveur WEB
*     - Déplacer l'interrupteur pour déclencher le relais
*       sur le GPIO 26
*     - Remplacement de la DEL bleue par une DEL RGB
*     - La broche «rouge» de la DEL RGB se relie sur GPIO 25
*     - La broche «verte» de la DEL RGB se relie sur GPIO 33
*     2019_01_08
*     - Intégrer l'interface Bluetooth et Web ensemble
*     - PIN_DETECTEUR_LASER_1  D17  Détecteur de faisceau laser soudé directement sur la carte
*     - PIN_DETECTEUR_SONORE   D22  Détecteur de son. Passe à LOW si le son dépasse le seuil fixé 
*     - PIN_BOUTON_DECLENCHEUR D26  Interrupteur
*   
*     
*/

// ----------------------------------------------------------------------------- 
//             Importation des fichiers et définition des variables
// ----------------------------------------------------------------------------- 

//******* Affichage DEL ********
// Afin d'ajuster au besoin l'intensité et la couleur de la DEL, le programme
// fait appel une fonction (ledcWrite) qui module la sortie PWM des broches
// selon la valeur fournie à la fonction
#define LEDC_CHANNEL_0_VERT     0
#define LEDC_CHANNEL_1_ROUGE    1

// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT  13

// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ     5000

#define DELROUGE  25 // DEL rouge reliée au GPIO25
#define DELVERTE  33 // DEL verte reliée au GPIO33

byte byBrightnessVert;
byte byBrightnessRouge;

//******* Convertisseurs Analogique/Numérique ******
#include <driver/adc.h>   
//ADC1_CHANNEL_7 D35 35

//*******   EEPROM   *****************
// Inclure la librairie de lecture et d'écriture de la mémoire flash
#include "EEPROM.h"

// définie le nombre de Bytes que l'on veut accéder
#define EEPROM_SIZE 64

//******  WIFI *********************
#include "connect_id_Wifi.h"
#include <WiFi.h>
WiFiServer server(80);

const char* chStatusWifi[] ={"WL_IDLE_STATUS", "WL_NO_SSID_AVAIL", "-", 
                       "WL_CONNECTED ", "WL_CONNECT_FAILED ", "-",
                       "WL_DISCONNECTED"};

String stWifiConnectionNetwork = "Connecté";

//******  Bluetooth *********************
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;

#define MAX_PACKETSIZE 32   //Tampon de réception en série
char buffUART[MAX_PACKETSIZE];
unsigned int buffUARTIndex = 0;
unsigned long preUARTTick  = 0;

// ***** Mesure de voltage ************  
float flCalibrationDiviseurTsn = 8.02/7.97; // Valeur réelle diviser par
                                            // flVoltMesure lorsque 
                                            // flCalibrationDiviseurTsn
                                            // égal à 1

int inSeuilDeVoltage = 7;              // Niveau d'alerte de basse tension 
                                       // de l'alimentation d'entrée

float flReading;
float flVoltAlimCtrlReduit;
float flVoltMesure;


//*****  Interupteurs, détecteurs et sorties ******** 
#define PIN_ACTIVE_RELAIS      32       // Sortie pour déclencher le relais
#define PIN_DETECTEUR_LASER_1  17       // Détecte une MALT à l'entrée D17
                                        // Détecteur fixe sur la plaquette
#define PIN_DETECTEUR_SONORE   22       // Détecte une MALT à l'entrée D22
#define PIN_BOUTON_DECLENCHEUR 26       // Détecte une MALT à l'entrée D26

volatile boolean blJetonOperRelais = 0; // L'état est conservé dans la mémoire
                                        // de travail même lors des interruptions 
boolean blEtatBtnDeclencheur; 
boolean blTamponEtatBouton         = 1;
boolean blDeclencheRelais          = 0;
boolean blUnitDlReactMicroScd      = 0; // Unité du délai de réaction 
                                        // 1 => microseconde
                                        // 0 => milliseconde

// La variable suivante est de type «uint64_t» car le temps, 
// mesuré en millisecondes, deviendra rapidement un nombre grand
uint64_t u64HorodatageBtnDeclencheur = 0;  // La dernière fois que la broche
                                           // de sortie a été basculée
                                         
uint32_t u32DelaiReActInterup = 3000;  // Délai de réactivation
                                       // Pas plus d'un changement d'état 
                                       // au 3 secondes pour éliminer
                                       // les intermittences    
                                   

uint64_t u64HorodatageRayonCoupe = 0;  // La dernière fois que le rayon
                                       // laser a été coupé
uint32_t u32DelaiReActRayon = 3000;    // Pas plus d'un changement d'état 
                                       // au 3 secondes pour éliminer
                                       // les intermittences    

// Les prochaines variables sont de type «unsigned int»
// Ceci évite des valeurs négatives lors de la première lecture du EEPROM
// au SETUP avant qu'il y est eu une première écriture
// Sinon, il pourrait y avoir blocage du programme
// Ces données sont aléatoires avant la première écriture                                
uint32_t u32DelaiDeReaction  = 0;      // Durée d'attente avant d'activer le relais
uint32_t u32TempsRelaisActif = 2000;   // Durée d'activation du relais en milliseconde
uint32_t u32DelaiAvantRetour = 1000;   // Délai en milliseconde avant de redonner
                                       // la main à la suite du programme après
                                       // l'activation du relais


//******** Divers ***************
int inChronoDebutIndicModReseau = 0;   // Chrono Indique le mode réseau
int inChronoDebutIndicBattFbl   = 0;   // Chrono Indique batterie faible

 
// ------------------------------------------------------------------------------- 
// FONCTION  FONCTION   FONCTION    FONCTION    FONCTION    FONCTION    FONCTION
// ------------------------------------------------------------------------------- 

//*****  Activation du DEL   *****************
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
  // calculate duty, 8191 from 2 ^ 13 - 1
  if (value > valueMax){value = valueMax;}
  uint32_t duty = (8191 / valueMax) * value;
  
  // write duty to LEDC
  ledcWrite(channel, duty);
}

//******  Enregistrement dans la mémoire flash *******
void memFlashDataUser(){
  EEPROM.writeInt(0,  u32DelaiDeReaction);
  EEPROM.writeInt(4,  u32TempsRelaisActif);
  EEPROM.writeInt(8,  u32DelaiAvantRetour);
  EEPROM.writeInt(12, blUnitDlReactMicroScd);
  EEPROM.commit();
  delay(100);
}

//***  Attente selon le délai de réaction ****
void delaiDeReaction(){
  // Les «Serial.print» sont là pour le développement
  // En fonctionnement normal vaut mieux les mettre en 
  // commentaire. Ils influencent le temps d'exécution
  // des routines et faussent les délais programmés
  // Serial.println("Délai de réaction amorcé");
  if (blUnitDlReactMicroScd){
    delayMicroseconds(u32DelaiDeReaction);   // délai avant d'activer
                                             // le relais (en microseconde)
  }
  else {
    delay(u32DelaiDeReaction);               // délai avant d'activer
                                             // le relais (en milliseconde)
  } 
}


//******   Activation du relais **************
void declencheRelais(){
  Serial.println("Déclenchement du relais amorcé");
  digitalWrite(PIN_ACTIVE_RELAIS, HIGH);     // Déclenche le relais
  delay(u32TempsRelaisActif);                // Attente en milliseconde 
  digitalWrite(PIN_ACTIVE_RELAIS, LOW);      // Relâche le relais
  Serial.println("Délai avant retour amorcé");
  delay(u32DelaiAvantRetour);                // Attente en milliseconde  
  Serial.println("Processus déclenchement du relais terminé"); 
  Serial.println("");                  
}


void oper_delai_plus_relais(){
   delaiDeReaction();
   declencheRelais();  // inclus le délai de retour 
}


void demande_oper_relais(){
  blJetonOperRelais = 1;
}


//*****  Choix d'affichage de la couleur du DEL *******
void AfficheVertCWRougePA(){
   if (stWifiConnectionNetwork=="Non connecté au réseau") {
      byBrightnessVert  = 0 ;
      byBrightnessRouge = 255 ;
      // set the brightness on LEDC channel 0
      ledcAnalogWrite(LEDC_CHANNEL_0_VERT, byBrightnessVert);
      // set the brightness on LEDC channel 1
      ledcAnalogWrite(LEDC_CHANNEL_1_ROUGE,byBrightnessRouge);
  }
  else
  {
      byBrightnessVert  = 255;
      byBrightnessRouge = 0 ;
      ledcAnalogWrite(LEDC_CHANNEL_0_VERT, byBrightnessVert);
      ledcAnalogWrite(LEDC_CHANNEL_1_ROUGE,byBrightnessRouge);
  }
}


 // *******  html Serveur Web ******** 
 #include "do_Web.h"

 
 // *******  Traite les échanges sur BLUETOOTH ******** 
 #include "echange_Bluetooth_et_traitement.h"
 

// -------------------------------------------------------------------------------
// SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP
// ------------------------------------------------------------------------------- 
void setup() {
  Serial.begin(115200);
  Serial.println();


  //**********  EEPROM *************
  if (!EEPROM.begin(EEPROM_SIZE))
  {
    Serial.println("failed to initialise EEPROM"); delay(1000000);
  }
  
  Serial.println();
 
 
  //**********  ENTRÉES - SORTIES *************
  pinMode(PIN_ACTIVE_RELAIS, OUTPUT );
  digitalWrite(PIN_ACTIVE_RELAIS, LOW);

  pinMode(PIN_DETECTEUR_LASER_1,  INPUT);
  pinMode(PIN_DETECTEUR_SONORE,   INPUT);
  pinMode(PIN_BOUTON_DECLENCHEUR, INPUT_PULLUP);   // active la résistance
                                                   // de pull-up interne sur le +3V
                                                   
  // Un petit délai pour laisser les choses se stabiliser
  delay(30);
  
  attachInterrupt(digitalPinToInterrupt(PIN_DETECTEUR_LASER_1), demande_oper_relais, FALLING);
  attachInterrupt(digitalPinToInterrupt(PIN_DETECTEUR_SONORE),  demande_oper_relais, FALLING);


// de pull-up interne sur le +3V

  //**********  CONVERTISSEURS ANALOGIQUE/NUMÉRIQUE *************
  //     Configuration pour faire des mesures sur D35
  //     (voltage de la source d'alimentation) ******
  adc1_config_width(ADC_WIDTH_BIT_12);         // Définie la résolution (0 à 4095)
  adc1_config_channel_atten(ADC1_CHANNEL_7,    // Le voltage maximum au GPIO
                            ADC_ATTEN_DB_11);  // est de 3.3V

   
  // *********** BLUETOOTH ****************************
  // Ce Bluetooth n'est pas pris en charge pas IOS
  if(!SerialBT.begin("ESP32_DeclencheurDeRelais")){ //Bluetooth device name , NIP non disponible
    Serial.println("Erreur lors de l'initialisation du Bluetooth");
  }else{
    Serial.println("Bluetooth initialisé");
  } 

  delay(50);

  // *********** WIFI ****************************
  // Configuration d'une adresse IP statique
  if (!WiFi.config(local_IP, gateway, subnet)) {
    Serial.println("STA Failed to configure");
  }
  
  WiFi.begin(ssid, password);
  delay(1000);
  uint8_t retries = 15;
 
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print("..");
      Serial.print(WiFi.status());
      Serial.print("-");
      Serial.println(retries);
      retries--;
      if (retries == 0) {
        int intStatus = WiFi.status();
        if (intStatus==255){intStatus=2;}
        Serial.print("..");
        Serial.print(WiFi.status());
        Serial.print("-");
        Serial.println(retries);
        Serial.print("WiFi status :");
        Serial.print(WiFi.status());
        Serial.print("->");
        Serial.println(chStatusWifi[intStatus]); 
        stWifiConnectionNetwork = "Non connecté au réseau";
        break;
      }
  }

    Serial.println(stWifiConnectionNetwork);
  if (stWifiConnectionNetwork=="Non connecté au réseau") {
     Serial.println("- * Activation du point d'accès Wifi * - ");
     WiFi.softAP(ssid_AP, password_AP);
     IPAddress myIP = WiFi.softAPIP();
     Serial.print("AP IP address: ");
     Serial.println(myIP);
  }
  else{
  Serial.print("WiFi status :");
  Serial.println(WiFi.status());
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  }
    
  server.begin();



  //**********  DEL *************
  // Setup timer and attach timer to a led pin
  ledcSetup(LEDC_CHANNEL_0_VERT, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(DELVERTE, LEDC_CHANNEL_0_VERT);
  ledcSetup(LEDC_CHANNEL_1_ROUGE, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(DELROUGE, LEDC_CHANNEL_1_ROUGE);

  AfficheVertCWRougePA();

   // Lecture des valeurs sauvegardées dans le EEPROM 
  u32DelaiDeReaction     = EEPROM.readInt(0);
  u32TempsRelaisActif    = EEPROM.readInt(4); 
  u32DelaiAvantRetour    = EEPROM.readInt(8);
  blUnitDlReactMicroScd  = EEPROM.readInt(12);  

  if (u32DelaiDeReaction == 4294967295){ // valeur par défaut du ESP
      u32DelaiDeReaction  = 0;           // Changer sinon le programme est figé  
      u32TempsRelaisActif = 1000;        // pour longtemps 
      u32DelaiAvantRetour = 0;
      
      memFlashDataUser();
      
      u32DelaiDeReaction     = EEPROM.readInt(0);  // Validation 
      u32TempsRelaisActif    = EEPROM.readInt(4); 
      u32DelaiAvantRetour    = EEPROM.readInt(8);
      blUnitDlReactMicroScd  = EEPROM.readInt(12);  
  }
  
  Serial.print(u32DelaiDeReaction);
  Serial.println(" delaiDeReaction " );

  Serial.print(u32TempsRelaisActif);
  Serial.println(" tempsRelaisActif " );

  Serial.print(u32DelaiAvantRetour);
  Serial.println(" delaiAvantRetour " );

  Serial.print(blUnitDlReactMicroScd);
  Serial.println(" Bool unité délai de réaction " );


  //***** Divers ******
  inChronoDebutIndicModReseau = millis();
  Serial.println("PRÊT");
}

// ------------------------------------------------------------------------------- 
// LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP 
// ------------------------------------------------------------------------------- 
void loop() {  
  if (blJetonOperRelais) {
     oper_delai_plus_relais();
     blJetonOperRelais = 0;
  }

  if (!blJetonOperRelais) {
     //******* Lecture des entrées numériques  ******  

     blEtatBtnDeclencheur = digitalRead(PIN_BOUTON_DECLENCHEUR);
     if (blEtatBtnDeclencheur != blTamponEtatBouton){
        if ((millis() - u64HorodatageBtnDeclencheur) > u32DelaiReActInterup) {
           blTamponEtatBouton = blEtatBtnDeclencheur; // Mémorise le nouvel état
           u64HorodatageBtnDeclencheur = millis();
         }
     }
  }

  if (!blJetonOperRelais) {
     //***********  ACTIONS *****************
     if (!blTamponEtatBouton){;   // si l'état du bouton est 0
       delaiDeReaction();
       declencheRelais();  // inclus le délai de retour
       blTamponEtatBouton = 1;
     }
     
     if (blDeclencheRelais){;     // si la commande web D reçue
       blDeclencheRelais = 0;
       delaiDeReaction();
       declencheRelais();
     }
  }

  if (!blJetonOperRelais) {
     // ******* ********   Lecture du voltage d'alimentation   **********************
     //    
     // Méthode de G6EJD  (applicable si l'atténuation est 11dB
     // et la résolution est 12 bits)
     flReading = analogRead(35);
     flVoltAlimCtrlReduit = -0.000000000000016*pow(flReading,4)
                               +0.000000000118171*pow(flReading,3)
                               -0.000000301211691*pow(flReading,2)
                               +0.001109019271794*flReading+0.034143524634089;
     flVoltMesure = flVoltAlimCtrlReduit*122/22;        // Diviseur de tension
                                                        // 100K, 22K
     flVoltMesure = flVoltMesure*flCalibrationDiviseurTsn; // correction attribuable aux 
                                                        // valeurs imprécises du diviseur 
                                                        // de tension et au changement
                                                        // de ESP32

/* 
  Serial.print(flReading); Serial.print(" DigitalValueVoltAlimCtrl ");
  Serial.print(flVoltAlimCtrlReduit); Serial.print(" flVoltAlimCtrlReduit  ");
  Serial.print(flVoltMesure); Serial.println(" flVoltMesure"); 
  Serial.println(" "); 
*/

/* 
  Serial.print(blEtatLaser1); Serial.print(" État détecteur Laser,");
  Serial.print(blEtatBtnDeclencheur); Serial.print(" État Interrupteur,");
  Serial.print(flVoltMesure); Serial.println(" Voltage d'alimentation,");
*/
  }

if (!blJetonOperRelais) {
  // *****************   Traitement de l'affichage du DEL  ************************
  //     
  if (flVoltMesure > inSeuilDeVoltage ){          // Voltage d'alimentation > 7 volts 
     AfficheVertCWRougePA();
  }else{                                          // Voltage d'alimentation < 7 volts 
    if ((millis() - inChronoDebutIndicModReseau) > 1000){
       if (inChronoDebutIndicBattFbl == 0) {
          inChronoDebutIndicBattFbl= millis();    // Démarre le chrono Indique
                                                  // batterie faible
       }   
       if ((millis() - inChronoDebutIndicBattFbl) < 1000){ // DEL ORANGE pendant
                                                           // 1 seconde
          ledcAnalogWrite(LEDC_CHANNEL_0_VERT,   32);
          ledcAnalogWrite(LEDC_CHANNEL_1_ROUGE, 128);
       } 
       else{
          AfficheVertCWRougePA();                 // Vert Client Wifi
                                                  // Rouge Point d'accès
          inChronoDebutIndicModReseau = millis(); // Démarre le chrono
                                                  // Indication le mode réseau
          inChronoDebutIndicBattFbl = 0;          // Remet à zéro le chrono
                                                  // Indication batterie faible
      }
    }
  }
}


  if (!blJetonOperRelais) {
     // ***************   Traite les échanges sur BLUETOOTH   *****************
     do_Uart_Tick(); 
  }


  if (!blJetonOperRelais) {
     do_Web();
  }


  
} // # Fin du Void Loop

do_Web

// ------------------------------------------------------------------------------- 
//   serveur WEB    serveur WEB     serveur WEB      serveur WEB      serveur WEB 
// ------------------------------------------------------------------------------- 

void do_Web(){
   WiFiClient client = server.available(); // Écouter les clients entrants

  if (client) {                           // si vous avez un client,
    Serial.println("Nouveau Client!");    // imprimer un message sur le port série
    int inChronoDebutConnexion= millis();   
    String currentLine = "";              // Variable de type String pour contenir
                                          // les données entrantes du client
    while (client.connected()) {          // boucle alors que le client est connecté

      if ((millis() - inChronoDebutConnexion) > 1000){ // Déconnecte les fureteurs qui restent
          client.stop();                               // connecter sans avoir d'échange à
          inChronoDebutConnexion= millis();            // faire comme Chrome                           
       }   
       
      if (client.available()) {           // s'il y a des octets à lire du client,
         char c = client.read();          // lire un octet, puis
         //Serial.write(c);               // Imprimez sur le moniteur série
         if (c == '\n') {                 // si l'octet est un caractère
                                          // de nouvelle ligne

           // si la ligne en cours est vide, vous avez
           // deux caractères de nouvelle ligne consécutifs.
           // c'est la fin de la requête HTTP du client,
           // alors envoyez une réponse:
           if (currentLine.length() == 0) {
             client.println("HTTP/1.1 200 OK");
             client.println("Content-Type: text/html\n");
             
             // Début du HTML
             client.println("<!DOCTYPE html><html>");
             client.println("<head>");
             client.println("<title>DÉCLENCHEUR Web Server</title>");
             client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
             client.println("<link rel=\"icon\" href=\"data:,\">");
             // CSS to style the on/off buttons 
             client.println("<style>html { font-family: Helvetica;}");
             client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
             client.println("text-decoration: none; font-size: 40px; margin: 2px; cursor: pointer;}");
             client.println("</style>");
             client.println("</head>");

             client.println("<table align=\"center\"  style=\"background-color:#5EA084\"><tr><td>");
             
             client.println("<table>");
             client.println("<tr><th colspan=\"2\"><h1>DÉCLENCHEUR</h1></th></tr>");
             
             client.println("<tr><td>");
             client.println(flVoltMesure);
             client.println("</td><td>");
             client.println("V - Voltage de la source d'alimentation");
             client.println("</td></tr>");
             
             client.println("<tr><td>");
             client.println(u32DelaiDeReaction);
             client.println("</td><td>");
             if (blUnitDlReactMicroScd){
                client.println("us ");
             }
             else {
                client.println("ms ");
             }
             client.println("Délai de réaction");
             client.println("</td></tr>");
             
             client.println("<tr><td>");
             client.println(u32TempsRelaisActif);
             client.println("</td><td>");
             client.println("ms Durée d'activation du relais<br>");
             client.println("</td></tr>");
             
             client.println("<tr><td>");
             client.println(u32DelaiAvantRetour);
             client.println("</td><td>");
             client.println("ms Délai avant le retour aux détecteurs");
             client.println("</td></tr>");
             
             client.println("<tr><th colspan=\"2\"><br><a href=\"/D\"><button class=\"button\">RELAIS</button></a><br><br></th></tr>");
             client.println("</table>");
             
             client.println("<form action=\"/action_page.php\">");
             client.println("<table><tr><td>Délai de réaction:</td><td><input type=\"text\" name=\"dlyReact\"></td></tr>");
             client.println("<tr><td>Temps actif:</td><td><input type=\"text\" name=\"TmpsActif\"></td></tr>");
             client.println("<tr><td>Délai de retour:</td><td><input type=\"text\" name=\"dlyRtour\"></td></tr>");

             if (blUnitDlReactMicroScd){
                client.println("<tr><td colspan=\"2\"><input type=\"radio\" name=\"unitDelaiReactMS\" value=\"1\" checked>Délais de réaction en microseconde</td></tr>");
                client.println("<tr><td colspan=\"2\"><input type=\"radio\" name=\"unitDelaiReactMS\" value=\"0\" >Délais de réaction en milliseconde</td></tr>");
             }
             else {
                client.println("<tr><td colspan=\"2\"><input type=\"radio\" name=\"unitDelaiReactMS\" value=\"1\" >Délais de réaction en microseconde</td></tr>");
                client.println("<tr><td colspan=\"2\"><input type=\"radio\" name=\"unitDelaiReactMS\" value=\"0\" checked>Délais de réaction en milliseconde</td></tr>");
             }
                          
             client.println("<tr><th colspan=\"2\"><br><input type=\"submit\" value=\"Soumettre\"><br><br></th></tr>");
             client.println("</table>");
             client.println("</form>");
             
             client.println("<table>");
             client.println("<tr><td><br>  <a href=\"/P\">+ Augmenter le délai de réaction</a></td></tr>");
             client.println("<tr><td><br><br>  <a href=\"/M\">- Diminuer le délai de réaction</a></td></tr>");
             client.println("</table>");

             client.println("<br><br></td></tr></table>");
             client.println("</body>\n</html>");
             // break out of the while loop:
             break;
           } 
           else 
           {    // si vous avez une nouvelle ligne, effacez currentLine:
            int posDlyReact = currentLine.indexOf("dlyReact=");
            int posTmpsActif = currentLine.indexOf("TmpsActif=");
            int posDlyRtour = currentLine.indexOf("dlyRtour=");
            int posUnitDelaiReactMS = currentLine.indexOf("unitDelaiReactMS=");
            int posHTTP = currentLine.indexOf("HTTP");
            if (currentLine.startsWith("GET /action_page.php?")){
              if (posDlyReact >0) { 
                Serial.println("");
                Serial.println("***" );
                Serial.print(posDlyReact);
                Serial.println(" position du dlyReact" );
                Serial.print(posTmpsActif);
                Serial.println(" position du TmpsActif" );
                Serial.print(posDlyRtour);
                Serial.println(" position du dlyRtour" );
                Serial.print(posUnitDelaiReactMS);
                Serial.println(" position du unitDelaiReactMS" );
                Serial.println(currentLine);

                String strDlyReact = currentLine.substring(posDlyReact+9,posTmpsActif-1);
                Serial.println(strDlyReact);
                String strTmpsActif = currentLine.substring(posTmpsActif+10,posDlyRtour-1);
                Serial.println(strTmpsActif);
                String strDlyRtour = currentLine.substring(posDlyRtour+9,posUnitDelaiReactMS-1);
                Serial.println(strDlyRtour);
                String strUnitDelaiReactMS = currentLine.substring(posUnitDelaiReactMS+17,posHTTP-1);
                Serial.println(strUnitDelaiReactMS);

                if (strDlyReact != ""){
                  u32DelaiDeReaction =  strDlyReact.toInt();
                  memFlashDataUser(); 
                }
                if (strTmpsActif != ""){
                  u32TempsRelaisActif =  strTmpsActif.toInt();
                  memFlashDataUser(); 
                }
                if (strDlyRtour != ""){
                  u32DelaiAvantRetour =  strDlyRtour.toInt();
                  memFlashDataUser(); 
                }
                if (strUnitDelaiReactMS != ""){
                  blUnitDlReactMicroScd = strUnitDelaiReactMS.toInt();
                  memFlashDataUser(); 
                }
            }
           } 
            currentLine = "";
           }
         } 
         else if (c != '\r') 
         {  // si vous avez autre chose qu'un caractère de retour de chariot,
          currentLine += c;      // l'ajouter à la fin de la currentLine
         }
         
         // Vérifiez si la demande du client
         if (currentLine.endsWith("GET /P")) {
            u32DelaiDeReaction ++; // Augmente la durée d'activation du relais
            memFlashDataUser(); 
            currentLine = "";   
         }
         if (currentLine.endsWith("GET /M")) {
            u32DelaiDeReaction --; // Diminue la durée d'activation du relais
            if (u32DelaiDeReaction == 4294967295){ u32DelaiDeReaction =0;}
            memFlashDataUser(); 
            currentLine = "";    
         }    
         if (currentLine.endsWith("GET /D")) {
           Serial.println(currentLine);
           blDeclencheRelais = 1; // 
           currentLine = "";    
         }
        } // # if (client.available())
     } // # fin du while (client.connected())
      
  } // # fin du if (client) 
  // close the connection:
  client.stop();
  //Serial.println("Client Disconnected.");
  delay(0);
  }
 

echange_Bluetooth_et_traitement.h

// ------------------------------------------------------------------------------- 
//            ÉCHANGE ET TRAITEMENT BLUETOOTH
// ------------------------------------------------------------------------------- 
//
//***** Renvoi des données du ESP32 vers le Client ****
// ****Trame de réponse : [ |DATA|#|#|#|#|#| ]  # est un nombre.
void envoieDataVersClient(){

      Serial.print(flVoltMesure);
      Serial.println(" flVoltMesure " );
      Serial.print(u32DelaiDeReaction);
      Serial.println(" delaiDeReaction " );
      Serial.print(u32TempsRelaisActif);
      Serial.println(" tempsRelaisActif " );
      Serial.print(u32DelaiAvantRetour);
      Serial.println(" delaiAvantRetour " );
      Serial.print(blUnitDlReactMicroScd);
      Serial.println(" Bool unité délai de réaction " );
      Serial.println();
      delay(0);
      int inPauseDeTransmission = 100;  // > 50 Temporisation pour éviter les engorgements 
      SerialBT.print("[ |");                 delay(inPauseDeTransmission);
      SerialBT.print("DATA|");               delay(inPauseDeTransmission);
      SerialBT.print(flVoltMesure);          delay(inPauseDeTransmission);
      SerialBT.print("|");                   delay(inPauseDeTransmission);
      SerialBT.print(u32DelaiDeReaction);    delay(inPauseDeTransmission);
      SerialBT.print("|");                   delay(inPauseDeTransmission);
      SerialBT.print(u32TempsRelaisActif);   delay(inPauseDeTransmission);
      SerialBT.print("|");                   delay(inPauseDeTransmission);
      SerialBT.print(u32DelaiAvantRetour);   delay(inPauseDeTransmission);
      SerialBT.print("|");                   delay(inPauseDeTransmission);
      SerialBT.print(blUnitDlReactMicroScd); delay(inPauseDeTransmission);
      SerialBT.print("| ]");
}


//*****  Réception et traitement des échanges sur BLUETOOTH
void do_Uart_Tick()
{
  char charUart_Data=0;
   
  if(SerialBT.available()) 
  {
    size_t len = SerialBT.available();  // size_t  integer non signé, 
                                        // len =  nombre de caractères à lire
    uint8_t u8SerialBuffer[len + 1];    // uint8_t integer non signé 8 bits,
                                        // équivaut à byte
    u8SerialBuffer[len] = 0x00;
    SerialBT.readBytes(u8SerialBuffer, len);
    memcpy(buffUART + buffUARTIndex, u8SerialBuffer, len);// s'assurer que le
                                                          // port série peut
                                                          // lire l'intégralité
                                                          // de la trame de données
    buffUARTIndex += len;
    preUARTTick = millis();
    if(buffUARTIndex >= MAX_PACKETSIZE - 1) 
    {
      buffUARTIndex = MAX_PACKETSIZE - 2;
      preUARTTick = preUARTTick - 200;
    }
  }
  if(buffUARTIndex > 0 && (millis() - preUARTTick >= 100))
  { //données prêtes
    buffUART[buffUARTIndex] = 0x00;
    if(buffUART[0]=='X')                    // Réserve
    {
    }

    //***********  Demande de déclenchement du relais ****
    else if (buffUART[0]=='C')   // CLIC,D           
    {
      Serial.print("Data brut du buffer de réception ->");
      Serial.println(buffUART);
      sscanf(buffUART,"CLIC,%s",&charUart_Data);
      Serial.print("Data après traitement ->"); 
      Serial.print(charUart_Data);
      Serial.println();
    }
    //***********  Démarrage, connexion Bluetooth réussie, envoie des données initiales ****
    //***********  Envoie des données du ESP32 vers le Client ****
    else if (buffUART[0]=='I')   // INIT,I           
    {
      Serial.print("Data brut du buffer de réception ->");
      Serial.println(buffUART);
      sscanf(buffUART,"INIT,%s",&charUart_Data);
      Serial.print("Data après traitement ->"); 
      Serial.print(charUart_Data);
      Serial.println();
    }
    else if (buffUART[0]=='M')   // Unité : délai de réaction = ms
    {
      charUart_Data='M';
      blUnitDlReactMicroScd = 0;
      Serial.print(blUnitDlReactMicroScd);
      Serial.println(" Milliseconde ");
      
    }
    //***** Réception des données venant de la TABLLETTE allant vers le ESP32  ****
    //      Nouveau DATA
    else if (buffUART[0]=='N') // Venant de l'action du bouton d'envoie
    {
      charUart_Data='N';
      Serial.print("Data brut du buffer de réception ->");
      Serial.println(buffUART);
      sscanf(buffUART,"NDATA,%i,%i,%i",&u32DelaiDeReaction,&u32TempsRelaisActif,&u32DelaiAvantRetour);
      Serial.print("Data après traitement ->");  
      Serial.print(u32DelaiDeReaction);
      Serial.print("/");
      Serial.print(u32TempsRelaisActif);
      Serial.print("/");
      Serial.println(u32DelaiAvantRetour);
      Serial.println();
    }
    else if (buffUART[0]=='U')   // Unité : délai de réaction = us
    {
      charUart_Data='U';
      blUnitDlReactMicroScd = 1;
      Serial.print(blUnitDlReactMicroScd);
      Serial.println(" Microseconde ");
    }
    else  charUart_Data=buffUART[0];
    buffUARTIndex = 0;
  }



  //****** EXÉCUTE LES DEMANDES ****
  //    
  switch (charUart_Data)    
    {    
      // ***** DÉCLENCHEMENT DU RELAIS ********
      case 'D':
      delaiDeReaction();
      declencheRelais();  // inclus le délai de retour
      break;
      
      // ***** Envoie des données du ESP32 vers le Client ********
      case 'I':
      envoieDataVersClient();
      break;
      
      case 'M':
      // Enregistrement des données dans le EEPROM
      memFlashDataUser();   
      //***** Renvoi des données du ESP32 vers le Client ****
      envoieDataVersClient();
      break;

      case 'N':
      // Enregistrement des données dans le EEPROM
      memFlashDataUser();  
      //***** Renvoi des données du ESP32 vers le Client ****
      envoieDataVersClient();
      break;

      case 'U':
      // Enregistrement des données dans le EEPROM
      memFlashDataUser();  
      //***** Renvoi des données du ESP32 vers le Client ****
      envoieDataVersClient();
      break;
      
      
      default:break;
    }
}



<- L’interface BLUETOOTH du déclencheur de relais ( 2 de 2 )         Déclenchement d’appareil photo et de flashs ->