Créer bibliothèque pour assigner les entrées sorties et utiliser des fonctions

Bonjour,
J'ai fait un programme qui fonctionne dans lequel j'attribue les entrées/sorties et je défini des fonctions francisées.

/*nom et cablage des entrees et des sorties*/
#include <Servo.h>   /* autorise l'utilisation d'un servomoteur*/
Servo servomoteur;   /* Servomoteur sur D9*/
int led1 =13;/* module LED sur D13*/
int led2 =12;/* module LED sur D12*/
int ledvar1 =11;/* module LED sur D11*/
int ledvar2 =10;/* module LED sur D10*/
int buzzer =3;/* module buzzer sur D3*/
int bp1 =8;/* module bp, inter ou ils sur D8*/
int bp2 =7;/* module bp, inter ou ils sur D7*/
int bp3 =6;/* module bp, inter ou ils sur D6*/
int bp4 =5;/* module bp, inter ou ils sur D5*/
int Ma =1;/* D1 sur Ma du module L293D*/
int Mb =0;/* D0 sur MB du module L293D*/
int Mc = 4;/*moteur 2 */
int Md = 2; /*moteur 2*/
int ldr =0;/* module LDR sur A0*/
int temp =2;/* module TEMP sur A2*/
int ir =3;/* module Barrierre IR sur A3*/
int frappe =4;/* module capteur de frappe sur A4*/
int ligne1 =1; /*suiveur deligne1*/
int ligne2 =5; /*suiveur de ligne 2*/
int etatbp1;/* variable qui enregistre la valeur du module bp1*/
int etatbp2;/* variable qui enregistre la valeur du module bp2*/
int etatbp3;/* variable qui enregistre la valeur du module bp3*/
int etatbp4;/* variable qui enregistre la valeur du module bp4*/
int lumiere;/* variable qui enregistre la valeur du module LDR*/
int temperature;/* variable qui enregistre la valeur du module TEMPERATURE*/
int barriere;/* variable qui enregistre la valeur du module Barri�re IR(infrarouge)*/
int intensite;/* variable qui enregistre la valeur du module capteur de frappe */
int couleur1;/*vleur luepar le suiveur deligne 1*/
int couleur2; /*valeur lue par le suiveurde ligne2*/
/*declaration des entrees et des sorties*/void setup(){
  Serial.begin(9600);
  pinMode(led1,OUTPUT); 
  pinMode(led2,OUTPUT);
  pinMode(ledvar1,OUTPUT);
  pinMode(ledvar2,OUTPUT);
  pinMode(bp1, HIGH);
  pinMode(bp2, HIGH);
  pinMode(bp3, HIGH);
  pinMode(bp4, HIGH);
  pinMode(buzzer, OUTPUT);
  servomoteur.attach(9);  
  pinMode(Ma, OUTPUT);
  pinMode(Mb, OUTPUT);
}



/************************************/
/** Boucle du programme principal **/
/**********************************/
void loop()
{






}

/**************************************/
/**************************************/






























// fonctions à utiliser dans le programme principal//
void allumer(int quoi)
{
  digitalWrite(quoi,HIGH);
}
void eteindre(int quoi)
{
  digitalWrite(quoi,LOW);
}
void clignoter(int quoi, int millisecondes)
{
  digitalWrite(quoi,HIGH);
  delay(millisecondes);
  digitalWrite(quoi,LOW);
  delay(millisecondes);
}
void varierled(int quoi,int valeur)
{
  analogWrite(quoi, valeur);
}
void pendant(int millisecondes)
{
  delay(millisecondes);
}
void avancer()// avec le circuit L293D
{ 
  digitalWrite(Ma, HIGH);
  digitalWrite(Mb,LOW);
  digitalWrite(Mc, HIGH);
  digitalWrite(Md,LOW);
  delay(5);
}
void reculer()// avec le circuit L293D
{ 
  digitalWrite(Ma, LOW);
  digitalWrite(Mb,HIGH);
  digitalWrite(Mc, LOW);
  digitalWrite(Md,HIGH);
  delay(5);
}
void arret()// avec le circuit L293D
{ 
  digitalWrite(Ma, LOW);
  digitalWrite(Mb,LOW); 
  digitalWrite(Mc, LOW);
  digitalWrite(Md,LOW); 
  delay(5);
}
void gauche()// avec le circuit L293D
{
  digitalWrite(Ma, HIGH);
  digitalWrite(Mb,LOW);
  digitalWrite(Mc, LOW);
  digitalWrite(Md,HIGH);
  delay(5);
}
void droite()// avec le circuit L293D
{
  digitalWrite(Ma, LOW);
  digitalWrite(Mb,HIGH);
  digitalWrite(Mc, HIGH);
  digitalWrite(Md,LOW);
  delay(5);
}

