- Programme pour l’Arduino Pro Mini de transmission :
Édit du 15 mai 2020 !
Électro-Bidouilleur a enfin sorti une vidéo sur le module HC-12 et nous informe que la librairie <SoftwareSerial.h> est à éviter, ce que j'aurais bien voulu savoir à l'époque étant donné que j'ai effectivement rencontré des problèmes de réception. Il faut donc lui préférer la librairie <AltSoftSerial.h>. Je n'ai pas le temps de me pencher dessus, donc j'ai laissé tel quel le code suivant, sur github et en annexe du billet, à vous de changer la librairie.
#include <SoftwareSerial.h>
/****************/
/* DÉCLARATIONS */
/****************/
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin
char MessageTensionBatterie[] = " VOL / "; // message to be sent; '\n' is a forced terminator char
char MessageCourant[] = " AMP\n"; // message to be sent; '\n' is a forced terminator char
String chaine;
#define ATpin 7 // used to switch HC-12 to AT mode
float Courant=0;
float SupplyVoltage=12;
const int Voie_0=0; // declaration constante de broche analogique
int mesure_brute=0; // Variable pour acquisition résultat brut de conversion analogique numérique
float mesuref=0.0; // Variable pour calcul résultat décimal de conversion analogique numérique
float tension=0.0; // Variable tension mesurée
float tension_batterie=0.0; // Variable tension batterie calculée
float tension_regulateur=8925.0; // Variable tension réelle aux bornes du régulateur -9V (en mV)
int PIN_ACS712 = A1;
double Voltage = 0;
double Current = 0;
/*********/
/* SETUP */
/*********/
void setup() {
// Serial.begin(9600); // Debug
HC12.begin(9600); // Serial port to HC12
// Pin capteurs
pinMode(PIN_ACS712, INPUT);
pinMode(ATpin, OUTPUT);
digitalWrite(ATpin, LOW); // Set HC-12 into AT Command mode
delay(500);
HC12.print("AT+C056"); // passer sur le canal 006 (433.4Mhz + 56x400KHz)
delay(500);
digitalWrite(ATpin, HIGH); // HC-12 en normal mode
}
/*************/
/* PROGRAMME */
/*************/
void loop() {
MesureCourant();
MesureBrute();
TensionMesuree();
TensionBatterie();
chaine = String(tension_batterie,3) + MessageTensionBatterie + String(Current,3) + MessageCourant; // construction du message
Serial.println ( "chaine String : " +chaine );
HC12.print(chaine); // send radio data
delay(100);
}
/*************/
/* FONCTIONS */
/*************/
void MesureCourant() {
// Serial.print("Courant : ");
// Serial.print(Courant);
// Serial.print(" A | Puissance : ");
// Serial.print(Courant*SupplyVoltage);
// Serial.println(" Watt");
// Voltage is Sensed 1000 Times for precision
for(int i = 0; i < 1000; i++) { // ça ralentis tout, mais c'est indispensable !
Voltage = (Voltage + (0.004882812 * analogRead(PIN_ACS712))); // (5 V / 1024 (Analog) = 0.0049) which converter Measured analog input voltage to 5 V Range
delay(1);
}
Voltage = Voltage /1000;
Current = (Voltage -2.5)/ 0.100; // Sensed voltage is converter to current (0.100 pour modèle 20A)
Serial.print("\n Voltage Sensed (V) = "); // shows the measured voltage
Serial.print(Voltage,3); // the ‘2’ after voltage allows you to display 2 digits after decimal point
Serial.print("\t Current (A) = "); // shows the voltage measured
Serial.println(Current,3); // the ‘2’ after voltage allows you to display 2 digits after decimal point
}
void MesureBrute() {
//-------- mesure brute --------
mesure_brute=analogRead(Voie_0);
// Serial.print ("Valeur brute = ");
// Serial.print (mesure_brute);
// Serial.println (" "); // espace de propreté
}
void TensionMesuree() {
//---------- tension mesurée ---------
mesuref=float(mesure_brute)*5000.0/1024.0;
tension=mesuref/1000.0; // en Volts
// Serial.print ("Tension = ");
// Serial.print(tension,3); // float avec 2 décimales
// Serial.println(" V "); // unité et espace de propreté
}
void TensionBatterie() {
//---------- tension batterie ---------
tension_batterie=mesuref+tension_regulateur;
tension_batterie=tension_batterie/1000.0; // en Volts
// lcd.setCursor(0,1) ; // positionne le curseur à l'endroit voulu (colonne, ligne)
// lcd.print ("Batt:");
// lcd.print (tension_batterie,2); // float avec 2 décimales
// lcd.print ("V "); // unité et espace de propreté
Serial.print ("Batterie = ");
Serial.print(tension_batterie,3); // float avec 2 décimales
Serial.println(" V ");
// Serial.println(" ");
}
Le boîtier client, partie récepteur avec affichage :
Voici le montage avec un afficheur LCD standard :

