Publié le 13 août 2016 - par

La Saga Blink Suite : Elle clignote toujours

figure08La led dans tous ses états. Un petit complément à la saga blink La Saga Blink s’avère nécessaire pour les raisons suivantes :
et nous, les utilisateurs de l’écosystème Arduino, on n’a pas droit au C++
– exploiter le partage des ressources utilisées par les applicatifs de la saga blink,
saluer la « copine clignotante qui vient de nous rejoindre : Plongez dans le Go

Introduction

La présentation s’adresse, toujours, aux débutants expérimentés c’est à dire ceux qui disposent d’un Raspberry Pi opérationnel et qui n’ont pas peur d’utiliser la console pour l’élaboration des programmes. Les experts n’ont pas besoin de cette présentation et la trouveront certainement encore plus inutile que la première.

Par contre, leurs remarques et commentaires sont les bienvenus pour nous permettre d’évoluer.

Base d’expérimentation

Comme il s’agit d’un complément, pour l’instant, tout est identique au chapitre 2 de la « saga Blink ».

Langage C++

Que les experts du C++ me pardonnent car la suite n’est pas conforme au concept C++, mais notre but est de s’amuser et de prendre en mains notre framboise. Ce qui est important pour nous, c’est que cela « tombe en marche ».

Comme la structure de nos programmes C sont compatibles avec C++, il suffit de renommer les fichiers dans un premier temps. Puis, il faudra les recompiler.
Comment ! ; aurais-je fait du « C++ sans que j’en susse rien » (je n’ai pas résisté à la parodie du Bourgeois gentilhomme de Molière).

Une utilisation spécifique du raspberry Pi en C++ fera l’objet d’un autre chapitre.

Langage C++ (boucle infinie)

Voir chapitre 2.4 de la « saga blink ».

wiringPi

Programme

Il suffit de renommer le fichier blink80.c en blink80.cpp avec la commande si dessous :

mv blink80.c blink80.cpp

Exécution du programme

Pour exécuter se programme, il faut d’abord le compiler. La compilation se fait par la commande ci-dessous (en mode console) :

g++ -Wall -o blink80 blink80.cpp -lwiringPi

Le résultat de la compilation est un fichier : blink80

Lancement du programme :

sudo ./blink80

Pour sortir de la boucle infinie, il suffit de faire un Ctrl+c au clavier.

Remarque : On aurait aussi pu utiliser gcc à la place de g++ car le compilateur fait la différence entre les fichier .c et les fichier .cpp (g++ est un alias de gcc).

perso

Programme

Il suffit de renommer le fichier blink50.c en blink50.cpp et ipsGPIO.c en ipsGPIO.cpp avec la commande si dessous :

mv blink50.c blink50.cpp
mv ipsGPIO.c ipsGPIO.cpp

Exécution du programme

Pour exécuter se programme, il faut d’abord le compiler. La compilation se fait par la commande ci-dessous (en mode console) pour les différents fichiers C en créant des fichier objet :

g++ -Wall -c ipsGPIO.cpp
g++ -Wall -c blink50.cpp

Et pour terminer, il faut créer le fichier final via l’éditeur de lien :

g++ -Wall -o blink50 blink50.o ipsGPIO.o

Le résultat de la compilation est un fichier : blink50

Lancement du programme :

sudo ./blink50

Pour sortir de la boucle infinie, il suffit de faire un Ctrl+c au clavier.

Remarque : On peut supprimer les fichiers objets (.o) du répertoire courant par :

rm *.o

Langage C++ (boucle infinie avec sortie)

Voir chapitre 7 de la « saga blink ».

wiringPi

Pour ce programme, on utilise la même méthode pour sortir de la boucle infinie que pour pigpio. La saisie non bloquante d’un caractère clavier est incluse dans un fichier .h. Les experts du C vont voir tout rouge car on ne met pas de code dans un fichier .h, mais cela fonctionne et l’on fera mieux dans le prochain source.

Programme

Il suffit de renommer le fichier blink81.c en blink81.cpp avec la commande si dessous :

mv blink81.c blink81.cpp

Exécution du programme

Pour exécuter se programme, il faut d’abord le compiler. La compilation se fait par la commande ci-dessous (en mode console) :

g++ -Wall -o blink81 blink81.cpp -lwiringPi

Le résultat de la compilation est un fichier : blink81

Lancement du programme :

sudo ./blink81

Pour sortir de la boucle infinie, il suffit de faire un ‘q’ ou ‘Q’ au clavier.

perso

Programme

Il suffit de renommer le fichier blink52.c en blink52.cpp, ipsGPIO.c en ipsGPIO.cpp et saisieCarac.c en saisieCarac.cpp avec la commande si dessous :

mv blink52.c blink52.cpp
mv ipsGPIO.c ipsGPIO.cpp
mv saisieCarac.c saisieCarac.cpp

Exécution du programme

Pour exécuter se programme, il faut d’abord le compiler. La compilation se fait par la commande ci-dessous (en mode console) pour les différents fichiers CPP en créant des fichier objet :

g++ -Wall -c ipsGPIO.cpp
g++ -Wall -c saisieCarac.cpp
g++ -Wall -c blink52.cpp

Et pour terminer, il faut créer le fichier final via l’éditeur de lien :

g++ -Wall -o blink52 blink52.o ipsGPIO.o saisieCarac.o

Le résultat de la compilation est un fichier : blink52

Lancement du programme :

sudo ./blink52

Pour sortir de la boucle infinie, il suffit de faire un Ctrl+c au clavier.

Remarque : On peut supprimer les fichiers objets (.o) du répertoire courant par :

rm *.o

Langage C++ – Plus Classe

Pour la suite de la présentation, nous allons modifier notre cahier des charges et notre organigramme. Le câblage restera en tout point identique à celui du début de la saga. Cette modification nous permettra de mettre en évidence le temps de réaction du programme et la consommation de ressources.

Pour la programmation en C++ et la notion de class, vous trouverez de nombreux tutoriels et cours sur la toile ou dans des ouvrages spécialisés sur le sujet.

Cahier des charges et Organigramme

Notre nouveau cahier des charges se résume à celui du paragraphe 2.3 de la saga blink en y ajoutant une sortie de la boucle infernale.

1) si appuie touche clavier, si appuie alors 1) assignation ports GPIO
2) allumer led, 2)arrêt programme
3) attendre 1 seconde,
4) éteindre led,
5) attendre 1 seconde,
6) continuer en 1)

Nous avons opté pour cet organigramme pour satisfaire les ardeurs des aficionados de la ressource cpu en incluant une attente bloquante. Dans la vraie vie, il faudra trouver le bon compromis entre réactivité/ressource.

figure09
Le première étape consiste à initialiser le port GPIO23 pour qu’elle puisse piloter la led.
L’étape suivante teste si on a appuyé sur une touche clavier (q ou Q). Si la condition est vérifiée, on libère la ressource et l’on quitte le programme.
Puis, on allume la led,
Étape suivante, attendre x secondes,
Après cette attente, on éteint la led,
Suivi d’une nouvelle attente,
Pour finalement recommencer le cycle.

Programme C++

Programme

Ce programme se compose d’un fichier blink15.cpp et de la bibliothèque saisieCarac pour la saisie clavier non bloquante. L’interface avec les ports GPIO est assurée par la bibliothèque wiringPi.

saisieCarac.h et saisieCarac.cpp