void angleservo(int angle)
{
  servomoteur.write(angle);
  delay(15);
}
void avanceservo()
{
  servomoteur.write(0);
  delay(15);
}
void reculeservo()
{
  servomoteur.write(180);
  delay(15);
}
void stopservo()
{
  servomoteur.write(90);
  delay(15);
}
void lire(int quoi)
{
  if(quoi==bp1){
    etatbp1=digitalRead(bp1);
  }
  else if(quoi==bp2){
    etatbp2=digitalRead(bp2);
  }
  else if(quoi==bp3){
    etatbp3=digitalRead(bp3);
  }
  else if(quoi==bp4){
    etatbp4=digitalRead(bp4);
  }
}
void lirecapteur(int quoi)
{
  if(quoi==ldr){
    lumiere=analogRead(ldr);
  }
  else if (quoi==ir){
    barriere=analogRead(ir);
  }
  else if (quoi==frappe){
    intensite=analogRead(frappe);
  }
  else if (quoi==ligne1){
    int testcouleur1=analogRead(ligne1);
    if (testcouleur1<=500){
      couleur1=0;
    } 
    else {
      couleur1=1;
    }
  }  // donne une valeur logique à la couleur 1=noir 
  else if (quoi==ligne2){
    int testcouleur2=analogRead(ligne2);
    if (testcouleur2<=500){
      couleur2=0;
    }  
    else {
      couleur2=1;
    }
  } // idem
}
void liretemp()
{
  int tempc = 0;	 		// variables pour stocker les valeurs de temp�ratures.
  int samples[8]; 		// variables pour calculer la temp�rature avec pr�scision
  int maxi = -100,mini = 100; 	// valeurs initiales des temp�ratures min/max
  int i; 				//variable de comptage

  for(i = 0;i<=7;i++){ 		// enregistre 8 valeurs de temp�ratures et fait une moyenne
    samples[i] = ( 5.0 * analogRead(temp) * 100.0) / 1024.0;
    tempc = tempc + samples[i];
    delay(1000);
  }

  tempc = tempc/8.0; 		// calcule la temp�rature

  if(tempc > maxi) {
    maxi = tempc;
  } // set max temperature
  if(tempc < mini) {
    mini = tempc;
  } // set min temperature

  delay(1000); // attend 1s avant une nouvelle mesure
  temperature=tempc; // enregistre la valeur de la temp�rature
}
void melodie()
{          
  byte names[] = {
    'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'  };  
  int tones[] = {
    1915, 1700, 1519, 1432, 1275, 1136, 1014, 956  };
  byte melody[] = "2d2a1f2c2d2a2d2c2f2d2a2c2d2a1f2c2d2a2a2g2p8p8p8p";
  // count length: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
  //                                10                  20                  30
  int count = 0;
  int count2 = 0;
  int count3 = 0;
  int MAX_COUNT = 24;
  digitalWrite(buzzer, LOW);     
  for (count = 0; count < MAX_COUNT; count++) {
    for (count3 = 0; count3 <= (melody[count*2] - 48) * 30; count3++) {
      for (count2=0;count2<8;count2++) {
        if (names[count2] == melody[count*2 + 1]) {       
          digitalWrite(buzzer,HIGH);
          delayMicroseconds(tones[count2]);
          digitalWrite(buzzer, LOW);
          delayMicroseconds(tones[count2]);
        }
      }
    }
  }
}

Je souhaite créer une ou deux librairies afin de fixer deux modes de fonctionnement :

  • avec les entrées sorties ci dessus;
  • avec d'autres attributions pour faire un robot (2 servomoteurs continus).

J'ai regardé les tutoriels Morse et les librairies disponibles, j'ai essayer de copier/adapter, mais il y a toujours des erreurs de compilation, alors j’essaie de faire simple pour comprendre.

