Routeur Solaire. Mesure de Puissance avec un ESP32

Version V1 avec relais

Une version V2, disposant d’un Triac pour une injection précise de la surproduction est disponible ici: https://f1atb.fr/realisez-un-routeur-solaire-pour-gerer-la-surproduction/

Mesurer en temps réel la puissance électrique consommée, voire produite par une installation solaire permet une meilleure gestion. Par exemple, en cas d’excédant, dans une installation en autoconsommation, on peut enclencher la fabrication d’eau chaude.
Le montage ci-après:
– mesure la puissance
– fourni la courbe instantanée de la tension et du courant sur une page web
– actionne un relais en cas de production au-dessus de la consommation
– fourni un rapport au système central de domotique (Domoticz) pour l’enregistrement.

L’ESP32 est un microcontrôleur adapté à notre besoin. Il comprend :
– des entrées analogiques pour mesurer des tensions,
– des entrées/sorties numériques pour actionner un relais si besoin,
– une liaison WIFI pour faire du reporting à distance sur une page web ou un système de domotique.

Tableau des Versions

Différentes versions de routeur ont été décrites :

VersionMesure courant / puissanceActionneursModulaireDomoticzMQTT / Home AssistantDescription
1Sonde AmpèremétriqueRelaisNonOuiNonRouteur Solaire. Mesure de Puissance avec un ESP32
2Sonde AmpèremétriqueTriac + RelaisNonOuiNonRéalisez un Routeur Solaire pour gérer la surproduction
3.00_UxISonde AmpèremétriqueTriac + RelaisOuiOuiOuiU x I : Routeur Solaire pour gérer la surproduction photovoltaïque
3.10 LinkyLinkyTriac + RelaisOuiOuiOuiRéalisez un Routeur Solaire avec un Linky
Routeur Solaire

Capteur du Courant

Transformateur de courant 100A/50mA

Pour mesurer le courant, on utilise un capteur de courant dans lequel on fait passer le fil de phase du secteur. En sortie, agissant comme un transformateur, il fourni un courant identique, mais 2000 fois plus faible. Ce courant est envoyé aux bornes d’une résistance et nous allons mesurer la tension générée.

Il existe différents modèles suivant le courant Max que l’on souhaite mesurer. La version 100A est adaptée à un domicile ayant une puissance max délivrée de 12kVA. On la trouve en Chine chez Aliexpress.

Capteur de la tension

Transformateur 220V/6V

Pour mesurer la tension, on utilise un transformateur bobiné classique abaisseur de tension qui nous isole du secteur. Par exemple un 230v/6v. Il faut un modèle le plus petit possible, on ne prélève aucune puissance. Cela n’est plus très facile à trouver. Un transformateur, dit de sonnette, peut faire l’affaire.

Mesure Courant et Tension

La mesure des 2 tensions représentantes du courant et le la tension secteur se fait par les entrées analogiques de l’ESP32. Ces entrées acceptent une tension entre 0 et 3.3V et numérisent la valeur sur 12 bits, valeurs entre 0 et 4095. Pour s’adapter à la dynamique d’entrée, on crée une référence de tension au milieu de la plage à 1.65V =3.3V/2.

On prélève le 3.3V de l’ESP32 qui en passant par un pont de 2 résistances (R6 et R7) de 4700 ohm connecté à la masse nous fourni au milieu une référence de 1.65V. Pour éviter du bruit de mesure, un condensateur de 470uF (C2) filtre le 3.3V et un autre de 10uF (C1) filtre le point milieu à 1.65V.

Afin de ne pas dépasser les 3.3V crête à crête des signaux à mesurer, ou 1.65V crête, on se fixe une limite de +-1V efficace maximum.

Pour la sonde de courant avec 80A et une résistance de 24 ohm , on arrive à peu près au 1V.

24*80A/2000=0.96V

Chez moi, avec un abonnement de 12KVA, je ne devrai pas dépasser les 60A.

Pour la mesure de tension, il faut mettre un pont de résistances (R4 et R5) pour abaisser le 6V autour de 1V efficace.

Raccordement à l’ESP32

ESP32 Development Board 2*19 pins

Le jeu de piste avec ces cartes qui intègrent un ESP32, est de trouver les GPIO disponibles et non utilisés pour la programmation Flash etc.
Dans notre cas, on mesure les tensions suivantes:
– GPIO 35 : la tension de référence à 1.65V en théorie.
– GPIO 33 : la tension représentant le courant à mesurer
– GPIO 32 : la tension en sortie du transformateur

2 LED sur les GPIO 18 et 19 clignotent toutes les 2s. La jaune si on consomme du courant, la verte si on fournit du courant, car nous sommes en surproduction.

2 relais solides sur les GPIO 22 et 23 permettent:
– d’allumer une lumière dans le local commandé par l’interrupteur sur le GPIO 05,
– exciter le relais de puissance de mise en route du chauffe-eau en cas de production importante d’électricité.