Pour saisir le programme saisieCarc.h, il faut faire dans la console :

nano saisieCarac.h

Cette commande ouvre un fichier de texte vide appelé saisieCarac.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme saisie non bloquante caractère au clavier
Fichier entête de saisieCarac.cpp
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 21/07/2016
date de mise à jour : 21/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#ifndef SAISIE_CARAC_h
#define SAISIE_CARAC_h
/* -------------------------------------------------------------------------- */
//prototypes fonctions
int kbhit(void);
/* -------------------------------------------------------------------------- */
#endif

Pour saisir le programme saisieCarc.cpp, il faut faire dans la console :

nano saisieCarac.cpp

Cette commande ouvre un fichier de texte vide appelé saisieCarac.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme saisie non bloquante caractère au clavier
os                  : RPi Linux 4.4.13+
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 22/06/2016
date de mise à jour : 22/06/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
Bibliothèques
----------------------------------------------------------------------------- */
#include <stdio.h>                  //bibliothèque standard
#include <termios.h>                //bibliothèque entrées/sorties terminal
#include <unistd.h>                 //bibliothèque constantes symboliques
#include <fcntl.h>                  //bibliothèque descripteur de fichier
#include "saisieCarac.h"            //
/* -------------------------------------------------------------------------- */
int kbhit(void){                    //fonction indiquant si frappe clavier
    struct termios oldt, newt;
    int ch;
    int oldf;

    tcgetattr(STDIN_FILENO, &oldt); //sauve paramètres terminal
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
                                    //nouveaux paramètres terminal
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

    ch = getchar();                 //lecture caractère

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
                                    //restaure paramètres terminal
    fcntl(STDIN_FILENO, F_SETFL, oldf);

    if(ch != EOF){
        ungetc(ch, stdin);          //replace le caractère dans le flux stdin
                                    //affiche le caractère dans la console
        return 1;                   //valeur de retour caractère saisie
}
return 0;                          //valeur de retour pas de caractère
}
/* -------------------------------------------------------------------------- */

blink15.cpp

Pour saisir le programme blink15.cpp, il faut faire dans la console :

nano blink15.cpp

Cette commande ouvre un fichier de texte vide appelé blink15.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique LED clignotante
Led rouge sur GPIO23 (4) via une résistance de 330 ohms
os                  : RPi Linux 4.4.13+
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 28/07/2016
date de mise à jour : 28/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : www.wiringpi.com
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
Bibliothèques
----------------------------------------------------------------------------- */
#include <stdio.h>                     //utilisé pour printf()
#include <iostream>                    //pour endl
#include "saisieCarac.h"               //entête saisie non bloquante
#include <wiringPi.h>                  //bibliothèque wiringPi
//------------------------------------------------------------------------------
#define LED 4 //numéro led = GPIO23
#define DUREE 1000                     //durée demi-période en millis-sec

using namespace std;                   //espace de nommage

int main(void){                        //programme principale
    int c(0);
    cout << "Led clignotante" << endl; //IHM
    cout << "q ou Q pour quitter :";   //IHM
    wiringPiSetup();                   //numérotation wiringPi ou "pseudo Arduino"
    digitalWrite(LED, LOW);            //led éteinte
    pinMode(LED, OUTPUT);              //pin en sortie
    for(;;){                           //boucle infinie
        if(kbhit())                    //si touche saisie
            c = getchar();             //lecture touche
        if(tolower(c) == 'q')          //si q ou Q
            break;                     //sortie boucle
        digitalWrite(LED, HIGH);       //allume led
        delay (DUREE);                 //attente DUREE
        digitalWrite(LED, LOW);        //éteind led
        delay (DUREE);                 //attente DUREE
    }
    digitalWrite(LED, LOW);            //éteint led
    pinMode(LED, INPUT);               //pin en entrée
    cout << endl << "Fin du programme" << endl;
                                       //IHM
    return(0);                         //code sortie
}
//------------------------------------------------------------------------------

Exécution du programme

Pour exécuter se programme, il faut au préalable le compiler. La compilation se fait par la commande ci-dessous (en mode console) pour les différents fichiers C++ en créant les fichiers objets correspondants.

g++ -Wall -c saisieCarac.cpp
g++ -Wall -c blink15.cpp

Et pour terminer, il faut créer le fichier final via l’éditeur de lien :

g++ -Wall -o blink15 blink15.o saisieCarac.o -lwiringPi

Le résultat de la compilation est un fichier : blink15

Lancement du programme :

sudo ./blink15

Pour sortir de la boucle, il suffit de faire q ou Q au clavier.

Remarque : On peut supprimer les fichiers objets (.o) du répertoire courant par :

rm *.o

Commentaire

La sortie de la boucle infinie va être tributaire de l’instant où l’on entre le caractère q au clavier. En effet, si la saisie de q intervient lorsque le programme exécute la ligne 43, la prise en compte de l’ordre de sortie va intervenir quasiment de suite (temps proche de 0 seconde). Par contre, si la saisie se fait lors de l’exécution de la ligne 39, il faudra attendre le passage par la ligne 35 pour provoquer la sortie (soit environ 2 seconde plus tard). C’est d’ailleurs le principal inconvénient des attentes bloquantes sur les cartes embarquées.

Attendre 2 secondes parce que la température de la piscine est passée sous la température basse et qu’il faut chauffer l’eau n’est pas un problème. En effet, ce temps ne représente rien par rapport à l’inertie thermique de la piscine.

Attendre 2 secondes pour arrêter un dispositif mécanique en mouvement lorsqu’on actionne un fin de course est une autre affaire. Je vous fait grâce, des contraintes mécaniques, des déformations physiques, de la casse matériel et, des éventuelles, atteintes à l’intégrité physique des personnes.

Tout est possible, ce n’est qu’un problème de choix mais il faut le faire en toute connaissance de cause.

Programme C++ avec Class

Programme

Profitons de C++ pour créer une classe qui nous permettra d’instancier notre (nos) led (leds). Pour créer notre classe GPIOClassOut nous utiliserons les drivers Linux (utilisés dans de nombreux exemples précédents) pour accéder aux ports GPIO. Cet technique n’est pas la plus efficace mais elle permet de savoir ce que l’on fait.

Notre programme comporte un fichier blink05.cpp (programme principal) et de deux librairies saisieCarc.h et GPIOClassOut.h.

Comme d’habitude les fichiers saisieCarac.h et saisieCarc.cpp sont des fichiers C. Je sais, ce n’est pas bien mais je n’ai pas d’autres solutions pour l’instant.
Nota : Si l’un des lecteurs à une solution élégante pour saisir un caractère non bloquante au clavier en C++, je suis preneur.

saisieCarac.h et saisieCarac.cpp

Identique aux programmes du chapitre 4.2.1.1

GPIOClassOut.h et GPIOClassOut.cpp

Pour saisir le programme GPIOClassOut.h, il faut faire dans la console :

nano GPIOClassOut.h

Cette commande ouvre un fichier de texte vide appelé GPIOClassOut.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique LED clignotante
Fichier entête de GPIOClassOut.cpp
os                  : RPi Linux 4.4.13+
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 21/07/2016
date de mise à jour : 21/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#ifndef GPIOClassOut_H
#define GPIOClassOut_H

