Le graphique de la consommation électrique (A) - sur iPad avec PLCLink.
La réalisation d'un graphique du courant consommé ou d'une autre variable suppose un enregistrement des valeurs, on se propose de lire et conserver à l'aide du Raspberry PI le courant mesuré avec un autre dispositif : Mesure de courant. Cette solution laisse le Rasberry sans aucune contrainte de position, sa liaison réseau est en WiFi.
L'important est que la variable enregistrée soit disponible sur votre réseau, le Raspberry ira la relire, on ne donne pas ici la méthode utilisé pour relire votre variable, avec un automate Wago une solution simple est la lecture en ModBus avec PHP si votre automate le permet (Wago souvent utilisé).
L'idéal serait que le Raspberry lui-même fasse la mesure, on ne détaillera pas ici le montage utile mais avec le capteur de courant LA-55P si on lui ajoute un CAN connecté en I2C ou SPI sur le Rasberry, le montage serait totalement autonome mais bloqué proche de l'arrivée électrique.
La carte Raspberry PI avec sa mémoire sur carte SD et la faible consommation est adapté pour un usage
d'enregistrement et conservation des mesures. La période envisagée est de l'ordre de l'année avec une mesure par minute. En ajoutant la date
et la valeur il faut compter 25 à 30 octets par minute soit 45Ko par jour.
Une année de stockage donne au maximum 15 Mo de data ce qui au regard de la taille des cartes SD est plutôt faible.
La méthode la plus rapide est de réaliser un fichier texte de type .csv les informations sont séparées par des ";". Mais la taille envisagée 15Mo par année rends le traitement aléatoire sur le Raspberry, il faudra en effet extraire de ce fichier les informations pour construire le graphique avec divers paramètres.
Une méthode plus efficace est de profiter de mySQl largement disponible avec les divers distributions Linux. On installera aussi "phpmyadmin" pour réaliser une base avec une table pour les mesures.
Après quelques essais d'affichage le package graphique "dygraphs" donne de bon résultats on le trouve ici :
http://dygraphs.com
Lors de l'appel de la page il faudra construire le tableau des valeurs donc en relisant la table SQL, on
propose un graphique des 2 dernières heures, des 24 dernières heures et de la semaine en cours.
La conservation des informations en base SQL facilite l'extraction, pour lire par exemple les 120 derniers enregistrements pour les deux dernières heures etc... vous en trouverez d'autres utile, mais attention une semaine comportera 10080 points de mesure !
Pour des raisons de taille d'affichage sur iPhone avec PLCLink qui affichera le graphique il sera inutile de
transmettre plus de 2000 points par graphique, un espacement d'échantillonnage et traitement
préalable sera fortement utile. Le package Dygraphs permet le zoom dans les valeurs.
Limiter les points évite aussi l'attente trop longue du graphique, le traitement pour 1 semaine de 10000 points
est déjà de l'ordre de 10 secondes contre 0.4 secondes pour les deux dernières heures.
Seront nécessaire les services suivants sur le Raspberry PI :
Vous trouverez sur de nombreux sites comment installer ces composants pour le Rasberry PI, il n'y a pas de problèmes
particuliers. Dans cette installation le Raspberry n'est connecté que sur son alimentation, une clef USB WiFi (N150) lui
permet de se connecter sur le réseau local. Il sera donc disposé à n'importe quel endroit pratique. On fixe l'IP avec une règle dans le routeur associant le numéro MAC de
la clef WiFi avec un IP fixe. Les scripts seront moins instables avec un IP définitif.
Pour simplifier conservez tout les paramètres par défaut.
Le CRON est un dispositif qui lance régulièrement une procédure, ici on va lancer toutes les minutes un fichier script PHP de lecture du courant, on ajoutera #!/usr/bin/php en première ligne pour indiquer le chemin de l'interpreteur.
Installer "webmin" pour placer un CRON, c'est plus facile que la méthode manuelle, on dispose aussi d'un moyen de test de ce script.
La ligne ajoutée dans la crontab reste toutefois au plus simple :
* * * * * /var/www/courant.php
Installez "phpmyadmin" pour monter une base "courant" comportant une table "historique" avec 3 colonnes "ref", "date" et "courant", ref sera l'index pour les recherches dans la table, uniquement des extractions des dernières valeurs.
#!/usr/bin/php <? // demande le courant et sortie vers la base "courant" $courant = getCourant(); // base sql de service : $c = mysql_connect("localhost", "root", "raspberry"); mysql_select_db("courant"); storeCourant($courant); // ----------------------------- function storeCourant($courant) { $q2 = mysql_query("INSERT INTO historique(date,courant) VALUES(NOW(), '$courant')"); } // ----------------------------- function getCourant() { // ici votre procedure de lecture du courant return $courant; } ?>
Ce fichier est à copier dans le dossier /var/www, il sera appelé par un CRON chaque minute, vous devez compléter avec votre méthode d'obtention du courant, soit une lecture d'url, un appel ModBus, un fichier xml dans l'automate etc... Avec un complément matériel le Raspberry serait capable de faire lui même la mesure du courant, avec une boucle magnétique et un convertisseur analogique en I2C par exemple.
Utilisez webmin pour définir un nouveau CRON avec ce script comme cible, il est en /var/www/courant.php. Vérifiez aussi avec webmin que ce fichier est exécutable, au besoin ajuster les autorisations sur ce fichier.
La base doit commencer à se remplir avec 1 mesure par minute, à vérifier avec phpmyadmin.
Au passage vous pouvez ajuster la valeur du courant mesuré en le moyennant et aussi ajouter un comparateur avec une valeur maximale et déclencher une alerte PUSH pour PLCLink avec un simple appel à une URL de push, voir les détails sur : Le push sur PLCLink vous serez ainsi informé rapidement du dépassement possible de la valeur actuelle.
Ce script est à placer dans le serveur /var/www/graph.php, emplacement par défaut standard. Il sera appelé par un navigateur : http://IP_raspberry/graph.php et va produire le graphique. Il est aussi possible de définir cette adresse pour une iFrame dans PLCLink qui se chargera de l'afficher.
<? // lecture fichier du courant en base "courant" table "historique" $c = mysql_connect("localhost", "root", "raspberry"); mysql_select_db("courant"); // 3 methodes de dessin $t = $_GET["t"]; if($t == "heure") dernierHeure(); else if($t == "jour") dernierJour(); else if($t == "semaine") dernierSemaine(); else dernierJour(); // ------ dernier jour ------------------------- function dernierJour() { $f = fopen("/var/www/courant.js","w"); fwrite($f, "function NoisyData() {\n return \"\" +\n\"Date,Courant\\n\" +\n" ); $q1 = mysql_query("SELECT * FROM (SELECT * FROM historique ORDER BY ref DESC LIMIT 0,1500) AS historique ORDER BY ref"); // lecture totale 1500 = 1 journée $num_rows = mysql_num_rows($q1); $ind = 0; if($q1) while ($result = mysql_fetch_array($q1) ) { $date = $result[date]; $courant = sprintf("%01.2f",$result[courant]); $erreur = sprintf("%01.2f",$courant * 0.05); // 5% erreur mesure $fin = ($num_rows-1 > $ind++) ? "+" : ";"; fwrite($f,"\"" . $date . "," .$courant . ",".$erreur."\\n\" ".$fin."\n"); } fwrite($f, "}"); fclose($f); } function dernierHeure() { $f = fopen("/var/www/courant.js","w"); fwrite($f, "function NoisyData() {\n return \"\" +\n\"Date,Courant\\n\" +\n" ); $q1 = mysql_query("SELECT * FROM (SELECT * FROM historique ORDER BY ref DESC LIMIT 0,120) AS historique ORDER BY ref"); // lecture totale 120 = 2 heures $num_rows = mysql_num_rows($q1); $ind = 0; if($q1) while ($result = mysql_fetch_array($q1) ) { $date = $result[date]; $courant = sprintf("%01.2f",$result[courant]); $erreur = sprintf("%01.2f",$courant * 0.05); // 5% erreur mesure $fin = ($num_rows-1 > $ind++) ? "+" : ";"; fwrite($f,"\"" . $date . "," .$courant . ",".$erreur."\\n\" ".$fin."\n"); } fwrite($f, "}"); fclose($f); } // ------ dernier semaine ------------------------- // 1 pt/2 a voir function dernierSemaine() { $f = fopen("/var/www/courant.js","w"); fwrite($f, "function NoisyData() {\n return \"\" +\n\"Date,Courant\\n\" +\n" ); $q1 = mysql_query("SELECT * FROM (SELECT * FROM historique ORDER BY ref DESC LIMIT 0,10100) AS historique ORDER BY ref"); // lecture totale 10080 = 1 semaine $num_rows = mysql_num_rows($q1); $ind = 0; while ($result = mysql_fetch_array($q1) ) { $date = $result[date]; $courant = $result[courant]; $erreur = sprintf("%01.2f",$courant * 0.05); // 5% erreur mesure $fin = ($num_rows-1 > $ind++) ? "+" : ";"; if($fin == ";") fwrite($f,"\"" . $date . "," .$courant . ",".$erreur."\\n\" ".$fin."\n"); else if($ind%10==0) fwrite($f,"\"" . $date . "," .$courant . ",".$erreur."\\n\" ".$fin."\n"); } fwrite($f, "}"); fclose($f); } ?> <!DOCTYPE html> <html> <head> <title>Graphique courant</title> <script type="text/javascript" src="dygraphs-master/dygraph-combined.js"></script> <script type="text/javascript" src="courant.js"></script> <style type="text/css"> #div_g14 .dygraph-legend { width: 100px; background-color: transparent !important; left: 40px !important; } </style> </head> <body> <div id="div_g14" style="height:200px;"></div> <div style="position:absolute; text-align:center; width:300px; top:0; "> <input type="button" value="Heure" onclick="Heure();" style="width:60px;" /> <input type="button" value="Jour" onclick="Jour();" style="width:60px;"/> <input type="button" value="Semaine" onclick="Semaine();" style="width:60px;" /> </div> <script> function Heure() { location.href="graph.php?t=heure"; } function Jour(){ location.href="graph.php?t=jour"; } function Semaine(){ location.href="graph.php?t=semaine"; } </script> <script type="text/javascript"> g14 = new Dygraph( document.getElementById("div_g14"), NoisyData, { rollPeriod: 2, errorBars: true, labelsSeparateLines: true, yAxisLabelWidth: 20 } ); </script> </body> </html>
On trouve trois fonctions pour le graphique par heure, par jour ou pour la semaine. Le but
est de construire un fichier "courant.js" à la volée pour le graphique.
On réalise une jointure SQL dans le SELECT pour extraire dans l'ordre les 120 derniers enregistrements :
"SELECT * FROM (SELECT * FROM historique ORDER BY ref DESC LIMIT 0,120) AS historique ORDER BY ref"
Conserver l'extraction primaire en ordre inverse dessine correctement le graphique mais un message est généré
pour chaque données.
Ensuite une boucle dans l'extraction permet de réaliser dynamiquement le fichier courant.js avec la structure suivante :
function NoisyData() { return "" + "Date,Courant\n" + "2013-03-24 14:45:01,6.49,0.32\n" + ... "2013-03-24 15:00:01,5.91,0.30\n" + "2013-03-24 15:01:02,2.71,0.14\n" ; }
Ce fichier comporte une fonction javascript retournant les points de mesures, la date est directement issue
de la colonne "date" de la table, ensuite le courant mesuré et l'erreur de mesure (5%) calculée, les valeurs sont
séparées par une virgule.
La fonction Jour est identique avec 1500 points, la fonction Semaine avec plus de 10000 valeurs donne beaucoup trop d'information
pour réduire les transferts 1 point sur 10 est conservé if($ind%10==0).... Un moyennage ou une sortie du maximum des 10 points serait possible.
<item id="0"> <title>Titre</title> <name>Courant</name> <description>Courant</description> <type>direct</type> <affichage>iframe</affichage> <url>http://192.168.0.20/graph.php</url> </item>
Un item "iframe" permet l'affichage d'une page web, la page est réalisée avec le script PHP décris ci-dessus.
Les boutons ajoutés en superposition permettent de choisir l'échelle de visualisation.
La bib javascript Dygraphs donne aussi un moyen de zoomer dans le temps.
L'image ci-contre montre la présentation sur iPhone avec PLCLink, le navigateur Safari est utilisable aussi.
La documentation de Wagolink est ici : Wagolink La documentation de PLCLink est ici : PLCLink
Nancy 2012-17 - contact : Pautex JF