Mesure

La mesure des 2 valeurs représentant la tension et le courant prend environ 120uS. En pratique, on prévoit sur une période de 20ms (1/50Hz) de prélever 100 couples de valeurs, ce qui donnera une bonne description de la tension à priori sinusoidale et du courant souvent chahuté par les alimentations à découpage.

Formules de calcul des puissances

Pour bien caler dans le temps chaque mesure, on utilise l’horloge en micro seconde de l’ESP32.

Toutes les 2 s, on effectue :
– la mesure des tensions et courants durant 20ms
– le calcul du courant efficace
– le calcul de la tension efficace
– le calcul de la puissance en kVA
– le calcul de la puissance en kW

Un calibrage préalable doit être fait pour définir la constante multiplicative kV dans le programme qui permet la conversion de la tension mesurée en binaire vers la tension réelle. De même pour le courant, la constante kI . Utilisez un voltmètre, une pince ampèremétrique ou votre compteur Linky pour la calibration.

Code

L’ensemble du code est écrit en utilisant l’IDE Arduino. Il est injecté dans un premier temps par la liaison série, puis une fois en place, on peut le modifier si besoin par le WIFI comme décrit ici.

#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ArduinoOTA.h>
#include <RemoteDebug.h>

const char* ssid = "******";
const char* password = "*******";
RemoteDebug Debug;
unsigned long previousComputeMillis;
unsigned long previousClignoteMillis;
unsigned long previousLightMillis;
bool Clignote = false;
bool LightOn =false;

// Set your Static IP address
IPAddress local_IP(192, 168, 0, 208);
// Set your Gateway IP address
IPAddress gateway(192, 168, 0, 254);

IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional

WebServer server(80);

//PINS
const int AnalogIn0 = 35;  // GPIO 35
const int AnalogIn1 = 32;  // GPIO 32
const int AnalogIn2 = 33;  // GPIO 33
const int RelayLight = 22;
const int RelayWaterHeater = 23;
const int LedYellow = 18;
const int LedGreen = 19;
const int Inter = 5;


int value0;
int value1[100];
int value2[100];

int WIFIbug = 0;

float Uef;
float Ief;
float PVA;
float PW;
float PowerFactor;
float kV = 0.2083;
float kI = 0.0642;
float Wh = 0;


//Client of Domoticz
const char* host = "192.168.0.99";
const int httpPort = 8080;
const int idxPower = 1012;
int Nloop = 0;
int day = -1;

//  SERVER
//***********
void handleRoot() {
  String S;
  Debug.println(F("Client Web"));
  S = "<body style='background: linear-gradient(#118,#55b,#118);font-size:150%;'  onload='setTimeout(\"location.reload();\",2000);'><h2 style='text-align:center;color:white'>Total Power Consumption</h2>";
  S += "<div style='text-align:center;width:96%;margin:auto;''>";
    S += "<div style='width:400px;margin:auto;'><table align='center' style='border:3px inset grey;padding:4px;background-color:white;font-size:120%;width:100%;'>";
    S += "<tr><td>U :</td><td style='text-align: right;'>" + String(Uef) + "</td></tr>";
    S += "<tr><td>I :</td><td style='text-align: right;'>" + String(Ief) + "</td></tr>";
    S += "<tr><td>P Watt :</td><td style='text-align: right;'>" + String(PW) + "</td></tr>";
    S += "<tr><td>P VA :</td><td style='text-align: right;'>" + String(PVA) + "</td></tr>";
    S += "<tr><td>Power Factor : </td><td style='text-align: right;'>" + String(PowerFactor) + "</td></tr>";
    S += "<tr><td>kWh :</td><td style='text-align: right;'>" + String(Wh / 1000) + "</td></tr>";
    S += "<tr><td>Heure :</td><td style='text-align: right;'>" + String(floor(millis()/ 36000)/100) + "</td></tr>";
    S += "</table></div>";

    S +="<div style='text-align:center;width:1000px;margin:auto;'>";
      S += "<div style='text-align:center;'><h3><span style='color:red;'>U_</span><span style='color:lightgreen;'> I_</span></h3>";
      S += "<p><svg height='400' width='1000' style='border:3px inset grey;background-color:white;'>";
      S += "<line x1='0' y1='400' x2='0' y2='0' style='stroke:rgb(0,0,0);stroke-width:2' />";
      S += "<line x1='0' y1='200' x2='1000' y2='200' style='stroke:rgb(0,0,0);stroke-width:2' />";
      int Vmax = 1;
      int Imax = 1;
      for (int i = 0; i < 100; i++) {
        Vmax = max(abs(value1[i]), Vmax);
        Imax = max(abs(value2[i]), Imax);
        Debug.println(value1[i]);
      }
      S += "<polyline points='";
      for (int i = 0; i < 100; i++) {
        int Y = 200 - 200 * value1[i] / Vmax;
        int X = 10 * i;
        S += String(X) + "," + String(Y) + " ";
      }
      S += "' style='fill:none;stroke:red;stroke-width:6' />";
      S += "<polyline points='";
      for (int i = 0; i < 100; i++) {
        int Y = 200 - 200 * value2[i] / Imax;
        int X = 10 * i;
        S += String(X) + "," + String(Y) + " ";
      }
      S += "' style='fill:none;stroke:green;stroke-width:6' />";
      S += "</svg></p></div>";

      S += "<div style='width:96%;margin:auto;border:3px inset grey;background-color:#666;height:20px;position:relative;'>";
      int X = 0;
      int Y = 99 - 99 * PW / 12000;
      String C="yellow";
      if (PW < 0) {
        X = 198 - Y;
        Y = 0;
        C="green";
      }
        S += "<div style='position:absolute;top:3px;height:14px;background-color:" +C +";left:" + String(X) + "%;right:" + String(Y) + "%;'></div>";
      S += "</div>";
    S +="</div>";
  S +="<div></body>";
  server.send(200, "text/html", S );
}