class GPIOClassOut{                     //classe GPIO en sortie
public:                                 //attributs et méthodes publics
    GPIOClassOut();
    void begin(int broche);             //initialise la sortie
    void on();                          //met la sortie à 1 (3.3V)
    void off();                         //met la sortie à 0 (0V)
    void close();                       //ferme la / les sortie(s)
    void toggle();                      //inverse état de la sortie
private:                                //attributs et méthodes privés
    void export_gpio();                 //méthode export
    void gpio_direction();              //méthode direction uniquement sortie
                                        //pour notre exemple
    void unexport_gpio();               //méthode unexport
    char read_gpio();                   //lecture état port sortie
    int _broche;                        //numéro du port
};
#endif

Le fichier entête contient les attributs (variables) et les méthodes (fonctions) de notre class GPIOClassOut.cpp. Certains attributs et certaines méthodes sont déclarés en « public » et elles sont accessibles à partir de notre programme blink.

Tout ce qui est déclaré en « private«  est uniquement à usage interne de la Class.

Pour saisir le programme GPIOClassOut.cpp, il faut faire dans la console :

nano GPIOClassOut.cpp

Cette commande ouvre un fichier de texte vide appelé GPIOClassOut.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique LED clignotante
Fichier bibliothèque class GPIOClassOut.cpp
os                  : RPi Linux 4.4.13+
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 21/07/2016
date de mise à jour : 21/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
 Biliothèques
----------------------------------------------------------------------------- */
#include "GPIOClassOut.h"               //entête class
#include <stdlib.h>                     //pour .c_str()
#include <sstream>                      //pour stringstream
#include <fstream>                      //pour la lecture fichier

using namespace std;                    //espace de nommage
/* -------------------------------------------------------------------------- */
/*
Classe GPIOClassOut
*/
GPIOClassOut::GPIOClassOut():
    _broche(0)                          //valeur par défaut
{
}
/*
Initialisation sortie
*/
void GPIOClassOut::begin(int broche){
    _broche = broche;                   //copie dans variable privée
    if(_broche <= 0){                   //si <= 0
        _broche = 23;                   //valeur par défaut
    }
    export_gpio();                      //méthode export
    gpio_direction();                   //méthode direction
}
/*
Exporte la sortie
*/
void GPIOClassOut::export_gpio(){
    string commande;                    //variable commande à transmettre
    stringstream ss;                    //variable de conversion
    string broche;                      //numéro broche en string
    ss << _broche;                      //conversion de int en string, on aurait
    ss >> broche;                       //pu utiliser la méthode .to_string()
                                        //mais nécésitait une directive de
                                        //compilation supplémentaire
    commande = "echo " + broche + " > /sys/class/gpio/export";
                                        //constitution de la commande à
                                        //transmettre
    system(commande.c_str());           //transmission de la commande linux
}
/*
Assigne la sortie
*/
void GPIOClassOut::gpio_direction(){
    string commande;                    //variable commande à transmettre
    stringstream ss;                    //variable de conversion
    string broche;                      //numéro broche en string
    ss << _broche;                      //conversion de int en string
    ss >> broche;                       //conversion de int en string
    commande = "echo out > /sys/class/gpio/gpio" + broche + "/direction";
                                        //constitution de la commande à
                                        //transmettre
    system(commande.c_str());           //transmission de la commande linux
}
/*
Libère la ressource
*/
void GPIOClassOut::unexport_gpio(){
    string commande;                    //variable commande à transmettre
    stringstream ss;                    //variable de conversion
    string broche;                      //numéro broche en string
    ss << _broche;                      //conversion de int en string
    ss >> broche;                       //conversion de int en string
    commande = "echo " + broche + " > /sys/class/gpio/unexport";
                                        //constitution de la commande à
                                        //transmettre
    system(commande.c_str());           //transmission de la commande linux
}
/*
Inverse l'état de la sortie
*/
void GPIOClassOut::toggle(){
    char etat = read_gpio();            //lecture état de la sortie
    if(etat == '1')                     //si état haut
        off();                          //mettre à 0 par méthode off
    else                                //si état bas
        on();                           //mettre à 1 par méthode on
}
/*
Mise à 1 (3.3V) de la sortie
*/
void GPIOClassOut::on(){
    string commande;                    //variable commande à transmettre
    stringstream ss;                    //variable de conversion
    string broche;                      //numéro broche en string
    ss << _broche;                      //conversion de int en string
    ss >> broche;                       //conversion de int en string
    commande = "echo 1 > /sys/class/gpio/gpio" + broche + "/value";
                                        //constitution de la commande à
                                        //transmettre
    system(commande.c_str());           //transmission de la commande linux
}
/*
Mise à 0 (0V) de la sortie
*/
void GPIOClassOut::off(){
    string commande;                    //variable commande à transmettre
    stringstream ss;                    //variable de conversion
    string broche;                      //numéro broche en string
    ss << _broche;                      //conversion de int en string
    ss >> broche;                       //conversion de int en string
    commande = "echo 0 > /sys/class/gpio/gpio" + broche + "/value";
                                        //constitution de la commande à
                                        //transmettre
    system(commande.c_str());           //transmission de la commande linux
}
/*
Libère la ressource
*/
void GPIOClassOut::close(){
    unexport_gpio();                    //méthode unexport
}
/*
Lit l'état de la sortie
*/
char GPIOClassOut::read_gpio(){
    string nomFichier;                  //variable pour le nom fichier
    stringstream ss;                    //variable de conversion
    string broche;                      //numéro broche en string
    ss << _broche;                      //conversion de int en string
    ss >> broche;                       //conversion de int en string
    nomFichier = "/sys/class/gpio/gpio" + broche + "/value";
                                        //constitution du chemin et nom fichier
    ifstream Fp(nomFichier.c_str(), ios::in);
                                        //ouverture fichier
    char valeur = 0;                    //valeur contenu fichier
    Fp.get(valeur);                     //lire et mettre dans valeur
    Fp.close();                         //ferme le fichier
    return valeur;                      //valeur de retour
}
/* -------------------------------------------------------------------------- */

Normalement le programme sur-commenté devrait suffisant pour la compréhension.

blink05.cpp

Pour saisir le programme blink05.cpp, il faut faire dans la console :

nano blink05.cpp

Cette commande ouvre un fichier de texte vide appelé blink05.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique LED clignotante
Led rouge sur GPIO23 via une résistance de 330 ohms
Ajout sortie boucle infinie
os                  : RPi Linux 4.4.13+
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 29/07/2016
date de mise à jour : 29/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
 Bibliothèques
----------------------------------------------------------------------------- */
#include "GPIOClassOut.h"               //entête class
#include <iostream>                     //pour cout et endl
#include <unistd.h>                     //pour usleep
#include "saisieCarac.h"                //entête saisie caractère non bloquant
#include <stdio.h>                      //bibliothèque entrées/sorties

#define DUREE 1000000                   //durée demi-période en micro seconde

using namespace std;                    //espace nommage
/* -------------------------------------------------------------------------- */
int main(void){
    int c;
    cout << "LED's clignotantes" << endl;
    cout << "'q' pour sortir" << endl;  //IHM
    GPIOClassOut led;                   //instance led
    led.begin(23);                      //initialise led sur GPIO23
    led.on();                           //allume led
    for(;;){                            //boucle infinie
       if(kbhit())                      //si touche saisie
          c = getchar();                //lecture touche
       if(tolower(c) == 'q')            //test si 'q' ou 'Q'
          break;                        //sortie boucle infernale
       led.toggle();                    //permute état led
       usleep(DUREE);                   //attente pendant DUREE
    }
    led.close();                        //libère la ressource
    cout << "\nFin du programme" << endl;
    return 0;                           //code sortie
}
/* -------------------------------------------------------------------------- */

