Syntaxe projet multi fichiers

Bonjour,

Je réalise un projet domotique, le programme étant lourd je souhaite le diviser en plusieurs fichier “.cpp” et “.h”

Je bloque sur un point:

pour simplifier la chose je prends un exemple :

Fichier principal contenant setup() et loop() => ProjetX.ino
Fichiers complémentaires contenant un sous programme hello() => FichierPlus.cpp et FichierPlus.h

Dans mon fichier ProjetX.ino je déclare un objet “lcd”:

#include <LiquidCrystal_I2C.h>
#include "FichiePlus.h"

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display 



void setup() {

lcd.print("Boucle setup"); // affiche le texte sur le LCD

}

void loop(){

hello();

}

FichierPlus.cpp :

#include "FichierPlus.h"

void hello(void);
{
lcd.print("Boucle hello"); // affiche le teste sur le LCD
}

FichierPlus.h :

#ifndef FICHIERPLUS_H_
#define FICHIERPLUS_H_

void hello(void);


#endif

La compilation ne fonctionne pas car l’objet “lcd” n’est pas déclaré dans le sous programme hello()

Comment je peu faire ?

Merci de vos réponses

FichierPlus.h devrait
a) inclure la librairie liquidCristal (ce n'est pas bien grave si elle est aussi incluse dans votre *.ino)
b) déclarer lcd (et votre lcd() ne devrait être que là: la retirer du .ino)

Bonjour,

Le déclarer extern dans le fichier .cpp ou le .h

#include <LiquidCrystal_I2C.h>
extern LiquidCrystal_I2C lcd;

Merci pour vos réponses :slight_smile:

Ça fonctionne avec la méthode de kamil.

Tes noms de fichiers sont peu parlants.
Il faut savoir avant tout à quel module .ino ou .cpp l'objet lcd appartient.

Si tu considères qu'il appartient à ton module FichierPlus, l'objet lcd doit être instancié dans le fichier FichierPlus.cpp et la déclaration "extern" dans FichierPlus.h (éventuellement).

Laisser l'instanciation de l'objet lcd dans le .ino et la déclaration "extern" dans FichierPlus.h n'est pas optimal pour la bonne raison que si un jour tu transformes FichierPlus.cpp et FichierPlus.h en librairie, l'instanciation de l'objet lcd n'en fera pas partie.
Alors que si l'instanciation de l'objet lcd est dans FichierPlus.cpp, ta librairie est complète. Instancier l'objet lcd dans le .ino n'est plus utile.
D'autre part, si l'instanciation de l'objet lcd se trouve dans FichierPlus.cpp, il devient inutile de la déclarer en "extern" dans FichierPlus.h, la rendant ainsi invisible du .ino.
Dans ce cas l'instanciation peut même être "static".

Mais tu peux aussi laisser la déclaration "extern" dans FichierPlus.h pour que tu puisses l'utiliser dans le .ino
C'est un choix. Soit tu masques les variables, soit tu les rends visibles.

Si les fichiers de ton module s'appellaient lcd.cpp et lcd.h, cela serait encore plus cohérent, et dans ce cas la question de savoir où instancier l'objet lcd ne se poserait même pas : dans lcd.cpp

Bonjour hbachetti

Merci pour les explications complètes. Les noms de fichiers sont pour l'exemple.

Mon projet comporte un fichier principal en .ino et plusieurs fichier auxiliaires .cpp et .h par fonction :

  • Communication réseaux et serveur web
  • Mesure PH / ORP
  • Mesure de température
  • etc ...

J'ai instancié mes objets dans le .ino et fait une déclaration en "extern" dans chaque fichier auxiliaire qui utilise cet objet.

Pour le coté librairies je n'en suis pas encore a ce step !

Merci
David

J’ai instancié mes objets dans le .ino et fait une déclaration en “extern” dans chaque fichier auxiliaire qui utilise cet objet.

Justement, non.

Il est préférable d’instancier l’objet dans le .cpp qui le gère.

Ensuite le code du .ino utilise les fonctions du module .cpp dont les prototypes sont déclarés dans le .h associé.
Rien ne t’empêche de déclarer l’instance en “extern” dans le .h également. Ainsi le code du .ino pourra utiliser ses méthodes et attributs.
Mais normalement on préfère accéder par des fonctions.

// temp.cpp


#include <OneWire.h>
#include <DallasTemperature.h>

#include "temp.h"

#define ONE_WIRE_BUS          3

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;

bool initDS18B20(void)
{
  sensors.begin();
  if (!sensors.getAddress(insideThermometer, 0)) {
    Serial.println("Unable to find address for Device 0");
    return false;
  }
  sensors.setResolution(insideThermometer, 9);
  return true;
}

float readDS18B20(void)
{
  sensors.requestTemperatures();
  float tempC = sensors.getTempC(insideThermometer);
  return tempC;
}

// temp.h


#ifndef __TEMP_H__
#define __TEMP_H__

bool initDS18B20(void);
float readDS18B20(void);

#endif

// sketch_jun26a.ino


#include "temp.h"

bool ds18b20OK;

void setup()
{
  Serial.begin(115200);
  if ((ds18b20OK = initDS18B20()) == false) {
    Serial.println("initDS18B20 failed");
  }
}

void loop()
{
  if (ds18b20OK) {
    float temp = readDS18B20();
    Serial.print("Temperature: ");
    Serial.println(temp);
  }
  else {
    Serial.println("No DS18B20");
  }
  delay(1000);
}

Remarque : temp.h est inclus dans le .ino mais aussi dans temp.cpp. Cela permet au compilateur de vérifier que les prototypes sont conformes.

L’étape suivante : une classe …

Ok c'est plus clair. J'ai modifié :slight_smile:

Merci beaucoup