Go Down

Topic: Affichage "externe" dans une librairie (Read 409 times) previous topic - next topic

nlb

Bonjour

Je dispose d'un capteur dont tout le travail se fait dans la librairie (ici)
A plusieurs reprises, lorsqu'on lance le programme, des affichages sont envoyés sur le moniteur série.
En ce qui me concerne, j'aimerai pouvoir faire afficher sur un écran lcd : j'ai essayé de prendre la même procédure que si on l'utilisait dans le corps du programme mais cela ne fonctionne pas.

Est-ce possible et si oui comment puis-je procéder ?
Merci

dbrion06

Pour développer, vous avez toujours le moniteur série.
Pour rajouter le lcd, je le fais en 3 étapes
a) je fais tourner un exemple de la librairie (écrire "bonjour") après avoir vérifié plutôt 2 fois qu'une mon câblage.
b) je garde les affichages série qui font moins de 16-20 caractères -risque de débordement de buffers- , et je les doublonne si nécessaire par un affichage sur lcd. (le "Serial.println " se traduit par "aller à la gauche de la ligne)
c) je regarde les affichages sur lcd qui génèrent un clignotement ou qui sont trrop rapides (un homme ne peut pas les lire confortablement) et je simplifie encore.
PS: -post scriptum, sans contre façon- :
Si vous donniez un bout de code qui ne marche pas, ça serait plus facile de chercher plus loin que des généralités.

nlb

Bonjour

Mon problème n'est pas d'utiliser le lcd, ça j'y arrive dans un programme "normal".
Dans mon cas, c'est dans la blibliothèque (fichier DFRobot_PH.cpp) que l'affichage est programmé. Par exemple,
Code: [Select]
/*
 * file DFRobot_PH.cpp * @ https://github.com/DFRobot/DFRobot_PH
 *
 * Arduino library for Gravity: Analog pH Sensor / Meter Kit V2, SKU: SEN0161-V2
 *
 * Copyright   [DFRobot](http://www.dfrobot.com), 2018
 * Copyright   GNU Lesser General Public License
 *
 * version  V1.0
 * date  2018-04
 */


#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "DFRobot_PH.h"
#include <EEPROM.h>


#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

#define PHVALUEADDR 0x00    //the start address of the pH calibration parameters stored in the EEPROM


DFRobot_PH::DFRobot_PH()
{
    this->_temperature    = 25.0;
    this->_phValue        = 7.0;
    this->_acidVoltage    = 2032.44;    //buffer solution 4.0 at 25C
    this->_neutralVoltage = 1500.0;     //buffer solution 7.0 at 25C
    this->_voltage        = 1500.0;
}

DFRobot_PH::~DFRobot_PH()
{

}

void DFRobot_PH::begin()
{
    EEPROM_read(PHVALUEADDR, this->_neutralVoltage);  //load the neutral (pH = 7.0)voltage of the pH board from the EEPROM
    //Serial.print("_neutralVoltage:");
    //Serial.println(this->_neutralVoltage);
    if(EEPROM.read(PHVALUEADDR)==0xFF && EEPROM.read(PHVALUEADDR+1)==0xFF && EEPROM.read(PHVALUEADDR+2)==0xFF && EEPROM.read(PHVALUEADDR+3)==0xFF){
        this->_neutralVoltage = 1500.0;  // new EEPROM, write typical voltage
        EEPROM_write(PHVALUEADDR, this->_neutralVoltage);
    }
    EEPROM_read(PHVALUEADDR+4, this->_acidVoltage);//load the acid (pH = 4.0) voltage of the pH board from the EEPROM
    //Serial.print("_acidVoltage:");
    //Serial.println(this->_acidVoltage);
    if(EEPROM.read(PHVALUEADDR+4)==0xFF && EEPROM.read(PHVALUEADDR+5)==0xFF && EEPROM.read(PHVALUEADDR+6)==0xFF && EEPROM.read(PHVALUEADDR+7)==0xFF){
        this->_acidVoltage = 2032.44;  // new EEPROM, write typical voltage
        EEPROM_write(PHVALUEADDR+4, this->_acidVoltage);
    }
Serial.println("Appuyer ETALON  ");
Serial.println("pour etalonnage ");
Serial.println("ou attendre 10 s");
Serial.println("pour mesurer pH ");
delay(10);
}


