Bannière liberation Rennes 2.jpg

A l'occasion des 80 ans de la libération de Rennes, (re)découvrez l'ensemble des
contributions autour de la Seconde Guerre mondiale et de la libération sur Wiki-Rennes.

« Fabrication d’un chargeur universel pour vélo » : différence entre les versions

De WikiRennes
Aller à la navigationAller à la recherche
m (correction)
(ajouter le code pour envoyer les variables sur une page web servie par l' ESP D1)
 
(2 versions intermédiaires par un autre utilisateur non affichées)
Ligne 15 : Ligne 15 :
----Cette approche offre une solution simple et économique pour surveiller à distance le niveau de charge de la batterie d'un vélo électrique.
----Cette approche offre une solution simple et économique pour surveiller à distance le niveau de charge de la batterie d'un vélo électrique.
[[Fichier:Lecture tension.jpg|vignette|441x441px|Lecture des valeurs via port série]]
[[Fichier:Lecture tension.jpg|vignette|441x441px|Lecture des valeurs via port série]]
[[Fichier:Prototype.jpg|alt=montage|centré|vignette|Prototype|536x536px]]
[[Fichier:Courbe de charge 18650.png|vignette|493x493px|Courbe de charge cellule 18650]]
[[Fichier:Prototype.jpg|alt=montage|vignette|Prototype|536x536px]]


=== Étapes du Projet ===
=== Étapes du Projet ===
Ligne 65 : Ligne 66 :
#** Assurer que les valeurs de tension, courant, puissance et énergie sont correctement mises à jour.
#** Assurer que les valeurs de tension, courant, puissance et énergie sont correctement mises à jour.
#** Surveiller l’évolution des valeurs pendant la charge de la batterie de vélo électrique.
#** Surveiller l’évolution des valeurs pendant la charge de la batterie de vélo électrique.
<syntaxhighlight lang="cpp" line="1">
#include <ModbusMaster.h>
// Crée une instance de ModbusMaster
ModbusMaster node;
void setup() {
  // Initialisation de la communication série
  Serial.begin(9600);
  Serial.println("Initialisation Modbus...");
  // Configuration du port série pour Modbus
  node.begin(1, Serial); // Adresse esclave 1, communication via le port série
}
void loop() {
  uint8_t result;
  uint16_t data[8];
  // Lecture de 8 registres à partir de l'adresse 0x0000
  result = node.readInputRegisters(0x0000, 8);
  if (result == node.ku8MBSuccess) {
    // Stocke les données lues dans le tableau `data`
    for (int i = 0; i < 8; i++) {
      data[i] = node.getResponseBuffer(i);
    }
    // Affichage des valeurs lues
    float voltage = data[0] * 0.01; // La tension est à l'adresse 0x0000
    float current = data[1] * 0.01; // Le courant est à l'adresse 0x0001
    float power = (data[3] << 16 | data[2]) * 0.1; // La puissance est sur 2 registres, à l'adresse 0x0002 et 0x0003
    float energy = (data[5] << 16 | data[4]) * 1;  // L'énergie est sur 2 registres, à l'adresse 0x0004 et 0x0005
    Serial.print("Tension: ");
    Serial.print(voltage);
    Serial.println(" V");
    Serial.print("Courant: ");
    Serial.print(current);
    Serial.println(" A");
    Serial.print("Puissance: ");
    Serial.print(power);
    Serial.println(" W");
    Serial.print("Energie: ");
    Serial.print(energy);
    Serial.println(" Wh");
  } else {
    Serial.print("Erreur lors de la lecture des registres: ");
    Serial.println(result, HEX);
  }
  delay(2000); // Pause de 2 secondes avant la prochaine lecture
}
</syntaxhighlight>Visualisation par serveur web<syntaxhighlight lang="c">
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ModbusMaster.h>
const char* ssid = "Pixelm";
const char* password = "bienveillance";
ESP8266WebServer server(80);
ModbusMaster node;
// Variables pour stocker les données Modbus
float voltage = 0;
float current = 0;
float power = 0;
float energy = 0;
// Constante pour le délai entre les lectures
const unsigned long READ_INTERVAL = 2000;
unsigned long lastReadTime = 0;
void setup() {
  Serial.begin(9600);
  Serial.println("Initialisation Modbus...");
 
  // Initialisation Modbus
  node.begin(1, Serial); // Adresse esclave 1, communication via le port série
 
  // Connexion Wi-Fi
  connectToWiFi();
  // Initialisation serveur Web
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Serveur HTTP démarré.");
}
void loop() {
  server.handleClient();
 
  // Lecture des données Modbus toutes les READ_INTERVAL millisecondes
  if (millis() - lastReadTime >= READ_INTERVAL) {
    lastReadTime = millis();
    readModbusData();
  }
}
void connectToWiFi() {
  WiFi.begin(ssid, password);
  Serial.println("Connexion au Wi-Fi...");
  unsigned long startTime = millis();
  while (WiFi.status() != WL_CONNECTED) {
    if (millis() - startTime > 30000) { // Limite de 30 secondes pour la connexion
      Serial.println("Erreur de connexion au Wi-Fi.");
      return;
    }
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Connecté au Wi-Fi.");
  Serial.print("Adresse IP: ");
  Serial.println(WiFi.localIP());
}
void readModbusData() {
  uint8_t result;
  uint16_t data[8];
  // Lecture de 8 registres à partir de l'adresse 0x0000
  result = node.readInputRegisters(0x0000, 8);
  if (result == node.ku8MBSuccess) {
    // Stocker les données dans le tableau `data`
    for (int i = 0; i < 8; i++) {
      data[i] = node.getResponseBuffer(i);
    }
    // Mise à jour des variables globales
    voltage = data[0] * 0.01;
    current = data[1] * 0.01;
    power = (data[3] << 16 | data[2]) * 0.1;
    energy = (data[5] << 16 | data[4]) * 1;
    // Affichage des valeurs lues sur le port série
    printModbusValues();
  } else {
    Serial.print("Erreur lors de la lecture des registres: ");
    Serial.println(result, HEX);
  }
}
void printModbusValues() {
  Serial.print("Tension: ");
  Serial.print(voltage);
  Serial.println(" V");
  Serial.print("Courant: ");
  Serial.print(current);
  Serial.println(" A");
  Serial.print("Puissance: ");
  Serial.print(power);
  Serial.println(" W");
  Serial.print("Energie: ");
  Serial.print(energy);
  Serial.println(" Wh");
}
void handleRoot() {
  String html = "<html><head><title>Données Modbus</title></head><body>";
  html += "<h1>Données Modbus</h1>";
  html += "<p><strong>Tension: </strong>" + String(voltage) + " V</p>";
  html += "<p><strong>Courant: </strong>" + String(current) + " A</p>";
  html += "<p><strong>Puissance: </strong>" + String(power) + " W</p>";
  html += "<p><strong>Energie: </strong>" + String(energy) + " Wh</p>";
  html += "</body></html>";
  server.send(200, "text/html", html);
}
</syntaxhighlight>

Version actuelle datée du 18 septembre 2024 à 13:39

Fabrication d’un chargeur universel pour vélo

Objectif du projet

Ce projet vise à doter un vélo électrique de capacités de mesure en temps réel des courants et tensions de charge en courant continu. L'objectif est de développer un module qui s'interface entre le chargeur d'origine et la batterie (système de gestion de batterie, BMS) du vélo, afin de surveiller à distance le niveau de charge de la batterie via un réseau sans fil.

Description du prototype

Le premier prototype est conçu avec des composants à faible coût pour tester la faisabilité du projet. Il repose sur :

  • Un module PZEM-003 (Peacefair) : utilisé pour mesurer des paramètres essentiels tels que la tension continue, le courant, la puissance active et la consommation d'énergie.
  • Deux connecteurs mâle/femelle XLR 4 broches
  • Un ESP8266 (clone D1 mini) : microcontrôleur doté d'une connexion Wi-Fi, permettant la transmission des données de mesure vers un réseau sans fil.

Modifications techniques

Pour permettre la communication entre l'ESP8266 et le PZEM-003, deux fils ont été soudés en amont de la puce MAX485 du PZEM. Ainsi, l'ESP8266 peut directement dialoguer avec le module PZEM en utilisant le protocole UART.


Cette approche offre une solution simple et économique pour surveiller à distance le niveau de charge de la batterie d'un vélo électrique.

Lecture des valeurs via port série
Courbe de charge cellule 18650
montage
Prototype

Étapes du Projet

  1. Préparation du Matériel
    • Composants nécessaires :
      • ESP8266 : module de communication Wi-Fi
      • PZEM 003 : capteur de mesure de tension et courant
      • Batterie de vélo électrique : pour mesurer la consommation réelle de l'énergie
      • Optocoupleur : pour isoler les parties énergie et données
      • Connecteurs femelles et mâles : pour connecter les fils sans couper le chargeur
    • Outils :
      • Soudure, câbles, breadboard, alimentation 3.3V
  2. Installation des Composants
    • Placer le PZEM 003 entre le chargeur et la batterie de vélo électrique.
      • Utiliser les connecteurs femelles et mâles pour éviter de couper les fils du chargeur.
    • Souder les fils :
      • Souder deux fils à la sortie de l’optocoupleur pour récupérer les données en protocole UART.
    • Connexion de l'optocoupleur :
      • Alimenter l'optocoupleur en 3.3V depuis la breadboard de l’ESP8266.
  3. Configuration du logiciel
    • Télécharger et installer l’IDE Arduino :
      • Aller sur File > Preferences et ajouter l’URL : http://arduino.esp8266.com/stable/package_esp8266com_index.json
      • Activer le package ESP8266 : Tools > Board > Board Manager et chercher « esp82 », puis cliquer sur « Installer ».
      • Sélectionner la carte : Tools > Board > LOLIN D1 mini (clone).
    • Tester la carte :
      • Ouvrir un exemple : File > Examples > ESP8266 > Blink et cliquer sur « Upload ».
  4. Programmation de l’ESP8266
    • Écrire le code :
      • Inclure la bibliothèque ModbusMaster.
      • Configurer le port série pour communiquer avec le l'ESP82.
      • Lire les registres du PZEM et afficher les données (tension, courant, puissance, énergie).
    • Installer la bibliothèque ModbusMaster :
      • Aller dans l’IDE Arduino, cliquer sur l’icône « Bibliothèque », rechercher « ModbusMaster » et l’installer.
    • Téléverser le code :
      • Connecter l’ESP8266 à l’ordinateur et téléverser le code.
  5. Connexion et tests
    • Branchement de l’alimentation :
      • Côté ESP8266 : entre GND (ground) et 3.3V.
      • Côté PZEM 003 : sur les bornes 5V (en 3.3V) et GND.
    • Vérifier les valeurs :
      • Ouvrir le Serial Monitor dans l’IDE Arduino (Tools > Serial Monitor).
      • Réinitialiser l’ESP8266 et vérifier les valeurs affichées toutes les 2 secondes (les valeurs de courant et puissance doivent être 0 si aucune charge n’est connectée).
    • Branchement de la batterie de vélo électrique :
      • Connecter la batterie aux bornes P+ et P- du PZEM 003.
      • Vérifier que la batterie charge bien.
  6. Vérification finale
    • Observer les données :
      • Assurer que les valeurs de tension, courant, puissance et énergie sont correctement mises à jour.
      • Surveiller l’évolution des valeurs pendant la charge de la batterie de vélo électrique.
#include <ModbusMaster.h>

// Crée une instance de ModbusMaster
ModbusMaster node;

void setup() {
  // Initialisation de la communication série
  Serial.begin(9600);
  Serial.println("Initialisation Modbus...");

  // Configuration du port série pour Modbus
  node.begin(1, Serial); // Adresse esclave 1, communication via le port série
}

void loop() {
  uint8_t result;
  uint16_t data[8];

  // Lecture de 8 registres à partir de l'adresse 0x0000
  result = node.readInputRegisters(0x0000, 8);

  if (result == node.ku8MBSuccess) {
    // Stocke les données lues dans le tableau `data`
    for (int i = 0; i < 8; i++) {
      data[i] = node.getResponseBuffer(i);
    }

    // Affichage des valeurs lues
    float voltage = data[0] * 0.01; // La tension est à l'adresse 0x0000
    float current = data[1] * 0.01; // Le courant est à l'adresse 0x0001
    float power = (data[3] << 16 | data[2]) * 0.1; // La puissance est sur 2 registres, à l'adresse 0x0002 et 0x0003
    float energy = (data[5] << 16 | data[4]) * 1;  // L'énergie est sur 2 registres, à l'adresse 0x0004 et 0x0005

    Serial.print("Tension: ");
    Serial.print(voltage);
    Serial.println(" V");

    Serial.print("Courant: ");
    Serial.print(current);
    Serial.println(" A");

    Serial.print("Puissance: ");
    Serial.print(power);
    Serial.println(" W");

    Serial.print("Energie: ");
    Serial.print(energy);
    Serial.println(" Wh");
  } else {
    Serial.print("Erreur lors de la lecture des registres: ");
    Serial.println(result, HEX);
  }

  delay(2000); // Pause de 2 secondes avant la prochaine lecture
}

Visualisation par serveur web

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ModbusMaster.h>

const char* ssid = "Pixelm";
const char* password = "bienveillance";

ESP8266WebServer server(80);
ModbusMaster node;

// Variables pour stocker les données Modbus
float voltage = 0;
float current = 0;
float power = 0;
float energy = 0;

// Constante pour le délai entre les lectures
const unsigned long READ_INTERVAL = 2000;
unsigned long lastReadTime = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("Initialisation Modbus...");
  
  // Initialisation Modbus
  node.begin(1, Serial); // Adresse esclave 1, communication via le port série
  
  // Connexion Wi-Fi
  connectToWiFi();

  // Initialisation serveur Web
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Serveur HTTP démarré.");
}

void loop() {
  server.handleClient();
  
  // Lecture des données Modbus toutes les READ_INTERVAL millisecondes
  if (millis() - lastReadTime >= READ_INTERVAL) {
    lastReadTime = millis();
    readModbusData();
  }
}

void connectToWiFi() {
  WiFi.begin(ssid, password);
  Serial.println("Connexion au Wi-Fi...");

  unsigned long startTime = millis();
  while (WiFi.status() != WL_CONNECTED) {
    if (millis() - startTime > 30000) { // Limite de 30 secondes pour la connexion
      Serial.println("Erreur de connexion au Wi-Fi.");
      return;
    }
    delay(1000);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("Connecté au Wi-Fi.");
  Serial.print("Adresse IP: ");
  Serial.println(WiFi.localIP());
}

void readModbusData() {
  uint8_t result;
  uint16_t data[8];

  // Lecture de 8 registres à partir de l'adresse 0x0000
  result = node.readInputRegisters(0x0000, 8);

  if (result == node.ku8MBSuccess) {
    // Stocker les données dans le tableau `data`
    for (int i = 0; i < 8; i++) {
      data[i] = node.getResponseBuffer(i);
    }

    // Mise à jour des variables globales
    voltage = data[0] * 0.01;
    current = data[1] * 0.01;
    power = (data[3] << 16 | data[2]) * 0.1;
    energy = (data[5] << 16 | data[4]) * 1;

    // Affichage des valeurs lues sur le port série
    printModbusValues();
  } else {
    Serial.print("Erreur lors de la lecture des registres: ");
    Serial.println(result, HEX);
  }
}

void printModbusValues() {
  Serial.print("Tension: ");
  Serial.print(voltage);
  Serial.println(" V");

  Serial.print("Courant: ");
  Serial.print(current);
  Serial.println(" A");

  Serial.print("Puissance: ");
  Serial.print(power);
  Serial.println(" W");

  Serial.print("Energie: ");
  Serial.print(energy);
  Serial.println(" Wh");
}

void handleRoot() {
  String html = "<html><head><title>Données Modbus</title></head><body>";
  html += "<h1>Données Modbus</h1>";
  html += "<p><strong>Tension: </strong>" + String(voltage) + " V</p>";
  html += "<p><strong>Courant: </strong>" + String(current) + " A</p>";
  html += "<p><strong>Puissance: </strong>" + String(power) + " W</p>";
  html += "<p><strong>Energie: </strong>" + String(energy) + " Wh</p>";
  html += "</body></html>";

  server.send(200, "text/html", html);
}