Exécution du programme

Pour exécuter ce programme, il faut au préalable le compiler. La compilation se fait par la commande ci-dessous (en mode console) pour les différents fichiers C++ en créant les fichiers objets correspondants.

g++ -Wall -c saisieCarac.cpp
g++ -Wall -c GPIOClassOut.cpp&lt;/span&gt;
g++ -Wall -c blink05.cpp

Et pour terminer, il faut créer le fichier final via l’éditeur de lien :

g++ -Wall -o blink05 blink05.o saisieCarac.o -GPIOClassOut

Le résultat de la compilation est un fichier : blink05

Lancement du programme :

sudo ./blink05

Pour sortir de la boucle, il suffit de faire q ou Q au clavier.

Remarque : On peut supprimer les fichiers objets (.o) du répertoire courant par :

rm *.o

Commentaire

La sortie de la boucle infinie va être tributaire de l’instant où l’on entre le caractère q au clavier. En effet, si la saisie de q intervient lorsque le programme exécute la ligne 42, la prise en compte de l’ordre de sortie va intervenir quasiment de suite (temps proche de 0 seconde). Par contre, si la saisie se fait lors de l’exécution de la ligne 40, il faudra attendre le passage par la ligne 36 pour provoquer la sortie (soit environ 1 seconde plus tard). Si l’on avait utilisé les méthodes on() et off() pour faire clignoter notre led, l’attente serait d’environ 2 secondes.

Conclusion saga blink

A force de triturer cette led qui clignote dans tous les sens, nous avons de plus en plus d’idées de mise en œuvre. L’utilisation de leds multicolores ou de leds intelligentes type WS2812b permettrait également de proposer des petits programmes intéressants pour les débutants. Mais le but n’est pas d’écrire un ouvrage de 458 pages sur la led clignotante.

Tout doit avoir une fin. Quoi que !

Les threads

Tous ceux qui veulent en savoir plus, peuvent consulter les différentes documentations du web, ouvrages spécialisés ou l’article de Bud Spencer : Penser ‘Thread’ pour simplifier vos programmes

Je ne vais pas vous faire un cours sur les threads, j’en suis parfaitement incapable. De formation charcutier/zingueur qui aspire à devenir pâtissier/couvreur, on ne peut pas tout assumer.

figure10C’est quoi les threads ? Cela ne se mange pas, même s’ils sont difficiles à digérer. Pour faire simple, notre programme va créer un ou plusieurs « programmes » (threads ou fils ou tâches) qui vont s’exécuter de manière parallèle (en même temps ou quasiment en même temps) que notre programme. Pendant que le thread effectue une tâche plus ou moins bloquante, un autre thread peut assurer une surveillance, par exemple, des entrées ou clavier (voir figure).

Exemples de threads

Dans nos exemples nous n’utiliserons pas les notions d’échanges d’informations entre threads, de blocage, etc… Les mutex ou autres termes pharmaceutiques, tout droit issus du Codex, sont du domaine des spécialistes que nous ne sommes pas. Pour nous la framboise est un fruit ou un objet d’amusement.

Un thread

Pour faire des tests avec ce concept, nous avons opté pour une approche hors ports GPIO. Tous ces programmes pourront être testés sur le Raspberry Pi ou sur votre ordinateur de bureau.

Langage C

Programme

Pour saisir le programme thread01.c, il faut faire dans la console :

nano thread01.c

Cette commande ouvre un fichier de texte vide appelé thread01.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques           :
----------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
//fonction thread
void* fctThread(){
    printf("<thread>\n");
    while(1){                               //boucle infinie
        printf("*");                        //affiche des *
        fflush(stdout);                     //affichage immédiat
        usleep(500000);                     //attente 500 ms
    }
    return NULL;
}
//programme principal
int main(){
    pthread_t monThread;                    //instance thread
    printf("Début programme\n");
    printf("Zone d'initialisation\n");
    printf("\ntouche <Entrée> pour quitter !\n\n");
    pthread_create(&monThread, NULL, fctThread, NULL);
                                            //création du thread
    getchar();                              //attente saisie clavier
    pthread_cancel(monThread);              //supprime le thread
    pthread_join(monThread, NULL);          //attente fin thread
    printf("\nZone libération des ressources\n");
    printf("Fin du programme\n");
    return 0;
}

La fonction lignes 18 à 25 est exécutée par un thread en parallèle du programme main().
On déclare une instance thread à la ligne 29, la création proprement dite du thread est faite ligne 33.
Ligne 35, notre programme main() attend une saisie au clavier.
La ligne 36 se charge de la destruction du thread et l’instruction de la ligne 37 attend la fin du cycle du thread.

Exécution du programme

Pour exécuter se programme, il faut au préalable le compiler. La compilation se fait par la commande ci-dessous (en mode console).

gcc -Wall -o thread01 thread01.c -lpthread

Le résultat de la compilation est un fichier : thread01

Lancement du programme :

./thread01

Pour sortir de la boucle, il suffit de faire <Entrée> au clavier.

Résultat du programme

Vous devriez voir dans votre console un affichage semblable à celui ci :

Début programme
Zone d'initialisation

touche <Entrée> pour quitter !

<thread>
*************************************************************************************************

Zone libération des ressources
Fin du programme

La « Zone d’initialisation » correspond à l’emplacement où l’on peut initialiser les paramètres de nos ports GPIO.
La « Zone libération des ressources » correspond à l’emplacement où l’on libère les ressources de la carte.
<thread> : Message de démarrage du thread.
**********…….*********** : Le résultat de l’exécution du thread, peut être une led qui clignote.

Autre présentation

L’utilisation de la structure précédente fonctionne très bien mais il serait plus simple, d’un point de vue développement, de déporter le code de notre thread dans un fichier annexe.
Dans ce cas, notre programme thread01.c deviendrait un pseudo-ordonnanceur pour la led clignotante.

La nouvelle version se compose des fichiers thread02.c, monProg.h et monProg.c.
Pour saisir le programme monProg.h, il faut faire dans la console :

nano monProg.h

Cette commande ouvre un fichier de texte vide appelé monProg.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Fichier entête pour monProg.c
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques :
----------------------------------------------------------------------------- */
#ifndef MON_PROG_H
#define MON_PROG_H
//prototypes
void* fctThread();
#endif

Pour saisir le programme monProg.c, il faut faire dans la console :

nano monProg.c

Cette commande ouvre un fichier de texte vide appelé monProg.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Simulation programme raspberry Pi
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques           :
----------------------------------------------------------------------------- */
#include "monProg.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void* fctThread(){
    while(1){                           //boucle infinie
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        printf("*");                    //affiche des *
        fflush(stdout);                 //affichage immédiat
        usleep(500000);                 //attente 500 ms
    }
    return NULL;
}

Pour saisir le programme thread02.c, il faut faire dans la console :

nano thread02.c

Cette commande ouvre un fichier de texte vide appelé thread02.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques           :
----------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "monProg.h"

