explication de certaine lignes

Bonjour

En copiant des code trouver ici et ailleurs j'ai fait un petit code qui fonctionne (même si il est optimisable ) le but est de comprendre

Mes question concerne la compréhension de plusieurs lignes.

Je vais donc vous demander petit à petit si vous pouviez m'expliquer mes lacunes

ne pouvant poster plus de 9000 caractères, je vais essayer de poster le code en deux fois

// encodeur par impulsion
// 2 capteurs de tempratures  DS18B20 sur bus   OneWire pin 10
//LCD 20x4   I2C  SCL sur pin a5
//                SDA sur pin a4
// Horloge DS3231 idem que lcd
// Encodeur VMA435 vellman CLK sur pin3
//                         DT sur pin2
//                         SW sur pin7

// Encodeur  VMA435
const byte pinEncodeurA = 2;  // patte CLK  de l'encodeur sur 2 numerique
const byte pinEncodeurB = 3; //  patte DT de l'encodeur sur 3 numerique
const unsigned long dureeAntiRebond = 10;  // temporisation avant nouvelle impulsion 10 milisecondes
volatile byte compte = 0; // variable de comptage des impulsions
int afficherEncodeur = 0; // variable pour autoriser l'affichage de l'action sur l'encodeur si il est différente de compte
int etatBouton = 0;  // variable de l'état du bouton de l'encodeur à 0 appuyé à 1 laché


// capteurs de temperature DS18B20
#include <OneWire.h>  // inclure la librairie pour le bus OneWire pour les capteur dallas
const byte BROCHE_ONEWIRE = 10;  // patte S (sortie) des capteurs sur pin 10 numerique
const byte SENSOR_ADDRESS_1[] = { 0x28, 0xFF, 0x1C, 0x4E, 0xA0, 0x17, 0x05, 0xAB };  // adresse du premier capteur de temperature
const byte SENSOR_ADDRESS_2[] = { 0x28, 0xFF, 0xA2, 0x6A, 0xA2, 0x17, 0x05, 0x77 };  // adresse du deuxieme capteur de temperature
boolean minuterieTemp = 0;  // minuterie pour autoriser la lecture de la temperature si il est à 1
int TempoTemperature = 60; // une minutes = 600 secondes.pour prise de temperature 
unsigned long TempsPasseT;// variable comptant la durre de la tempo avant la prochaine mesure de temperature
unsigned long DebutTempsT; // variable initialisant une nouvelle temporisation pour la mesure de temperature
OneWire ds(BROCHE_ONEWIRE); // création d'un obje OneWire  ??? je supose qu'on utilise un foction de la bibliothèque OneWire (fonction ds)

#include <Wire.h> // inclure la libraire pour le bus I2C pour l'horloge et le LCD

//  horloge sur bus I2C
#include "RTClib.h"  // inclure la librairie RTC pour le module DS3231
int annee = 0;  // variable pour autoriser l'affichage de l'année (pour éviter de l'afficher à chaque cycle de la boucle loop
int mois = 0;   // idem que annee pour les mois
int jours = 0;  // etc...
int heure = 0;
int minutes = 60;
int secondes = 60;


// Afficheur LCD I2C
#include <LCD.h>   // inclure une bibliothèque generale pour les afficheur LCD (sans certitudes) 
#include <LiquidCrystal_I2C.h>  // inclure une bibliothèque qui utilise des fonction de la bibliothèque LCD pour pouvoir l'utiliser en mode I2C
//LiquidCrystal_I2C lcd(0x27,20,4);     // en essayant de déclarer l'afficheur comme ça et sans #include <LCD.h> ça ne fonctionne pas
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // ??? pas encore trouvé, mais je suppose qu'on déclare une sorte de fonction 


// horloge 
RTC_DS3231 rtc;     // ??? mystère également certainement qu'on déclare que RTC_DS3231 s'appel rtc  mais pas sûr