Matériel requis :
- 1 Arduino Pro Mini 5V.
- Un ordi avec port USB et le soft Arduino IDE.
- 1 plaquette HC-12 et son antenne.
- 1 diode 1N4007.
- 1 afficheur LCD type HD44780 16 ou 20 x 2.
- 1 NodeMCUv3 LoLin.
- 1 condensateur électrochimique polarisé de 220µF.
- J'ai simulé le générateur avec une alimentation 12V et la batterie par une ampoule :
Principe de fonctionnement :
- L'Arduino reçoit les valeurs transmises par le port série du HC-12 et les affiche instantanément sur l'écran LCD.
- Le NodeMCU reçoit les valeurs transmises par le port série du HC-12 et les transmet à la Base de données InfluxDB.
- Grafana s'occupera de tracer les graphiques à partir des données.
- Programme pour l’Arduino Pro Mini de réception :
Édit du 15 mai 2020 !
Électro-Bidouilleur a enfin sorti une vidéo sur le module HC-12 et nous informe que la librairie <SoftwareSerial.h> est à éviter, ce que j'aurais bien voulu savoir à l'époque étant donné que j'ai effectivement rencontré des problèmes de réception. Il faut donc lui préférer la librairie <AltSoftSerial.h>. Je n'ai pas le temps de me pencher dessus, donc j'ai laissé tel quel le code suivant, sur github et en annexe du billet, à vous de changer la librairie.
//———— Que fait ce programme ? ————
// ---> Récupére les données transmise par un module HC-12,
// ---> Affichage la mesure de la tension d'une batterie au plomb 12V sur un écran LCD.
// ---> Affichage l'intensité et la puissance fournie à la batterie par une génératrice 12V.
//———— Fonctionnalités utilisées ————
// Utilise un afficheur LCD alphanumérique2x20 en mode 4 bits
//———— Circuit à réaliser ————
// Broche 12 sur la broche RS du LCD
// Broche 11 sur la broche E du LCD
// Broche 5 sur la broche D4 du LCD
// Broche 4 sur la broche D5 du LCD
// Broche 3 sur la broche D6 du LCD
// Broche 2 sur la broche D7 du LCD
// Broche 7 sur HC-12 to AT mode
// Broche 8 HC-12 TX Pin
// Broche 9 HC-12 RX Pin
//———— Réglages possibles ————
// Canal de réception (voir setup)
// Voltage : Utilisé pour le calcul de la puissance en Watt.
// MiniC : pour régler le courant minimum mesuré en dessous duquel la valeur est forcée à 0, pour prendre
// en compte le fait que la mesure du zero ne tombe jamais pile.
#include <LiquidCrystal.h> // lib LCD
#include <SoftwareSerial.h> // lib Transmission série
//################
//# DÉCLARATIONS #
//################
//——— Radio HC-12 ———//
SoftwareSerial HC12(8, 9); // HC-12 TX Pin, HC-12 RX Pin
#define ATpin 7 // poir passer le HC-12 en AT mode
char acquis_data;
String chaine;
float Voltage=12;
float MiniC=0.08; // courant minimum mesuré en dessous duquel la valeur est forcée à 0.
float tension_batterie_float;
float Courant_float;
//——— Écran LCD ———//
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; // Déclaration LCD
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // Pins LCD en mode 4 bits
byte carre00[8] = { // caractères personnalisés
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B11111
};
byte carre01[8] = {
B11111,
B00000,
B10000,
B10000,
B10000,
B10000,
B00000,
B11111
};
byte carre02[8] = {
B11111,
B00000,
B11000,
B11000,
B11000,
B11000,
B00000,
B11111
};
byte carre03[8] = {
B11111,
B00000,
B11100,
B11100,
B11100,
B11100,
B00000,
B11111
};
byte carre04[8] = {
B11111,
B00000,
B11110,
B11110,
B11110,
B11110,
B00000,
B11111
};
byte carre05[8] = {
B11111,
B00000,
B11111,
B11111,
B11111,
B11111,
B00000,
B11111
};
byte crochetouvrant[8] = {
B00011,
B00010,
B00010,
B00010,
B00010,
B00010,
B00010,
B00011
};
byte crochetfermant[8] = {
B11000,
B01000,
B01110,
B01110,
B01110,
B01110,
B01000,
B11000
};
//——— Fonction pour pemettre le map avec variable float ———
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
//#########
//# SETUP #
//#########
void setup() {
// Serial.begin(9600); // Debug
//——— HC12 ———//
HC12.begin(9600); // Serial port to HC12
pinMode(ATpin, OUTPUT);
digitalWrite(ATpin, LOW); // HC-12 en mode commande AT
delay(500);
HC12.print("AT+C056"); // passer sur le canal 056 (433.4Mhz + 56x400KHz)
delay(500);
digitalWrite(ATpin, HIGH); // HC-12 en normal mode
//——— LCD ———//
lcd.begin(20,2); // Initialise le LCD avec 20 colonnes x 2 lignes
delay(10);
lcd.print("LCD OK"); // affiche LCD OK
delay(2000);
lcd.clear();
delay(10);
lcd.createChar(0, carre00); // Les 8 caractères personnalisés
lcd.createChar(1, carre01);
lcd.createChar(2, carre02);
lcd.createChar(3, carre03);
lcd.createChar(4, carre04);
lcd.createChar(5, carre05);
lcd.createChar(6, crochetouvrant);
lcd.createChar(7, crochetfermant);
}
//#############
//# PROGRAMME #
//#############
void loop() {
Reception();
Jauge();
delay(200);
}
//#############
//# FONCTIONS #
//#############
void Reception() {
// surtout pas de delay dans cette boucle, sinon les data reçues sont erronnées.
while (HC12.available()) { // If HC-12 has data
acquis_data = HC12.read();
chaine = chaine + acquis_data;
// Serial.println (chaine); // Attention, chaine est donc une String
/* message reçu de la forme
12.665 VOL / 0.045 AMP
pour chaque ligne on fait :*/
if (chaine.endsWith("\n")) { //détection de fin de ligne : méthodes String
// Serial.println ("fin de ligne"); // debug
// String phrase = "12.665 VOL / 0.045 AMP"; //debug
char tension_batterie[5]; // chaine de 6 caractères pour stocker le texte avant le mot VOL
char Courant[3]; // chaine de 4 caractères pour stocker le texte avant le mot AMP
// sscanf(phrase.c_str(), "%s VOL / %s AMP", tension_batterie, &Courant); //debug
sscanf(chaine.c_str(), "%s VOL / %s AMP", tension_batterie, &Courant); // la chaine à parser est dans une String, avec la méthode c_str()
tension_batterie_float = atof(tension_batterie),3; // char convertie en Float, avec 3 décimales
Courant_float = atof(Courant),2; // char convertie en Float, avec 2 décimales
Serial.print("VOLTS: ");
Serial.println(tension_batterie_float,3); // float avec 3 décimales
Serial.print("AMPERES: ");
Serial.println(Courant_float,3);
Serial.print("Watt: ");
Serial.println(Courant_float*Voltage,0); // float avec 0 décimales
Serial.println(' ');
// Affichage LCD courant et Puissance
if ( Courant_float < MiniC ){ // remise à zero forcée si valeur mesurée très petite
Courant_float = 0;
}
lcd.setCursor(0,0);
lcd.print ("Power:");
lcd.print (Courant_float,2); // float avec 2 décimales
lcd.print ("A "); // unité et espace
lcd.setCursor(12,0);
lcd.write(0b01111110); // caractère : fleche, depuis le Standard Character Pattern du LCD
lcd.print (" ");
lcd.print (Courant_float*Voltage,0);
lcd.print ("Watt ");
// Affichage LCD Batterie
lcd.setCursor(0,1);
lcd.print ("Batt:");
lcd.print (tension_batterie_float,3);
lcd.print ("V ");
chaine = ""; // vide la String chaine
}
}
}
void Jauge() { // Jauge de charge batterie
lcd.setCursor(12, 1);
lcd.write(byte(6)); // crochet ouvrant
lcd.setCursor(19, 1);
lcd.write(byte(7)); // crochet fermant
float NiveauBatterie = mapfloat(tension_batterie_float, 11.4, 12.73, 0, 30); // Discrétise la valeur de la tension batterie
int NiveauBatterieBarre = (int)NiveauBatterie; // conversion en entier
if (NiveauBatterie > 30) { // en cas de dépassement des limites haute et basse et permettre l'affichage non-erroné
NiveauBatterieBarre = 30;
lcd.setCursor(13, 1);
lcd.print ("Pleine");
delay (1000);
}
else if (NiveauBatterie < 0) {
NiveauBatterieBarre = 0;
lcd.setCursor(13, 1);
lcd.print ("Erreur");
delay (1000);
}
// Serial.print ("NiveauBatterieBarre = ");
// Serial.print(NiveauBatterieBarre);
// Serial.println(" ");
switch (NiveauBatterieBarre) {
case 0:
lcd.setCursor(13, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(14, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 1:
lcd.setCursor(13, 1);
lcd.write(byte(1)); // carre01
lcd.setCursor(14, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 2:
lcd.setCursor(13, 1);
lcd.write(byte(2)); // carre02
lcd.setCursor(14, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 3:
lcd.setCursor(13, 1);
lcd.write(byte(3)); // carre03
lcd.setCursor(14, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 4:
lcd.setCursor(13, 1);
lcd.write(byte(4)); // carre04
lcd.setCursor(14, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 5:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 6:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(1)); // carre01
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 7:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(2)); // carre02
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 8:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(3)); // carre03
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 9:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(4)); // carre04
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 10:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 11:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(1)); // carre01
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 12:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(2)); // carre02
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 13:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(3)); // carre03
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 14:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(4)); // carre04
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 15:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 16:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(1)); // carre01
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 17:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(2)); // carre02
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 18:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(3)); // carre03
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 19:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(4)); // carre04
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 20:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(0)); // carre00
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 21:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(1)); // carre01
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 22:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(2)); // carre02
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 23:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(3)); // carre03
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 24:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(4)); // carre04
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 25:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(18, 1);
lcd.write(byte(0)); // carre00
break;
case 26:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(18, 1);
lcd.write(byte(1)); // carre01
break;
case 27:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(18, 1);
lcd.write(byte(2)); // carre02
break;
case 28:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(18, 1);
lcd.write(byte(3)); // carre03
break;
case 29:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(18, 1);
lcd.write(byte(4)); // carre04
break;
case 30:
lcd.setCursor(13, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(14, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(15, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(16, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(17, 1);
lcd.write(byte(5)); // carre05
lcd.setCursor(18, 1);
lcd.write(byte(5)); // carre05
break;
default:
// statements
break;
}
}
- Programme pour le NodeMCU de réception :
Édit du 15 mai 2020 !
Électro-Bidouilleur a enfin sorti une vidéo sur le module HC-12 et nous informe que la librairie <SoftwareSerial.h> est à éviter, ce que j'aurais bien voulu savoir à l'époque étant donné que j'ai effectivement rencontré des problèmes de réception. Il faut donc lui préférer la librairie <AltSoftSerial.h>. Je n'ai pas le temps de me pencher dessus, donc j'ai laissé tel quel le code suivant, sur github et en annexe du billet, à vous de changer la librairie.
// Ressources :
//https://forum.arduino.cc/index.php?topic=553743.0
//https://plaisirarduino.fr/moniteur-serie/
#include "ESPinfluxdb.h" // lib ESP InfluxDB
#include <SoftwareSerial.h> // lib Transmission série
#include <ESP8266WiFi.h> // lib ESP Wifi
#include <ESP8266WiFiMulti.h>
//################
//# DÉCLARATIONS #
//################
//——— Radio HC-12 ———//
SoftwareSerial HC12(D5, D6); // HC-12 TX Pin et RX Pin
char acquis_data;
String chaine;
float Voltage=12;
float MiniC=0.08; // courant minimum mesuré en dessous duquel la valeur est forcée à 0.
float tension_batterie_float;
float Courant_float;
//——— InfluxDB ———//
const char *INFLUXDB_HOST = "xx.org";
const uint16_t INFLUXDB_PORT = xx;
const char *DATABASE = "xx";
const char *DB_USER = "xx";
const char *DB_PASSWORD = "xxxx";
Influxdb influxdb(INFLUXDB_HOST, INFLUXDB_PORT); //https://github.com/projetsdiy/grafana-dashboard-influxdb-exp8266-ina219-solar-panel-monitoring/tree/master/solar_panel_monitoring
int compteur = 1;
//——— WiFi ———//
char ssid[] = "xx";
char password[] = "xxxxx";
ESP8266WiFiMulti WiFiMulti;
//#########
//# SETUP #
//#########
void setup() {
Serial.begin(9600); // Debug
//——— HC12 ———//
HC12.begin(9600); // Serial port to HC12
//——— WiFi ———//
WiFiMulti.addAP(ssid, password); // Connection au réseau WiFi
while (WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
Serial.println ("WiFi Connecté");
//——— InfluxDB ———//
while (influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD)!=DB_SUCCESS) { // Connexion à la base InfluxDB
delay(10000);
}
Serial.println ("Connexion DataBase OK");
}
//#############
//# PROGRAMME #
//#############
void loop() {
Reception();
if (compteur > 100) { // envoie la data toutes les 6 secondes (delay 10 x 100 = 1000 ms, et l'opération prend 5 secondes à transférer/écrire en base)
SendDataToInfluxdbServer();
compteur = 1;
}
else {
compteur++;
}
delay(10); // refresh la data sur l'afficheur toutes les 10 ms
}
//#############
//# FONCTIONS #
//#############
void Reception() {
// surtout pas de delay dans cette boucle, sinon les data reçues sont erronnées.
while (HC12.available()) { // If HC-12 has data
acquis_data = HC12.read();
chaine = chaine + acquis_data;
// Serial.println (chaine); // Attention, chaine est donc une String
/* message reçu de la forme
12.665 VOL / 0.045 AMP
pour chaque ligne on fait :*/
if (chaine.endsWith("\n")) { //détection de fin de ligne : méthodes String
// Serial.println ("fin de ligne"); // debug
// String phrase = "12.665 VOL / 0.045 AMP"; //debug
char tension_batterie[5]; // chaine de 6 caractères pour stocker le texte avant le mot VOL
char Courant[3]; // chaine de 4 caractères pour stocker le texte avant le mot AMP
// sscanf(phrase.c_str(), "%s VOL / %s AMP", tension_batterie, &Courant); //debug
sscanf(chaine.c_str(), "%s VOL / %s AMP", tension_batterie, &Courant); // la chaine à parser est dans une String, avec la méthode c_str()
tension_batterie_float = atof(tension_batterie),3; // char convertie en Float, avec 3 décimales
Courant_float = atof(Courant),2; // char convertie en Float, avec 2 décimales
Serial.print("VOLTS: ");
Serial.println(tension_batterie_float,3); // float avec 3 décimales
Serial.print("AMPERES: ");
Serial.println(Courant_float,3);
Serial.print("Watt: ");
Serial.println(Courant_float*Voltage,0); // float avec 0 décimales
Serial.println(' ');
// Affichage LCD courant et Puissance
if ( Courant_float < MiniC ){ // remise à zero forcée si valeur mesurée très petite
Courant_float = 0;
}
chaine = ""; // vide la String chaine
}
}
}
void SendDataToInfluxdbServer() { //Writing data with influxdb HTTP API: https://docs.influxdata.com/influxdb/v1.5/guides/writing_data/
//Querying Data: https://docs.influxdata.com/influxdb/v1.5/query_language/
dbMeasurement rowDATA("Data");
rowDATA.addField("tension_batterie", tension_batterie_float);
rowDATA.addField("Courant", Courant_float);
// Serial.println(influxdb.write(rowDATA) == DB_SUCCESS ? " - rowDATA write success" : " - Writing failed");
influxdb.write(rowDATA);
// Vide les données - Empty field object.
rowDATA.empty();
}
Configuration de la Grafana :
- Concernant cette partie, je vous laisse voir la fin de ce billet, vu que c'est la même chose !
Vous pourriez obtenir ce genre de chose :
Le code est aussi documenté ici, et en annexe du billet.
Boîtiers 3D dispos sur Thingiverse
Ressources :
https://wiki.mchobby.be/index.php?title=SENSEUR-COURANT-ACS712
https://www.sparkfun.com/datasheets/BreakoutBoards/0712.pdf
http://www.mon-club-elec.fr/pmwiki_mon_club_elec/pmwiki.php?n=MAIN.ProjetBatterieMesureTension