//programme principal
int main(){
    pthread_t monThread;                //instance thread
    printf("Début programme\n");
    printf("Zone d'initialisation\n");
    printf("\ntouche <Entrée> pour quitter !\n\n");
    pthread_create(&monThread, NULL, fctThread, NULL);
                                        //création du thread
    getchar();                          //attente saisie clavier
    pthread_cancel(monThread);          //supprime le thread
    pthread_join(monThread, NULL);      //attente fin thread
    printf("\nZone libération des ressources\n");
    printf("Fin du programme\n");
    return 0;
}

Pour l’exécution, il faudra faire :

gcc -Wall -o thread02 thread02.c monProg.c -lpthread

Le résultat sera un fichier : thread02

Lancement du programme :

./thread02

Pour sortir de la boucle, il suffit de faire <Entrée> au clavier.

L’affichage dans la console sera, en tout point, identique au précédent exemple.

Langage C++

Programme

Notre programme est composé par trois fichiers : monProg.h, monProg.cpp et thread05.cpp.
Pour saisir le programme monProg.h, il faut faire dans la console :

nano monProg.h

Cette commande ouvre un fichier de texte vide appelé monProg.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Fichier entête pour monProg.cpp
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques :
----------------------------------------------------------------------------- */
#ifndef MON_PROG_H
#define MON_PROG_H
//prototypes
void* fctThread(void *);
#endif

Pour saisir le programme monProg.cpp, il faut faire dans la console :

nano monProg.cpp

Cette commande ouvre un fichier de texte vide appelé monProg.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Simulation programme raspberry Pi
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques :
----------------------------------------------------------------------------- */
#include "monProg.h"
#include <cstdio>
#include <iostream>
#include <unistd.h>

using namespace std;

void* fctThread(void *){
    while(1){ //boucle infinie
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        cout << "*" << flush;
        usleep(500000); //attente 500 ms
    }
    return NULL;
}

Pour saisir le programme thread05.cpp, il faut faire dans la console :

nano thread05.cpp

