Afficheur (afficher un mot)
Nous allons maintenant nous intéresser au développement d'une application embarqué sur pcDuino afin de gérer
l'afficheur AM-03127-LED . Nous avons déjà largement travaillé avec ce système, mais les programmes réalisés jusqu'à présent
étaient sous forme structuré programmation fonctionnelle . L'objectif de ce TP est pour l'instant de proposer les
mêmes fonctionnalités que précédemment mais avec une programmation plus modulaire en utilisant les objets. Le but est donc de
mettre au point une nouvelle classe Afficheur qui s'occupe de la gestion de l'affichage de cet élément physique AM-03127-LED .
Diagramme des cas d'utilisation
Le programme à réaliser est extrêmement simple puisqu'il s'agit d'afficher un seul mot, sur une seule page de l'afficheur avec une
durée limité de 10 secondes. Lorsque le temps est écoulé l'afficheur ne doit plus rien afficher. Mis à part le temps écoulé, nous
avons déjà réaliser ce type de programme, mais cette fois-ci la conception est plus modulaire et respecte la modélisation objet.
Diagramme de déploiement
Le diagramme de déploiement nous permet de bien voir les différents systèmes mis en jeu. Vous devez mettre en oeuvre du cross-développement
pour créer votre programme qui sera automatiquement déployé sur le système embarqué pcDuino à l'aide des trois fichiers
nécessaires à l'élaboration du projet. La classe Afficheur sera développée dans les deux fichiers afficheur.h et afficheur.cpp .
Vous placerez les fonctionnalités attendues dans le fichier principal main.cpp .
Diagramme des classes
D'après ce diagramme vous remarquez que la classe Afficheur est composée de deux attributs. D'une part l'attribut connexion
qui nous précise si le système est bien en communication avec avec l'afficheur AM-03127-LED prise USB branchée .
D'autre part l'attribut usb , issu de la classe serialib , qui représente l'interface série par connexion USB,
avec ses trois méthodes utiles pour ce projet : l'ouverture du port de communication, sa fermeture et la possibilité d'envoyer des
messages textuels.
Diagramme de séquence
Mise en oeuvre du codage
Respectez l'ensemble de ces diagrammes. Il est judicieux de s'occuper en premier de la classe Afficheur . Une fois que vous l'avez complètement constituée, vous vous préoccupez
ensuite de la fonction principale main() .
AfficheurClasses.pro
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle qt
SOURCES += main.cpp afficheur.cpp serialib.cpp
HEADERS += afficheur.h serialib.h
TARGET = afficheur
target.path = /home/ubuntu/Public
INSTALLS += target
afficheur.h
#ifndef AFFICHEUR_H
#define AFFICHEUR_H
#include "serialib.h"
#include <string>
using namespace std;
class Afficheur
{
serialib usb;
bool connexion;
public:
Afficheur() { connexion = usb.Open("/dev/ttyUSB0", 9600) == 1; }
~Afficheur() { affichePage(" "); usb.Close(); }
bool etat() { return connexion; }
void affichePage(const string &message);
private:
string checksum(string texte);
};
#endif // AFFICHEUR_H
afficheur.cpp
#include "afficheur.h"
#include <sstream>
void Afficheur::affichePage(const string &message)
{
string commande = "<L1><PA><FE><MA><WC><FE><CE>";
commande += message;
ostringstream trame;
trame << "<ID01>" << commande << checksum(commande) << "<E>";
usb.WriteString(trame.str().c_str());
usleep(50000);
}
string Afficheur::checksum(string texte)
{
char calcul = 0;
for (char octet : texte) calcul^=octet;
char bas = calcul & 0b00001111;
char haut = (calcul & 0b11110000) >> 4;
bas = bas < 10 ? bas+=0x30 :bas+=0x41-10;
haut = haut < 10 ? haut+=0x30 : haut+=0x41-10;
return {haut, bas};
}
main.cpp
#include "afficheur.h"
#include #include "afficheur.h"
#include <iostream>
using namespace std;
int main()
{
string mot;
Afficheur lcd;
if (lcd.etat())
{
cout << "Afficheur connecté" << endl;
cout << "Tapez votre mot à afficher : ";
cin >> mot;
lcd.affichePage(mot);
cout << "Fin du programme dans 10s !" << endl;
cout << "L'afficheur va s'éteindre complètement..." << endl;
sleep(10); // attente de 10s
}
else cout << "Afficheur non connecté" << endl;
}
Modification du programme principal
Modifiez la fonction principale, dans le fichier main.cpp , de telle sorte que nous voyons l'écoulement du temps des 10
secondes d'attente, comme cela vous est montré dans la figure ci-dessous :
main.cpp
#include "afficheur.h"
#include #include "afficheur.h"
#include <iostream>
using namespace std;
int main()
{
string mot;
Afficheur lcd;
if (lcd.etat())
{
cout << "Afficheur connecté" << endl;
cout << "Tapez votre mot à afficher : ";
cin >> mot;
lcd.affichePage(mot);
cout << "Fin du programme dans 9s";
cout.flush();
for (int temps=8; temps>=0; temps--)
{
sleep(1); // attente de 1s
cout << "\b\b" << temps << 's';
cout.flush();
}
cout << endl;
}
else cout << "Afficheur non connecté" << endl;
}
Afficheur (afficher plusieurs pages)
Continuons à nous intéresser au développement de l'application embarqué sur le pcDuino afin de gérer l'afficheur AM-03127-LED .
Nous allons modifier la structure logicielle du projet précédent afin de permettre l'afiichage de plusieurs pages en même temps limitation
de 5 pages sur 26 permises . Cette fois-ci, pour chaque message, nous pouvons choisir la couleur, le clignotement, le
défilement ainsi que le temps d'affichage. Afin de permettre cet ensemble de fonctionnalités, l'idéal est de décomposer la gestion
de l'affichage sur deux classes : la première, Afficheur qui gère la communication globale avec l'afficheur physique, la
deuxième, Page qui comme son nom l'indique, s'occupe de la gestion de chaque message avec la couleur, le défilement, etc.
Diagramme des cas d'utilisation
Dans cette description du fonctionnement, vous remarquez que le système doit pouvoir afficher au moins une page sur l'afficheur,
le nombre maximum étant limité à cinq. Au départ, pour éviter d'avoir l'affichage d'usine, il est souhaitable de proposer une seule
page mais avec une chaîne de caractères vide. Ensuite, à tout moment, nous pouvons rajouter d'autres pages, d'en enlever une ou
même de ne plus en afficher, sachant que nous avons toujours au moins une page et qu'il ne faut pas dépasser la limite de 5 .
Lorsque vous introduisez une nouvelle page, il est également possible de régler la façon de l'afficher défilement,
clignotement, la couleur, le temps de repos .
Diagramme de déploiement
Le diagramme de déploiement nous permet de bien voir les différents systèmes mis en jeu. Vous devez mettre en oeuvre du cross-développement
pour créer votre programme qui sera automatiquement déployé sur le système embarqué pcDuino à l'aide des sept fichiers
nécessaires à l'élaboration du projet. Vous remarquez que le nom du processus programme qui est exécuté sur la pcDuino
se nomme pages .
Diagramme des classes
Cette fois-ci, la structure des classes est très différente du projet précédent puisque nous pouvons maintenant afficher plusieurs
pages avec, pour chacune d'entre elles, la possibilité de faire des réglages particuliers, comme le choix de la couleur, le
clignotement, etc. Afin de réaliser ce genre de traitement, nous avons maintenant une nouvelle classe Page dont l'objectif
est de recenser les différentes possibilités d'affichage et finalement de fournir une trame bien constituée pour la classe Afficheur .
En réalité, cette classe Page s'occupe uniquement de gérer correctement les différentes balises constituant la trame.
La classe Afficheur s'est étoffée sensiblement. Elle dispose, en plus de celles déjà existantes, des méthodes
correspondant au fonctionnement attendu, défini par le diagramme de cas d'utilisation, comme ajouter() , enleverDernierePage()
et neRienAfficher() . Elle dispose également d'une méthode privée choisirNombrePage() qui permet à chaque
changement de situation de spécifier à l'afficheur les pages à afficher. Enfin, nous avons maintenant une méthode envoyerTrame()
qui se préoccupe, comme son nom l'indique, d'envoyer les trames correspondant, soit à la nouvelle page à afficher ou soit à la
commande correspondant au nombre de pages à afficher à ce moment là.
Le comportement de la classe Afficheur pour les phases de création et de destruction change pour ce projet.
L'afficheur doit être éteint au démarrage du processus. Lorsque le programme se termine, l'afficheur reste dans l'état où il était
juste avant la demande d'arrêt.
Diagramme de séquence - Ajouter une page
Mise en oeuvre du codage
Respectez l'ensemble de ces diagrammes. Il est judicieux de s'occuper en premier de la classe Page . Une fois que vous
l'aurez complètement constituée, vous implémenterez uniquement le code correspondant à la séquence décrite ci-dessus Ajouter
une page , sans vous préoccuper des autres fonctionnalités, comme Enlever dernière page , Ne plus rien afficher ,
Afficher une page vide , etc. Une fois que vous aurez validez la première partie, vous pourrez par la suite rajouter ces
différentes fonctionnalités une à une .
AfficheurPages.pro
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle qt
SOURCES += main.cpp afficheur.cpp serialib.cpp page.cpp
HEADERS += afficheur.h serialib.h page.h
TARGET = pages
target.path = /home/ubuntu/Public
INSTALLS += target
page.h
#ifndef PAGE_H
#define PAGE_H
#include <string>
using namespace std;
enum Couleur {Vert, Orange, Rouge, ArcEnCiel};
class Page
{
string numero;
string message;
string defilement = "<FE>";
string clignotement = "<MA>";
string temps = "<WC>";
string couleur = "<CE>";
public:
Page(const string &texte);
void setNumero(unsigned page);
void setDefilement(bool actif);
void setClignotement(bool actif);
void setTemps(unsigned secondes);
void setCouleur(Couleur c);
void changerMessage(const string &texte);
string trame() const;
bool vide() const;
};
#endif // PAGE_H
page.cpp
#include "page.h"
Page::Page(const string &texte) : message(texte) {}
void Page::setNumero(unsigned page)
{
numero = "<L1><P";
numero += 'A' + page - 1;
numero += '>';
}
void Page::setDefilement(bool actif)
{
defilement = "<F";
defilement += actif ? "E>" : "A>";
}
void Page::setClignotement(bool actif)
{
clignotement = "<M";
clignotement += actif ? "B>" : "A>";
}
void Page::setTemps(unsigned secondes)
{
temps = "<W";
temps += 'A'+secondes;
temps += '>';
}
void Page::setCouleur(unsigned c)
{
char coul;
switch (c) {
default:
case Vert : coul='E'; break;
case Orange : coul='H'; break;
case Rouge : coul='B'; break;
case ArcEnCiel : coul='S'; break;
}
couleur = "<C";
couleur += coul;
couleur += '>';
}
void Page::changerMessage(const string &texte) { message = texte; }
string Page::trame() const
{
return numero+defilement+clignotement+temps+defilement+couleur+message;
}
bool Page::vide() const { return message.empty(); }
afficheur.h
#ifndef AFFICHEUR_H
#define AFFICHEUR_H
#include "serialib.h"
#include "page.h"
#include <string>
#include <vector>
using namespace std;
class Afficheur
{
serialib usb;
bool connexion;
vector<Page> pages;
public:
Afficheur();
~Afficheur();
bool etat() const { return connexion; }
void ajouter(Page &page);
void enleverDernierePage();
void neRienAfficher();
private:
void choisirNombrePage(unsigned nombre);
void envoyerTrame(const string &commande);
string checksum(string texte);
};
#endif // AFFICHEUR_H
afficheur.cpp
#include "afficheur.h"
Afficheur::Afficheur()
{
connexion = usb.Open("/dev/ttyUSB0", 9600) == 1;
Page page("");
ajouter(page);
}
Afficheur::~Afficheur()
{
usb.Close();
}
void Afficheur::ajouter(Page &page)
{
if (pages.size()==5) return;
if (pages.size()==1 && pages[0].vide()) {
pages.clear();
page.setNumero(1);
pages.push_back(page);
envoyerTrame(page.trame());
}
else {
unsigned nombrePage = pages.size()+1;
page.setNumero(nombrePage);
pages.push_back(page);
choisirNombrePage(nombrePage);
envoyerTrame(page.trame());
}
}
void Afficheur::enleverDernierePage()
{
if (pages.size()>1) {
pages.pop_back();
choisirNombrePage(pages.size());
}
else if (!pages[0].vide()) {
pages[0].changerMessage("");
envoyerTrame(pages[0].trame());
}
}
void Afficheur::neRienAfficher()
{
pages.clear();
Page page("");
ajouter(page);
}
void Afficheur::choisirNombrePage(unsigned nombre)
{
string commande = "<TA>00000000009900000000";
for (int i=0; i<nombre; i++) commande += 'A'+i;
envoyerTrame(commande);
}
void Afficheur::envoyerTrame(const string &commande)
{
string trame = "<ID01>";
trame += commande;
trame += checksum(commande);
trame += "<E>";
usb.WriteString(trame.c_str());
usleep(100000); // Attente de 1/10ème de seconde entre chaque trame
}
string Afficheur::checksum(string texte)
{
char calcul = 0;
for (char octet : texte) calcul^=octet;
char bas = calcul & 0b00001111;
char haut = (calcul & 0b11110000) >> 4;
bas = bas < 10 ? bas+=0x30 :bas+=0x41-10;
haut = haut < 10 ? haut+=0x30 : haut+=0x41-10;
return {haut, bas};
}
main.cpp
#include "afficheur.h"
#include <iostream>
using namespace std;
void menu()
{
cout << "----------------------------" << endl;
cout << "Ajouter un message ........1" << endl;
cout << "Enlever dernier message ...2" << endl;
cout << "Ne plus rien afficher .....3" << endl;
cout << "Quitter le programme ......0" << endl;
cout << "----------------------------" << endl;
cout << "Votre choix ? ";
}
void reglerPage(Page &page)
{
char choix;
cout << "Souhaitez-vous faire défiler votre message (o/n) ? ";
cin >> choix;
page.setDefilement(choix=='o');
cout << "Souhaitez-vous faire clignoter votre message (o/n) ? ";
cin >> choix;
page.setClignotement(choix=='o');
unsigned temps;
cout << "Durée d'affichage de votre message (1s minimum) ? ";
cin >> temps;
page.setTemps(temps);
int couleur;
cout << "Choisissez votre couleur (Vert=0, Orange=1, Rouge=2, Arc-en-ciel=3) ? ";
cin >> couleur;
page.setCouleur((Couleur)couleur);
}
int main()
{
Afficheur lcd;
int choix;
char reglage;
string message;
if (lcd.etat())
{
cout << "Afficheur connecté" << endl;
do {
menu();
cin >> choix;
switch (choix) {
case 1:
{
cout << "Quel message désirez-vous ajouter ? ";
cin >> message;
Page page(message);
cout << "Désirez-vous faire des réglages sur votre message (o/n) ? ";
cin >> reglage;
if (reglage=='o') reglerPage(page);
lcd.ajouter(page);
break;
}
case 2:
lcd.enleverDernierePage();
break;
case 3:
lcd.neRienAfficher();
break;
case 0:
cout << "Fin du programme, à bientôt!" << endl;
default:
break;
}
}
while (choix!=0);
}
else cout << "Afficheur non connecté" << endl;
}
Entrées sorties sur pcDuino - GPIO
Dans ce chapitre nous allons nous consacrer à l'étude des entrées sorties digitales de la carte pcDuino . Dans cette
première étape, notre intention sera de récupérer une impulsion provoquée par un bouton poussoir et d'activer une sortie de la
carte afin qu'une led puisse s'éclairer. Vous voyez que notre démarche est très modeste. L'objectif est, comme les projets
précédents, de créer une classe qui va encapsuler toute la démarche nécessaire pour que l'utilisation des entrées-sorties tout ou
rien de la carte pcDuino soit extrêmement simple à utiliser. La mise en place sera ainsi intuitive et très rapide à
expérimenter.
Caractéristiques des broches E/S numériques et analogiques du pcDuino
GPIO : 18 E/S en 3.3V.
Entrées Analogiques : 2 x 6 bits en 0-2V et 4 x 12 bits en 0-3.3V.
Sorties analogiques : 6 x PWM 2 broches « fast » en 520Hz – 8 bits et 4 broches « slow » en 5Hz – 20
niveaux .
Communication Sérielles : I2C, SPI, UART.
Nous retrouvons la plupart des possibilités de l'Arduino à quelques adaptation près.
Le brochage du pcDuino avec l'alimentation et les entrées analogiques
Le brochage des entrées-sorties tout-ou-rien
Caractéristiques électriques : Ces broches fonctionnent en 3,3V et pas en 5V et ne peuvent
fournir que quelques mA... donc attention, prudence... !
Principe d'accès aux broches E/S
Il est possible de gérer les broches E/S comme de simples fichiers c'est un principe général sous Gnu/Linux... . Le
fichier de chaque broche est alors de la forme gpioX où X correspond au numéro de la broche. Il existe deux
types de fichier de nature différentes :
Les fichiers fixant le mode entrée ou sortie sont placés dans le répertoire : /sys/devices/virtual/misc/gpio/mode/
Les fichiers contenant/définissant l'état des broches sont placés dans le répertoire : /sys/devices/virtual/misc/gpio/pin/
Fixer le sens d'une broche
Pour fixer le sens d'une broche, c'est simple : il suffit d'ouvrir le fichier et d'écrire la valeur voulue sachant :
0 la broche en entrée = INPUT
1 pour la broche en sortie = OUTPUT
8 pour la broche en entrée avec rappel si plus activé auto-maintien pour les boutons poussoirs .
Diagramme des cas d'utilisation
Après toutes ces considérations techniques qui nous ont permis de comprendre les différents fonctionnements, nous allons
maintenant mettre en oeuvre un petit programme qui permet, dès le départ, d'activer une sortie du pcDuino qui est
connectée à une simple led. Cette led reste affichée indéfiniment jusqu'à ce que l'utilisateur appuie sur un bouton poussoir. Cette
action provoque l'arrêt du programme en même temps que l'extinction de la led.
Diagramme de déploiement
Comme précédemment, le diagramme de déploiement nous permet de bien voir les différents systèmes mis en jeu. Vous devez mettre en
oeuvre du cross-développement pour créer votre programme qui sera automatiquement déployé sur le système embarqué pcDuino
à l'aide des trois fichiers nécessaires à l'élaboration du projet. La classe GPIO sera développée dans les deux fichiers gpio.h
et gpio.cpp . Vous placerez les fonctionnalités attendues dans le fichier principal main.cpp .
Diagramme des classes
D'après ce diagramme vous remarquez que la classe GPIO est composée de deux attributs :
D'une part l'attribut broche qui nous permet d'être en relation avec le fichier représentant la broche utilisée en
lecture et en écriture . C'est dans ce fichier que vous allez proposer la valeur 1 ou 0 suivant
l'activation que vous souhaitez soumettre broche configurée en sortie , et c'est toujours dans ce fichier que vous
pouvez récupérer l'état de l'activation broche configurée en entrée .
D'autre part l'attribut mode , issu de l'énumération MODE , qui permet de fixer une fois pour toute si la
broche concernée doit être considérée comme une entrée ou comme une sortie une fois que le sens de la broche est fixé, il
ne doit plus être possible de le changer .
Cette classe GPIO possède uniquement quatre méthodes qui d'un point de vue utilisation sont très très simples à manipuler.
Leurs noms sont très évocateurs et intuitifs. Toute la partie délicate à traiter se situe à l'intérieur des méthodes. Le
développeur qui va utiliser cette classe pourra réaliser des algorithmes sophistiqués sans qu'il se rende compte de la difficulté
interne. Toute la problématique est ainsi encapsulée à l'intérieur de la classe. C'est ce qui fait l'intérêt de la programmation
objet.
Le constructeur : Lorsque vous devez créer un nouvel objet de type GPIO , vous devez spécifier le numéro de
la broche concernée et s'il s'agit d'une entrée ou d'une sortie en proposant l'un des énumérateur . Votre objectif
dans l'élaboration de ce constructeur sera de configurer le fichier qui permet de fixer le sens de la broche concernée. Ensuite,
vous ouvrirez le fichier qui permet de fixer ou de lire l'état de la broche configurée. Ce fichier sera associé à l'attribut broche
et ainsi cette dernière sera accessible instantanément.
Le destructeur : la phase de destruction est toujours l'inverse de ce qui se passe en phase de construction. Ainsi,
il serait judicieux de fermer le fichier associé à l'attribut broche qui a été ouvert dans le
constructeur. Au préalable, si la broche a été configurée en sortie, il serait souhaitable de mettre la sortie à 0 avant
de détruire l'objet concerné.
La méthode etat() : Que ce soit en entrée ou en sortie, comme son nom l'indique, cette méthode nous indique l'état
de la broche à ce moment précis. Pour la mise en oeuvre de cette méthode, je tiens à vous préciser quelques détails
importants. Lorsque nous effectuons une lecture dans un flot, nous ne pouvons plus relire ce que nous venons de récupérer le
curseur du flot s'est automatiquement décalé . Il faudrait alors clôturer le fichier. Seulement, cela prendrait
beaucoup de temps pour systématiquement ouvrir le fichier concernant la broche à consulter et le fermer par la suite n'oubliez
pas que l'ouverture se déroule uniquement dans le constructeur et la fermeture dans le destructeur . La solution
consiste à faire un accès direct à une position absolue dans le fichier voir la définition ci-dessous . Voici
deux méthodes de la classe fstream qui peuvent être utiles dans votre cas.
int peek() ; Cette méthode fournit le prochain caractère disponible sur le flot concerné, mais
sans l’extraire du flot. Il sera donc de nouveau disponible lors d’une prochaine lecture sur le flot.
istream& seekg(int pos_courante) ; Le pointeur de fichier pointe sur la
position absolue pos_courante .
Accès direct à une position absolue dans le fichier
Le terme flot indique bien que nous soutirons l’information à la volée sous forme séquentielle. Toutefois, il est possible
d’accéder à un endroit précis du fichier pour prendre juste la valeur désirée. L’accès direct est implémenté sous la forme
d’un pointeur de fichier, c'est-à-dire un nombre précisant le rang du prochain octet à lire ou à écrire. Après chaque
opération de lecture ou d’écriture, ce pointeur est incrémenté du nombre d’octets transférés. Ainsi, lorsque nous n’agissons
pas explicitement sur ce pointeur, nous réalisons en fait un accès séquentiel classique; c’est d’ailleurs ce que nous avons
fait jusqu’à présent.
La méthode activer() : Dans le cas d'une broche configurée en sortie, cette méthode permet d'activer la sortie ou
pas.
Mise en oeuvre du codage
Dans un premier temps, vous pouvez réaliser des expériences afin de bien maîtriser cette notion de fichiers et de flot. Une fois
que vous aurez compris tous les mécanisme en jeu, vous pouvez coder votre classe GPIO et respecter l'algorithme prévu pour
élaborer votre projet.
gpio.pro
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle qt
SOURCES += main.cpp gpio.cpp
HEADERS += gpio.h
target.path = /home/ubuntu/Public
INSTALLS += target
gpio.h
#ifndef GPIO_H
#define GPIO_H
#include <fstream>
using namespace std;
enum MODE {Entree, Sortie};
class GPIO
{
fstream broche;
const MODE mode;
public:
GPIO(MODE m, unsigned numero);
~GPIO();
bool etat();
void activer(bool action);
};
#endif // GPIO_H
gpio.cpp
#include "gpio.h"
GPIO::GPIO(MODE m, unsigned numero) : mode(m)
{
string localisation = "/sys/devices/virtual/misc/gpio/mode/gpio";
localisation += '0' + numero;
ofstream modeGPIO(localisation.c_str());
modeGPIO << (mode==Sortie ? '1' : '0');
modeGPIO.close();
localisation = "/sys/devices/virtual/misc/gpio/pin/gpio";
localisation += '0' + numero;
broche.open(localisation.c_str());
}
GPIO::~GPIO()
{
if (mode==Sortie) broche << '0';
broche.close();
}
void GPIO::activer(bool action)
{
if (mode==Sortie) {
broche << (action ? '1' : '0');
broche.flush();
}
}
bool GPIO::etat()
{
broche.seekg(0);
return broche.peek()=='1';
}
main.cpp
#include <iostream>
#include <unistd.h>
using namespace std;
#include "gpio.h"
int main()
{
GPIO bouton(Entree, 6);
GPIO led(Sortie, 3);
led.activer(true);
while (!bouton.etat()) usleep(100000);
return 0;
}
Conclusion sur la programmation orientée objet
Dans le fichier principal, vous remarquez que cette classe GPIO est très très simple à utiliser. Il suffit de déclarer
les objets relatifs avec des noms évocateurs comme bouton et led . Toutes les phases délicates se situent
dans le constructeur et le destructeur , mais ces deux méthodes particulières ne se voient pas
puisqu'elles sont appelées implicitement. Du coup le code correspondant à l'algorithme de fonctionnement est très très court et
rapide à construire. Je me répète, mais la programmation modulaire comme l'est la programmation orientée objet nous donne à la fois
une conception intuitive et très rapide à mettre en oeuvre. Cela facilite le développement d'applications.