void setup()
  {
  Serial.begin(115200);         // vitesse bus serie 115200 bauds
  Wire.begin();                 // initialisation I2C pour le LCD et l'horloge
  DebutTempsT = millis()/1000;  // l'initialisation du debut du chronometre vaut le temps actuel en secondes, pour mesure de la température  
 
  // encodeur 
   pinMode(pinEncodeurA,INPUT); // pin2 CLK
   pinMode(pinEncodeurB,INPUT); //pin3 DT
   attachInterrupt(0, encodeurFrontClk, FALLING); //crée une interruption sur le front descendant du CLK
   delay(10); // temporiser 10 milisecondes (j'imagine pour l'anti rebonb) evite un double ou triple comptage sur un seul front
  
   // bouton de l'encodeur
   pinMode(7, INPUT);            // switch  de l'encodeur sur PIN 7  

   // Affichage
  lcd.begin(20,4);                     // initialisation lcd 20 colone 4 lignes
  lcd.backlight();                     //initialisé le retroéclairage lcd

    
  affichage_menu();    // appel la fonction affichage du menu 

  }
void loop()          // fonction de lecture infinie
   {
    
    // Température
    tempo_temperature();        // lancer le chronometre pour la température
    if (minuterieTemp != 0)     // si le chronometre est terminé minuterieTemp passe à 1 du coup on va lire la temperature
       {
      mesure_temperatures();    //appel la fonction mesurer et afficher la température
       }
       
    // affichage encodeur
if (afficherEncodeur != compte) // si compte à changer (si l'afficheur à bougé) on modifie la position du cursseur et on affiche l'étoile
{
      lcd.setCursor(0,3);                 //cursseur sur 1er colone ,ligne du bas
      lcd.print("                    ");  // imprimer des espaces pour effacer la ligne
      lcd.setCursor(compte+10,3);         // positioner le curseur sur la bonne colonne
      lcd.print("*");                     // afficher l'étoile
      delay(20);                          // ?? je ne vois pas pourquoi, mais a priori il faut mettre une temporisation (ça marche sans)??
      afficherEncodeur = compte;          // on verouille l'affichage de l'étoile 
}

      //  Vérifier si le bouton est appuyé     
      etatBouton = digitalRead(7);        // lire l'état de la pin 7
if (etatBouton != 1)                     //  si le bouton est appuyé (car quand on appuye il passe à 0) on autorise l'affichage de Bp
{
      lcd.setCursor(18, 0);               // le curseur sur colone 18, 1ere ligne du haut
      lcd.print("Bp");                    // on affiche Bp
      while (digitalRead(7) == 0)         //attendre tant que le bouton est appuyé (en fait on bloque alors tout le programe)
      delay(10);                          // on temporise 10miliseconde (anti-rebond)
      lcd.setCursor(18, 0);               //  on remet le cursseur en position de départ
      lcd.print("  ");                    // et on efface Bp en affichant 2 espaces
}  

afficheheureetdate();                     //appeler la fonction afficher la date et l'heure
}  // Fin de la boucle infinie fin du programme


}

Eric 1/2

suite 2/2

// Les fonctions


// affichage fixe une seul fois au debut
void affichage_menu()                   // création de la fonction affichage_menu qui ne recoit et ne renvoie aucune variable
{

   lcd.setCursor(0, 0);                //curseur sur 1ere colone, 1ere ligne (du haut)
   lcd.print("Heure");                 // afficher Heure
   lcd.setCursor(8, 0);                // curseur sur 8eme colone ,1ere ligne (du haut)
   lcd.print(":");                     // etc...
   lcd.setCursor(11, 0);
   lcd.print(":");
   lcd.setCursor(0, 1);
   lcd.print("Date");
   lcd.setCursor(8, 1);
   lcd.print(":");
   lcd.setCursor(11, 1);
   lcd.print(":");
   lcd.setCursor(0, 2);
   lcd.print("T 1:");
   lcd.setCursor(10, 2);
   lcd.print("T 2:");
}


// affichage de la date et de l'heure uniquement lors d'un changement
void afficheheureetdate()