Cette commande ouvre un fichier de texte vide appelé thread05.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : g++ (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques :
----------------------------------------------------------------------------- */
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "monProg.h"

using namespace std;

//programme principal
int main(){
    pthread_t monThread;                //instance thread
    cout << "Début programme" << endl;
    cout << "Zone d'initialisation" << endl;
    cout << endl << "touche <Entrée> pour quitter !" << endl << endl;
    pthread_create(&monThread, NULL, fctThread, NULL);
                                        //création du thread
    cin.ignore();                       //attente saisie clavier
    pthread_cancel(monThread);          //supprime le thread
    pthread_join(monThread, NULL);      //attente fin thread
    cout << endl << "Zone libération des ressources" << endl;
    cout << "Fin du programme" << endl;
    return 0;
}
Exécution du programme

Pour exécuter se programme, il faut au préalable le compiler. La compilation se fait par la commande ci-dessous (en mode console).

gcc -Wall -o thread05 thread05.cpp monProg.cpp -lpthread

 

Le résultat de la compilation est un fichier : thread05

Lancement du programme :

./thread05

Pour sortir de la boucle, il suffit de faire <Entrée> au clavier.

Résultat du programme

Vous devriez voir dans votre console un affichage semblable à celui ci :

Début programme
Zone d'initialisation

touche <Entrée> pour quitter !

<thread>
*************************************************************************************************

Zone libération des ressources
Fin du programme

Remarque : On notera la similitude entre les programmes C et C++.

Python

L’exemple ci-dessous utilise la même structure de programme, c’est-à-dire un programme principal (main) qui se charge de lancer le thread et de la détruire lors d’une saisie clavier.

Programme

Pour saisir le programme monProg.py, il faut faire dans la console :

nano monProg.py

Cette commande ouvre un fichier de texte vide appelé monProg.py (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme de test des threads
Fonction d'affichage des *
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
Remarques           : 

"""
import sys
import time

debut = True #variable globale

def fctThread():
    """affichage * dans la console"""
    global debut #transfaire de variable
    while debut: #affichage message au premier passage
        print("<thread>") #signal start thread
        debut = False
 
    sys.stdout.write("*") #affichage *
    sys.stdout.flush() #affichage immédiat
    time.sleep(0.5) #attente 500 msec

Pour saisir le programme thread50.py, il faut faire dans la console :

nano thread50.py

Cette commande ouvre un fichier de texte vide appelé thread50.py (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme de test des threads
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
Remarques           : 

"""
import sys
import time
from threading import Thread
from monProg import *

class Afficheur(Thread):
    """Lanceur de fonction"""
    def __init__(self):
        Thread.__init__(self)
        self.running = True
        self.debut = True
 
    def run(self):
        while self.running:
            fctThread()                 #notre fonction programme
 
    def stop(self):
        self.running = False

if __name__ == '__main__':
    """Programme principal"""
    print("Début programme")
    print("Zone d'initialisation")
    print()
    print("touche <Entrée> pour quitter !")
    print()
 
    thread_1 = Afficheur()              #création du thread
    thread_1.start()                    #lancement du thread
    input()                             #attente saisie clavier
    thread_1.stop()                     #détruit le thread
    thread_1.join()                     #attente fin cycle thread

    print()
    print("Zone libération des ressources")
    print("Fin du programme")
Exécution du programme

Pour exécuter se programme, il suffit de lancer la commande ci-dessous (en mode console).

python3 thread50.py

Pour sortir de la boucle, il suffit de faire <Entrée> au clavier.

Résultat du programme
Début programme
Zone d'initialisation

touche <Entrée> pour quitter !

<thread>
*************************************************************************************************

Zone libération des ressources
Fin du programme

Remarque : On notera la similitude entre les programmes python, C et C++.

Et pour quelques threads de plus

Pour créer deux ou plusieurs threads, il suffit d’étendre ce que l’on a mis en œuvre dans le chapitre suivant. Par exemple, sous la forme :

instance thread_1
instance thread_2
création thread_1
création thread_2
lancement thread_1
lancement thread_2
attente saisie clavier
destruction thread_1
destruction thread_2
attente fin thread_1
attente fin thread_2

Dans ce synoptique, le programme principal lance les deux threads (qui vivent leur vie) et attend une action de l’utilisateur pour sortie du programme.
Dans le cas de carte embarquée, la priorité n’est pas de terminer le programme mais de boucler indéfiniment pour assurer la fonction qui est la sienne. La structure adoptée au paragraphe précédent peut convenir à sortir proprement d’une ou plusieurs boucles sans fin à des fins de débogages.

Pour l’exploitation du raspberry Pi en tant que carte embarquée, il peut être préférable de créer au minimum deux threads. L’un des threads traiterait les actionneurs en sortie (plus en moins rapide) et l’autre l’acquisition des capteurs nécessitant un traitement plus rapide (réactivité, stabilité, sécurité, etc…).

Pour répondre à cette problématique, il nous faudrait une structure de la forme :

instance thread_1
instance thread_2
création thread_1
création thread_2
lancement thread_1
lancement thread_2
attente fin thread_1
attente fin thread_2

Notre programme principal instancie, créé et lance les threads puis attend que cela se passe (jusqu’à l’arrêt des deux threads). Bref, couché sur une plage de sable fin, les doigts de pieds en éventail et entrain de « siroter » une boisson fraîche.

Dans les exemples de ce chapitre, nous allons utiliser ce principe. Un des thread affichera nos petits astérisques (sortie) et l’autre attendra une saisie clavier (entrée).

Langage C

Programme

L’exemple se compose des fichiers thread10.c, monProg2.h et monProg2.c.
Pour saisir le programme thread10.c, il faut faire dans la console :

nano thread10.c

Cette commande ouvre un fichier de texte vide appelé thread10.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "monProg2.h"

volatile char leCarac = '\0';

//programme principal
int main(){
    pthread_t monThread_1, monThread_2; //instances thread
    printf("Début programme\n");
    printf("Zone d'initialisation\n\n");
    pthread_create(&monThread_1, NULL, sortie, NULL);
                                        //création du thread
    pthread_create(&monThread_2, NULL, entree, NULL);
                                        //création du thread
    pthread_join(monThread_1, NULL);    //attente fin thread
    pthread_join(monThread_2, NULL);    //attente fin thread
    printf("\nZone libération des ressources\n");
    printf("Fin du programme\n");
    return 0;
}

A la ligne 19, on déclare une variable globale utilisée dans nos threads.
Ligne 23, on crée instances Threads. La création des threads se fait aux lignes 26 et 28 avec l’appel des fonctions à exécuter sortie() et entree().
Aux lignes 30 et 31, on attend la fin des threads.

Pour saisir le programme monProg2.h, il faut faire dans la console :

nano monProg.h

Cette commande ouvre un fichier de texte vide appelé monProg2.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Fichier entête pour monProg1.c
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#ifndef MON_PROG2_H
#define MON_PROG2_H
//prototypes
void* sortie();
void* entree();
#endif

Pour saisir le programme monProg2.c, il faut faire dans la console :

nano monProg.c

Cette commande ouvre un fichier de texte vide appelé monProg2.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Simulation programme raspberry Pi
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#include "monProg2.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern volatile char leCarac; //variable globale

//fonction sortie() affiche *
void* sortie(){
    while(leCarac != 'q'){ //tant que différent de q
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        printf("*"); //affiche des *
        fflush(stdout); //affichage immédiat
        usleep(500000); //attente 500 ms
    }
    return NULL;
}
//fonction entrée saisie clavier
void* entree(){
    while(leCarac != 'q'){ //tant que différent de q
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        printf("q pour quitter !\n");
        leCarac = getchar(); //saisie clavier q+<Entrée>
    }
    return NULL;
}

La fonction sortie() affiche nos petites astérisques tant que le leCarc est différent de ‘q’.
La fonction entree() attend une saisie clavier tant que leCarc est différent de ‘q’.

Exécution du programme

Pour l’exécution, il faudra compiler nos différents programmes par :

gcc -Wall -o thread10 thread10.c monProg2.c -lpthread

Le résultat sera un fichier : thread10

Lancement du programme :

./thread10

Pour sortir de la boucle, il suffit de faire q+<Entrée> au clavier.

L’affichage dans la console sera similaire aux exemples précédents.

Résultat du programme

Vous devriez voir dans votre console un affichage semblable à celui ci :

Début programme
Zone d'initialisation

q pour quitter !
*********************************q**

Zone libération des ressources
Fin du programme

La « Zone d’initialisation » correspond à l’emplacement où l’on peut initialiser les paramètres de nos ports GPIO.
La « Zone libération des ressources » correspond à l’emplacement où l’on libère les ressources de la carte.
**********…….*********** : Le résultat de l’exécution du thread, pourquoi pas une led qui clignote.

Langage C++

Programme

L’exemple se compose des fichiers thread30.cpp, monProg2.h et monProg2.cpp.
Pour saisir le programme thread30.cpp, il faut faire dans la console :

nano thread30.cpp

Cette commande ouvre un fichier de texte vide appelé thread30.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "monProg2.h"

using namespace std;
volatile char leCarac = '\0';           //variable globale pour les threads

//programme principal
int main(){
    pthread_t monThread_1, monThread_2; //instances thread
    cout << "Début programme" << endl;
    cout << "Zone d'initialisation" << endl << endl;
    pthread_create(&monThread_1, NULL, sortie, NULL);
                                        //création du thread
    pthread_create(&monThread_2, NULL, entree, NULL);
                                        //création du thread
    pthread_join(monThread_1, NULL);    //attente fin thread
    pthread_join(monThread_2, NULL);    //attente fin thread
    cout << endl << "Zone libération des ressources" << endl;
    cout << "Fin du programme" << endl;
    return 0;
}

Notre programme est, en tout point, conforme à celui de l’exemple précédent hormis les syntaxes pour l’affichage console.

 Pour saisir le programme monProg2.h, il faut faire dans la console :

nano monProg2.h

Cette commande ouvre un fichier de texte vide appelé monProg2.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Fichier entête pour monProg1.cpp
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#ifndef MON_PROG2_H
#define MON_PROG2_H
//prototypes
void* sortie(void *);
void* entree(void *);
#endif

Pour saisir le programme monProg2.cpp, il faut faire dans la console :

nano monProg2.cpp

Cette commande ouvre un fichier de texte vide appelé monProg2.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme de test des threads
Simulation programme raspberry Pi
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#include <cstdio>
#include <unistd.h>
#include <iostream>
#include "monProg2.h"

using namespace std;
extern volatile char leCarac;           //variable globale :(

//fonction sortie() affiche *
void* sortie(void *){
    while(leCarac != 'q'){              //tant que différent de q
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        cout << "*" << flush;           //affiche immédiatement les *
        usleep(500000);                 //attente 500 ms
    }
    return NULL;
}
//fonction entrée saisie clavier
void* entree(void *){
    while(leCarac != 'q'){              //tant que différent de q
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        cout << "q pour quitter !" << endl;
        leCarac = getchar();            //saisie clavier q+<Entrée>
    }
    return NULL;
}

Les commentaires du programme et ceux des exemples précédents sont suffisants à la compréhension.

Exécution du programme

Pour l’exécution, il faudra compiler nos différents programmes par :

g++ -Wall -o thread30 thread30.cpp monProg2.cpp -lpthread

 Le résultat sera un fichier : thread30

Lancement du programme :

./thread30

Pour sortir de la boucle, il suffit de faire q+<Entrée> au clavier.

L’affichage dans la console sera similaire aux exemples précédents.

Résultat du programme

Vous devriez voir dans votre console un affichage semblable à celui ci :

Début programme
Zone d'initialisation

q pour quitter !
*********************************q**

Zone libération des ressources
Fin du programme

Remarque : Les puristes C++ auraient utilisés la bibliothèque thread à la place de thread.h et chrono à la place unistd.h. Mais je ne suis pas à un blasphème près.

Langage Python

Programme

Notre programme se compose de deux fichiers thread70.py et monProg2.py.
Pour saisir le programme monProg2.py, il faut faire dans la console :

nano monProg2.py

Cette commande ouvre un fichier de texte vide appelé monProg2.py (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme de test des threads
Fonctions d'affichage des * et saisie clavier
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
Remarques           : 

"""
import sys
import time
from thread70 import leCarac            #importe la variable globale

def sortie():
    """affichage * dans la console"""
    global leCarac
    while(leCarac != 'q'):              #boucle tant que leCarac différent de q
        #
        #on pourra mettre dans la boucle notre programme raspberry Pi
        #
        sys.stdout.write("*")           #affiche *
        sys.stdout.flush()              #affichage immédiat
        time.sleep(0.5)                 #attente 500 msec
        
def entree():
    """saisie caractère au clavier"""
    global leCarac
    while(leCarac != 'q'):              #boucle tant que leCarac différent de q
        #
        #on pourra mettre dans la boucle notre programme raspberry Pi
        #
        leCarac = input()               #saisie caractère

Ce fichier contient les deux fonctions exécutées par les threads.

Pour saisir le programme thread70.py, il faut faire dans la console :

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme de test des threads
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :

"""
import sys
import time
from threading import Thread
from monProg2 import *

leCarac = '\0'                          #variables globale

class MonThread(Thread):
    """Lanceur de fonction"""
    def __init__(self, fonction):
        Thread.__init__(self, None, fonction)
        self._fonction = fonction
        self.running = True

    def run(self):
        while self.running:
            self._fonction()            #notre fonction programme

    def stop(self):
        self.running = False

if __name__ == '__main__':
    """Programme principal"""
    print("Début programme")
    print("Zone d'initialisation")
    print()
    print("q pour quitter !")
    print()

    thread_1 = MonThread(sortie)        #création du thread
    thread_2 = MonThread(entree)
    thread_1.start()                    #lancement du thread
    thread_2.start()
    thread_1.stop()                     #détruit le thread
    thread_2.stop()
#    thread_1.join()                    #attente fin cycle thread
    thread_2.join()

    print()
    print("Zone libération des ressources")
    print("Fin du programme")

Lignes 22 à 34, on retrouve notre classe qui permet de créer, lancer et arrêter nos threads.

Exécution du programme

Pour exécuter se programme, il suffit de lancer la commande ci-dessous (en mode console).

python3 thread70.py

Pour sortir de la boucle, il suffit de faire q+<Entrée> au clavier.

Résultat du programme

Vous devriez voir dans votre console un affichage semblable à celui ci :

Début programme
Zone d'initialisation

q pour quitter !
*********************************q**

Zone libération des ressources
Fin du programme

Led clignotante et threads

Revenons à nos moutons ! Après cet interlude sur ma vision des threads, nous allons les mettre en pratique.

Langage C

Pour cet exemple, nous allons utiliser un thread pour commander notre led et sortir de la boucle infinie par la touche <Entrée> du clavier.

Programme

Le programme est composé des fichier thread20.c, monProg3.h et monProg3.c.
Pour saisir le programme thread20.c, il faut faire dans la console :

nano thread20.c

Cette commande ouvre un fichier de texte vide appelé thread20.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique led clignotante
Led rouge sur GPIO23 (4) via une résistance de 330 ohms
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer 
Remarques           :
----------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "monProg3.h"
#include <wiringPi.h>

//programme principal
int main(){
    pthread_t monThread;                //instance thread
    printf("Led clignotante\n");
    //initialisation port
    wiringPiSetup();                    //pseudo-Arduino
    pinMode(LED, OUTPUT);               //broche en sortie
    //fin initialisation port
    printf("\ntouche <Entrée> pour quitter !\n");
    pthread_create(&monThread, NULL, sortie, NULL);
                                        //création du thread
    getchar();                          //attente saisie clavier
    pthread_cancel(monThread);          //supprime le thread
    pthread_join(monThread, NULL);      //attente fin thread
    //libération ressources
    digitalWrite(LED, LOW);             //éteint led
    pinMode(LED, INPUT);                //broche en entrée
    //fin libération ressources
    printf("Fin du programme\n");
    return 0;
}

L’initialisation se fait lignes 26 et 27, et la libération de ressources se fait lignes 36 et 37. Le reste du programme est conforme à la structure du paragraphe 6.1.1.1.4.
La directive LED est déclarée dans le fichier monProg3.h.

Pour saisir le programme monProg3.h, il faut faire dans la console :

nano monProg3.h

Cette commande ouvre un fichier de texte vide appelé monProg3.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique led clignotante
Fichier entête pour monProg3.c
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques           :
----------------------------------------------------------------------------- */
#ifndef MON_PROG3_H
#define MON_PROG3_H
//directives
#define LED 4                           //numéro port led=GPIO23
#define DUREE 500                       //demi-période 500 ms

//prototypes
void* sortie();                         //led clignotante
#endif

Pour saisir le programme monProg3.c, il faut faire dans la console :

nano monProg3.c

Cette commande ouvre un fichier de texte vide appelé monProg3.c (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique led clignotante
Fonction sortie()
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : Bud Spencer
Remarques           :
----------------------------------------------------------------------------- */
#include "monProg3.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>

void* sortie(){
    while(1){                           //boucle infinie
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        digitalWrite(LED, HIGH);        //allume led
        delay(DUREE);                   //attente
        digitalWrite(LED, LOW);         //éteint led
        delay(DUREE);                   //attente
    }
    return NULL;
}

On retrouve ci-dessus que des choses déjà vus.

Exécution du programme

Pour l’exécution, il faudra faire :

gcc -Wall -o thread20 thread20.c monProg3.c -lpthread -lwiringPi

 

Le résultat sera un fichier : thread20

Lancement du programme :

sudo ./thread20

Pour sortir de la boucle, il suffit de faire <Entrée> au clavier.

Miracle, notre led est toujours en vie et clignote dans toute sa spendeur.

Langage C++

Pour cet exemple, nous allons utiliser deux thread pour commander notre led et sortir de la boucle infinie par la touche q+<Entrée> du clavier.

Programme

Le programme est composé des fichiers thread35.cpp, monProg3.h et monProg3.cpp.
Pour saisir le programme thread35.cpp, il faut faire dans la console :

nano thread35.cpp

Cette commande ouvre un fichier de texte vide appelé thread35.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique led clignotante
Led rouge sur GPIO23 (4) via une résistance 330 ohms
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#include <cstdio>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "monProg3.h"
#include <wiringPi.h>

using namespace std;
volatile char leCarac = '\0';           //variable globale pour les threads

//programme principal
int main(){
    pthread_t monThread_1, monThread_2; //instances thread
    cout << "Led clignotante" << endl << endl;
    //initialisation
    wiringPiSetup();                    //pseudo-Arduino
    pinMode(LED, OUTPUT);               //en mode sortie
    //fin initialisation
    pthread_create(&monThread_1, NULL, sortie, NULL);
                                        //création du thread
    pthread_create(&monThread_2, NULL, entree, NULL);
                                        //création du thread
    pthread_join(monThread_1, NULL);    //attente fin thread
    pthread_join(monThread_2, NULL);    //attente fin thread
    //libération ressources
    digitalWrite(LED, LOW);             //éteint led
    pinMode(LED, INPUT);                //broche en entrée
    cout << "Fin du programme" << endl;
    return 0;
}

Pour saisir le programme monProg3.h, il faut faire dans la console :

nano monProg3.h

Cette commande ouvre un fichier de texte vide appelé monProg3.h (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique led clignotante
Fichier entête pour monProg3.cpp
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#ifndef MON_PROG3_H
#define MON_PROG3_H
//directives
#define LED 4                           //numéro port led=GPIO23
#define DUREE 500                       //demi-période en ms
//prototypes
void* sortie(void *);                   //led clignotante
void* entree(void *);                   //saisie clacvier
#endif

Pour saisir le programme monProg3.cpp, il faut faire dans la console :

nano monProg3.cpp

Cette commande ouvre un fichier de texte vide appelé monProg3.cpp (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique led clignotante
Fonctions sortie() et entree()
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#include <cstdio>
#include <unistd.h>
#include <iostream>
#include "monProg3.h"
#include <wiringPi.h>

using namespace std;
extern volatile char leCarac;           //variable globale

//fonction sortie() affiche *
void* sortie(void *){
    while(leCarac != 'q'){              //tant que différent de q
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        digitalWrite(LED, HIGH);        //allume led
        delay(DUREE);                   //attente
        digitalWrite(LED, LOW);         //éteint led
        delay(DUREE);                   //attente
    }
    return NULL;
}
//fonction entrée saisie clavier
void* entree(void *){
    while(leCarac != 'q'){              //tant que différent de q
        //
        //On pourra mettre dans la boucle while notre programme raspberry Pi
        //
        cout << "q pour quitter !" << endl;
        leCarac = getchar();            //saisie clavier q+<Entrée>
    }
    return NULL;
}

Exécution du programme

Pour l’exécution, il faudra faire :

g++ -Wall -o thread35 thread35.cpp monProg3.cpp -lpthread -lwiringPi

Le résultat sera un fichier : thread35

Lancement du programme :

sudo ./thread35

Pour sortir de la boucle, il suffit de faire q+<Entrée> au clavier.

Le résultat est toujours le même, notre led bien aimée clignote !

Langage Python

Pour cet exemple, nous utiliserons à nouveau deux thread pour commander notre led et sortir de la boucle infinie par la touche q+<Entrée> du clavier.
Les plus courageux pourront facilement faire la version mono-thread.

Programme

Notre programme se compose de deux fichiers thread75.py et monProg3.py.
Pour saisir le programme monProg3.py, il faut faire dans la console :

nano monProg3.py

Cette commande ouvre un fichier de texte vide appelé monProg3.py (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme classique led clignotante
Fonctions sortie() et saisie clavier
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
Remarques           : 

"""
import sys
import time
from thread75 import leCarac            #importe la variable globale
import RPi.GPIO as GPIO

def sortie():
    """affichage * dans la console"""
    global leCarac
    GPIO.setmode(GPIO.BCM)
    while(leCarac != 'q'):              #boucle tant que leCarac différent de q
        #
        #on pourra mettre dans la boucle notre programme raspberry Pi
        #
        GPIO.output(23, GPIO.HIGH)      #allume led
        time.sleep(1)                   #attente 1 s
        GPIO.output(23, GPIO.LOW)       #éteint led
        time.sleep(1)                   #attente 1 s
 
def entree():
    """saisie caractère au clavier"""
    global leCarac
    while(leCarac != 'q'):              #boucle tant que leCarac différent de q
        #
        #on pourra mettre dans la boucle notre programme raspberry Pi
        #
        leCarac = input()               #saisie caractère

Pour saisir le programme thread35.py, il faut faire dans la console :

nano thread35.py

Cette commande ouvre un fichier de texte vide appelé thread35.py (pour la sauvegarde faire ctrl+o et pour sortie de l’éditeur faire ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme classique led clignotante
Led rouge sur GPIO23 via une résistance de 330 ohms
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 30/07/2016
date de mise à jour : 30/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
Remarques           : 

"""
import sys
import time
from threading import Thread
from monProg3 import *
import RPi.GPIO as GPIO

leCarac = '\0'                          #variables globale

class MonThread(Thread):
    """Lanceur de fonction"""
    def __init__(self, fonction):
        Thread.__init__(self, None, fonction)
        self._fonction = fonction
        self.running = True
        
    def run(self):
        while self.running:
            self._fonction()            #notre fonction programme
            
    def stop(self):
        self.running = False

def init():
    """initialisation ports"""
    GPIO.setwarnings(False)             #désactive le mode alerte
    GPIO.setmode(GPIO.BCM)              #numérotation ports processeur
    GPIO.setup(23, GPIO.OUT)            #GPIO23 en sortie


if __name__ == '__main__':
    """Programme principal"""
    print("Led clignotante")
    #initialisation
    init()                              #initialisation
    #fin initialisation
    print()
    print("q pour quitter !")
    
    thread_1 = MonThread(sortie)        #création du thread
    thread_2 = MonThread(entree)
    thread_1.start()                    #lancement du thread
    thread_2.start()
    thread_1.stop()                     #détruit le thread
    thread_2.stop()
#    thread_1.join()                     #attente fin cycle thread
    thread_2.join()

    #libération des ressources
    GPIO.output(23, GPIO.LOW)           #éteint led
    GPIO.cleanup()                      #remet les pins en entrée
    #fin libération des ressources
    print("Fin du programme")

Exécution du programme

Pour exécuter ce programme, il faut lancer la commande suivante dans la console Linux :

python3 thread35.py

Pour sortir de l’application, il suffit de faire q+<Entrée> au clavier.

Nota : Pour l’interface avec les ports GPIO, on peut utiliser une des autres bibliothèques adorbées dans la saga blink

Conclusion

L’utilisation des threads n’est pas la panacée universel mais l’une des solutions envisageables dans certains cas.
Et si notre belle led clignotante tombait amoureuse d’un beau Thread ! Dans le cadre de notre class GPIOClassOut, on pourrait imaginer de créer, les méthodes blink(), blink(int tempsAllumage, int tempsExtinction) et blinkStop().

Je fais une addiction à la led qui clignote et il est temps que je me soigne en passant à autre chose, par exemple, la « saga Push Button »

A force de parcourir des tutoriels sur la toile, nous avions noté qu’il existait de nombreux « tutos » très bien faits. Par contre, on constate également que souvent, il manquait le petit bout de quelque « chose » pour que tout se déroule bien.
Ce petit quelque « chose«  que les utilisateurs avertis font sans réfléchir mais qui pose de problème aux débutants. Fort de ce constat, j’ai essayé de faire une présentation un peu différente en y intégrant toutes les étapes de la saisie jusqu’à l’exécution des programmes (Pas très écologique en terme de pages).
Faire des recherches pour comprendre est, en soi, une bonne chose mais je préfère la méthode « à force de répéter cela finira par le faire ».

Toutes les remarques, critiques, suggestions et autres approches sont les bienvenues, à partir du moment où l’on peut les partager avec les autres. Les dénigrements sont également acceptés mais dans le respect de l’autre.

A tous présents et à venir. Salut !

Sources

On pourra télécharger l’ensemble des sources sous :
http://psl.ibidouille.net/Images_forum/raspberryPi/sagaBlinkComp.zip

3 réflexions au sujet de « La Saga Blink Suite : Elle clignote toujours »

  1. Ping : La Saga Blink : Un Raspberry pour faire clignoter une LED ! | Framboise 314, le Raspberry Pi à la sauce française….

  2. Patrice SEIBEL Auteur de l’article

    Bonjour Denis,
    Merci.
    Nano possède également la coloration syntaxique
    Je ne connais pas joe et je viens de faire un test. Plus sympa, il me rappelle wordstar sous dos.
    Finalement le meilleur éditeur de texte et celui que l’on maîtrise.

    Répondre
    1. Patrice Seibel

      Bonjour,
      Merci pour le retour.
      L’usage de l’assembleur pour le Pi n’est pas une chose simple. Cela nécessiterait un investissement de temps non négligeable que je n’ai malheureusement pas.
      Mais bon qui sait !

      Répondre
  3. Ping : Le bouton poussoir un composant banal, ô combien, étonnant. - Framboise 314, le Raspberry Pi à la sauce française....

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Complétez ce captcha SVP *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.