J'aimerai que les dernières lignes, au lieu d'être visualisées dans le moniteur série, le soient sur l'écran LCD.

dbrion06

Déjà, sauf si vous avez un afficheur à 4 lignes, c'est impossible (chacune des lignes a moins de 16 caractères: ça tient en largeur). essayez d'être plus concis ("appui ETALON ou attente 10s" ? tient sur 2 lignes).

Ensuite, votre delay(10) est très bien si les lignes défilent... Je doute qu'un oeil réagisse en 1/100 seconde: si vous affichez quelque chose immédiatement après ce message, il sera perdu)

nlb

J'utilise un afficheur 4x20 (celui-ci en l'occurrence) : c'est pour cette raison que j'ai mis en forme de cette manière.

Le delay de 10 était pour un test.

dbrion06

Pour un test, remplacer le delay(10) par while(1) qui vous laissera le temps de voir venir et de contempler...
Ensuite, je suis allé voir comment positionner le curseur dans https://www.arduino.cc/en/Tutorial/LiquidCrystalSetCursor
Ce qui me donne le code :

Code: [Select]

lcd.clr();
lcd.setCursor(0, 0); // colonne 0, ligne ..0
lcd.print("Appuyer ETALON  ");
lcd.setCursor(0, 1); // colonne 0, ligne 1
lcd.println("pour etalonnage ");
lcd.setCursor(0, 2); // colonne 0, ligne 2
lcd.println("ou attendre 10 s");

lcd.setCursor(0, 3); // colonne 0, ligne 1
lcd.println("pour mesurer pH ");
while(1==1);

nlb

Cela me donne une erreur lors de la compilation "error: 'lcd' was not declared in this scope" car je n'ai pas déclaré lcd sauf que je ne sais pas comment déclarer cette variable dans ma librairie
j'ai essayé de rajouter les lignes dans le fichier DFRobot_PH.cpp
Code: [Select]
#include<LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);


pour créer l'objet lcd mais j'ai la même erreur

dbrion06

Verifiez que les 8 lignes que je vous ai passées fonctionnent dans un test autonome, sans autre librairie que Lcd_I2C

Mettez (pour essai) vos deux lignes avant l'inclusion de  DFRobot_PH.h, dans votre programme (un *.ino, pas un *.cpp ) : je sais que ce n'est pas beau, mais c'est le plus rapide.

... ou mettez les 8 lignes que je vosu ai passées dans le setup() (ne complexifie pas une librairie prééxistante; si vous passez à des afficheurs graphiques, ce sera plus simple)

nlb

J'avais bien réussi au préalable à faire fonctionner l'écran lcd.
Je vais tester la dernière méthode

dbrion06

Bonjour:
la première méthode a peu de chances de marcher: vous avez raison de tester la seconde .
Tous les affichages étant en dehors de votre librairie, et les modes d'affichage sont très variés (radio, ouaibe, liason serie, lcd, TFT): si on met des affichages dans une librairie, sa complexité ne peut que croître dramatiquement au cours du temps.
A noter que votre menu de démarrage peut être mis sur une feuille de papier, évitant du logiciel, et peut être plus agréable à lire qu'un lcd.

nlb

Bonjour

En passant dans le setup, j'arrive bien à écrire les premières lignes : il est vrai qu'elles ne sont pas intimement liées à la librairie, elles ne sont que dans la partie d'initialisation
Par contre, dans la librairie, il y a du texte qui s'affiche (et que j'aimerais pouvoir faire apparaître sur mon écran lcd) que je ne peux pas écrire dans le programme car le texte dépend d'une commande dans la librairie.
Je copie la partie correspondante
Code: [Select]
byte DFRobot_PH::cmdParse(const char* cmd)
{
    byte modeIndex = 0;
    if(strstr(cmd, "ENTERPH")      != NULL){
        modeIndex = 1;
    }else if(strstr(cmd, "EXITPH") != NULL){
        modeIndex = 3;
    }else if(strstr(cmd, "CALPH")  != NULL){
        modeIndex = 2;
    }
    return modeIndex;
}