{                                        // début de la fonction
DateTime now = rtc.now();               // Création d'un ''objet variable ??" qui vaut l'heure/date actuelle prise dans le module horloge DS3231
     // Heure
     if (heure != now.hour())   //si l'heure à changée, on va afficher 
    {
    lcd.setCursor(6, 0);       //curseur à droite de HEURE
    heure = now.hour();        // on verrouille ajuste heure pour que lors du prochaine appel on passe à la suite sans afficher l'heure
      if (heure <10)           // si on on reste en dessous de 10 , l'heure utilise qu'une colone du coup 
      {
      lcd.print("0");          //on met un 0 dans la premiere des deux colone prévue pour l'heure
      }
    lcd.print(now.hour());     // puis on affiche l'heure on pourrait ecrire lcd.print(heure);
    
    }

    // Minute Idem que les heures
    if (minutes != now.minute())
    {
    lcd.setCursor(9, 0);
    minutes = now.minute();
      if (minutes <10)
      {
        lcd.print("0");
      }
    lcd.print(now.minute());
    }

     // Secondes Idem que les heures
    if (secondes != now.second())
    {
    lcd.setCursor(12, 0);
    secondes = now.second();
      if (secondes <10)
      {
        lcd.print("0");
      }
    lcd.print(now.second());
    }

    // Jours Idem que les heures
    if (jours != now.day())
    jours = now.day();
    {
    lcd.setCursor(6, 1);
       if (jours <10)
      {
        lcd.print("0");
      }
    lcd.print(now.day());
    }

    // Mois Idem que les heures
    if (mois != now.month())
    mois = now.month();
    {
    lcd.setCursor(9, 1);
       if (mois <10)
      {
        lcd.print("0");
      }
    lcd.print(now.month());
    }

    // annee Idem que les heures
    if (annee != now.year())
    annee = now.year();
    {
    lcd.setCursor(12, 1);
    lcd.print(now.year());
    }
    return;    // je l'ai mis car a priori il faut, mais ça marche sans
}            //fin de la fonction affichage de l'heure et de la date


// Encodeur
void encodeurFrontClk()    // fonction detection de front et sens de rotation
{
      static unsigned long dateDernierChangement = 0;   // on mémorise l'heure du dernier changement afain d'évité de compter avant la fin de l'anti-rebond
     
      unsigned long date = millis();                             // on prend le temps actuel (dans date)
      if ((date - dateDernierChangement) > dureeAntiRebond) {    // si la duree de l'antirebond est passé (10ms)
        if (digitalRead(pinEncodeurB) == LOW) {                  // si la patte DT est à 0 ça veux dir qu'on tourne dans le sens horaire
          compte++;                                              // on incrémente la variable compte
        }
        else {                                                   //sinon 
          compte--;                                              // on décrémente
        }
        dateDernierChangement = date;                            // on ajuste dateDernierChangement pour attendre le prochain changement
      }
}



// Temporisation pour la mesure de temperature
void tempo_temperature()                                        // temporisation d'une minutes car #define TempoTemperature 60 soit 60secondes
      {
      TempsPasseT = (millis()/1000) - DebutTempsT;             // on mémorise le temps passé depuis qu'on a initialise DebutTempsT
      if (TempsPasseT == TempoTemperature)                     // si ça fait 60secondes (valeurs de TempoTemperature)
          {
          DebutTempsT = millis()/1000;                        // on initialise le chronometre
          minuterieTemp = 1;                                  // on passe à 1 pour autoriser l'appel de mesure_temperatures()
          }
      }

                    //Serial.print(hour()),Serial.print(":"),Serial.print(minute()),Serial.print(":"),Serial.print(second()),Serial.print(" "),Serial.pri
                    //Serial.print(temps_perso),Serial.println();
                    //Serial.print(time),Serial.println();

