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...

74 réponses

  1. 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

  2. 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

  3. JACOLET dit :

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

  4. 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

  5. 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.

  6. 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

  7. Marc dit :

    d’accord merci. je vais essayer
    cdt

  8. 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.

  9. 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é

  10. 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

    • F1ATB André dit :

      Pour le tri, il n’y a que les solutions Shelly 3em et Emphase. Je n’ai pas développé de solution UxI avec 3 sondes.
      Cdlt

      • François dit :

        Merci, dans un 1er temp je vais faire 3 systèmes UxI sans actionneur pour voir ce qu’il se passe dans mon installation.
        Bonne fêtes

  11. PLANTIER dit :

    bonjour
    j’ai découvert votre site ,et je ne pouvais pas espérer mieux
    Je suis en train de faire mon routeur solaire,et j’aimerai mettre deux gradateurs
    Robotdyn 40a (deux cumulus) sur un esp32 est ce que c’est un schéma de’ branchement classique.??
    encore merci

    • F1ATB André dit :

      Mettez un gradateur et un relais SSR ou 2 relais SSR 40A.

      Cdlt

      • PLANTIER dit :

        Bonjours
        Merci pour cette réponse rapide
        Peut être avec deux esp 32 les gradateur pourraient fonctionner ensemble???
        Super votre site internet
        Merci