void handleNotFound() {
  Debug.println(F("File Not Found"));
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);

}
// DOMOTICZ client
//****************
void SendToDomoticz() {
  String url;
  Nloop = (Nloop + 1) % 10;

  if (Nloop == 0 || Nloop == 2) {
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    if (!client.connect(host, httpPort)) {
      Serial.println("connection failed");
      return;
    }
    if (Nloop == 2) {
      // We now create a URI for the request
      url = "/json.htm?type=command&param=getServerTime";  //Obtain time from Domoticz server

    } else {
      // We now create a URI for the request
      url = "/json.htm?type=command&param=udevice&idx=";
      url += String(idxPower);
      url += "&nvalue=0&svalue=";
      url += String(PW);
      url += ";";
      url += String(Wh);


    }

    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");
    unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 5000) {
        Serial.println(">>> Client Timeout !");
        client.stop();
        return;
      }
    }

    // Read all the lines of the reply from server and print them to Serial
    while (client.available()) {
      String line = client.readStringUntil('\r');
      // Serial.print(line);
      int p = line.indexOf("ServerTime");
      if (p > 0) {
        String subline = line.substring(p + 14, p + 32);
        p = subline.lastIndexOf("-");
        subline = subline.substring(p + 1, p + 3); //day after month
        // Serial.print(subline);
        int theday = subline.toInt();
        if (day != theday) {
          day = theday;
          Wh = 0; // Rest Watt Heure of the day
          //   Serial.println("Reset Watt Hour");
        }
      }

    }

    //  Serial.println();
    //  Serial.println("closing connection");
  }

}

// POWER
//********
void MeasurePower() {
  int i;
  value0 = analogRead(AnalogIn0);
  unsigned long MeasureMillis = millis();
  unsigned long T= micros();
  while (millis() - MeasureMillis < 21) { //Read values during 20ms
    i = (micros() % 20000) / 200;
    value1[i] = analogRead(AnalogIn1) - value0;
    value2[i] = analogRead(AnalogIn2) - value0;
  }
 
}
void ComputePower() {
  float V;
  float I;
  Uef = 0;
  Ief = 0;
  PW = 0;
  for (int i = 0; i < 100; i++) {
    V = kV * float(value1[i]);
    Uef += sq(V);
    I = kI * float(value2[i]);
    Ief += sq(I );
    PW += V * I;
  }
  Uef = sqrt(Uef / 100) ;
  Ief = sqrt(Ief / 100) ;
  PW = floor(PW / 100);
  PVA = floor(Uef * Ief);
  PowerFactor = floor(100 * PW / PVA) / 100;
  Wh += PW / 360; //Every 10s
}

void Overproduction(){
  if (PW <-700){ //switch On water heater    
    digitalWrite(RelayWaterHeater,HIGH);
  }
  if (PW>1000){ //Switch Off with hyteresis
     digitalWrite(RelayWaterHeater,LOW) ; 
  }
}


// SETUP
//*******
void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  // Configures static IP address
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  //WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Debug.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
  // init remote debug
  Debug.begin("ESP32");

  initOTA();
  Debug.println("Ready");
  Debug.print("IP address: ");
  Debug.println(WiFi.localIP());
  Serial.print("IP address: ");
  server.on("/", handleRoot);

  server.on("/inline", []() {
    server.send(200, "text/plain", "this works as well");
  });

  server.onNotFound(handleNotFound);

  server.begin();
  Debug.println("HTTP server started");
  previousComputeMillis = millis();
  previousClignoteMillis = millis();

  pinMode( RelayLight , OUTPUT);
  pinMode( RelayWaterHeater , OUTPUT);
  pinMode( LedYellow , OUTPUT);
  pinMode( LedGreen , OUTPUT);
  pinMode( Inter , INPUT_PULLUP);
  digitalWrite(RelayLight, LOW);
  digitalWrite(RelayWaterHeater, LOW);
  digitalWrite(LedYellow, LOW);
  digitalWrite(LedGreen, LOW);
}