fichier .h

/*  MODUA.H    */
/*  2/2/13     */
#define LED 13
#ifndef MODUA_H
#define MODUA_H
#include <Arduino.h>

class MODU // Objet
{
    private :
	int temps;
    public:
	MODU();
	int led;
    void allumer(int); 
	void initialiser();
int broche;		
};
 #endif

fichier .ccp

/*  MODU1.ccp    */
/*  2/2/13     */
#include "MODUA.h"
MODU::MODU()
{}
MODU ::~MODU()
{} //utile ? 
void MODU::allumer(int broche)
{
    digitalWrite(broche,HIGH);
}
void MODU:: initialiser()
{
LED =13;
pinMode(LED, OUTPUT);}
/*void MODU::eteindre()
{
    digitalWrite(broche,LOW);
}*/
void MODU::pendant(int time)
{
   int temps= time
   delay(temps);
}

Le croquis de test

#include <MODUA.h>
MODU robot;

void setup(){
robot.initialiser();}
void loop()
{
//MODU::allumer(13);//modu.allumer();
//pendant(1000);
//modu.eteindre();
//modu.pendant(1000);

}

L'erreur du moment :

sketch_feb02a.cpp.o: In function __static_initialization_and_destruction_0': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:5: undefined reference to MODU::MODU()'
sketch_feb02a.cpp.o: In function setup': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:8: undefined reference to MODU::initialiser()'

Si vous avez quelques conseils pour m'aider peu à peu à comprendre comment parvenir à transformer le code du haut en bibliothèque qui compile, je vous en remercie d'avance.

Arduino est assez rigide au niveau des librairies.
Le répertoire contenant la librairie doit être dans un répertoire libraries situé lui-même dans sketchbook.
Le nom du répertoire doit être celui de la classe déclarée et celui du .cpp principal.
Si tu fais ça, ton code compile. Il génère quelques erreurs de syntaxe qui une fois corrigées donne un code à priori correct.
Au niveau des erreurs:
il manque un point virgule à la fin d'une ligne
tu fais un #define LED 13 dans le .h et ensuite dans le .cpp tu fais LED = 13 (ce qui n'a pas de sens après passage dans le pré-processeur cela donne 13=13)

Salut, merci.
J'ai enlevé le LED=13 et ajouté le ; manquant.
MODUA.h

/*  MODUA.H    */
/*  2/2/13     */
#define LED 13 //*fixe l'utilisation d'une led sur D13
#ifndef MODUA_H
#define MODUA_H
#include <Arduino.h>

class MODU // Objet
{
    private :
	int temps; //utilisée dans pendant()
    public:
	MODU();
	void allumer(int); // pour faire allumer(LED); dans le croquis
	void initialiser(); // pour déclarer les entrées/sorties avant setup ou dedans
	int broche;		// utilisée dans initialiser()
};
 #endif

MODUA.ccp

/*  MODU1.ccp    */
/*  2/2/13     */
#include "MODUA.h"
MODU::MODU() // objet MODU apparemment obligatoire
{}
MODU ::~MODU() // utile ? vue dans des librairies
{} 
void MODU::allumer(int broche) // pour allumer une led dont la broche est déclaré en define dans le .h
{
    digitalWrite(broche,HIGH);
}
void MODU:: initialiser() // déclarer D13 en sortie
{
	pinMode(LED, OUTPUT);
}

void MODU::pendant(int time)// fait un delay
{
   int temps= time;
   delay(temps);
}

Les ccp et h sont bien dans le dossier librairies/MODUA
croquis :

#include <MODUA.h>
MODU robot;
void setup(){
robot.initialiser();}
void loop()
{
MODU::allumer(LED);//modu.allumer();
MODU::pendant(1000);
}

Les erreurs à présent sont

sketch_feb02a.cpp: In function 'void loop()':
sketch_feb02a:7: error: cannot call member function 'void MODU::allumer(int)' without object
sketch_feb02a:8: error: 'pendant' is not a member of 'MODU'

il ne reconnait pas mes fonctions. il semble y avoir un problème entre le int de la fonction allumer et le void de MODU().

Bah oui : pendant() n'est pas déclaré dans le .h