byte DFRobot_PH::cmdParse()
{
    byte modeIndex = 0;
    if(strstr(this->_cmdReceivedBuffer, "ENTERPH")      != NULL){
        modeIndex = 1;
    }else if(strstr(this->_cmdReceivedBuffer, "EXITPH") != NULL){
        modeIndex = 3;
    }else if(strstr(this->_cmdReceivedBuffer, "CALPH")  != NULL){
        modeIndex = 2;
    }
    return modeIndex;
}

void DFRobot_PH::phCalibration(byte mode)
{
    char *receivedBufferPtr;
    static boolean phCalibrationFinish  = 0;
    static boolean enterCalibrationFlag = 0;
    switch(mode){
        case 0:
        if(enterCalibrationFlag){
            Serial.println(F(">>>Command Error<<<"));
        }
        break;

        case 1:
        enterCalibrationFlag = 1;
        phCalibrationFinish  = 0;
        Serial.println();
        Serial.println(F(">>>Mode étalonnage du pHmètre<<<"));
        Serial.println(F(">>>Mettre la sonde de pH dans la solution tampon 4.0 ou 7.0<<<"));
Serial.println(F(">>>Attendre quelques mesures de pH"));
Serial.println(F(">>>Puis saisir CALPH<<<"));
Serial.println(F(">>>pour annuler saisir EXITPH<<<"));
        Serial.println();
        break;

        case 2:
        if(enterCalibrationFlag){
            if((this->_voltage>1322)&&(this->_voltage<1678)){        // buffer solution:7.0{
                Serial.println();
                Serial.print(F(">>>Solution tampon : 7.0"));
                this->_neutralVoltage =  this->_voltage;
                Serial.println(F(",Taper EXITPH pour sauvegarder et quitter<<<"));
                Serial.println();
                phCalibrationFinish = 1;
            }else if((this->_voltage>1854)&&(this->_voltage<2210)){  //buffer solution:4.0
                Serial.println();
                Serial.print(F(">>>Solution tampon : 4.0"));
                this->_acidVoltage =  this->_voltage;
                Serial.println(F(",Taper EXITPH pour sauvegarder et quitter<<<<<<"));
                Serial.println();
                phCalibrationFinish = 1;
            }else{
                Serial.println();
                Serial.print(F(">>>Changer de solution tampon<<<"));
                Serial.println();                                    // not buffer solution or faulty operation
                phCalibrationFinish = 0;
            }
        }
        break;

        case 3:
        if(enterCalibrationFlag){
            Serial.println();
            if(phCalibrationFinish){
                if((this->_voltage>1322)&&(this->_voltage<1678)){
                    EEPROM_write(PHVALUEADDR, this->_neutralVoltage);
                }else if((this->_voltage>1854)&&(this->_voltage<2210)){
                    EEPROM_write(PHVALUEADDR+4, this->_acidVoltage);
                }
                Serial.print(F(">>>Etalonnage réussi"));
            }else{
                Serial.print(F(">>>Echec de l'étalonnage Failed"));
            }
            Serial.println(F(",Exit PH Calibration Mode<<<"));
            Serial.println();
            phCalibrationFinish  = 0;
            enterCalibrationFlag = 0;
        }
        break;
    }


Bien sûr, je corrigerai plus tard les lignes pour qu'elles rentrent en taille sur l'écran

J-M-L

Vous pourriez modifier la librairie pour rendre dispo les messages dans un « callback » vers votre programme
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

nlb

Vous pourriez modifier la librairie pour rendre dispo les messages dans un « callback » vers votre programme
Comment on ajoute un "callback" vers le programme ?

dbrion06

Une fonction C (ou Fortran, depuis les années 70...) a la possibilité d'avoir en argument une autre (ou plusieurs autres) fonction(s) C. C'est assez tordu, mais, lors de l'invocation de la calibration, si vous avez fabriqué une liste de fonctions qui gèrent le dialogue suivant votre configuration (avez vous une liaison serie? un LCD? un lcd sur I2C) , ce peut être une solution brillante. Cela implique de modifier l'appel de (au moins) phCalibration ... et son contenu... (la dernière fois que j'ai joué avec des callback fonctions en c++ , c'était il y a un an et je ne me souviens pas comment faire.....)

nlb

Uavez vous une liaison serie? un LCD? un lcd sur I2C)
Mon écran LCD est branché en I2C

Go Up