Ces notes s’adressent spécifiquement à la structure de projet PlatformIO. Pour Arduino IDE, la même approche est valide, mais on place les fichiers
.h
et.cpp
dans le même dossier que le projet.ino
.
On peut créer du code qui est utile dans plusieurs projets. Au lieu de le copier-coller à chaque fois, on peut le mettre dans une bibliothèque. Cela nous permet de réutiliser le code plus facilement et de le partager avec d’autres personnes. Ça garde aussi le code unique du nouveau projet plus propre en gardant le code commun dans d’autres fichiers.
.h
qui contient les déclarations des fonctions. C’est ce fichier qui est importé avec la directive #include
dans d’autres fichiers et permet à ce code de savoir ce qui est disponible dans la bibliothèque..cpp
qui définit les fonctions qui sont déclarées dans le fichier d’en-tête de la bibliothèque. Le fichier principal du programme, souvent main.cpp
, est aussi un fichier source.lib
()
, et;
(pas un corps {}
)Des déclarations se trouvent dans un fichier d’en-tête mais peuvent aussi se trouver dans un fichier source si les fonctions sont définies après leur première utilisation (p. ex. on utilise une fonction dans loop()
mais on le définit après loop()
-> ça prend une déclaration avant loop()
).
définition : le code qui implémente une fonction, incluant sa signature et le corps de la fonction. Le corps est la paire de {}
avec toutes les instructions qu’on écrit entre ces accolades.
Vous devrez être capable de :
Suivre ces instructions dans votre plus récent projet PlatformIO, soit le projet
forward-movement
.
Selon le fichier README inclut dans le dossier lib
de votre projet PlatformIO, voici la structure la plus simple pour une bibliothèque personnelle (nommée Foo
dans cet exemple) :
1
2
3
4
5
6
7
Project
|-- ...
|-- lib
| `-- Foo
| |-- Foo.h
| `-- Foo.cpp
|-- ...
et le fichier src/main.cpp
qui utilise la bibliothèque Foo
inclut alors le fichier d’en-tête de la bibliothèque :
1
2
3
4
#include <Arduino.h>
#include <Foo.h>
//...
Alors, ce qu’il faut faire est :
.h
pour les déclarations et un fichier .cpp
pour les définitions, les deux ayant le même nom que le dossier.lib
du projet PlatformIO, s’il n’est pas déjà là.RobotDrive
Plaçons le code pour contrôler les moteurs de notre robot à entraînement différentiel dans une bibliothèque nommée RobotDrive
. Voici la structure de fichiers pour cette bibliothèque :
1
2
3
4
5
6
7
Project
|-- ...
|-- lib
| `-- RobotDrive
| |-- RobotDrive.h
| `-- RobotDrive.cpp
|-- ...
#ifndef
(if not defined) : une directive qui vérifie si un symbole n’a pas été défini avant. Si ce n’est pas le cas, le code entre #ifndef
et #endif
est inclus. Cela permet d’éviter d’inclure plusieurs fois le même fichier d’en-tête, ce qui revient à copier-coller plusieurs fois les mêmes déclarations de fonctions générant des erreurs de compilation.
La structure d’un fichier .h
est généralement la suivante :
1
2
3
4
5
6
#ifndef NomDuFichier_h
#define NomDuFichier_h
// déclarations des fonctions
#endif
Note importante : le
.h
devient_h
dans les directives#ifndef
et#define
.
Spécifiquement pour RobotDrive.h
, on a :
1
2
3
4
5
6
7
8
9
10
11
#ifndef RobotDrive_h
#define RobotDrive_h
void setRobotDrivePins(int leftPin, int rightPin);
void stop();
void forward();
void backward();
void turnLeft();
void turnRight();
#endif
Notez qu’il n’y a aucun code ici, seulement les déclarations des fonctions.
Ce fichier ressemble plus à un programme Arduino standard, mais sans la fonction setup()
et loop()
. On inclut le fichier d’en-tête pour avoir accès aux déclarations des fonctions, et ensuite on définit ces fonctions.
Pour RobotDrive.cpp
, on a :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <Servo.h> // inclure la bibliothèque pour les Servo
#include <RobotDrive.h> // inclure notre bibliothèque
Servo leftMotor;
Servo rightMotor;
void setRobotDrivePins(int leftPin, int rightPin) {
leftMotor.attach(leftPin);
rightMotor.attach(rightPin);
}
void stop() {
leftMotor.writeMicroseconds(1500);
rightMotor.writeMicroseconds(1500);
}
void forward() {
leftMotor.writeMicroseconds(1700);
rightMotor.writeMicroseconds(1300);
}
void backward() {
leftMotor.writeMicroseconds(1300);
rightMotor.writeMicroseconds(1700);
}
void turnLeft() {
leftMotor.writeMicroseconds(1300);
rightMotor.writeMicroseconds(1300);
}
void turnRight() {
leftMotor.writeMicroseconds(1700);
rightMotor.writeMicroseconds(1700);
}
RobotDrive
Maintenant, dans notre fichier src/main.cpp
, on inclut le fichier d’en-tête de la bibliothèque RobotDrive
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <Arduino.h>
#include <RobotDrive.h>
void setup() {
setRobotDrivePins(10, 11);
forward();
delay(2000);
stop();
delay(1000);
backward();
delay(2000);
stop();
delay(1000);
turnLeft();
delay(2000);
stop();
delay(1000);
turnRight();
delay(2000);
stop();
}
void loop() {} // ne fait rien
N’est-ce pas plus propre et plus facile à lire?
Et la prochaine fois que vous avez besoin de cette fonctionnalité, vous n’avez qu’à copier le dossier RobotDrive
dans le dossier lib
de votre nouveau projet.
Les variables déclarées dans le fichier source de la bibliothèque - comme leftMotor
et rightMotor
dans RobotDrive.cpp
- ne sont pas accessibles dans le fichier principal main.cpp
. Alors il faut faire attention à ce que les fonctions de la bibliothèque s’occupent de fournir toutes les manipulations nécessaires pour les variables internes, afin que le programme principal n’ait pas besoin de les utiliser directement.
Note : Inclure des variables accessibles à l’extérieur d’une bibliothèque dépasse le cadre de cette introduction. Mais c’est possible, notament en utilisant des classes.
Afin de plus facilement réutiliser vos bibliothèques personnelles dans d’autres projets, vous pouvez :
libraries
à la racine de votre dossier PlatformIO/Projects/
.RobotDrive
, et le coller dans ce dossier libraries
.libraries
sera visible quand vous travaillez dans d’autres projets.libraries
et le coller dans le dossier lib
de votre nouveau projet.Ainsi, votre dossier PlatformIO/Projects/
pourrait ressembler à ceci :
1
2
3
4
5
6
7
8
9
Projects
|-- libraries
| |-- RobotDrive
| |-- ...autres dossiers de bibliothèques personnelles
|-- Project1
| |-- lib
| | |-- RobotDrive (copié de `libraries`)
| |...autres dossiers et fichiers de projet
|...autres projets