Merci, à force, je fais des erreurs bêtes, J'ai rajouté void pendant(int);

L'erreur est à présent la suivante :
sketch_feb02a.cpp: In function 'void loop()':
sketch_feb02a:6: error: cannot call member function 'void MODU::allumer(int)' without object
sketch_feb02a:7: error: cannot call member function 'void MODU::pendant(int)' without object

Ne prend-il pas en compte mon define LED 13 du.h pour allumer ? Le 1000 du pendant(), il ne veut pas l'utiliser dans delay ?

relies ce que j'ai écrit au-dessus.
La classe doit porter le même nom que le répertoire et que le .cpp
Donc si la classe s'appelle MODUA elle est dans le répertoire libraries/MODUA où il doit y avoir un fichier MODUA.cpp

#include <MODUA.h>
MODU robot;                   <--------- la classe s'appelle MODUA pas MODU et robot c'est l'objet de type MODUA que tu instancies
void setup(){
robot.initialiser();}
void loop()
{
MODU::allumer(LED);//modu.allumer();         <--------- donc ici c'est robot que l'on doit trouver est pas MODU
MODU::pendant(1000);                 <---------- tu as oublié de le définir dans le .h
}

Lorsque tu appliques une méthode à une instance tu dois utiliser l'opérateur "."
Ce qui donne:

robot.allumer();
robot.pendant()

J'ai transformé tous les MODU en MODUA (erreur liée au fait que j'ai fait plusieurs tests avec des noms diférents).

Les nouvelles erreurs :

sketch_feb02a.cpp.o: In function __static_initialization_and_destruction_0': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:5: undefined reference to MODUA::MODUA()'
sketch_feb02a.cpp.o: In function loop': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:10: undefined reference to MODUA::allumer(int)'
C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:11: undefined reference to MODUA::pendant(int)' sketch_feb02a.cpp.o: In function setup':
C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:7: undefined reference to `MODUA::initialiser()'

/*  MODUA.H    */
/*  2/2/13     */
#define LED 13 //*fixe l'utilisation d'une led sur D13
#ifndef MODUA_H
#define MODUA_H
#include <Arduino.h>

class MODUA // Objet
{
    private :
	int temps; //utilisée dans pendant()
    public:
	MODUA();
	void allumer(int); // pour faire allumer(LED); dans le croquis
	void initialiser(); // pour déclarer les entrées/sorties avant setup ou dedans
	int broche;		// utilisée dans initialiser()
	void pendant(int);
};
 #endif
/*  MODUA.ccp    */
/*  2/2/13     */
#include "MODUA.h"
MODUA::MODUA() // objet MODU apparemment obligatoire
{}
MODUA::~MODUA() // utile ? vue dans des librairies
{} 
void MODUA::allumer(int broche) // pour allumer une led dont la broche est déclaré en define dans le .h
{
    digitalWrite(broche,HIGH);
}
void MODUA:: initialiser() // déclarer D13 en sortie
{
	pinMode(LED, OUTPUT);
}

void MODUA::pendant(int time)// fait un delay
{
   int temps= time;
   delay(temps);
}
#include <MODUA.h>
MODUA robot;
void setup(){
robot.initialiser();}
void loop()
{
robot.allumer(LED);//modu.allumer();
robot.pendant(1000);
}

Je suis pas assez doué apparemment. Merci pour l'aide.

MODUA.h

#define LED 13 //*fixe l'utilisation d'une led sur D13
#ifndef MODUA_H
#define MODUA_H
#include <Arduino.h>

class MODUA // Objet
{
    private :
	int temps; //utilisée dans pendant()
    public:
	MODUA();
	void allumer(int); // pour faire allumer(LED); dans le croquis
	void initialiser(); // pour déclarer les entrées/sorties avant setup ou dedans
	int broche;		// utilisée dans initialiser()
	void pendant(int);
};
 #endif
MODUA.cpp

#include "MODUA.h"
MODUA::MODUA() // objet MODU apparemment obligatoire
{} 
void MODUA::allumer(int broche) // pour allumer une led dont la broche est déclaré en define dans le .h
{
    digitalWrite(broche,HIGH);
}
void MODUA:: initialiser() // déclarer D13 en sortie
{
	pinMode(LED, OUTPUT);
}

void MODUA::pendant(int time)// fait un delay
{
   int temps= time;
   delay(temps);
}

Toujours les mêmes erreurs de compilations. Je ne comprends pas.

Dans ton .h les arguments ne sont pas complets :

void allumer(int);
void pendant(int);

Il faut :

void allumer(int broche);
void pendant(int time);

Je viens de modifier et toujours la même erreur.

sketch_feb02a.cpp.o: In function __static_initialization_and_destruction_0': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:5: undefined reference to MODUA::MODUA()'
sketch_feb02a.cpp.o: In function loop': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:10: undefined reference to MODUA::allumer(int)'
C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:11: undefined reference to MODUA::pendant(int)' sketch_feb02a.cpp.o: In function setup':
C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:7: undefined reference to `MODUA::initialiser()'