// LOOP
//******
void loop() {
  ArduinoOTA.handle();
  Debug.handle();
  server.handleClient();

  if (millis() - previousComputeMillis >= 2000) {
    previousComputeMillis = millis();
    MeasurePower();
    ComputePower();
    Overproduction();

    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
      Debug.println("Connection Failed! #" +String(WIFIbug));
       WIFIbug ++;
       if ( WIFIbug >20) {
        ESP.restart();
       }
    } else {
     Debug.println("Connection OK! ");
     WIFIbug = 0;
    }
    
    SendToDomoticz();
    Debug.println("Power:"+String(PW));
  }
  if (millis() - previousClignoteMillis >= 2000) {
    Clignote = !Clignote;
    if (Clignote) {
      previousClignoteMillis = millis() - 1950;

    } else {
      previousClignoteMillis = millis();
    }
    if (PW >= 0) {
      digitalWrite(LedYellow, Clignote);
      digitalWrite(LedGreen, LOW);
    } else {
      digitalWrite(LedYellow, LOW);
      digitalWrite(LedGreen, Clignote);
    }
  }
  //Light
  if (digitalRead(Inter)==LOW  &&  (millis()-previousLightMillis) >500) {
    LightOn=!LightOn;
    digitalWrite(RelayLight,LightOn);
    previousLightMillis=millis();
  }
  if (millis() - previousLightMillis >= 120000) {
    LightOn=false;
    digitalWrite(RelayLight,LightOn);
    previousLightMillis=millis();
  }


}

// OTA
//******
void initOTA() {
  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);
  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname("ESP32-Power");
  // No authentication by default
  ArduinoOTA.setPassword("admin");
  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
  ArduinoOTA
  .onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
      type = "sketch";
    else // U_SPIFFS
      type = "filesystem";
    // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    Debug.println("Start updating " + type);
  })
  .onEnd([]() {
    Debug.println("\nEnd");
  })
  .onProgress([](unsigned int progress, unsigned int total) {
    Debug.printf("Progress: %u%%\r", (progress / (total / 100)));
  })
  .onError([](ota_error_t error) {
    Debug.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Debug.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Debug.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Debug.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Debug.println("Receive Failed");
    else if (error == OTA_END_ERROR) Debug.println("End Failed");
  });
  ArduinoOTA.begin();
}

Page Web

Le code comprend un petit serveur Web qui permet d’afficher sur une page, les différentes mesures ainsi que la tension et le courant durant une période de 20 ms.

Montage

Montage

Dans une boite d’électricien on installe :

  • La carte ESP32 (AZ-Delivery)
  • Une alimentation 5V 1A pour l’ESP32
  • Un transformateur basse tension pour mesurer la tension
  • 2 Relais solide branché en 3.3V, commandé par l’ESP32
  • En face avant en option, un bouton poussoir et 2 LEDs

Raccordé à cette boite, on a la sonde de courant à placer autour du fil de phase du secteur à mesurer.

Mesure de puissance en entrée maison

Sécurité

En travaillant sur ce projet en 230V, vous acceptez d’assumer la responsabilité de votre propre sécurité et de prendre toutes les précautions nécessaires pour éviter les accidents électriques.

Articles sur le photovoltaïque

F1ATB André

Radio Amateur - Domotique - Photovoltaïque

Vous aimerez aussi...

