Table des matières

Tags :


Suivi de la téléinformation ERDF avec arduino

Fonctionnement de la téléinformation EDF

La téléinformation s’obtient sur les compteurs possédant les bornes I1 et I2, appelés compteur bleu (modèle pour les particuliers) ou compteur jaune (modèle pour les professionnels).

Compteur « bleu »

Il s’agit d’un port série à 1200 bps, les données voyageant sur un courant porteur (j’ai mesuré 6V environ, mais la documentation erdf/enedis indique que le système doit pouvoir assumer exceptionnellement 220V). On peut obtenir :

Pour l'instant, je n'ai pas encore de Linky, donc je ne peux rien dire sur les possibilités avec ce dernier. Néanmoins, il parait que c'est la même chose.

Partie arduino

Hardware

Composants necessaires :

La DEL permet d’avoir un retour de l’activité : elle clignote quand il y a un transfert d’information. Cette partie du montage est optionnelle.

La diode permet de supprimer une alternance du signal, le photocoupleur permet d’isoler le signal du circuit électronique.

D’après Planète-domotique :

Schéma électronique

Software

teleinfo.ino
#include <UIPEthernet.h>
byte mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x25 };
byte ip[] = { 192, 168, 1, 25 };
EthernetServer server(80);
 
#include <SoftwareSerial.h>
SoftwareSerial cptSerial(2, 3);
#define startFrame 0x02
#define endFrame 0x03
#define startLine 0x0A
#define endLine 0x0D
 
void setup()
{
    cptSerial.begin(1200);
    Ethernet.begin(mac, ip);
    server.begin();
}
 
String GetTeleInfo()
{
    String TeleInfo = "";
    char charIn = 0;
    while (charIn != startLine)
    {
        charIn = cptSerial.read() & 0x7F;
    }
    while (charIn != endLine)
    {
        if (cptSerial.available() > 0)
        {
            charIn = cptSerial.read() & 0x7F;
            TeleInfo += charIn;
        }
    }
    return TeleInfo;
}
 
String ShowTeleInfo(String keyword, String unit, int length)
{
    int essai = 0;
    // Nombre d'étiquettes maximum, cf documentation ERDF
    int max_essais = 33;
    String data = "";
    String msg = "";
    while(data.substring(0,keyword.length()) != keyword && essai != max_essais)
    {
        data = GetTeleInfo();
        essai++;
    }
    msg = "\t<";
    msg += keyword;
    msg += " unit=\"";
    msg += unit;
    msg += "\">";
    if (essai != max_essais)
    {
        msg += data.substring((keyword.length() + 1),(length + (keyword.length() + 1)));
    }
    else
    {
        msg += "NA";
    }
    msg += "</";
    msg += keyword;
    msg += ">";
    return msg;
}
 
void loop()
{
  EthernetClient client = server.available();
  if (client)
  {
    boolean current_line_is_blank = true;
    while (client.connected())
    {
        if (client.available())
        {
            char c = client.read();
            if (c == '\n' && current_line_is_blank)
            {
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/xml");
                client.println();
                client.println("<?xml version=\"1.0\"?>");
                client.println("<teleinformation>");
                client.println(ShowTeleInfo("ADCO","",12));
                client.println(ShowTeleInfo("OPTARIF","",4));
                client.println(ShowTeleInfo("ISOUSC","A",2));
                client.println(ShowTeleInfo("BASE","Wh",9));
                client.println(ShowTeleInfo("HCHC","Wh",9));
                client.println(ShowTeleInfo("HCHP","Wh",9));
                client.println(ShowTeleInfo("EJPHN","Wh",9));
                client.println(ShowTeleInfo("EJPHPM","Wh",9));
                client.println(ShowTeleInfo("BBRHCJB","Wh",9));
                client.println(ShowTeleInfo("BBRHPJB","Wh",9));
                client.println(ShowTeleInfo("BBRHCJW","Wh",9));
                client.println(ShowTeleInfo("BBRHPJW","Wh",9));
                client.println(ShowTeleInfo("BBRHCJR","Wh",9));
                client.println(ShowTeleInfo("BBRHPJR","Wh",9));
                client.println(ShowTeleInfo("PEJP","min",2));
                client.println(ShowTeleInfo("PTEC","",4));
                client.println(ShowTeleInfo("DEMAIN","",4));
                client.println(ShowTeleInfo("IINST","A",3));
                client.println(ShowTeleInfo("IINST1","A",3));
                client.println(ShowTeleInfo("IINST2","A",3));
                client.println(ShowTeleInfo("IINST3","A",3));
                client.println(ShowTeleInfo("IMAX","A",3));
                client.println(ShowTeleInfo("IMAX1","A",3));
                client.println(ShowTeleInfo("IMAX2","A",3));
                client.println(ShowTeleInfo("IMAX3","A",3));
                client.println(ShowTeleInfo("PMAX","W",5));
                client.println(ShowTeleInfo("PAPP","VA",5));
                client.println(ShowTeleInfo("HHPHC","",1));
                client.println(ShowTeleInfo("MOTDETAT","",6));
                client.println(ShowTeleInfo("PPOT","",2));
                // On ne retiens pas ADIR(1,2,3) ou ADPS (peuvent être calculés)
                client.println("</teleinformation>");
                break;
            }
        if (c == '\n')
        {
            current_line_is_blank = true;
        }
        else if (c != '\r')
        {
            current_line_is_blank = false;
        }
      }
    }
    delay(200);
    client.stop();
  }
}