Ca devrait fonctionner. Je vais tenter en installant une nouvelle version propre.

@telkel : Je ne sais pas ce que tu fais mais le code que j'ai donné compile sans erreur. Tu as bien placé la librairie dans le bon répertoire?

@batto: non dans le .h seul le type est nécessaire. Il permet au compilateur de connaître le type des arguments attendus.

Ah oki ^^

telkel:
Je viens de modifier et toujours la même erreur.

sketch_feb02a.cpp.o: In function __static_initialization_and_destruction_0': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:5: undefined reference to MODUA::MODUA()'
sketch_feb02a.cpp.o: In function loop': C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:10: undefined reference to MODUA::allumer(int)'
C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:11: undefined reference to MODUA::pendant(int)' sketch_feb02a.cpp.o: In function setup':
C:\Users\NOAR\AppData\Local\Temp\build4035633229277018135.tmp/sketch_feb02a.cpp:7: undefined reference to `MODUA::initialiser()'

Ca devrait fonctionner. Je vais tenter en installant une nouvelle version propre.

j'ai l'impression que tu ne lis pas correctement les informations que je t'ai données précédemment ou alors tu repris du code plus ancien.
Dans ton sketch tu ne dois as faire référence au nom de la classe mais à l'instance de cette classe que tu crées localement.

#include <MODUA.h>
MODUA robot;
void setup(){
robot.initialiser();}
void loop()
{
robot.allumer(LED);//modu.allumer();
robot.pendant(1000);
}

J'ai bien lu. J'ai essayé sur un autre ide installé autre part, même erreur.

Je vais le tenter demain au travail. Merci pour la patience.

Merci aux contributeurs, j'ai donc réussi (enfin) à tout debbuger.
Ca fonctionne correctement et est utilisable. Je vais tester cette version avec mes classes en fin d'année, le temps de faire le dossier d'accompagnement qui va avec.

Le programme de base dans lequel on utilise les nouvelles instructions :

#include <Modules.h>
#include <Servo.h>
Modules robot;
//______________________________________________________//
PARTIE CONFIGURATION()
{
  INITIALISER();//configure les broches d'entree_sortie
  //MONITEURSERIE(9600);//enlever les "//" pour autoriser l'utilisation du moniteur serie
}
//______________________________________________________//
BOUCLE PROGRAMME() //Ecrire le programme entre les deux accolades
{
  
}

Un exemple d'utilisation :

//**** MONTAGE : Brancher une LED sur D13 et Gnd, un BP sur D8 et 5V, un BP sur D7 et 5V
//**** Ce programme fait bouger un servomoteur si bp1 et BP2 sont enfoncés
#include <Modules.h>
#include <Servo.h>
Modules robot;
/********************/
PARTIE CONFIGURATION()
{
INITIALISER();
MONITEURSERIE(9600);
}
/*******************/
BOUCLE PROGRAMME()
{
  SI(TEST(BP1) EST ENFONCE ET TEST(BP2) EST RELACHE)
  {
    AFFICHE("Les deux boutons sont enfoncés");
    RETOURALALIGNE();
  
  REPETER(int compteur = 0; compteur<=180; compteur++)
    {ANGLESERVO(compteur);
     PENDANT(500);}
  }
}

Il me reste à tout tester avec le matériel et enlever les quelques erreurs ou redondances.

Modules.cpp (5.48 KB)

Modules.h (4.68 KB)

keywords.txt (1.68 KB)

Je dois regarder à nouveau l'affichage ou la façon de l'utiliser.