Bonjour à tous,
J'utilise un Mega2560 avec un esp8266 embarqué afin de lire le relevé d'une sonde pH (partie Mega) et de l'envoyer à l'esp pour la transmettre via wifi sur un broker mqtt (partie esp, en l'occurrence le broker est un mosquitto installé sur une box jeedom).
Cela fonctionne durant quelques minutes voire une heure ou deux, et puis au bout d'un moment je ne reçois plus rien sur mon broker, ou alors des valeurs vides.
Voici le code Mega (je me suis inspiré de quelqu'un l'ayant fait avant moi) :
#include <Wire.h> // bibliotheque pour sonde ph
#include <LiquidCrystal_I2C.h> // bibliothèque de l'écran LCD
// Parametrage adresse LCD (ici c'est 0x27) pour un 16 colonnes et 2 lignes.
LiquidCrystal_I2C lcd(0x27, 16, 2);
//Pin sonde PH
int PowerPh1 = 52; //+
int PowerPh2 = 53; //- (GND)
const int analogInPin = A15;
//Pin Ecran LCD
int PowerLcd1 = 33; //+
int PowerLcd2 = 35;// - (GND)
//declaration des variable du calcul ph
float calibration = 17.60; // ceci est un coefficient à modifier pour ajuster/calibrer les valeurs ph
float phValue = 0;
int sensorValue = 0;
unsigned long int avgValue;
float b;
int buf[10],temp;
void setup() {
Serial.begin(115200);
Serial3.begin(115200); // port de com avec esp
// Initialisation des pins d'alimentation
pinMode(PowerPh1, OUTPUT);
pinMode(PowerPh2, OUTPUT);
pinMode(PowerLcd1, OUTPUT);
pinMode(PowerLcd2, OUTPUT);
digitalWrite(PowerPh1, LOW);
digitalWrite(PowerPh2, LOW);
digitalWrite(PowerLcd1, LOW);
digitalWrite(PowerLcd2, LOW);
//Allumage écran + test
setPinOut(PowerLcd1,HIGH);
lcd.init();
lcd.begin(16,2);
lcd.clear();
lcd.backlight();
lcd.print("Sensor PH");
delay(2000);
setPinOut(PowerLcd1,LOW);
}
void loop()
{
// allume sonde PH
setPinOut(PowerPh1,HIGH);
// prend 10 mesure de ph
for(int i=0;i<10;i++) {
// appel 10x la fonction de calcul de ph toutes les 1 secondes
getPh();
delay(1000);
}
// éteins la sonde ph pour économiser de l'énergie
setPinOut(PowerPh1,LOW);
// affiche la dernière valeur sur l'écran LCD
displayLCD();
phValue = 0;
}
void displayLCD(){
//allumage du LCD
setPinOut(PowerLcd1,HIGH);
// initialize the LCD
lcd.begin(16,2);
// Allume écran et affiche message
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Mesure : ");
lcd.setCursor(0,1);
lcd.print("Ph = ");
lcd.print(phValue);
delay(10000);
lcd.clear();
setPinOut(PowerLcd1,LOW);
}
void getPh(){
// boucle qui fait ressortir une moyenne de 10 mesures de ph
for(int i=0;i<10;i++)
{
buf[i]=analogRead(analogInPin);
delay(30);
}
for(int i=0;i<9;i++)
{
for(int j=i+1;j<10;j++)
{
if(buf[i]>buf[j])
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(int i=2;i<8;i++)
avgValue+=buf[i];
float pHVol=(float)avgValue*5.0/1024/6;
float coeff = 1.02; // coefficient d'ajustement perso pour affiner la valeur du ph
phValue = coeff * -5.70 * pHVol + calibration;
// affichage sur le serial
Serial.print("Sensor Ph = ");
Serial.println(phValue);
//envoie des data vers ESP8266 sur Serial 3
Serial.println("Envoie data vers ESP8266 sur Serial 3 ");
Serial3.print("$");
Serial3.print(phValue);
Serial3.println("$");
}
// fonction qui allume et éteint l'écran et la sonde ph avec sortie d'info sur le serial
void setPinOut(int pin , char state ) {
Serial.print("PIN :" );
Serial.println(pin);
Serial.print("STATE :" );
if (state == LOW ){
Serial.println("OFF");
}else{
Serial.println("ON");
}
digitalWrite(pin, state); // sets the digital pin
delay(500); // laisse du temps à la sonde Ph + écran pour s'allumer et se stabiliser
}
et voici le code ESP :
// Bibliothèque wifi
#include <ESP8266WiFi.h>
// Bilbliothèque Mqtt
#include <PubSubClient.h>
// Entrez ici vos identifant reseau
const char* ssid = "xxx";
const char* password = "xxx";
// Brooker mqtt -> vous devez en créer un sur votre box perso ou se connecter à un brooker gratuit en ligne
// ou vous pourrez récupérer vos informations
const char* mqttServer = "xxx.xxx.xxx.xxx"; //ip du broker
const int mqttPort = xxxx; // port di broker
const char* mqttUser = "xxx"; // nom user
const char* mqttPassword = "xxx"; // pass user
// initialisation de l'objet wifi et mqtt
WiFiClient espClient;
PubSubClient client(espClient);
//Adresse de publication perso du topic mqtt ( a modifier avec votre adresse)
#define mqtt_publish_topic_ph "xxx"
// Reception des donnees ph
const byte numChars = 32;
byte receivedChars_ph[numChars]; // an array to store the received ph data
// boolean pour déclenchement de la publication mqtt si data présente
boolean newData_ph = false;
void setup() {
Serial.begin(115200);
// Connection wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to the WiFi network");
// Connection broker Mqqt
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
Serial.println("Connected to MQTT");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
// Publication d'un message test de départ
client.publish( mqtt_publish_topic_ph , "Hello from ESP8266");
client.subscribe("esp/test"); // pour tester le message callback (inutilisé dans ce tuto)
}
// fonction Mqtt pour récupérer et afficher les messages entrant (inutilisé ici)
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void loop() {
reconnect(); // Reconnexion si connexion perdue
client.loop(); // verification de connection mqtt
recepetionData(); // ecoute et parsage des données arrivante
publishValue(); // publication sur le brooker mqtt
}
void recepetionData() {
Serial.println("début de receptionData()");
// boolean qui active ou pas l'enregistrement des data
static boolean recvInProgress_ph = false;
static byte ndx = 0;
//MARQUEURS qui entoure les données ph
char startMarker_ph = '$';
char endMarker_ph = '$';
// VAR POUR ENREGISTER LES DONNEES
byte rc;
// Reception des donnees du serial
while (Serial.available() > 0 )
{
rc = Serial.read();
// ph parsing
if (recvInProgress_ph == true) { //boucle pour commencer a entrer les valeur ds la tableau juqu au end marker
if (rc != endMarker_ph) {
receivedChars_ph[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars_ph[ndx] = '\0'; // terminate the string apres une case blanche
recvInProgress_ph = false;
ndx = 0;
newData_ph = true;
Serial.println("Data Ph arriving...");
Serial.print('Ph = ');
Serial.println(String((char*)receivedChars_ph));
}
}
else if (rc == startMarker_ph) { //découverte du marqueur et enclenchement de l'enregistrement
recvInProgress_ph = true;
}
}
Serial.println("fin de receptionData()");
}
void publishValue() // Publication Mqtt si data présente
{
Serial.println("début de publishValue()");
if (newData_ph == true )
{
Serial.println("Publishing to broker MQTT");
client.publish( mqtt_publish_topic_ph , String((char*)receivedChars_ph).c_str() , true );
newData_ph = false;
}
Serial.println("fin de publishValue()");
}
void reconnect(){
if (client.connected()) {
Serial.println("Connecté MQTT");
}
else {
Serial.println("Déconnecté MQTT");
}
while (!client.connected()) {
Serial.println("Connection au serveur MQTT ...");
if (client.connect("ESP32Client")) {
Serial.println("MQTT connecté");
}
else {
Serial.print("echec, code erreur= ");
Serial.println(client.state());
Serial.println("nouvel essai dans 2s");
delay(2000);
}
}
}
Voici les logs de mon broker, lorsque ça fonctionne et lorsque ça ne fonctionne pas :
Pour info, le mega affiche directement sur un écran LCD la valeur lue, et elle n'est jamais vide. Donc je pense que le souci vient + de la partie ESP qu'autre chose.
Un peu novice avec Arduino/esp/tout ça, j'avoue que je vois pas trop comment voir d'où vient le souci, peut-être qu'avec le code vous verrez immédiatement quelque chose qui ne va pas ?
Merci de vos retours
bonne journée.
Guillaume.