71 réponses

  1. Allgood dit :

    bonjour
    ça fait quelques temps que j’essaie de programmer ce type de produit non sans mal, merci de l’avoir publié ça va me faciliter grandement la tâche.
    petite variante que j’aurais à proposer et de piloter non pas un relais mais un variateur de puissance (dimmer) pour injecter dans le chauffe-eau que le surplus ni plus ni moins, je n’hésiterai pas à le partager si j’arrive à l’intégrer.
    encore merci

  2. SEBASTIEN dit :

    Un grand merci pour le temps passé et pour tout le travail exposé.
    Pour pinailler un peu mais en aucun cas une critique de ma part, j’ai été déçu de l’esp32 sur la mesure analogique car la plage de mesure n’est pas linéaire sur la plage 0 / 3.3V . Pour des mesures de puissances, les résultats sont plus fiables pour ma part avec un bon Atmega328 ( Arduino UNO) malgré une précisions plus faible que l ESP
    Mais le gros point fort de l’ESP32 c’est de pouvoir tout faire avec sans ajout de trop de composants externes comme un convertisseur NA.
    Merci encore, heureux d’avoir découvert ton site

    • F1ATB André dit :

      La non linéarité de l’ESP32 autour de OV et 3.3V est connue. Avec le schéma proposé, on est cadré au milieu et on ne va pas chercher le 0V ou le 3.3V suivant la résistance de charge choisie.
      Merci pour votre remarque pertinente.

  3. bern dit :

    Dans la procédure overproduction le relais n’est activé qu’à partir d’un excédant de 700W. Y-a-t-il une contre indication pour abaisser ce seuil à 300 ou 400W?

    • F1ATB André dit :

      On peut l’abaisser. Attention à ne pas transformer le système en oscillateur suivant la consommation. La valeur d’enclenchement doit être supérieure à la valeur de déconnexion du montant de la consommation.
      Pour s’adapter aux grosses consommations comme un chauffe-eau et les petites surproductions, je prépare une version 2 avec un triac à la place du relais pour pouvoir délivrer des puissances proportionnelles à la surproduction. J’attend les pièces de chine.

      • Michael dit :

        bonjour
        j’ai découvert votre site et j’adore le contenu est étonnant et simple je vous remercie de partager tous ces montages et en plus ils sont défaits par un vrai passionné et compétent j’aurais plaisir à vous suivre et partager.
        merci encore michaelangelo

  4. dominique dit :

    salut , super vidéos et super site aussi , mais je ne comprends pas bien l’utilité du transfo 220/6 v , seul l’intensité sous environ 230 v peux suffire a déterminer la puissance absorbée ou produite non ??
    cela dit je suis toujours étonné de voir les quantités de choses que l’on peut faire avec les ESP 8266 , les 12 et les 32
    encore bravo et merci pour vos travaux

    • F1ATB André dit :

      La tension est importante pour comparer sa phase avec celle du courant. C’est le seul moyen pour savoir dans quel sens se fait le transfert de puissance.

  5. FC dit :

    Bonjour,
    Je recherchais justement à réaliser un wattmetre qui pouvait voir si on était en production ou consommation.
    J’avais fait un premier montage avec un pzem-004t mais celui-ci ne donnait pas le sens du courant.
    Merci donc d’avoir publier ce projet avec des explications claires.

  6. Wilfried dit :

    vraiment merci pour ces explications et pour ce tutoriel

    j’ai un soucis quand je televerse le code je ne sais plus cmt continuer
    j’essaye de me connecter au serveur mais sans succès

    svp je souhaiterais avoir une marche à suivre une fois que le code est telversé

    • F1ATB André dit :

      Il faut definir dans le code l’adresse IP qui se trouve dans le groupe d’adresse gérée par votre box Internet et tapez l’adresse dans un navigateur.

  7. Wilfried dit :

    comment vous faites pour fixer les coefficients kV et Ki svp?

    • F1ATB André dit :

      Vos prenez un voltmètre et corrigé kV en faisant une règle de 3 par rapport à la valeur actuelle.
      Pour kI, faite la même chose avec une pince ampèremétrique ou un petit ampèremètre en serie en chargeant le systeme avec un courant acceptable (ex lampe à filament, radiateur). Evitez les alimentations à decoupage de LED.

  8. Deroche Guy dit :

    Bonjour
    Merci pour ce très bon document et la qualité des explications
    J’ai juste une petite question , après avoir décortiqué le code ; d’où viennent les valeurs KV et KI (0.2063 et 0.642)
    Je suppose qu’il s’agit de valeur de calibration ….ou bien ai-je raté quelque chose.
    Je mets en oeuvre cet am …
    Merci encore pour cet article et bon dimanche

    • F1ATB André dit :

      Oui kV et kI sont 2 coefficients de calibration à ajuster suivant votre systeme. La sortie du transfo etc en comparant avec les données d’un ampèremètre/voltmètre.

  9. Daniel dit :

    Bonjour, d’abord superbe travail pour le montage du esp32 jusqu’à présents j’ai bien suivi tout le montage et je pense que ça fonctionne bien, la seule chose qui m’a échappé c’est l’intégration dans Domoticz je n’ai pas encore trouvé comment vous avez pu faire.
    pouvez-vous m’expliquer comment faire merci d’avance pour tout?
    Daniel

    • F1ATB André dit :

      Dans domoticz, il faut un senseur virtuel, récupérer son index et on peut envoyer la commande http://…. qui contient les resultats.

      • BILLES dit :

        Bonjour Mr Buhart je reviens vers vous au sujet de la création d’un senseur virtuel dans domoticz je pense avoir tout ok mais vous parlez d’envoyer la commande je pense que nous penser à l’indice dans le menu dispositif de domoticz chez moi ça ne marche pas pouvez-vous m’en dire plus?

        • F1ATB André dit :

          Regardez la documentation de Domoticz qui détaille la syntaxe des reportings. Dans l’adresse de votre navigateur vous pouvez simuler un reporting http://… Il vous dira en retour s’il y a une erreur. Vérifiez bien l’index.

  10. Michel Voisin dit :

    Bonjour
    je termine mon installation solaire pour laquelle j’avais prévu un routeur Solaire Fronius Ohmpilot
    au final celui-ci n’est pas compatible àvec mon chauffe-eau stéatite.
    Je pratique modestement l’Arduino
    votre solution m’intéresse vivement mais j’ai un problème lors de la compilation
    j’ai cherché et pas trouvé le fichier ESPmDNS.h sur internet !!
    ——————————————————–
    Erreur de compilation:
    Routeur_solaire_ESP8266:2:10: fatal error: ESPmDNS.h: No such file or directory
    #include
    ^~~~~~~~~~~
    compilation terminated.
    Plusieurs bibliothèque trouvées pour « WiFi.h »
    Utilisé : C:\Program Files (x86)\Arduino\libraries\WiFi
    Non utilisé : C:\Users\admin\Documents\Arduino\libraries\WiFiEspAT
    exit status 1
    ESPmDNS.h: No such file or directory
    ————————————————-
    Remarque personnelle:
    Avec l’Arduino quand on galère rien que pour gérer les bibliothèques on se demande comment on peut produire un programme fonctionnel aussi complexe
    FELICITATIONS
    Cordialement

    • F1ATB André dit :

      Utilisez vous le version 2 d’Arduino? Elle contient plein d’exemples autour du web/DNS pour ESP32 etc. Essayez les. Je n’ai pas eu de souci de bibliothèque.

  11. Docquier Alex dit :

    comment fait-on pour une installation avec un onduleur tri-phasé ?
    Merci pour toutes les infos
    Au plaisir
    Alex

  12. Michaelangelo dit :

    bonjour
    j’attends avec impatience votre routeur 2.0
    a très bientôt
    😎

  13. schneider yves dit :

    Bonjour
    je voudrais faire le montage sur un ESP 8266,car j’en nais plusieurs.
    mais je ne trouve pas les mêmes sorties que sur ESP 32.
    Dans le programme je peut enlevé toute la partie wifi et avoir un afficheur simple pour la puissance de sortie en Wh ???
    Merci pour une réponse
    Salutations

    • F1ATB André dit :

      Le problème avec l’esp8266, c’est qu’il n’a qu’une seule entrée analogique et il en faut 3.
      Par contre si vous n’utilisez pas le wifi, vous pouvez utiliser un Arduino Nano ou Uno.
      La dynamique d’entrée de l’Arduino en analogique est de 0 à 5v sur 10 bits et non pas 0 à 3.3V sur 12bits.

  14. Lefoulon Christophe dit :

    Bonjour,
    Merci pour toutes ces informations qui m’ont bien été utiles pour mettre en place une solution équivalente mais avec en plus la mesure de la production solaire (avec un deuxième capteur de courant).
    Concernant la mesure de tension j’ai du utiliser une résistance de 47000 au lieu de 24000 (mini transfo de 6v) car je sortais de la plage de mesure de l’ESP32 (0-2V avec l’atténuation par défaut).
    Chez moi la tension est une sinusoïde déformée avec un décalage du courant (cos phi) (pas de production solaire au moment de la mesure).
    Voici un lien vers la courbe de tension et des courants (grid en orange et solaire en vert):
    http://racko.free.fr/tmp/pvwattmetre1.png
    Du coup j’ai une question : d’où vient ce décalage entre le courant et la tension, sachant qu’aucun moteur ne tourne au moment de la mesure, seulement des ordinateurs et des radiateurs ?
    Merci.

    • F1ATB André dit :

      La forme non sinusoïdal et décalée du courant est due à des alimentations à découpage : ordinateurs, chargeurs de téléphone etc. Si vous lancez une grosse consommation avec une charge bien résistive, vous aurez une courbe plus belle et en phase avec la tension.

      • Jacolet dit :

        Bonjour, j’ai réussi à corriger le plat sur la sinusoid de chaque côté avec une petite capacité de 220nf 60volts céramique en parallèle sur la résistance R5 de 4,7kohm. Il faux voir le résultat des mesures ?

  15. TOFIRE dit :

    Bonjour,
    Tout d’abord merci pour les nombreuses vidéos très instructives sur Youtube ainsi que votre site.
    Je commence à me renseigner justement pour « router » l’énergie créer par ma future installation photovoltaïque « autoconsommation » mais je ne trouve pas de réponse à ce que je désire faire sur mon installation.
    J’ai déjà fait installer il y a 11 ans 3kWc de panneaux photovoltaïques sur ma toiture en « revente » totale, je vais installer dans les semaines qui arrivent 4kWc environ de panneaux (soit en pergola soit en auvent) pour de l’autoconsommation.
    Je suis donc pour l’instant consommateur d’électricité venant de chez EDF, j’ai bien compris que le surplus (non consommé) de ma production de mes nouveaux panneaux est censé repartir dans le réseau gratuitement si je ne l’utilise pas, d’où l’intérêt d’avoir un routeur qui « force » la chauffe de l’eau.
    L’idée pour moi, lorsque la maison (la consommation électrique habituelle) ne consomme pas assez, le chauffe eau déjà au max et les voitures électriques (il y en a une pour Mme et Mr) ne sont pas là serait que le surplus reparte dans « la ligne » de « revente » de mon installation photovoltaïque existante. Je ne compte pas envoyer la totalité de ma production (ça n’aurait aucun sens) car je suis limité de mémoire à 4500kWh pour la revente et environ 5c dépassé ce plafond.
    D’après vous est-ce matériellement possible à faire ? Et si oui, partir sur un Esp32 ou Arduino avec plusieurs relais pour faire les déviations d’énergie est-il possible ?

    Merci d’avance pour votre réponse.

    • F1ATB André dit :

      En théorie, cela est possible d’envoyer la totalité. Contractuellement, je ne sais pas. Envoyer une partie de la puissance me semble hasardeux, sauf avec des micro-onduleurs qui permettent de commuter un panneau sur le 2eme réseau. Attention,ils auront besoin d’un temps de resynchronisation. Cela ne reste pas très flexible pour s’adapter rapidement aux variations de consommation de la maison.

  16. Philippe dit :

    Bonjour
    merci beaucoup pour ces explications très instructives , cela donne envie des aire des montage avec des ESP32.
    Avez vous déjà envisager d’utiliser un capteur de courant JSY – MK -194 capteur bidirectionnel à la place du capteur de courant et du transfo ?
    Merci d’avance pour votre réponse
    Philippe

    • F1ATB André dit :

      Je n’ai jamais fait l’essai avec ce capteur. L’ensemble transfo + sonde est bien moins cher et l’ESP32 peut faire le travail de calcul.
      Cdlt

  17. Franck dit :

    Bonjour,
    Est il possible de faire faire deux choses en mêmes temps à l’ESP? Par exemple, le montage de cette article et le montage de l’affichage en temps réel du Linky que vous avez présenté dans un autre article en utilisant la liaison série? J’aimerais faire les deux montages mais éviter d’utiliser deux ESP32.
    Merci

  18. Galliaerde dit :

    Bonjour,
    super travail, je vais donc me lancer. juste une question le routeur route à partir de quelle surplus puissance

    • F1ATB André dit :

      Le routeur est prévu pour avoir en entrée de la maison une consommation ou injection nulle. Si vous produisez 200W en trop, il bascule ces 200W vers votre chauffe-eau par exemple pour revenir à une consommation/injection nulle.
      Cdlt
      André

  19. Marc dit :

    Bonjour André.
    Merci pour tout ce que vous partagez et expliquez !
    J’ai réalisé ce routeur tout fonctionne correctement.
    j’aimerai rajouter une sonde de courant. j’ai essayé plusieurs choses sur le programme pour déclarer un PIN pour cette nouvelle sonde mais je n’y arrive pas. Je n’y connais pas grand chose en C++…
    Pouvez-vous juste me dire comment déclarer ce nouveau PIN ( GPI0 25 )
    Je vous remercie
    Cdt
    Marc

    • F1ATB André dit :

      const int AnalogIn3 = 25; // GPIO 25

      Mais attention derrière il y a de la programmation pour lire et stocker.
      Cdlt
      andré

  20. Marc dit :

    Merci.
    C’est ce que j’avais fait.
    C’est donc côté programmation que ça ne va pas…
    cdt,
    Marc

  21. Christophe dit :

    Bonjour,

    c’est très instructif, merci pour le travail et les explications.

    Avez-vous testé d’enregistrer la valeur retournée par : micros() pour chaque mesure ?
    il semblerait que le timing de mesure ne soit pas très stable (surtout sur les premières mesures)
    j’ai utilisé un code écrit moi même, peut etre que l’erreur vient de mon code 🙂

    Je trouve en tout cas la manière de mesurer les 200µs très habile

    • F1ATB André dit :

      En raison des interruptions, de WiFi etc, il y a des variations sur l’instant d’acquisition. En pratique on collecte 125 valeurs dans la boucle pour les 100 valeurs demandées.
      J’ai fais des essais qui ont montré que l’acquisition des 100 valeurs est toujours bonne.
      Cdlt

  22. Franck dit :

    Bonjour, pourquoi récupérer vous sur le GPIO35 la valeur de la masse virtuel (1.65v)?

    La plupart des routeurs utilise cette combinaison résistance/condo mais aucun ne récupère cette valeur, d’où ma question 🙂

    • F1ATB André dit :

      Les résistances employées sont en général 5% de précision. La mesure du point milieu permet plus de précision sachant que l’on mesure les valeurs sur 4096 points.
      Cordialement

  23. JACOLET dit :

    pour les sondes ampère métrique (pour le montage en triphasé) quel valeur utilisé 30A 1volts (3X )

  24. Joel dit :

    bonjour André et bravo pour ce routeur qui
    fonctionne a merveille ici.
    j’ai juste une question ,j’arrive a me connecter sur l’interface web en local (wifi) mais pas a distance en 4g pouvez vous me dire ce que j’ai loupé? cordiales 73 de F1JUA

    • F1ATB André dit :

      L’adresse IP que vous utilisez n’est valable qu’en interne sur votre réseau maison. C’est comme un numéro de poste de téléphone dans une entreprise.
      Pour accéder de l’extérieur, il faut mettre en place une règle NAT dans votre box internet.
      Le mieux, chercher sur GOOGLE, NAT et nom de votre box. Vous trouverez des dizaines de tutos. Espérons que vous n’êtes pas chez Orange qui change périodiquement votre adresse IP extérieur de la box. C’est faisable, mais plus compliqué.
      Cdlt

  25. Grandcollot dit :

    Pour utiliser le surplus solaire, j’utilise un ESP32 mais les mesures sont effectuées en amont de l’onduleur c’est à dire juste derrière les panneaux solaires. Le principe du programme est le suivant. Je mesure tension et courant des panneaux solaires. La charge appliquée impose un point de fonctionnement P1 qui est comparé à P2 la puissance précédente. Le programme alors choisit le sens d’incrément (+ ou -) et l’applique au variateur qui alimente le chauffe-eau depuis l’onduleur.

  26. Marc dit :

    Bonjour André.
    Je n’arrive pas à envoyer les données a mon serveur domoticz.
    Sur domoticz J’ai créé le matériel « dummy »puis créé dessus un capteur de type électrique (instantané+compteur), j’ai relevé l’idx correspondant à ce capteur ( idx = 1 ) puis j’ai renseigné cette valeur dans le programme de l’ESP 32 : const int idxPower = 1;
    J’ai bien renseigné l’adresse ip de mon serveur domoticz dans le programme de l’ESP 32 : const char* host = « 192.168.47.174 »; ainsi que le port : const int httpPort = 8080;
    Mais je ne reçois aucune valeur…
    Pouvez-vous m’aider svp ?

    Cdt

  27. Marc dit :

    d’accord merci. je vais essayer
    cdt

  28. jeep.ken dit :

    bonjour,
    bravo et merci pour ce travail. J’ai réalisé la V1 et cela fonctionne très bien. J’ai ajouté la notion de Wh injectés et Wh soutirés en fonction du signe de la puissance pour le suivi dans le temps et comparaison avec les données ENEDIS. et là, je suis étonné de voir que les données « Wh injectés » correspondent très bien avec les données ENEDIS (à env. 1,5 % prés), alors que les données « Wh soutirées » sont inférieures aux données ENEDIS (à env. >10%). Il s’agit pourtant du même capteur et même procédure. Notez que j’ai ajouté un capteur sur l’entrée panneaux solaire et avec le même principe les résultats correspondent bien aux données d’ENPHASE, ce qui exclu un problème d’acquisition ou de calcul.
    Et là j’en viens à douter du fonctionnement du compteur Linky. Qu’en pensez vous?? merci pour votre aide.

    • F1ATB André dit :

      Difficile de répondre. L’ESP32 avec des résistances à 5% n’est sûrement pas le meilleur appareil de mesure.
      Cdlt

      • jeep.ken dit :

        Merci d’avoir pris le temps de répondre. J’ai bien conscience que nous n’avons pas fabriqué un appareil de mesure. J’essayais de comprendre pourquoi, avec le même capteur les mêmes composants le même programme, l’énergie injectée vue par ENEDIS est comparable à ce que l’ESP32 me donne, alors que l’energie soutirée vue par ENEDIS est plus importante que celle donnée par l’ESP32 (+10%). C’est le même calcul: Whsoutirée=somme(énergies positives), WhInjectée=somme(énergies négatives). En filigrane, doit-on faire confiance absolue au linky.
        Merci encore, mais je comprends que vous ne puissiez pas répondre.

  29. Jean-Pierre dit :

    Bonjour et merci pour ce travail et explications.
    dans la procédure « ComputePower » on calcule l’énergie Wh sur une période de 10 s (Wh += PW /360).
    cependant ce calcul est exécuté toutes le 2 s (if (millis() – previousComputeMillis >= 2000) ), est-ce une erreur?

    • F1ATB André dit :

      Oui, je pense que vous avez raison à la relecture du code. C’est une vieille version. Actuellement j’en suis à la V4.

      Cdlt
      André

  30. François dit :

    Bonjour et merci pour ce partage.

    J’essaye de reproduire votre système plus pour apprendre que pour une réel utilisation. (je suis en revente total sur une grosse installation et j’ai quelques panneaux pour effacer mon talon électrique)

    Ma maison est en triphasé, si je veux une lecture de ma consommation, dois-je réaliser 3 fois le system UxL ou bien est-il envisageable de mutualiser l’ESP32?

    Encore merci
    François

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *