Dashboard Grafana. Monitoring d'un panneau solaire en WiFi avec un ESP8266 • Domotique et objets connectés à faire soi-même

Grafana permet de créer très rapidement des dashboards pour suivre graphiquement l’évolution de mesures physiques (température, ensoleillement, teneur en particules dans une pièce, taux de CO2…). Lorsqu’on veut fabriquer ses propres objets connectés, on se pose souvent la question de la source d’alimentation en énergie. Il n’y a pas toujours une prise de courant à proximité ! L’énergie solaire est une excellente solution pour recharger une batterie LiPo ou Li-Ion. Je vous propose ici un projet qui permet de mesurer la puissance délivrée par deux panneaux solaires à l’aide de deux modules INA219. Les mesures seront collectées à l’aide d’un ESP8266 puis transmises en WiFi à une base de données InfluxDB installée sur un Raspberry Pi 3. Les mesures sont ensuite affichées sur un dashboard à l’aide de Grafana. 

Vous pouvez également mesurer l’ensoleillement des panneaux solaire à l’aide d’un BH1750 déjà présenté dans ce tutoriel.

Ce que vous allez apprendre en réalisant ce projet DIY

Si vous débutez dans la fabrication de vos propres objets connectés, voici ce que vous allez apprendre :

  • Installer et configurer une base de données InfluxDB et Grafana
  • Mesurer la puissance consommée ou délivrée par un appareil électrique. Ici, la puissance délivrée par un panneau solaire.
  • Utiliser l’IDE Arduino, coder en C++, utiliser une librairie Arduino
  • Exécuter du code Arduino sur un ESP8266
  • Publier des mesures depuis un ESP8266 sur une base de données InfluxDB en WiFi avec du code Arduino
  • Créer un base de données InfluxDB, un utilisateur. Attribuer les droits de lecture et d’écriture à un utilisateur
  • Connecter Grafana base de données InfluxDB
  • Créer un dashboard Grafana et ajouter des graphiques en ligne

Matériel nécessaire

L’objectif de ce projet est pouvoir mesurer la puissance délivrée par au moins 2 panneaux solaires (tension, intensité, puissance) afin de déterminer si elle est suffisante pour alimenter un projet d’objet connecté. On pourra également vérifier le taux d’ensoleillement à l’aide du BH1750 en fonction de différents paramètres : heure de la la journée, inclinaison, localisation, orientation, saison…

Il est possible d’attribuer jusqu’à 4 adresses I2C (0x40, 0x41, 0x42, 0x43) à un module INA219. On pourra donc surveiller jusqu’à 4 panneaux. On pourra également surveiller la puissance délivrée par la batterie LiPo pour connaître l’autonomie restante…

Certains INA219 achetés en chine peuvent être défectueux, utilisez ce sujet sur le forum pour en savoir plus et partager vos expériences.

Pour ce tutoriel, nous allons comparer deux mini panneaux solaires en silicium mono-cristallin que l’on peut ce procurer pour moins d’un euro. L’INA219 peut mesurer une tension jusqu’à 26V et 3,2A. Ne dépassez pas (sans protection) la puissance admissible par l’INA219.

La puissance pour recharger une batterie Li-Ion ou LiPO est assez faible (moins de 1W). Je vous propose ici de comparer deux panneaux solaires de dimensions courantes, 80×55 mm et 85x115mm. Cela reste assez facile à intégrer dans un boitier par impression 3D.

Vous pouvez installer Grafana et InfluxDB sur un PC Windows, Linux ou un MAC. Pour rester dans l’esprit DIY, je vous propose d’utiliser un Raspberry Pi 3. Tout est installé en quelques minutes et il peut rester en permanence sans risquer d’alourdir votre note d’électricité.

Installer et configurer InfluxDB et Grafana

Pour installer et configurer Grafana et InfluxDB, suivez ces tutoriels précédents

Installer InfluxDB sur Raspberry Pi, Windows, macOS Découverte du Shell. Créer une base de données, politique de rétention Installer Grafana sur macOS et Raspbian pour Raspberry Pi Exemple de dashboard pour objet connecté MySensors avec Node-RED et InfluxDB

Configurer InfluxDB

Pour pouvoir publier des mesures dans une base InfluxDB, vous devez

  • Créer une base de données
  • Créer un utilisateur
  • Attribuer les droits de lecture et d’écriture à cet utilisateur