Exemple de sortie XML

<?xml version="1.0"?>
<teleinformation>
   <ADCO unit="">041430244526</ADCO>
   <OPTARIF unit="">HC..</OPTARIF>
   <ISOUSC unit="A">20</ISOUSC>
   <BASE unit="Wh">NA</BASE>
   <HCHC unit="Wh">001202472</HCHC>
   <HCHP unit="Wh">001965554</HCHP>
   <EJPHN unit="Wh">NA</EJPHN>
   <EJPHPM unit="Wh">NA</EJPHPM>
   <BBRHCJB unit="Wh">NA</BBRHCJB>
   <BBRHPJB unit="Wh">NA</BBRHPJB>
   <BBRHCJW unit="Wh">NA</BBRHCJW>
   <BBRHPJW unit="Wh">NA</BBRHPJW>
   <BBRHCJR unit="Wh">NA</BBRHCJR>
   <BBRHPJR unit="Wh">NA</BBRHPJR>
   <PEJP unit="min">NA</PEJP>
   <PTEC unit="">HP..</PTEC>
   <DEMAIN unit="">NA</DEMAIN>
   <IINST unit="A"> 00</IINST>
   <IINST1 unit="A">001</IINST1>
   <IINST2 unit="A">004</IINST2>
   <IINST3 unit="A">010</IINST3>
   <IMAX unit="A"> 01</IMAX>
   <IMAX1 unit="A">012</IMAX1>
   <IMAX2 unit="A">019</IMAX2>
   <IMAX3 unit="A">025</IMAX3>
   <PMAX unit="W">08230</PMAX>
   <PAPP unit="VA">03340</PAPP>
   <HHPHC unit="">C</HHPHC>
   <MOTDETAT unit="">000000</MOTDETAT>
   <PPOT unit="">00</PPOT>
</teleinformation>

Il est bien sûr tout à fait possible de faire la même chose avec une sortie json.

Plugin munin

Munin est un outil de surveillance des ressources, simple à utiliser et à programmer.

teleinfo.py
#!/bin/python3
from lxml import etree
import sys
 
ARDUINO_URL = '192.168.1.25'
 
if "config" in sys.argv:
    print("graph_title Compteur EDF")
    print("graph_period hour")
    print("graph_args --base 1000")
    print("graph_vlabel Consommation (Wh)")
    print("graph_category Domotique")
    print("graph_info Consommation electrique relevee par le compteur")
    print("hp.label Heures pleines")
    print("hc.label Heures creuses")
    print("hp.info Heures pleines")
    print("hc.info Heures creuses : 0h-8h")
    print("hp.type COUNTER")
    print("hc.type COUNTER")
else:
    root = etree.parse('http://{}'.format(ARDUINO_URL))
    infos = root.xpath('/teleinformation')
    HP = infos[0].find('HCHP').text
    HC = infos[0].find('HCHC').text
    print("hc.value ", HC)
    print("hp.value ", HP)

Exemple de graphique produit par Munin

Exemples d’applications

Liens