Domotique : Réalisation d'une centrale domotique

22 janvier 2020 rdorigny 0 commentaires

Je vais vous montrer comment réaliser un petit projet de centrale domotique afin d'afficher des informations utiles (température intérieure/extérieure, pression, humidité par exemple) et éventuellement d'être capable de nous alerter sur des événements particuliers (ouverture de la porte du garage dans mon cas). En particulier, la centrale domotique doit être en mesure de se connecter sur internet pour récupérer les informations stockés dans un hébergement cloud via des API.


Architecture d'ensemble du projet:
J'ai pris pour habitude de stocker les informations dans le "cloud". En effet, je dispose d'un hébergement privé chez 1and1 (IONOS), 250Go pour quelques euros par mois. Ce modèle est vraiment plus rentable qu'un serveur NAS ou un ordinateur, notamment sur le coût énergétique.

Bref, j'ai pour habitude de connecter tous mes IOT domotique à ma box Internet. Notamment, vous trouverez sur mon site les projets :
  • Capteur thermique : ESP32 et un capteur BMP280;
  • Détecteur d'ouverture de porte de garage sectionnelle : ESP32 et un sonar HY-SRF05.

  • L'avantage également de stocker les données dans une base de données sur un hébergement Internet et que l'on peut se faire sa propre application Android Domotique de surveillance de la maison puisque accessible de partout sur le réseau Internet mobile.

    Donc le principe d'architecture et que les objets connectés (IOT) domotique et la centrale sont tous connectés à la box Internet de la maison. Ils échangent avec les bases de données de mon hébergeur via un mécanisme d'interface API.


    Conception matériel:
    Le schéma du circuit ci-dessous est super simple, il est essentiellement basé autour d'un microcontrôleur ESP32, d'un écran Nextion et d'un capteur de présence.
  • Le microcontrôleur ESP32, qui dispose d'une connexion wifi, se connectera à une API afin de rapatrier les informations à afficher. Pour le modèle, j'ai choisi le Espressif ESP32 DevKitC V4 avec ESP32-WROOM-32 Rev. 1 et CP2102N USB-TTL. Il est plus coûteux mais j'en suis satisfait, et avec lui, je n'ai jamais rencontré de PB.
  • Le buzzer sera le moyen de signaler une alarme. Notamment pour mon cas, de l'état d'ouverture de la porte sectionnelle de mon garage. Il est commandé par un transistor BC547 et une résistance de 100 ohms pour limiter le courant
  • Des pinout sont prévus pour connecter l'écran Nextion en liaison série et le capteur de présence.
  • Enfin, il m'a parut utile, pour des raisons d'économie d'énergie, d'ajouter un capteur de présence. L'objectif étant d'allumer l'écran uniquement lorsque l'on est détecté présent dans la pièce.





  • Configuration de l'écran Nextion:
    Je ne vais pas vous faire un cours sur la configuration de cet écran, vous trouverez tout ce qu'il faut sur Internet. Simplement, le nextion dispose d'un logiciel qui permet d'éditer les fenêtres qui seront affichés. Ensuite, il suffit de communiquer les variables à afficher par la liaison série entre l'ESP32 et le Nextion.
    Ici, j'affiche les températures, l'humidité et la pression. L'image de la porte verte indique que la porte est bien fermée, elle passe en rouge lorsqu'elle est ouverte. Une checkbox (en haut à droite) va permettre de couper le buzzer, pratique si la porte reste trop longtemps ouverte.

    Le fichier de configuration du Nextion est ici. Vous pouvez le reprendre pour l'adapter à votre besoin.

    Conception logiciel:
    Au niveau programmation, il y a deux parties de code à implémenter:
  • le code de l'ESP32 : écrit en C, il est l’élément principal de la configuration de la centrale. J'y reviens après;
  • le script de l'API : écrit en php, la fonction get retransmet les données inscrites dans la base de données par les capteurs.
  • //***********************************************************************************************
    
                             Robert DORIGNY  rdorigny@free.fr www.doritique.fr
                                          version 1.0 le 11/11/2019
    
    Code de la centrale domotique DORITIQUE (ESP32 - LORAWAN - Nextion). 
    
    - Version 1.0 (11/11/2019) : 
        - La centrale DORITIQUE affiche les données météo et l'état d'ouverture de la porte du garage.
        - Un buzzer produit un signal sonore si la porte est ouverte. Une checkbox valide ou invalide le buzzer.
    - Version 1.1 (15/12/2019) : 
        - Mode économie d'énergie : Un détecteur de mouvement allume l'écran Nextion en veille.
    
    
    //***********************************************************************************************
    #include (ArduinoJson.h) remplacer () par <>
    #include (WiFi.h)        remplacer () par <>
    #include (HTTPClient.h   remplacer () par <>
    
    //Pour le wifi
    const char* ssid = "votressid";
    const char* password =  "votrecode";
    
    int cpt=0;
    String response="",tmp="";
    HTTPClient http;
    float temp=0;
    float tempext=0;
    float hum=0;
    float garage=0;
    float savposgarage=0;
    int pression=0;
    const char* dateint="";
    char buf[32];
    int pirValue;
    
    #define RXD2 16
    #define TXD2 17
    #define BIP 27
    #define pirPin 33
    #define timeSeconds 3600
    
    // Timers
    unsigned long now = millis();
    unsigned long lastTrigger = 0;
     
    // ********************************************************************
    void Transmit_Nextion(String str) 
      {
      tmp=str;
      tmp.toCharArray(buf,20);
      Serial.println(buf);
      Serial2.write(buf);
      Serial2.write(0xff);
      Serial2.write(0xff);
      Serial2.write(0xff); 
      delay(1000);    
      }
    
    // ********************************************************************
    void Beep() 
      {
      digitalWrite(BIP, HIGH);
      delay(2000);
      digitalWrite(BIP, LOW);  
      }
    // ********************************************************************
    int Verif_Checkbox(void) 
      {
      char tab[8];
      char retour[8]={0x71,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF};  
      // variable contenant le caractère à lire
      char carlu = 0;
      // variable contenant le nombre de caractère disponibles dans le buffer
      int cardispo = 0;
      int cpt=0;
      
      Transmit_Nextion("get c0.val");
      cardispo = Serial2.available();
      while(cardispo > 0) // tant qu'il y a des caractères à lire
        {
        carlu = Serial2.read(); // on lit le caractère
        tab[cpt]=carlu;
        cpt++;
        Serial.print(carlu, HEX); // puis on le renvoi à l’expéditeur tel quel
        cardispo = Serial2.available(); // on relit le nombre de caractères dispo
        }
      for(int i=0; i30)
          {
          Serial.println("Pas de connexion au wifi! Reboot automatique...");
          esp_restart();
          }
      }
      Serial.println("Connexion au réseau local wifi: OK!");
     
    }
    
    // ********************************************************************
    // boucle du programme
    void loop() {
        if(WiFi.status()== WL_CONNECTED) //Vérifie l'état de connexion du wifi
         {   
         //Emission de la requete vers l'API et recup dans la base de données
         http.begin("http://www.votresite.fr/Mon_api.php?action=get&var=temp");  
         http.addHeader("Content-Type", "text/plain");             //Specify content-type header
         int httpResponseCode = http.POST("POSTING from ESP32");   //Send the actual POST request
         Serial.println(httpResponseCode);   //Affiche le code rettour http
         if(httpResponseCode>0)
           {
           response = http.getString();   
           Serial.println(response);                       
           //Deserialisation
           StaticJsonDocument<2048> doc;  
           DeserializationError err=deserializeJson(doc,response); 
           if (err){
             Serial.print("Erreur");
             Serial.println(err.c_str());
             }
           else {
            temp=doc["pht"]["temp"];
            pression=doc["pht"]["pres"];
            hum=doc["pht"]["hum"];   
            dateint=doc["pht"]["date"];
            garage=doc["context"]["garage"];
            tempext=doc["phtext"]["tempext"];        
    
            Serial.println(Verif_Checkbox());        
            
            if (garage==1) 
              {
              Transmit_Nextion("p0.pic=1");
              Transmit_Nextion("sleep=0"); //réveille le Nextion
              }
            if (garage==0) Transmit_Nextion("p0.pic=0");
            if ((garage==1)&&(Verif_Checkbox()==1)) Beep();
            Transmit_Nextion("t7.txt=""+String(hum)+"%"");
            Transmit_Nextion("t4.txt=""+String(temp)+"C"");
            Transmit_Nextion("t5.txt=""+String(tempext)+"C"");       
            Transmit_Nextion("t6.txt=""+String(pression)+"Pa"");      
           }
         }
    
      //delay(5000);      // Attendre 5 seconds
    
      //Gestion de la veille de l'écran Nextion
      pirValue = digitalRead(pirPin);
      now = millis(); 
      if (pirValue == 1) lastTrigger = millis();
      Serial.println(pirValue);
      Serial.println(now - lastTrigger);
      Serial.println(timeSeconds*1000);
      if ((pirValue == 0) && ((now - lastTrigger) > (timeSeconds*1000))) {
        Serial.println("Mise en veille");
        Transmit_Nextion("sleep=1"); //Mise en veille du Nextion
        }
      else 
        {
        Serial.println("Réveil Nextion");
        Transmit_Nextion("sleep=0"); //réveille le Nextion
        }
      
      while (Serial2.available()) Serial.println(char(Serial2.read()));
      delay(10000);
      }
    else
      {
      Serial.println("Pas de wifi...");
      cpt++;
      if (cpt>30)
        {
        Serial.println("Pas de connexion au wifi! Reboot automatique...");
        esp_restart();
        }
      }
    }
    
    
    

    Pour le code de l'ESP32, j'ai opté pour ne pas utiliser de librairie d''échange avec le Nextion. Pour en savoir testé quelques-unes, elles sont toutes buggées ou mal-pensées. Alors qu'il suffit de communiquer en liaison série selon le protocole de commande du Nextion.

    Donc le microcontrôleur interroge en boucle l'API, récupère les données, les affiches et teste la détection du PIR (Passive Infrared Sensor). Rien de bien difficile, j'ai commenté le script pour vous aider à le comprendre.
    if ((isset($_GET["action"]))&&(isset($_GET["var"])))
      {
      switch ($_GET["action"])
        {
        case ("get") :
          api_get($_GET["var"]);
          break;
    	case ("set") :
    	  //if (isset($_GET["data"]))
    	    //api_set($_GET["var"],$_GET["data"]);
    	    api_set($_GET["var"]);
    	  break;
    	default:
          print("L'action appelée n'existe pas.");  
    	}
      }
    else 
      print("Erreur lors de l'utilisation de l'API");
    
    //******************************************************************************************
    //Fonction de récupération des données
    function api_get($var)
    {
    global $Con; //variable de connexion à la base de données
    
    switch ($var)
      {
      case ("temp") : //Récupération des données météo  	  
        $requete="select tpint,pr,hum,date,tpext from meteo ORDER BY num DESC LIMIT 1 "; 
        $resultat=mysqli_query($Con,$requete);
        if ($resultat)  
          $t=mysqli_fetch_row($resultat); 
        else
          $temp="Impossible d'obtenir les données météo.";  
    
        $tab["pht"] = array("pres"=>intval($t[1]),"hum"=>$t[2],"tempint"=>$t[0],"date"=>$t[3],"tempext"=>$t[4]);
    
        print(json_encode($tab));
        break;	
      default:
        print("La variable appelée n'existe pas.");
      } 
    }
    

    Voici un extrait ci-dessus du script PHP, qui réceptionne les variable et retourne une réponse en JSON avec les valeurs météo à afficher.

    Réalisation du PCB:
    J'ai choisi de réaliser un PCB et pas de le faire sur une plaque de prototypage comme je fais d'habitude. Pour cela, j'ai dessiné le PCB avec le logiciel Kicad qui est assez complet et très ergonomique. En particulier Kicad propose pas mal de fonctionnalités pour gérer les empreintes, le routage, les tests de continuité afin de détecter les mauvaises connexions ou défaut de conception.


    Ensuite, il suffit de passer par un site spécialisé dans la réalisation des circuits électroniques, pour moi JLCPCB, et de de transmettre un fichier gerber qui en fait est un fichier zip des différentes couches de fabrication du PCB. Vous trouverez ces fichiers dans le répertoire du projet Kicad. Le fichier gerber de mon PCB est disponible ici.

    J'ai reçu le colis moins d'une semaine après commande (5 PCB pour 16€). Ce qui est sympa avec ce site c'est que l'on est informé de l'avancement des étapes du processus de fabrication.



    Le résultat est impeccable, rien à redire, le PCB est proche d'une qualité professionnel. Pour le montage, rien de particulier à part que j'ai choisi de mettre une résistance CMS pour le fun et que je conseille vivement de ne pas souder l'ESP32 directement sur le PCB. Il vaut mieux mettre des connecteurs 2.54mm femelle. Cela pour changer l'ESP32 si besoin. Pas de condensateur proche de l'ESP32, la carte dispose de son propre découplage.



    Considération énergétique:
    Et du côté énergétique? A peine 1 W de consommation au maximum, ce qui est très faible et plutôt intéressant pour un système qui fonctionne H24. C'est ici que l'on voit également l’intérêt de l'ESP32 qui consomme vraiment très peu d'énergie. Donc bonne pioche!



    Réalisation du boitier:
    Réalisation c'est beaucoup dire. J'ai acheté un petit boitier en aluminium. D'ailleurs, j'aurais mieux fait de réfléchir un peu plus! Mettre un ESP32 dans un boitier métallique ce n'est pas une grande idée... Disons que le métal agit comme une cage de faraday et bloque la réception WIFI potentiellement. Enfin je croyais, mais au final ma centrale fonctionne assez bien malgré tout. J'ai eu de la chance sur ce coup là.



    Conclusion

    Vous avez tout dans ce post pour réaliser votre propre centrale domotique! J'ai fourni toutes les sources nécessaires pour y arriver assez simplement. Attention quand même, ma réalisation est prévue pur un modèle particulier d'ESP32, vérifiez juste que les pins 16-17 de votre ESP32 sont bien prévus pour une liaison série afin de commander l'écran Nextion. Contactez-moi si vous avez des questions.

    Ma centrale domotique fonctionne depuis presque un mois, aucun souci rencontré.









    Pseudonyme (obligatoire) :
    Adresse mail (obligatoire) :
    Site web :




    © 2020 www.doritique.fr par Robert DORIGNY