Voici un exemple à exécuter depuis le Shell InfluxDB

create database demo
create user nomutilisateur with password 'motdepasse'
use demo
grant all on demo to nomutilisateur

Assemblage du circuit : ESP8266, INA219, BH1750, panneaux solaire, TP4055

Comme nous l’avons déjà vu dans le tutoriel consacré à l’INA219, la mesure de puissance se fait entre la source et un consommateur de courant. Il suffit de brancher le fil positif venant du panneau solaire sur la broche Vin- de l’INA219. On connecte ensuite la sortie Vin+ sur un régulateur de charge (un TP4055 par exemple).

Remarque. Si la mesure de tension est négative, il suffit d’inverser Vin- et Vin+.

Code Arduino compatible ESP8266

Pour développer le code Arduino du projet, j’ai utilisé la librairie développée par Francesco d’Aloisio disponible sur GitHub ici.

Vous pouvez également télécharger le code complet du projet sur GitHub ici.

Avant de téléverser le croquis, vous devez modifier les paramètres suivants :

  • INFLUXDB_HOST, adresse IP sur serveur InfluxDB
  • DATABASE, la base de données InfluxDB
  • DB_USER, l’utilisateur autorisé à se connecter à la base InfluxDB
  • DB_PASSWORD, et son mot de passe
  • WiFiMulti.addAP, modifier le nom et le mot de passe du réseau WiFi
  • ina219b.begin(0x41), l’adresse I2C du second INA219
#include 
#include 
#include 
#include 
#include "ESPinfluxdb.h"

#if defined(ESP8266)
  #include 
  #include 
#elif defined(ESP32)
  #include 
  #include 
#endif

Adafruit_INA219 ina219;
Adafruit_INA219 ina219b;
BH1750 lightMeter(0x23);

const char *INFLUXDB_HOST = "ip_influxdb";
const uint16_t INFLUXDB_PORT = 8086;

const char *DATABASE = "database";
const char *DB_USER = "user";
const char *DB_PASSWORD = "password";

#if defined(ESP8266)
ESP8266WiFiMulti WiFiMulti;
#elif defined(ESP32)
WiFiMulti WiFiMulti;
#endif

Influxdb influxdb(INFLUXDB_HOST, INFLUXDB_PORT);

void setup() {
        Serial.begin(115200);
        WiFiMulti.addAP("ssid", "wifipass");
        while (WiFiMulti.run() != WL_CONNECTED) {
                delay(100);
        }
        Serial.println("Ready");
        
        ina219.begin(0x40);
        ina219b.begin(0x41);
        lightMeter.begin();

        //influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD);
        while (influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD)!=DB_SUCCESS) {
                Serial.println("Open database failed");
                delay(10000);
        }
}

void loop() {
  scani2c();
  float busvoltage = 0;
  float current_mA = 0;
  float busvoltageb = 0;
  float current_mAb = 0;
  uint16_t lux = 0;
  
  busvoltage = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  busvoltageb = ina219b.getBusVoltage_V();
  current_mAb = ina219b.getCurrent_mA();
  lux = lightMeter.readLightLevel();
  Serial.print(busvoltage);
  Serial.print(" V / ");
  Serial.print(current_mA);
  Serial.print(" mA - ina219b ");
  Serial.print(busvoltageb);
  Serial.print(" V / ");
  Serial.print(current_mAb);
  Serial.print(" mA - Lux ");
  Serial.println(lux);
  
  dbMeasurement row("80x55");
  row.addField("voltage", busvoltage);
  row.addField("Current", current_mA); 
  row.addField("power", busvoltage * current_mA);

  Serial.println(influxdb.write(row) == DB_SUCCESS ? " - Object write success" : " - Writing failed");
  dbMeasurement rowb("85x115");
  rowb.addField("voltage", busvoltageb);
  rowb.addField("Current", current_mAb); 
  rowb.addField("power", busvoltageb * current_mAb);
  Serial.println(influxdb.write(rowb) == DB_SUCCESS ? " - Object write success" : " - Writing failed");

  dbMeasurement rowlux("lux");
  rowlux.addField("lux", lux);
 Serial.println(influxdb.write(rowlux) == DB_SUCCESS ? " - Object write success" : " - Writing failed");
  
  // Empty field object.
  row.empty();
  rowb.empty();
  rowlux.empty();
  
  delay(5000);
}

void scani2c()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address