// Fontion de mesure des temperatures      
void mesure_temperatures()
{
  float temperature[2];                                     //création d'un variable temperature dans un tableau de deux colones
  startTemperatureMeasure(SENSOR_ADDRESS_1);                // appel de la fonction lancer une prise de temperature avec l'adresse du premier capteur
  startTemperatureMeasure(SENSOR_ADDRESS_2);                // appel de la fonction lancer une prise de temperature avec l'adresse du deuxieme capteur
  delay(800);                                               // attendre 800ms (temps modifiable en fonction de la précision souhaitée en nombre de bits
  temperature[0] = readTemperatureMeasure(SENSOR_ADDRESS_1); // appel de la fonctionlire la temperature avec l'adresse du premier capteur
  temperature[1] = readTemperatureMeasure(SENSOR_ADDRESS_2);// appel de la fonction lire la temperature avec l'adresse du deuxieme capteur
   //affichage températures
  lcd.setCursor(5,2);                     // curseur à droite de T1
  lcd.print(temperature[0], 2);          // afficher la valeur de la colone 0 du tableau temperature (temperature 1er capteur)
  lcd.setCursor(15,2);                   // curseur à droite de T1
  lcd.print(temperature[1], 2);          // afficher la valeur de la colone 1 du tableau temperature (temperature 1er capteur
  minuterieTemp = 0;                     // on remet à 0 pour interdire la prise de temperature avant la fin du prochain chronometre
}


// création fonction de lancement de prise de temperature
void startTemperatureMeasure(const byte addr[]) //?? je supose qu'on lance cette fonction avec la variable addr transmise lors de l'appel "startTemperatureMeasure(SENSOR_ADDRESS_1 ou 2)" 
{
  ds.reset();                        // initialisation du capteur de temperature
  ds.select(addr);                   // choix du capteur
  ds.write(0x44, 1);                 // lancer la prise de temperature
}


