Arduino est modulaire, et c’est tant mieux !
Nous avons choisi la plateforme Arduino pour sa facilité d’utilisation, son ouverture mais aussi parce que cette plateforme est incroyablement modulaire !
Arduino est le cerveau de projets issus de domaines variés : domotique, vêtements intelligents, drones, robotique, objets connectés, installations artistiques… Cette modularité est rendue possible grâce à l’extension des fonctions de base d’Arduino par des modules d’extensions. Transition parfaite puisque c’est le sujet de la semaine !
Après avoir abordé des composants électroniques simples dans les précédentes semaines, nous nous lançons dans la découverte d’un composant plus complexe : le servomoteur. C’est un moteur équipé d’un asservissement électronique qui nous permettra de contrôler sa position angulaire. Cette semaine, nous verrons comment brancher ce composant sur notre Arduino et comment utiliser une bibliothèque logicielle (un ensemble de fonctions) pour faciliter notre travail (en anglais library).
Nous verrons également comment améliorer notre code grâce à l’utilisation de boucles.
La semaine s’annonce chargée !
- Corrigé du TP 3
- Bibliothèques et sorties
- Complément de cours
- Les condensateurs
- Travaux pratiques
- Environnements de développement
- Séparer en fichiers
Corrigé du TP 3
Corrigé du TP Thérémine Lumineux
Voici la correction du TP de la semaine dernière qui reprend des éléments du cours sur les capteurs analogiques.
Code
Voici une des solutions possibles pour répondre au problème dans l’état actuel de nos connaissances.
/*
Thérémine lumineux
TP de la semaine 4 du MOOC "La Fabrication Numérique"
Le montage :
* Un piezo branché sur la broche 8
* Une photorésistance branchée sur la broche A0 depuis +5V
* Une résistance de 10kΩ branchée sur la broche A0 depuis GND
créé le 9 Avril 2014
par Baptiste Gaultier
Ce code est en CC0 1.0 Universal
https://www.france-universite-numerique-mooc.fr/courses/MinesTelecom/04002/Trimestre_1_2014/about
*/
// variable pour stocker la valeur reçue sur A0
int sensorValue;
void setup() {
}
void loop() {
// lire la valeur de la photorésistance
// et stocker ça dans une variable
sensorValue = analogRead(A0);
// re étalonne la variable vers un grand intervalle de fréquences audibles
int pitch = map(sensorValue, 0, 1023, 50, 3000);
// jouer la fréquence sur le piezo branché sur la broche 8
tone(8, pitch);
// attendre 10 ms
delay(10);
}
Schéma électronique
Comme on nous l’a demandé sur le forum, voici le schéma électronique créé avec Fritzing :
Montage
Pour réaliser ce montage, vous avez besoin de :
- Un Arduino ;
- Une platine de prototypage ;
- Un câble USB ;
- Une résistance de 10kΩ ;
- Des fils de prototypage ;
- Une photorésistance ;
- Un piézo ;
- Du temps
Notre correction s’arrête là. Pour des éclaircissements, nous vous invitons à poser vos questions sur le forum et à reparcourir le cours.
On vous laisse avec un montage réalisé par ProPhil qui nous a éclaté avec ce montage photo sur le forum :
Bibliothèques et sorties
Le Sweep
Cette semaine, nous tentons une nouvelle approche dans le cours avec le code directement expliqué dans le texte de la vidéo que vous venez de voir :
Salut à toutes et tous et bienvenue dans ce 5ème épisode où l’on va aborder les bibliothèques de code.
Bibliothèques, ça vient de l’anglais Libraries, qui signifie Bibliothèques. Peu importe ce que vous trouverez comme terme sur internet, l’idée c’est d’avoir sous la main un rassemblement de morceaux de code, classés par thématique, que vous invoquez à la demande. Un peu comme des supers pouvoirs qui vous évitent d’avoir à réinventer la roue à chaque projet !
Les Bibliothèques pour Arduino sont nombreuses, et abordent la plupart des besoins courants. On trouve ainsi les bibliothèques standard, pour par exemple gérer le Wifi, les écrans à cristaux liquide, utiliser simplement une carte SD, ou encore des moteurs. Pour l’occasion, nous allons nous intéresser à des moteurs un peu particuliers que l’on retrouve dans le monde du modélisme : les servomoteurs.
Au boulot ! Je vous laisse ouvrir l’exemple « sweep » que l’on trouve dans les exemples du dossier Servo : Fichier→Exemples→Servo→Sweep.
Détaillons maintenant les nouvelles instructions présentes dans ce programme.
Après quelques lignes de commentaires, nous trouvons une instruction particulière :
#include<Servo.h>
Voilà, vous venez de charger la bibliothèque et obtenez du même coup la
boîte à outils correspondante.
À partir de là, vous pouvez créer des objets en partant
du « moule » Servo
, un peu comme l’on fait de
nombreuse gaufres à partir d’un seul moule, à gaufre forcement !
C’est ce qu’on va tout de suite faire. En créant une gaufre
chantilly…
Non, pardon ! Un servomoteur, que nous appelons ici myservo
.
Servo myservo;
On déclare ensuite une variable pos
, pour stocker une position au
cours du programme :
int pos = 0;
Il est temps de passer au bloc setup()
. C’est vite réglé, puisqu’il suffit
d’attacher notre servo fraîchement créé à la broche 9 :
myservo.attach(9);
La méthode attach()
est disponible pour les objets de type Servo. La
bibliothèque de code gère le reste pour vous. Sympa, non ?
Comme indiqué sur la page de Mon Club
Elec,
les méthodes disponibles sur les objets de type Servo sont assez
explicites :
attach()
, write()
, detach()
.
Fin du setup, il est temps de looper à présent !
La boucle principale commence par… faire une boucle !
for(pos = 0; pos < 180; pos +=1) {
myservo.write(pos);
delay(15);
}
Cette “bouclette” à pour but de faire varier la position cible demandée
au moteur. Autrement dit, elle sert uniquement à faire varier la valeur
de pos
du minimum au maximum. En français, ça donne quelque chose
comme « Pour une valeur pos
ition allant de 0 à 179 et une marche à la
fois, demande au servo myservo
d’aller en position pos
»
Un pos += 4
vous aurait fait monter l’escalier 4 à 4
On laisse quelques millisecondes au moteur afin qu’il ait le temps d’aller une marche plus loin, concrètement de tourner de 1°.
C’est reparti pour un tour, cette fois-ci dans l’autre sens. Au lieu d’incrémenter la valeur de +1 à chaque passage de bouclette, on la décrémente ici de -1 :
for(pos = 180; pos >= 1; pos -= 1) {
myservo.write(pos);
delay(15);
}
Puisque nous arrivons en fin de boucle, notre servo va bientôt repartir. Certains d’entre vous doivent se dire : « Pourquoi ne pas être aller directement au but avec par exemple ? » :
myservo.write(0);
myservo.write(180);
La réponse tient en un mot : la douceur !
Utiliser un délai dans une boucle secondaire permet de ralentir le processus. Plus la valeur du délai sera importante dans votre programme, plus le déplacement du moteur sera doux dans la vrai vie… À vous d’adapter la valeur du délai à vos besoins de tendresse.
Nous pouvons maintenant téléverser (ou upload en anglais) notre programme sur l’Arduino.
Montage
Pour le réaliser, vous aurez besoin de :
- Un Arduino ;
- Un câble USB ;
- Des fils de prototypage ;
- Une platine de prototypage ;
- Un servomoteur.
Schéma
Code
Références
- La bibliothèque Servo par Xavier Hinault
- Référence officielle du langage Arduino (anglais) par l’équipe d’Arduino
Complément de cours
Puisque vous n’êtes pas aussi fainéant(e)s qu’il n’y paraît, nous allons appliquer le savoir nouvellement acquis, en réalisant un exemple d’application concrète.
Seulement voilà, un seul moteur qui bat la mesure, c’est vite barbant. Que diriez-vous d’une machine qui servirait votre boisson favorite, sans broncher ? Que diriez-vous de faire votre premier pas en robotique sans avoir l’air d’y toucher ?
… Voici venir le BoissonMatic' !
Vous qui rêvez d’une invention géniale et susceptible de révolutionner l’univers, j’ai ce qu’il vous faut !
Le BoissonMatic' est une réalisation totalement absurde et c’est bien ce qui la rend indispensable. Elle nous servira ici d’illustration de principe pour un montage fort utile: le Pan Tilt, ou Monture azimutale ("Fiche wikipédia sur la monture azimutale") dans notre bonne vieille langue de Molière.
Le principe est simple et consiste à monter un servo sur l’autre, perpendiculairement. Pendant que le premier moteur tourne à l’horizontal (panoramique), le second tourne à la vertical (azimut).
Avec des servomoteurs basiques, les déplacements de chacun des axes seront limités à 180°. Ceci étant, vous pouvez facilement trouver un servo tournant à 360° dans n’importe quelle boutique de modèle réduit, ou encore modifier un servo pour une rotation continue.
Code again
// BoissonMatic' 2014// john@labfab.fr sous licence WTFPL v2.0
#include <Servo.h>
Servo servoBas; // création d'un premier objet servo, pour le Pan
Servo servoHaut; // création du second, pour le tilt
int pos = 0; // variable pour stocker une position
// valeur mini du Pan, en degré.
int const MINPAN = 0;
// Un quart de tour panoramique
int const MAXPAN = MINPAN + 90;
// valeur mini du Tilt (en cas de servo monté "à l'envers" ! :] )
int const MINTILT = 180;
// avec un max au quart de tour
int const MAXTILT = MINTILT - 90;
void setup()
{
servoBas.attach(9); // attache le servo du bas à la broche 9
servoHaut.attach(10); // celui du haut à la broche 10
// Mise en place de la machine en position de départ
servoBas.write(MINPAN);
servoHaut.write(MINTILT);
delay(1000); // admettant qu'il faille une seconde pour faire demi-tour
// à un servo bien nourri.
}
void loop()
{
// on fait faire un quart de tour au servo panoramique
servoBas.write(MAXPAN);
// La boucle "for" permet d'adoucir le déplacement du moteur
for(pos = 180; pos>=70; pos-=1) // On dépasse le quart de tour,
// pour que le versement du liquide soit plus rapide
{
servoHaut.write(pos);
// le servo tourne de la valeur de l'angle indiqué par la variable 'pos'
delay(20);
// on laisse un peu de temp au servo pour arriver à la postion demandée
}
delay(3000); // encore du temps pour qu'assez de liquide coule du récipient.
for(pos = 70; pos<=180; pos+=1) // la même dans l'autre sens
{
servoHaut.write(pos);
delay(25);
}
servoBas.write(MINPAN ); // retour en position initiale
delay(400);
servoHaut.detach(); // on détache les moteurs un par un.
servoBas.detach();
// la séquence n'aura lieu donc physiquement lieu qu'une seule fois,
// même si la boucle principale loop() continue à tourner.
// devrait retourner quelque chose // comme "false" sur votre moniteur serie.
servoHaut.attached();
}
Vous l’aurez compris, la boucle for
est fort fort utile. C’est même la
base du fonctionnement d’Arduino, vous ne pouvez pas looper ça…
Pour rappel et pour ceux qui roupillaient au fond de la salle, sa syntaxe est toujours la même.
for (condition) {
// ici du code pour bouclette
}
Ce qui se trouve entre les {}
s’appelle un bloc d’instruction. Les
variables y ont un comportement spécifique que nous aborderons une autre
fois si vous le voulez bien !
Vous allez devoir apprendre à la boucler, car vous utiliserez cette
structure de contrôle pour de nombreux propos.
Imaginez par exemple une multitude de servomoteurs que vous voudriez
"détacher". En plaçant vos objets dans un tableau, vous appliquerez un
bon principe de fainéantise. Il ne vous restera plus qu’à parcourir ce
tableau d’un for
, et d’appliquer pour chaque tour de boucle
secondaire, la méthode detach
sur l’objet.
Si vous vous êtes amusé(e)s dans cette modeste découverte d’une bibliothèque standard particulièrement adaptée aux servos, adoptez le bon réflexe et sachez que pour chacun de vos projets, il en existe certainement une qui fera votre affaire.
Vous n’aurez ainsi pas à résoudre des problèmes déjà réglés, ni à recoder ce qui l’a déjà été mille fois. Vous pourrez ainsi vous concentrer sur votre problématique, et pas sur le code qui gère "la tuyauterie" sous-jacente. N’hésitez pas à parcourir les bibliothèques existantes, le soir au coin du feu. Vous apprendrez beaucoup, et gagnerez au final un temps précieux.
Ressources
- fichier source au format .dxf pour découpe laser du socle BoissonMatic’.
- des exemples de chassis sur thingiverse.
Pour celles et ceux qui n’auraient pas un second servomoteur à disposition, ni un lab dans les parages, vous pouvez toujours suivre le TP général qui n’utilise qu’un seul servo. Vous améliorerez votre feu bicolore en y ajoutant une barrière. Ceinture et bretelles !
Les condensateurs
Composants passifs
Nous avons pas mal discuté des résistances, composant incontournable dans les montages électroniques. Voici d’autres composants dits "passifs" que nous avons souvent à utiliser :
Les Condensateurs ou capacitances
Sujet un peu plus difficile si on veut tout comprendre des capacitances – mais nous allons rester simple… Voici le symbole électronique :
Leur construction et leur forme peut varier beaucoup mais leur principe reste le même : deux matériaux conducteurs (les deux traits verticaux), séparés par une matière isolante, appelée diélectrique (l’espace entre les traits), l’ensemble souvent en forme de "sandwich" ou parfois enroulés.
Condensateurs polarisés
Il faut noter que, à partir de la valeur d’environ 1uF, bon nombre de condensateurs sont polarisés - c’est à dire qu’ils ont un "+" et un "-". On les appellent souvent condensateurs chimiques. Il faut les brancher dans le bon sens afin d’éviter les surprises désagréables : inversés ils ont tendance à se gonfler jusqu’à parfois se rompre carrément. Les produits chimiques contenus dedans sont très corrosifs…
D’habitude c’est le fil "-" qui est repéré avec une bande noire sur le coté. Photo : merci Wikipedia :
Le condensateur est conçu pour stocker les charges électriques. Leur valeur est mesurée et calculée en Farads (F). Plus la valeur est grande et plus le condensateur peut stocker de charge. Les valeurs rencontrées dans l’électronique classique sont de l’ordre de nanofarads (10-9 Farads), jusqu’à des centaines de microfarads (10-6 F). Souvent les valeurs sont écrites de la manière suivante :
- 47uF = 47 microfarads ou 47 × 10-6 ;
- 100nF = 100 nanofarads ou 100 × 10-9 ;
- 14pF = 14 picofarads ou 14 × 10-12 (circuits radio) ;
À quoi servent des condensateurs ? Je vais vous montrer quelques exemples pratiques de leur utilisation.
Anti-rebond
Nous avons déjà utilisé des boutons afin de commander nos montages Arduino et vous avez sûrement eu à faire avec le problème de rebond des contacts (contact bounce, en anglais). La construction mécanique des boutons fait que les contacts rebondissent plusieurs fois avant de s’arrêter en position ouverte ou fermée. Avec un Arduino capable de réagir en un milliardième de seconde, ces rebonds sont un vrai casse-tête.
D’habitude on résout le problème dans le logiciel - on attend un certain nombre de millisecondes et on lit à nouveau l’entrée concernée pour déterminer l’état. Sachez toutefois qu’il y a aussi une solution électronique qui peut parfois nous simplifier la vie. Voici le branchement typique d’un bouton en entrée d’un microcontrôleur :
L’entrée est tenue au niveau 1 par la résistance. Quand on appuie sur le bouton l’entrée est 'tirée' vers le niveau 0. Regardons déjà à quoi ressemble le 'bounce' :
Cette trace d’oscilloscope correspond à une seule pression sur le bouton ! La durée dans le temps de cette trace est de 200 micro-seconds (uS). Chaque division fait 25uS. On voit bien que cela peut être interprété par le microcontrôleur comme au moins six pressions ! On peut améliorer la situation on ajoutant un condensateur (et oui, c’est toujours le sujet de ce chapitre…) comme ici :
Un condensateur a besoin de temps pour se charger et se décharger. L’ajout de ce (petit) condensateur en parallèle avec le bouton va 'ralentir' les changements de tension, supprimant les effets aléatoires dus aux faux contacts. Et avec cette petite modification, nous avons :
Ce n’est pas un carré parfait, mais notre Arduino ne verra qu’une seule pression. Sans avoir à ajouter du code spécifique anti-rebond. Utile les petits condensateurs !
Base de temps RC
Voilà un montage simple à construire avec l’Arduino. D’abord le montage sur la platine de prototypage ou "breadboard" (littéralement "planche à pain" en anglais…) :
Très simple à câbler, ce petit montage sert pour voir comment les condensateurs peuvent nous fournir des bases de temps. La sortie 13 de l’Arduino est celle équipée d’une DEL (LED) sur la platine de l’Arduino. Quand la sortie est au niveau '1' la DEL s’allume. Nous prenons la même sortie logique pour piloter notre montage. À travers la résistance de 10kΩ le condensateur se charge pendant que la sortie 13 est au niveau '1’, et se décharge pendant le niveau '0’. Le transistor est utilisé comme une sorte d’interrupteur piloté (nous allons parler des transistors bientôt…) pour allumer la DEL rouge. Voici le schéma :
Et le programme (ou sketch en anglais pour l’Arduino) : (l’exemple Blink modifié un peu)
/*
SlowBlink
Turns on an LED on for 5 seconds, then off for 5 seconds, repeatedly.
Derived from the 'Blink' example in the Arduino suite.
This example code is in the public domain.
*/
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(5000); // wait for 5 seconds
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(5000); // wait for 5 seconds
}
À partir des schémas, branchez les composants sur la platine de prototypage puis téléchargez le programme et vérifiez que la LED sur l’Arduino clignote (très) lentement. Regardez la LED rouge sur la platine d’expérimentation : elle clignote aussi, mais avec presque une seconde de retard. Le délai exact dépend de plusieurs paramètres, notamment le type de transistor.
Dans un monde idéal1, le temps de charge/décharge d’un condensateur se calcule facilement :
- le temps en secondes ;
- la résistance en Ohms ;
- la capacitance en Farads.
Merci à Glenn Smith pour ce cours !
- Mais ce temps dépend beaucoup des conditions de branchement, notamment la résistance de sortie du montage (souvent appelée l’impédance). Prenant l’exemple ici, nous avons R = 10000Ω et C = 0,00047F ce qui donne le temps de charge ou décharge de 4,7 secondes. Pourquoi notre DEL n’avait qu’un retard d’environ 1 seconde, alors ? La réponse au chapitre "transistors" ! Vous pouvez changer le condensateur pour un plus grand ou plus petit, ou en mettre plusieurs en parallèle ou série. Vous verrez que les valeurs des condensateurs en parallèle s’additionnent, et la valeur des condensateurs en série se calcule comme ceci : (exactement l’inverse que pour les résistances)↩
Travaux pratiques
TP à faire pour la semaine 6
Cette semaine, nous restons dans nos montages de feux en compliquant un peu la chose avec une barrière. Le montage à réaliser devra comporter :
- Un servomoteur qui jouera le rôle de barrière ;
- Un bouton pour demander l’ouverture de la barrière ;
- Un feu bicolore qui passera au vert lorsque la barrière sera complètement ouverte.
Le scénario sera le suivant :
Le fonctionnement normal est un feu allumé au rouge et une barrière fermée (0°). Le fonctionnement normal est interrompu par l’appui sur un bouton poussoir.
Si l’appui du bouton est détecté, alors la barrière (actionnée par le servomoteur) se relève doucement. Lorsque la barrière est à la verticale (90°), le feu vert s’allume pendant 5 secondes pendant lesquelles la barrière reste ouverte (90°). Après les 5 secondes, le feu repasse au rouge, la barrière redescend doucement et le fonctionnement normal reprend.
Aussi, nous souhaitons recevoir le message "Bouton appuyé" dans le moniteur série lorsque l’appui a été détecté.
Quelques indices
Vous aurez besoin de mobiliser toutes les compétences vues ces dernières semaines pour réaliser ce TP :
- L’utilisation de boucles
for
qui ont été décrites cette semaine ; - L’utilisation d’entrée et de sorties numériques ;
- Importation de bibliothèques et d’un servomoteur ;
- Utilisation des instructions
Serial
.
Quelques conseils
- Avertissez nous sur le fil de discussion ci-dessous si les consignes ne vous semblent pas claires ;
- N’allez pas regarder la solution sur Internet sinon il n’y a pas de fun ;
- Prenez toujours les hypothèses qui vous arrangent ;
- Seules les notions abordées dans le cours et sur cette page sont nécessaires pour mener à bien ce TP ;
- Il n’y a pas une mais plusieurs solutions à chaque problème. La meilleure est celle que vous comprenez !
Bon courage et bonne semaine,
L’équipe du MOOC
Environnements de développement
Annexe
Lors du montage de ce MOOC, nous avons fait le choix de parler du code : le langage que nous utilisons pour programmer Arduino.
Sachez cependant qu’il existe des alternatives pour développer des programmes pour Arduino :
- S4A (Scratch pour Arduino) : est un environnement de
programmation libre qui permet d’aborder la programmation de façon
ludique et intuitive. Le concept d’écriture du programme repose sur
un principe d’assemblage de modules classés par code couleur (comme
l’idée des Lego) et chaque module correspond à une instruction
(
if
,delay
,for
,digitalWrite
…). Pour installer ce logiciel et en savoir plus sur son utilisation, nous vous invitons à lire la section consacrée à S4A sur le FlossManual Arduino.
-
MATLAB : est un langage de haut niveau et un environnement interactif pour le calcul numérique, la visualisation et la programmation. Une extension de MATLAB appelée Simulink Coder permet de générer et exécuter du code pour Arduino à partir d’un langage graphique basé sur l’assemblage de briques symbolisant des instructions ou fonctions. Dans le cadre de ce MOOC, la société MathWorks a réalisé les vidéos d’initiations suivantes :
- Installation du Support Package pour Arduino
- Création d’un Modèle pour la Cible Arduino
- Exécution de Modèles sur la Cible Matérielle
MathWorks nous permet également de télécharger gratuitement une version de leurs outils durant toute la durée du MOOC. Cliquez ici pour en savoir plus et là pour récupérer une licence du logiciel.
- ArduBlock : est une extension libre du logiciel Arduino (celui utilisé dans le MOOC) qui permet de programmer en utilisant là encore des blocs symbolisants des tests, des boucles et des fonctions. Pour installer ce logiciel et en savoir plus sur son utilisation, nous vous invitons à lire cette page.
Licence
Licence CC-BY-SA : si vous faites des modifications, le contenu doit-être redistribué sous la même licence
Séparer en fichiers
Lorsque vous commencez à faire de gros projets, il devient utile voire indispensable de (très) bien organiser son code. Cela commence par séparer son code en différents fichiers afin d’avoir des entités logiques séparées les unes des autres.
Voyons cela !
Une opération simple à faire et qui permet de gagner beaucoup en
organisation de son code est de séparer ce dernier en différents
fichiers. Généralement, on fait un fichier par unités “logiques”. Par
exemple, imaginons que nous utilisions un composant un peu compliqué qui
sert d’horloge. Ce composant peut renvoyer une date en entier, juste le
jour, mois, année ou encore juste l’heure, la minute ou la seconde
courante. Pour bien faire, il nous faudrait une fonction par unité de
temps. On aurait ainsi au moins 6 fonctions pour récupérer
heure/minutes/secondes/jour/mois/année et 6 fonctions pour les régler
dans le composant. 12 fonctions + la loop()
et le setup()
et vous voilà avec
un fichier original bien encombré !
Pour créer un nouveau fichier dans l’IDE Arduino, il suffit de cliquer sur la petite flèche en haut de l’espace d’édition du code puis ensuite de cliquer sur “Nouvel Onglet” ou “New Tab” comme mis en évidence sur la capture d’écran ci-dessous :
Le fichier .h
lorsque l’on veut séparer son code en plusieurs fichiers, il y a
certaines choses à respecter. Ainsi, à chaque fois que l’on veut créer
un nouveau fichier de code on ne vas pas en créer un mais deux ! Le
premier fichier aura l’extension .h
signifiant header, c’est ce que
nous allons voir maintenant.
Ce fichier va regrouper les prototypes des fonctions ainsi que les définitions de structures ou de classes mais nous verrons cela après.
Le prototype d’une fonction représente un peu un contrat. Il va définir le nom de la fonction, ce qui rentre à l’intérieur (les paramètres) et ce qui en sort (la variable de retour). Ainsi, votre programme principal aura une idée de comment fonctionne extérieurement votre fonction. Un peu comme s’il s’adressait à une boîte noire.
Si l’on devait écrire l’exemple ci-dessus on pourrait avoir le contenu de fichier suivant :
horloge.h
char getHeure();
char getMinute();
char getSeconde();
char getJour();
char getMois();
char getAnnee();
void setHeure(char val);
void setMinute(char val);
void setSeconde(char val);
void setJour(char val);
void setMois(char val);
void setAnnee(char val);
void afficherDate();
void afficherHeure();
void afficherDateHeure();
Comme vous pouvez le voir, avec ces définitions on peut savoir ce qu’est supposée faire la fonction grâce à son nom et le type de variable qu’elle manipule en entrée et en sortie.
Bien, maintenant passons à la suite pour voir où et comment implémenter ces fonctions.
Le second fichier .cpp {#fichiercpp}
Le second fichier que nous allons créer sera avec une extension .cpp (pour C plus plus ou C++). Il regroupera le code à proprement parler, l’implémentation de vos fonctions. C’est ici que vous allez écrire le contenu de vos fonctions, ce qui est censé se passer à l’intérieur de ces dernières.
Pour faire cela, la première étape sera d’inclure le fichier de
prototypes via la commande de préprocesseur #include
:
#include "horloge.h" // horloge.h pour notre exemple
Cette ligne doit être la première de votre fichier .cpp et elle ne
prend pas de ;
à la fin.
Une fois cela fait, il va falloir taper le code de vos fonctions.
Pour le besoin de l’exercice, je vais me contenter d’écrire des instructions bidons. Dans la vraie vie de tous les jours, vous auriez bien sûr fait un joli code pour communiquer avec un module où je ne sais quoi encore bien sûr !
horloge.cpp
/* fichier horloge.cpp */
#include "horloge.h"
char getHeure() {
Serial.println("getHeure");
return 0;
}
char getMinute() {
Serial.println("getHeure");
return 0;
}
char getSeconde() {
Serial.println("getHeure");
return 0;
}
char getJour() {
Serial.println("getHeure");
return 0;
}
char getMois() {
Serial.println("getHeure");
return 0;
}
char getAnnee() {
Serial.println("getHeure");
return 0;
}
void setHeure(char val) {
Serial.print("setHeure : ");
Serial.println(val, DEC);
}
void setMinute(char val) {
Serial.print("setMinute : ");
Serial.println(val, DEC);
}
void setSeconde(char val) {
Serial.print("setSeconde : ");
Serial.println(val, DEC);
}
void setJour(char val) {
Serial.print("setJour : ");
Serial.println(val, DEC);
}
void setMois(char val) {
Serial.print("setMois : ");
Serial.println(val, DEC);
}
void setAnnee(char val) {
Serial.print("setAnnee : ");
Serial.println(val, DEC);
}
void afficherDate() {
Serial.println("afficherDate");
}
void afficherHeure() {
Serial.println("afficherHeure");
}
void afficherDateHeure() {
Serial.println("afficherDateHeure");
}
Lier nos fichiers au programme principal
Vos définitions sont écrites et vos fonctions sont implémentées ? Il ne reste plus qu’à les ajouter à votre programme principal ! C’est en fait très simple vous allez voir.
Tout d’abord, il va falloir s’assurer que vos fichiers .h et .cpp sont dans le même dossier que votre .ino où se trouve votre fichier de programme Arduino.
Comme ceci :
C’est bon ?
Bien, il ne reste qu’une seule chose à faire, l’inclure dans le
programme. Pour cela c’est tout bête, il suffit d’ajouter la ligne
#include "horloge.h"
en haut de votre fichier.
Et voilà ! Il ne vous reste plus qu’à faire des appels tout simples à
vos fonctions perso dans le programme (setup
ou loop
ou où vous voulez
!).
Maintenant, quand vous allez compiler, le compilateur va aller chercher le fichier pointé par le include, le compiler puis le lier dans votre programme principal.
Il peut arriver que le lien avec les symboles/bibliothèques Arduino ne se
fasse pas correctement. Dans ce cas là, rajoutez l’include suivant au
début de votre .h ou .cpp : #include "Arduino.h"
Séparer son code en fichiers est important pour facilement s’y retrouver, j’espère que vous l’avez bien compris. Une fois cette étape faite, vous devriez y voir plus clair dans vos gros programmes.
Les plus aguerris d’entre vous qui connaissent le C++ peuvent même coder en C++ pour créer des classes et ainsi pousser l’organisation encore plus loin !