Bonjour,
J'ai réussi à trouver mon erreur : désormais, j'arrive bien à naviguer entre mes menus à l'aide des boutons. Par contre j'ai un souci de boucle que je n'arrive pas à comprendre.
Dans ma boucle loop, la fonction cinetique n'est, selon moi, lancée que lorsque la variable etatInitialisation vaut PRET.
Quand je choisis le "parcours" de la variable etatInitialisation suivant : DEBUT -> MENU-> CINETIQUE -> ATTENTE -> ETALONNAGE -> CONFIRMATION -> ENREGISTREMENT -> ETALONNAGE -> CONFIRMATION -> ENREGISTREMENT -> VALIDATION, il me démarre la fonction cinetique en même temps que l'affichage lié à l'état VALIDATION sans pourtant être passé au préalable à l'état PRET ce qui me laisse perplexe.
Quelqu'un a-t-il une aide à m'apporter ?
Merci d'avance
Mon programme (j'ai oté toute la partie d'affichage de texte pour ne pas trop alourdir !) :
//IMPORT DES BIBLIOTHEQUES UTILISEES
#include "DFRobot_PH.h" //module conductimétrique
#include <EEPROM.h> //module de la mémoire pour stocker les mesures du pH à court terme
#include <Wire.h> //module wire pour la communication avec le protocole I2C
#include<LiquidCrystal_I2C.h> //bibliothèque pour l'écran lcd connecté en I2C
#include <OneWire.h> //module one wire pour la mesure de température avec sonde DS18B0
#include <DallasTemperature.h> //
#include <easyRun.h> // bibliothèque de @bricoleau https://github.com/bricoleau/easyRun
//Définition des connexions utilisées sur la carte Arduino
#define PH_PIN A2 //sonde conductimétrique
#define pinBoutonEnter 2 //bouton ENTER
#define pinBoutonCal 4 //bouton CAL
#define pinBoutonExit 7 //bouton EXIT
#define ONE_WIRE_BUS 12 //broche de connexion du capteurs température DS18B20
//DEFINITION DES VARIABLES UTILISEES PAR LE CAPTEUR DE CONDUCTIVITE (voir bibliothèque associée)
float voltage, phValue, temperature = 25;
//SIMPLIFICATION DES APPELS AU MODULE DE CONDUCTIVITE ET A L'ECRAN LCD
DFRobot_PH ph;
LiquidCrystal_I2C lcd(0x27, 20, 4);
boolean testEtalonnage = 0; //variable pour savoir si l'etalonnage est fini
button boutonEnter(pinBoutonEnter, true);
button boutonCal(pinBoutonCal, true);
button boutonExit(pinBoutonExit, true);
byte choixMode; //variable pour connaitre le mode de mesure (mesure simple, dosage, suivi cinétique)
// GESTION DES ETATS
enum : uint8_t {DEBUT, MENU, SIMPLE, DOSAGE, CINETIQUE, PREPA, ATTENTE, ETALONNAGE, ANNULATION, CONFIRMATION, ENREGISTREMENT, VALIDATION, PRET} etatInitialisation = DEBUT; //pour le choix du mode
enum t_etat : byte {PERIODE, DUREE, GO} etat = PERIODE; //pour le parametrage de l'acquisition
int nbCar ; //nombre de caractere de la variable affichée sur le lcd
unsigned long tempsZero;
unsigned long tempsCourant;
unsigned long tempsPrec;
float resultatph;
void setup()
{
//initialisation de la liaison série, du module pH et du lcd et du capteur de température
Serial.begin(250000);
ph.begin();
lcd.init(); // initialisation de l'afficheur
temp.begin();
lcd.backlight();
}
void loop()
{
if (etatInitialisation != PRET)
{
initialisation();
}
else
{
switch (choixMode)
{
case 1: //mode de mesure simple
mesure_simple();
break;
case 2: //mode de mesure dosage
dosage();
break;
case 3:
cinetique();
break;
}
}
}
void initialisation() {
easyRun();
switch (etatInitialisation) {
case DEBUT:
etatInitialisation = MENU;
break;
case MENU:
if (boutonExit)
{
etatInitialisation = SIMPLE;
lcd.clear();
}
else if (boutonCal)
{
etatInitialisation = DOSAGE;
lcd.clear();
}
else if (boutonEnter)
{
etatInitialisation = CINETIQUE;
lcd.clear();
}
break;
case SIMPLE:
choixMode = 1; //mode simple
if (boutonEnter)
{
etatInitialisation = ATTENTE;
lcd.clear();
}
else if (boutonExit)
{
etatInitialisation = DEBUT;
lcd.clear();
}
break;
case DOSAGE:
choixMode = 2; //mode dosage
if (boutonEnter)
{
etatInitialisation = ATTENTE;
lcd.clear();
ouverture_moniteur();
lcd.clear();
}
else if (boutonExit)
{
etatInitialisation = DEBUT;
lcd.clear();
}
break;
case CINETIQUE:
choixMode = 3; //mode cinétique
if (boutonEnter)
{
etatInitialisation = ATTENTE;
lcd.clear();
ouverture_moniteur();
lcd.clear();
}
else if (boutonExit)
{
etatInitialisation = DEBUT;
lcd.clear();
}
break;
case ATTENTE:
if (boutonCal)
{
etatInitialisation = ETALONNAGE;
lcd.clear();
}
else if (boutonExit)
{
etatInitialisation = PREPA;
lcd.clear();
}
break;
case ETALONNAGE:
if (testEtalonnage == 0)
affiche_texte_lcd(15, 2, "7");
else
affiche_texte_lcd(15, 2, "4");
affiche_texte_lcd(0, 3, "Appuyer CAL si OK");
if (boutonCal)
{
etalonnage(7);
if (testEtalonnage == 1)
testEtalonnage = 0;
else testEtalonnage = 1;
etatInitialisation = CONFIRMATION;
lcd.clear();
}
break;
case CONFIRMATION:
ph.calibration(voltage, temperature, Cal); // calibration process by Serail CMD
if (boutonExit)
{
etatInitialisation = ENREGISTREMENT;
lcd.clear();
}
break;
case ENREGISTREMENT:
ph.calibration(voltage, temperature, Exit); // calibration process by Serail CMD
//lcd.backlight();
affiche_texte_lcd(0, 0, "->Etalonnage termine");
delay(1000);
if (testEtalonnage)
{
etatInitialisation = ETALONNAGE;
lcd.clear();
}
else
{
etatInitialisation = VALIDATION;
lcd.clear();
}
break;
case VALIDATION:
mesure_simple();
affiche_texte_lcd(0, 0, "Etalonnage bon ?");
affiche_texte_lcd(0, 1, "oui --> ENTER");
affiche_texte_lcd(0, 2, "non --> CAL");
if (boutonCal)
{
etatInitialisation = ETALONNAGE;
testEtalonnage = 0;
lcd.clear();
}
else if (boutonEnter)
{
etatInitialisation = PREPA;
lcd.clear();
}
break;
case PREPA:
switch (choixMode)
{
case 1: //mode de mesure simple
etatInitialisation = PRET;
break;
case 3:
lcd.clear();
menuPeriode();
while (true) {
if (parametrage()) {
Serial.print(F("t")); // donne la date en seconde
Serial.print('\t');
Serial.println(F("pH")); // donne le pH
Serial.print(F("s")); // donne la date en seconde
Serial.print('\t');
Serial.println(F("")); // donne la valeur recalculée de la tension
break;
}
}
lcd.clear();
tempsZero = millis();
tempsPrec = 0;
etatInitialisation = PRET;
break;
}
case PRET:
break;
}
}
void etalonnage(byte valtampon)
{
float resultatvoltage = 0.0;
for (int i = 0; i < cycles; i++)
{
voltage = analogRead(PH_PIN) / 1024.0 * 5000; // read the voltage
resultatvoltage += voltage;
}
resultatvoltage /= cycles;
phValue = ph.readPH(resultatvoltage, temperature); // convert voltage to pH with temperature compensation
ph.calibration(resultatvoltage, temperature, Enter); // on envoie la commande ENTEREC au module pour commencer la calibration
affiche_texte_lcd(0, 2, "CAL pour valider ");
}
void menuPeriode()
{
Serial.println(F("Saisir la période d'échantillonnage (en s) : "));
etat = PERIODE;
}
void menuDuree()
{
Serial.println(F("Saisir la durée totale d'acquisition (en s) : "));
Serial.println(F("Saisir 0 pour revenir au menu précédent (choix période d'échantillonnage)\n"));
etat = DUREE;
}
void menuGo()
{
Serial.println(F("Saisir S pour démarrer l'acquisition : \n"));
etat = GO;
}
bool parametrage()
{
bool gestionTerminee = false;
switch (etat) {
case PERIODE:
if (messageDisponible()) { // si l'utilisteur a validé
if (!strcmp(message, "0")) { // a-t-il tapé 0 ?
//menuCalibre();
} else {
Serial.print(F("Période d'échantillonnage saisie : ")); Serial.print(message); Serial.println(F(" s\n"));
timeRes = 1000UL * atoi(message);
delay(2000);
menuDuree();
}
}
break;
case DUREE:
if (messageDisponible()) { // si l'utilisteur a validé
if (!strcmp(message, "0")) { // a-t-il tapé 0 ?
menuPeriode();
} else {
Serial.print(F("Durée d'acquisition saisie : ")); Serial.print(message); Serial.println(F(" s\n"));
dureeAcquisition = 1000UL * atoi(message);
nbrPoints = dureeAcquisition / timeRes;
delay(2000);
menuGo();
}
}
break;
case GO:
if (messageDisponible()) { // si l'utilisteur a validé
gestionTerminee = true;
//menuCalibre();
}
break;
}
return gestionTerminee;
}
void affiche_echantillonnage()
{
Serial.println(F("Saisir la période d'échantillonnage (en s) : "));
Serial.println(F("Saisir 0 pour revenir au menu précédent (choix calibre)\n"));
}
void affiche_duree()
{
Serial.println("Saisir la durée totale d'acquisition (en s) : ");
Serial.println(F("Saisir 0 pour revenir au menu précédent (choix période d'échantillonnage)\n"));
}
void mesure_simple()
{
resultatph = lecture();
affichage_ph();
}
void cinetique()
{
tempsCourant = millis() - tempsZero;
affiche_texte_lcd(0, 0, "Chrono : ");
lcd.setCursor(9, 0);
int longueur = lcd.print(tempsCourant / 1000);
affiche_texte_lcd(10 + longueur, 0, " s");
if ((tempsCourant >= tempsPrec) && (cpt <= nbrPoints + 1))
{
resultatph = lecture();
affichage_ph();
cpt++;
}
if (cpt == (nbrPoints + 2))
{
testFinAcquisition = 1; //l'acquisition est finie
resultatph = lecture();
affichage_ph();
}
}
float lecture() //fonction de lecture des données par le capteur
{
resultatph = 0.0;
for (int i = 0; i < cycles; i++) //on boucle pour prendre plusieurs valeurs et améliorer la précision
{
voltage = analogRead(PH_PIN) / 1024.0 * 5000; // lecture de la tension sur la borne de la cellule conductimétrique
phValue = ph.readPH(voltage, temperature); // conversion de la tension en conductivité avec prise en compte de la température
resultatph += phValue; //on cumule les valeurs pour le calcul de la moyenne
}
resultatph /= cycles; //on divise la somme des conductivités par le nombre de cycles pour obtenir la valeur moyenne
return resultatph;
}
void affichage_ph()
{
switch (choixMode)
{
case 1:
affiche_texte_lcd(0, 3, "pH = ");
lcd.setCursor(5, 3); //on se place sur la 3ème ligne, 8ème caractère de l'afficheur lcd
lcd.print(resultatph, 2); //donne le pH avec 2 chiffres après la virgule
break;
case 3:
if (testFinAcquisition == 0)
{
// Envoie les données sur moniteur série si pas la fin d'acquisition
Serial.print(tempsCourant / 1000); // donne la date en seconde
Serial.print('\t');
Serial.println(resultatph, 2); // donne le pH avec 2 chiffres après la virgule
affiche_texte_lcd(0, 3, "pH = ");
lcd.setCursor(5, 3); //on se place sur la 3ème ligne, 8ème caractère de l'afficheur lcd
lcd.print(resultatph, 2); //donne le pH avec 2 chiffres après la virgule
}
tempsPrec += timeRes;
Serial.println("dernierrem esure");
affiche_texte_lcd(0, 1, "Derniere mesure :");
affiche_texte_lcd(0, 2, "t = ");
lcd.print(tempsCourant / 1000);
affiche_texte_lcd(8, 2, "s");
affiche_texte_lcd(0, 3, "pH = ");
lcd.setCursor(5, 3); //on se place sur la 3ème ligne, 8ème caractère de l'afficheur lcd
lcd.print(resultatph, 2); //on affiche la moyenne avec 2 chiffre après la virgule
break;
}
}
void affiche_texte_lcd(byte caractere, byte ligne, const char* texte)
{
lcd.setCursor(caractere, ligne);
lcd.print(texte);
}
void ouverture_moniteur()
{
//Affichage des manipulations préalable à faire avant toute mesure
while (testBoutonEnter == 0)
{
affiche_texte_lcd(0, 0, "Ouvrir le moniteur");
affiche_texte_lcd(0, 1, "serie dans Arduino");
affiche_texte_lcd(0, 2, "Appuyer sur bouton");
affiche_texte_lcd(0, 3, "ENTER si c'est ok");
etatBoutonEnter = digitalRead(pinBoutonEnter); //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
if (etatBoutonEnter == LOW) //si le bouton était précédemment non appuyé alors lastBoutonEnter=1=HIGH
{
testBoutonEnter = 1;
}
}
testBoutonEnter = 0;
lcd.clear();
while (testBoutonEnter == 0)
{
affiche_texte_lcd(0, 0, "Verifier le flux de");
affiche_texte_lcd(0, 1, "la liaison serie :");
lcd.setCursor(0, 2);
lcd.print(flux);
affiche_texte_lcd(7, 2, "bauds");
affiche_texte_lcd(0, 3, "ENTER si c'est ok");
delay(100);
etatBoutonEnter = digitalRead(pinBoutonEnter); //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
if (etatBoutonEnter == LOW) //si le bouton était précédemment non appuyé alors lastBoutonEnter=1=HIGH
{
testBoutonEnter = 1;
}
}
testBoutonEnter = 0;
lcd.clear();
while (testBoutonEnter == 0)
{
affiche_texte_lcd(0, 0, "Verifier que la list");
affiche_texte_lcd(0, 1, "deroulante est sur");
affiche_texte_lcd(0, 2, "'les deux, NL et CR'");
affiche_texte_lcd(0, 3, "ENTER si c'est ok");
delay(100);
etatBoutonEnter = digitalRead(pinBoutonEnter); //si enter est presse etatBoutonEnter=LOW=0 car pin en mode pull up interne
if (etatBoutonEnter == LOW) //si le bouton était précédemment non appuyé alors lastBoutonEnter=1=HIGH
{
testBoutonEnter = 1;
}
}
}