//  création fonction de lecture de la temperature du capteur
float readTemperatureMeasure(const byte addr[]) //?? on lance la lecture du capteur dont l'adresse est transmise lors de l'appel "readTemperatureMeasure(SENSOR_ADDRESS_1 ou 2)"
{
  byte data[9];    // on cree un tableau de 9 colones
  ds.reset();      // on initialise le capteur
  ds.select(addr); // on choisi le bon capteur
  ds.write(0xBE);  // lecture du scratchpad dans le capteur (en fait 0X44 + OXBE équivalent à getTemperature)
    for (byte i = 0; i < 9; i++)   //on compte de 0 à 8
    {
    data[i] = ds.read();            // et on met les donnée lu dans les 9 cases 
    }
  return (int16_t) ((data[1] << 8) | data[0]) * 0.0625;    //on sort de la fonction en transmettant la temperature en °celcius (la c'est du chinois pou moi)

1ère question:
Ligne 29
OneWire ds(BROCHE_ONEWIRE); // création d'un objet OneWire ??? je suppose qu'on utilise une fonction de la bibliothèque OneWire (fonction ds)

Qu'est-ce qe cette commande . OneWire

Merci d'avance

Bonjour,

OneWire c'est une classe C++
ds c'est une instance de la class OneWire

Plus de détails ici

:confused:
bien, ......
heu, ....
alors, je vais chercher un peu ce que tu me dit. :o

j'ai la sensation d'être devant un notaire ou un médecin qui m'explique quelque chose.
auquel je répond merci, alors que je n'ai rien compris.

Désolé

je vais un peux potasser ton lien, plus accessible au nuls comme moi
:disappointed_relieved:

vais lire sur ce lien une explication https://openclassrooms.com/fr/courses/1894236-programmez-avec-le-langage-c/1897344-les-classes-partie-1-2

Merci pour ton aide

Eric

Oui il faut lire un tuto de base sur la programmation orientée objet et les bases du C++

Une classe c’est en gros une abstraction informatique d’un « truc » (une personne, un objet, un protocole, ...) et une instance c’est un exemplaire de cette abstraction

Par exemple si vous avez la classe « personne » alors zeric, J-M-L ou kamill pourraient être des instances de cette classe

Une instance a des attributs (pour une personne ce serait le sexe, date de naissance, pseudo sur le forum, email, etc) et des méthodes qui représentent des actions sur ces instances

Par exemple une instance de la classe Servo va représenter un servomoteur, ses attributs pourraient être la pin sur laquelle les commandes sont émises et les méthodes seraient «aller à l’angle x° » ou « désactiver le servo » etc

Dans votre cas ds est une instance de la classe OneWire qui gère un protocole et le matériel sous jacent

+1
Le C++ ne s'improvise pas.
On peut passer 1 à 2 semaine à apprendre le C++ avec un cours ou un tuto, en ayant au départ de bonnes bases en C.
C'est un investissement.

@+

Bonjour

Merci pour vos explications

J'ai parcouru hier (parcouru pas étudié) le site openclass ici

C'est très bien fait. Mais partant de 0 , je n'ai pas la prétention d'avoir tout compris

disons que pour le moment, je vais me contenté de ça, et petit à petit. :wink:

La Classe serait un mini programme spécialisé, dans lequel il y à des fonctions qu'on appel méthode et des variable qu'on appelle attribut
l'instance est un objet issue de cette classe

On pourra donc obtenir plusieurs résultats différent, en fonction des données transmises à la classe.

Exemple:
je transmet à la classe le N° de la pin ou est branché un bus OneWire , avec un nom prédéfinie (dans ce cas ds, car ds est l'instance que je veux obtenir de cette classe)
La Classe va utiliser cette information pour chaque commande qu'on va lui transmettre

exemple:
ds.reset(); // initialisation du capteur de température
ds.select(addr); // choix du capteur
ds.write(0x44, 1); // lancer la prise de température
ds.reset(); // on initialise le capteur
ds.select(addr); // on choisi le bon capteur
ds.write(0xBE); // lecture du scratchpad dans le capteur
etc...

Je suppose que:
ds est le nom utilisé par la classe OneWire pour traité les capteur de la série DS

ou

ds est un nom que je choisi pour utilisé le bus OneWire connecté en 10 afin qu'ensuite, je puisse y faire référence dans mes appel de fonctions dans cette classe
exemple
sur pin 10
const byte BROCHE_ONEWIRE = 10;
OneWire ds(BROCHE_ONEWIRE);

sur pin 11
const byte BROCHE_ONEWIRE2 = 11;
OneWire da(BROCHE_ONEWIRE2);

C'est mieux. En effet ds est le nom de l'instance et non pas une fonction.

@+ pour la suite.

Merci

ds est donc prédéfinie par la classe,

ou

ds est le nom que je choisi pour nommer l'instance qui va être fourni par cette classe ?

exemple ds pour la pin 10, et da pour la 11

ds est le nom que je choisi pour nommer l'instance qui va être fourni par cette classe ?

Oui c'est ça.

C'est comme écrire :

  int x;

x est le nom que tu choisis pour nommer l'instance de int.

@+

Super

Merci beaucoup pour ton coup de main

Bonjour

#include <OneWire.h>

inclure la classe (micro programme) pour le bus OneWire pour les capteur dallas

OneWire ds(BROCHE_ONEWIRE);

OnWire j'utilise la classe OneWire pour crée une instance (objet) que je nomme ds
la classe OneWire utilisera la pin (BROCHE_ONEWIRE)
(soit la pin 10 , car on à déclarée une constante de type byte qui s'appelle BROCHE_ONWIRE avec la valeur 10 const byte BROCHE_ONEWIRE = 10:wink:

quand on demandera de réaliser une des méthodes (fonctions dans cette classe) commençant par ds. , la classe OneWire utilisera la pin 10

si j'ai bon, une petite question supplémentaire :-*

J'ai trouver qu'une explication ici

une librairie ou bibliothèque serait en simplifiée comme une collection de fonctionnalités (gérer plusieurs sortes de périphériques par exemple)

une classe n’aurait qu'une fonctionnalité particulière (gérer un bus par exemple)

#include <OneWire.h>
#include <Wire.h>
#include "RTClib.h"
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

Ma question :
peut on dire que si on fait #include "blablabla" c'est une librairie
et si on fait #include c'est une classe

Merci

peut on dire que si on fait #include "blablabla" c'est une librairie
et si on fait #include c'est une classe

On peut le dire mais c’est faux :slight_smile:

En gros pour simplifier Les <> veulent dire au pré-processeur regarde partout dans les endroits standard pour trouver le fichier avec le nom donné et les “” veulent dirent regarde d’abord dans le répertoire courant et si tu ne trouves pas alors va voir partout où les <> auraient regardé

—> donc on utilise des guillemets si c’est un fichier à soi généralement, que l’on ne veut pas avoir à disposition dans tous les projets

Un fichier ensuite peut contenir plusieurs classes, des tas de fonctions etc... c’est à la liberté du programmeur (de mettre le bazar - mais généralement On essaye de rester organisé)

Merci pour ton explication

suffit pour ce soir

A+
Eric

Bonne nuit!

Bonjour

question du jour

#include <LCD.h>                                                   // inclure une bibliothèque générale pour les afficheur LCD (sans certitudes)

#include <LiquidCrystal_I2C.h>                                      // inclure une classe qui utilise des fonction de la bibliothèque LCD pour pouvoir l'utiliser en mode I2C

//LiquidCrystal_I2C lcd(0x27,20,4);                                 // en essayant de déclarer l'afficheur comme ça et sans #include <LCD.h> ça ne fonctionne pas

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);   // dans la classe" LiquidCrystal_I2C"  je nomme une instance "lcd" avec l'adresse "0x27", et des données "2, 1, 0, 4, 5, 6, 7, 3, POSITIVE "

J'ai essayé plusieurs solution pour utilisé mon afficheur LCD (le code fonctionne très bien comme ça)
Geekcreit® IIC I2C 2004 204 20 x 4 Caractère LCD

si j'essaye la solution préconisé par GOTRONIC
soit

#include <Wire.h>
#include <LiquidCrystal_I2C.h>     //-----Adressage matériel-----
                                          // En cas de non fonctionnement, mettez la ligne 8 en 
                                         // commentaire et retirez le commentaire à la ligne 9.
LiquidCrystal_I2C lcd(0x27, 20, 4);
// LiquidCrystal_I2C lcd(0x3F,20,4);

void setup()
{
lcd.init();                         // initialisation de l'afficheur
}

void loop()
{
lcd.backlight();              // Envoi du message
lcd.setCursor(0, 0);
lcd.print(" Go Tronic");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0, 2);
lcd.print(" I2C Serial");
lcd.setCursor(0, 3);
lcd.print(" LCD");
}

ça ne fonctionne pas.

Comment comprendre la meilleurs façon de procéder sans bêtement testé des codes jusqu'a trouver un qui marche ?

entre
LiquidCrystal_I2C lcd(0x27,20,4);
et
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

et une petite deuxième en relation:

#include <LCD.h> serait un librairie général pour les LCD
#include <LiquidCrystal_I2C.h> serait une Classe spécifique pour utiliser le bus I2C avec un afficheur de la librairie LCD

vrai ou faux ?

Merci

Eric

Ce n'est peut-être pas la bonne adresse I2C.
Cela pourrait être 0x3F.
I2Cscanner peut aider.
Regard ICI.

@+

Bonjour

si c'est 0X27

J'ai bien utiliser i2c scanner et tester d'autre codes,

peux importe, le code fonctionne avec
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

Mon interrogation porte sur comment trouver le bon code pour la bonne classe

J'ai impression qu'il existe plusieurs classe qui s'appelle LiquidCrystal_I2C
que tel ou tel fournisseur crée sa propre classe sans se soucié du fait que le nom est déja utilisé par un autre fournisseur du même produit

Tu n'as pas tord. C'est l'inconvénient de la richesse des solutions proposées.
La réglementation bride l’innovation, l’innovation débridée fiche la pagaille.
Cela vaut le coup de gérer ce petit inconvénient.

Merci pour vos réponses

l'explication pourrait alors être:

la classe que j'ai téléchargé et utlisé
#include <LiquidCrystal_I2C.h>

attend de l'utilisateur les données 0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE
adresse, différente pin à utiliser sur le LCD et positive

et ne peux pas utiliser uniquement 0x27,20,4
adresse ,nombre de lignes, nombre de colonnes

je vais essayé de trouver ce qu'il y à dans la classe que j'utilise

par exemple trouvé sur le net

sur une classe liquidcrystal_i2c on pourrait utiliser les données comme ça
#define I2C_ADDR 0x27 // <<—– Mettre votre adresse
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
#define BACKLIGHT_PIN 3

alors que sur celle de go tronic ce serzit ça
class LiquidCrystal_I2C : public Print {
LiquidCrystal_I2C(uint8_t lcd_Adrr , uint8_t lcd_cols , uint8_t lcd_rows);
etc....

Eric