Arduino et TeleInfo
par , le dimanche 19 mars 2017 à 23:55

Catégorie : Général
Mots clés : Arduino EDF TeleInfo

Les compteurs électriques blancs d'EDF intègrent une interface série, dite TeleInfo, permettant de recevoir, en continue, les informations de consommation.

Principe

L'interface TeleInfo est une interface série modulée sur du 50Hz alternatif. Elle se situe en bas à du compteur (marques I1 et I2) :

Compteur EDF

Un bon nombre de sites fournit le schéma du montage électronique qui sert d'interface avec une carte Arduino. Il s'agit d'un simple opto-coupleur associé à une diode qui isole et redresse le signal du compteur :

http://www.magdiblog.fr/gpio/teleinfo-edf-suivi-conso-de-votre-compteur-electrique/

Il existe des adaptateurs tout près mais c'est plus drôle de faire le sien.

Montage

Après quelques tests à l'oscilloscope, j'ai constaté que la LED signalétique présente sur le montage provoque une baisse de tension trop importante et rend le signal non lisible par Arduino, je l'ai donc retirée ainsi que la résistance associée (Arduino comportant déjà une résistance de pull-up) :

Compteur EDF

Compteur EDF Compteur EDF

Signal sortant du compteur :

Compteur EDF

Signal après redressement à la sortie de l'opto-coupleur :

Compteur EDF

Les mesures reçues sont de la forme :

Compteur EDF

Affichage des mesures

J'ai écrit quelques scripts shell très basiques pour récupérer les mesures intéressantes : consommation heures creuses/heures pleines, intensité instantanée, puissance apparente.

Et avec l'outil +rrdtool+ j'en ai fait une représentation graphique :

Compteur EDF

Scripts

Le 'croquis' Arduino pour l'interface est :

#include <SoftwareSerial.h>

SoftwareSerial cptSerial(2, 3);

#define startFrame 0x02
#define endFrame 0x03
#define startLine 0x0A
#define endLine 0x0D

void setup()
{
  Serial.begin(9600);
  cptSerial.begin(1200);
  pinMode(13, OUTPUT);
}

void loop()
{
    String TeleInfo = "";S
    char charIn = 0;

    while (charIn != startLine)
    {
      if (cptSerial.available() > 0)
          charIn = cptSerial.read() & 0x7F;
    }

    while (charIn != endLine)
    {
        if (cptSerial.available() > 0)
        {
            charIn = cptSerial.read() & 0x7F;
            TeleInfo += charIn;
        }
    }

    digitalWrite(13, HIGH);  
    Serial.println(TeleInfo);
    digitalWrite(13, LOW);  
}

et pour afficher le résultat j'ai développé 3 scripts :

script de création des bases, à ne lancer qu'une seule fois :

#!/bin/sh

rrdtool create /root/consommation/HCHC.rrd --step 1 --no-overwrite \
   "DS:HCHC:COUNTER:300:0:U" \
   "RRA:AVERAGE:0:60:1440" 

rrdtool create /root/consommation/HCHP.rrd --step 1 --no-overwrite \
   "DS:HCHP:COUNTER:300:0:U" \
   "RRA:AVERAGE:0:60:1440" 

rrdtool create /root/consommation/IINST.rrd --step 1 --no-overwrite \
   "DS:IINST:GAUGE:300:0:U" \
   "RRA:MIN:0:60:1440"     \
   "RRA:AVERAGE:0:60:1440" \
   "RRA:MAX:0:60:1440" 

rrdtool create /root/consommation/PAPP.rrd --step 1 --no-overwrite \
   "DS:PAPP:GAUGE:300:0:U" \
   "RRA:MIN:0:60:1440"     \
   "RRA:AVERAGE:0:60:1440" \
   "RRA:MAX:0:60:1440" 

script de récupération des valeurs et mise en base, tournant dans une session screen :

#!/bin/sh

stty -F /dev/ttyUSB0 ispeed 9600  cs8 -cstopb -parenb

cat /dev/ttyUSB0 | grep --line-buffered -E "(HCHC|HCHP|IINST|PAPP)" | unbuffer -p cut -s -d ' ' -f 1,2,3 | while read -r code value dummy
do
   echo $code $value
   rrdtool update /root/consommation/$code.rrd N:$value
done

script de génération des graphiques, à mettre en crontab :

#!/bin/sh

rrdtool graph /home/public/www/www.kozodo.com/htdocs/consommation/general.png -w 1440 -h 300 \
   "DEF:HCHC=/root/consommation/HCHC.rrd:HCHC:AVERAGE" \
   "DEF:HCHP=/root/consommation/HCHP.rrd:HCHP:AVERAGE" \
   "LINE1:HCHC#0000FF:Heures creuses" \
   "LINE1:HCHP#00FF00:Heures pleines"

rrdtool graph /home/public/www/www.kozodo.com/htdocs/consommation/general_ampere.png -w 1440 -h 300 \
   "DEF:IINST=/root/consommation/IINST.rrd:IINST:AVERAGE" \
   "DEF:IINSTMIN=/root/consommation/IINST.rrd:IINST:MIN"  \
   "DEF:IINSTMAX=/root/consommation/IINST.rrd:IINST:MAX"  \
   "LINE1:IINST#FF0000:Intensité moyenne" \
   "LINE1:IINSTMIN#00FF00:Intensité min"  \
   "LINE1:IINSTMAX#0000FF:Intensité max"

rrdtool graph /home/public/www/www.kozodo.com/htdocs/consommation/general_power.png -w 1440 -h 300 \
   "DEF:PAPP=/root/consommation/PAPP.rrd:PAPP:AVERAGE" \
   "DEF:PAPPMIN=/root/consommation/PAPP.rrd:PAPP:MIN"  \
   "DEF:PAPPMAX=/root/consommation/PAPP.rrd:PAPP:MAX"  \
   "LINE1:PAPP#FF0000:Puissance apparente moyenne" \
   "LINE1:PAPPMIN#00FF00:Puissance apparente min"  \
   "LINE1:PAPPMAX#0000FF:Puissance apparente max"

Montage soudé

Pour réduire l'ensemble du matériel, j'ai utilisé une carte Arduino Nano et réalisé un montage soudé sur circuit imprimé pastillé :

Montage Teleinfo sur CI pastillé Montage Teleinfo sur CI pastillé - dessous Nano Arduino + montage soudé

et j'ai réalisé un boîtier en impression 3D pour protéger le montage :

Plan boîtier Modélisation boîtier Boîtier Boîtier en fonctionnement

Pour terminé j'ai passé les mesures sur base InfluxDB et affichage sous Grafana :

InfluxDB + Grafana

A bientôt

Antoine

Ecrire à l'auteur