Publié le 23 juillet 2016 - par

La Saga Blink : Un Raspberry pour faire clignoter une LED !

SagaBlink_250pxJe dis toujours : « Avant de vous lancer dans un projet de tondeuse à gazon guidée par GPS avec évitement d’obstacles à laser et retour vidéo, apprenez déjà à allumer une LED 🙂  » …
yell_blEnfin, vous faites comme vous voulez, ce n’est que mon avis… Patrice nous propose dans son premier article pour framboise314 de faire clignoter une LED avec un Raspberry Pi … Un tracteur pour déplacer un œuf me direz vous !
Mais La Saga Blink aborde de nombreuse façons de le faire. Au menu: bash, Python, nodejs, wiringpi, pigpio, Rpi.GPIO …

Introduction

LED_breadboard

Figure 1 : RaspberryPi et sa LED

Rien de neuf sous les tropiques car il existe une multitude de tutoriels, de présentations et autres billets sur le sujet. La présentation s’adresse 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 inutile.
Il faut, à un moment donné, un début.
Faire clignoter une LED sur le Raspberry Pi ou autres cartes consœurs (Arduino, ChipKit, LaunchPad, etc…) est le pendant du traditionnel « Hello World ! » de l’apprentissage d’un langage de programmation.

 Base d’expérimentation.

Pour notre expérimentation, il nous faut :

  • Un raspberry Pi opérationnel,
  • Une LED,
  • Une résistance de 330 Ω (ou entre 330 et 470 Ω).

 Schéma électronique

connexion_LED_shema

Figure 2 : Schéma électronique

L’anode de la diode LED (patte longue) est raccordée à la sortie GPIO23 (broche 16 du connecteur P5).
La cathode (patte courte) est reliée à la masse du Raspberry Pi (Ground), par exemple la pin 20 du connecteur P5.
La résistance R1 sert à limiter le courant traversant la LED. Plus cette résistance est élevée et moins le courant sera élevé. Attention, une résistance trop faible risque de détruire la sortie GPIO par dépassement du courant maximal.

Schéma de câblage

LED_GPIO

Figure 3 : connexion directe Raspberry Pi 3

Le câblage est simple et demande que peu de composants. On peut le réaliser avec un cobbler comme sur la photo de la figure 1 ou par une connexion directe sur le port GPIO du raspberry (voir figure 3).
Le cobbler est un accessoire qui permet de déporter les pins du GPIO vers une plaque d’essai (breadboard).

connexion_LED_photoRemarque : Le RPI3 de la photo figure 3 est équipé de l’écran officiel de la Fondation mais non utilisé dans les expérimentations qui suivent.

Cahier des charges.

Tout programmeur qui se respecte doit disposer ou établir un cahier des charges qui défini les différentes opérations à réaliser. Dans notre cas, il sera très simple.
Notre cahier des charges :

  1. allumer la led,
  2. attendre 1 seconde,
  3. éteindre la led,
  4. attendre 1 seconde,
  5. continuer en 1) (on répète indéfiniment la boucle)

Organigramme

organigramme1L’organigramme est une représentation graphique du déroulement de notre programme. Il comporte les différentes étapes qui permettront une transcription dans un langage donné.

Le premier pavé, qui nous intéresse, est « Initialisation » qui consiste à préparer la pin GPIO23 pour qu’elle puisse piloter la led.

Après cette phase, il faut allumer la LED.

Puis attendre x secondes (dans notre cas 1 sec.).

Après cette attente, on éteint la LED.

Suivi d’une nouvelle attente de x secondes (1 sec. pour notre exemple).

Et finalement, on reprend le cycle en allumant la LED et cela indéfiniment (boucle infinie).

Programmation.

Les différents programmes abordés dans la suite peuvent être exécutés sur toutes les versions du Raspberry Pi (type A, B, jusqu’au RPI3 y compris le Zero).
La saisie des programmes se fait via un éditeur de texte graphique (par exemple geany) ou en mode console (par exemple nano).

5mm-blinking-red-led
L’accès au Raspberry Pi peut se faire via son interface écran HDMI / clavier ou bien par l’intermédiaire d’un connexion à distance (mode console ou graphique).
Pour ma part, j’utilise une connexion console via une liaison SSH.
Dans la suite, nous verrons quelques programmes qui effectuent tous les mêmes actions (allumer / éteindre la LED) mais dans des langages différents.

Bash

Dans l’os Linux tout est « fichier » donc nous ferons des opérations de création, lecture, écriture et suppression de fichiers.

Programme

Pour saisir ce programme, il faut faire dans la console :

 nano blink90.sh 

Cette commande ouvre un fichier texte vide appelé blink90.sh (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
La combinaison Ctrl+o signifie l’appuie sur la touche Ctrl ainsi que la touche o.
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/bin/bash
#Programme classique LED clignotante
#Led rouge sur GPIO23 via une résistance de 330 Ohms
#logiciel            : bash
#cible               : raspberry Pi
#date de création    : 17/06/2016
#date de mise à jour : 18/06/2016
#version             : 1.0
#auteur              : icarePetibles
#référence           : 
#Remarques           : Pour fonctionner, il faut être sous super utilisateur
#                      Il faut rendre le fichier exécutable avec
#                      sudo chmod +x blink90.sh
#                      Pour exécuter le fichier, il faut faire
#                      sudo ./blink90.sh
#
#Attention : Ce script à des effets de bord lorsqu'on interrompt la boucle
#            infinie par Ctrl-C. On a des messages d'errreur lors de la relance
#            du script mais fonctionne néanmoins
#
echo "23" > /sys/class/gpio/export                  #assigne pin
echo "out" > /sys/class/gpio/gpio23/direction       #en sortie
while true;                                         #boucle infinie
  do
    echo "1" > /sys/class/gpio/gpio23/value         #allume led
#    echo "Led allumée"                              #message IHM
    sleep 1;                                        #attente 1 sec
    echo "0" > /sys/class/gpio/gpio23/value         #éteint led
#    echo "Led éteinte"                              #message IHM
    sleep 1;                                        #attente 1 sec
  done
#fin script

Si l’on supprime les lignes de commentaires, il ne reste plus que 9 lignes.
Les commentaires sont importants si l’on souhaite reprendre un programme après quelques jours car notre mémoire n’est pas fiable. Ce qui était évident lors de l’écriture du programme devient incompréhensible. On peut également insérer des remarques concernant l’utilisation du programme (lignes 11 à 20).
Les lignes 21 et 22 correspondent à la phase « Initialisation« .
L’allumage de la LED se fait ligne 25 suivi d’une attente d’une seconde ligne 27.
L’extinction de la led se fait ligne 28 suivi de l’attente ligne 30.
Si l’on dé-commandante les lignes 26 et 29, le programme affiche également l’état de la LED dans la console.

Exécution du programme.

Pour exécuter ce programme bash, il faut le rendre exécutable avec la commande :

sudo chmod +x blink90.sh

Et pour l’exécuter :

sudo ./blink90.sh

Pour sortir de la boucle infinie, il suffit de faire un Ctrl+c au clavier (voir la remarque lignes 17 à 19 du programme).

Python

Le pilotage des ports GPIO, sous Python s’appuie sur des bibliothèques. Les bibliothèques RPi.GPIO et gpiozero sont incluses dans les versions de Python. Nous utiliserons également les bibliothèques pigpio et wiringpi qui devront être installées sous Python.

Rpi.GPIO

Programme

Pour saisir ce programme, il faut faire dans la console :

nano blink01.py

Cette commande ouvre un fichier texte vide appelé blink01.py (pour la sauvegarde faire Ctrl+o et pour sortir 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    : 08/06/2016
date de mise à jour : 08/06/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
import RPi.GPIO as GPIO                 #bibliothèque RPi.GPIO
import time                             #bibliothèque time
#-------------------------------------------------------------------------------
GPIO.setwarnings(False)                 #désactive le mode warning

GPIO.setmode(GPIO.BCM)                  #utilisation des numéros de ports du
                                        #processeur
GPIO.setup(23, GPIO.OUT)                #mise en sortie du port GPIO 23 (broche
                                        #16 du connecteur)
if __name__ == '__main__':
    """
    Programme par défaut
    """
#    print(sys.version)                  #affiche version python
    print("Début du programme LED clignotante")
                                        #message IHM
    while True :                        #boucle infinie
        GPIO.output(23, GPIO.HIGH)      #sortie 23 high
        time.sleep(1)                   #attente 1 seconde
        GPIO.output(23, GPIO.LOW)       #sortie 23 low
        time.sleep(1)                   #attente 1 seconde
#-------------------------------------------------------------------------------

Les lignes 20 à 24 correspondent à la phase « Initialisation ».
L’allumage de la LED se fait ligne 34 suivi d’une attente d’une seconde ligne 35.
L’extinction de la LED se fait ligne 36 suivie de l’attente ligne 37.
La ligne 31 transmet un message console signalant le démarrage du programme.

Exécution du programme

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

python3 blink01.py

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

Commentaire bibliothèque

La documentation concernant cette librairie est faible au niveau de la toile. On trouvera quelques informations sur le site :
https://sourceforge.net/p/raspberry-gpio-python/wiki/Home/

On peut également avoir des informations sous Python par les commandes suivantes :

python3
 >>> import Rpi.GPIO as gp
 >>> help(gp)

Rappel : pour sortir de l’interpréteur python, il suffit de faire Ctrl+d

Remarque : le contenu de cette librairie est étique et ne gère pas les bus I²C ou SPI.

gpiozero

Programme

Pour saisir ce programme, il faut faire dans la console :

nano blink20.py

Cette commande ouvre un fichier texte vide appelé blink20.py (pour la sauvegarde faire Ctrl+o et pour sortir 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    : 09/06/2016
date de mise à jour : 09/06/2016
version             : 1.0
auteur              : icarePetibles
référence           : https://gpiozero.readthedoc.io/en/v1.2.0/
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
from gpiozero import LED                #bibliothèque gpiozero
from time import sleep                  #sleep de la bibliothèque time
#-------------------------------------------------------------------------------
if __name__ == '__main__':
    """
    Programme par défaut
    """
    led = LED(23)                       #instance LED sur GPIO23
    while True:                         #boucle infinie
        led.on()                        #allume led
        sleep(0.5)                      #pause 0.5 sec
        led.off()                       #éteind led
        sleep(0.5)                      #pause 0.5 sec
#-------------------------------------------------------------------------------

La ligne 24 correspond à la phase « Initialisation ».
L’allumage de la LED se fait ligne 26 suivi d’une attente d’une demi-seconde ligne 27. L’extinction de la LED se fait ligne 28 suivi de l’attente ligne 29.

Exécution du programme

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

python3 blink20.py

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

Commentaire bibliothèque

La documentation pour cette librairie peut être consultée sur le site :
https://gpiozero.readthedocs.io/en/v1.2.0/
On peut également avoir quelques informations supplémentaires par les commandes suivantes :

python3
>>> import gpiozero
>>> help(gpiozero)

Rappel : pour sortir de l’interpréteur Python, il suffit de faire Ctrl+d

Remarque : le contenu de cette librairie est nettement plus riche en méthodes que la précédente et gère le bus I²C ou SPI.

wiringpi

Programme

Pour utiliser la bibliothèque wiringpi, il faut l’installer au préalable. On trouvera la procédure l’installation sous le lien :
https://github.com/WiringPi/WiringPi-Python/
Pour saisir ce programme, il faut faire dans la console :

nano blink60.py

Cette commande ouvre un fichier texte vide appelé blink60.py (pour la sauvegarde faire Ctrl+o et pour sortir 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    : 21/06/2016
date de mise à jour : 21/06/2016
version             : 1.0
auteur              : icarePetibles
référence           : wiringpi.com
Remarques           : 
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
import wiringpi                         #bibliothèque wiringpi
#-------------------------------------------------------------------------------
if __name__ == '__main__':
    """
    Programme par défaut
    """
    print("\nDébut du programme LED clignotante")
                                        #messages IHM
    LED = 4                             #sortie LED sur GPIO23 = 4 mode wiringpi
    DUREE = 1000                        #durée demi période = 1 sec
    ON = 1
    OFF = 0
    wiringpi.wiringPiSetup()            #mode wiringpi ou "pseudo Arduino"
    wiringpi.pinMode(LED, 1)            #pi en sortie sortie
    wiringpi.digitalWrite(LED, OFF)     #led éteinte
    while True:                         #boucle infinie
        wiringpi.digitalWrite(LED, ON)  #allume led
        wiringpi.delay(DUREE)           #attente DUREE
        wiringpi.digitalWrite(LED, OFF) #éteind led
        wiringpi.delay(DUREE)           #attente DUREE
#-------------------------------------------------------------------------------

Les lignes 30 à 32 correspondent à la phase « Initialisation ».
L’allumage de la LED se fait ligne 34 suivi d’une attente d’une seconde ligne 35.
L’extinction de la LED se fait ligne 36 suivi de l’attente ligne 37.
La ligne 24 transmet un message console signalant le démarrage du programme.

Exécution du programme

Pour exécuter ce programme, il faut lancer la commande suivante dans la console Linux avec les privilèges root :

sudo python3 blink60.py

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

Commentaire bibliothèque

La documentation pour cette librairie peut être consultée sur le site :
http://wiringpi.com/reference/

On peut également avoir quelques informations supplémentaires par les commandes suivantes :

python3
>>> import wiringpi
>>> help(wiringpi)

Rappel : pour sortir de l’interpréteur python, il suffit de faire Ctrl+d

Remarque : le contenu de cette librairie est également très riche en méthodes et gère le bus I²C ou SPI.

Langage C

Le pilotage des ports GPIO, sous C s’appuie sur la bibliothèque wiringPi. L’installation de cette bibliothèque et décrite sur le site de wiringPi sous le lien : http://wiringpi.com/download-and-install/

wiringPi

Programme

Pour saisir ce programme, il faut faire dans la console :

nano blink80.c

Cette commande ouvre un fichier texte vide appelé blink80.c (pour la sauvegarde faire Ctrl+o et pour sortir 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            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 21/06/2016
date de mise à jour : 22/06/2016
version             : 1.0
auteur              : icarePetibles
référence           : www.wiringpi.com
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
Bibliothèques
----------------------------------------------------------------------------- */
#include <stdio.h>                     //utilisé pour printf()
#include <wiringPi.h>                  //bibliothèque wiringPi
//------------------------------------------------------------------------------
#define LED 4                          //numéro led = GPIO23
int main(void){                        //programme principale
    printf("Led clignotante\n");       //IHM
    wiringPiSetup();                   //numérotation wiringPi ou "pseudo Arduino"
    pinMode(LED, OUTPUT);              //pin en sortie
    for(;;){                           //boucle infinie
        digitalWrite(LED, HIGH);       //allume led
        delay (500);                   //attente 0.5 sec
        digitalWrite(LED, LOW);        //éteint led
        delay (500);                   //attente 0.5 sec
    }
    return(0);                         //code sortie
}
//------------------------------------------------------------------------------

Les lignes 23 et 24 correspondent à la phase « Initialisation ».
L’allumage de la LED se fait ligne 26 suivi d’une attente de 0.5 seconde ligne 27.
L’extinction de la LED se fait ligne 28 suivie de l’attente ligne 29.
La ligne 22 transmet un message console signalant le démarrage du programme.

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) :

gcc -Wall -o blink80 blink80.c -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.

Commentaire bibliothèque

La documentation pour cette librairie peut être consultée sur le site :
http://wiringpi.com/reference/

Cette bibliothèque est la même que celle utilisée au paragraphe 4.3 mais qui elle était adaptée à Python.

Perso

Une petite récréation avec une bibliothèque GPIO personnelle qui n’apporte rien de particulier et elle est même un tantinet « capillotracté ».

La bibliothèque se compose de 2 fichiers ipsGPIO.h (fichier entête) et ipsGPIO.c (fichier fonctions) qui sont utilisés dans le programme blink50.c pour piloter le port GPIO du Raspberry Pi.

Programme

Bibliothèque perso

Pour saisir ce programme ipsGPIO.h, il faut faire dans la console :

nano ipsGPIO.h

Cette commande ouvre un fichier texte vide appelé ipsGPIO.h (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique LED clignotante
Fichier entête de ipsGPIO.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    : 26/06/2016
date de mise à jour : 28/06/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
#ifndef IPS_H
#define IPS_H
//directives constantes
#define ENTREE 0
#define SORTIE 1
#define DESACTIVE 2
#define HAUT 1
#define BAS 0
#define VRAI 1
#define FAUX 0
//prototypes fonctions
void afficheLn(const char * nom);      //eq. println()
void affiche(const char * nom);        //eq. print()
void modeBroche(int, int);             //eq. pinMode()
void ecritureDigitale(int, int);       //eq. digitalWrite()
void dormir(unsigned int);             //eq. delay()
unsigned long int mTemps(void);        //eq. millis()
#endif

Ce fichier contient les définitions des constantes et les prototypes des fonctions.
Pour saisir ce programme ipsGPIO.c, il faut faire dans la console :

nano ipsGPIO.c

Cette commande ouvre un fichier texte vide appelé ipsGPIO.c (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

/* -----------------------------------------------------------------------------
Programme classique LED clignotante
Fichier bibliothèque ipsGPIO.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    : 26/06/2016
date de mise à jour : 28/06/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
Bibliothèques
----------------------------------------------------------------------------- */
#include <stdio.h>                     //bibliothèque entrées/sorties
#include <string.h>                    //manipulation chaîne
#include <stdlib.h>                    //conversion nombre et autres
#include <unistd.h>                    //types et constantes
#include "ipsGPIO.h"                   //bibliothèque ipsGPIO
/* ----------------------------------------------------------------------------
Fonction affichage avec retour ligne suivant
SYNTAXE : afficheLn("texte")
eq. println()
---------------------------------------------------------------------------- */
void afficheLn(const char * nom){
    printf("%s\n", nom);               //IHM
}
/* ----------------------------------------------------------------------------
Fonction affichage sans retour ligne suivant
SYNTAXE : affiche("texte")
eq. print()
---------------------------------------------------------------------------- */
void affiche(const char * nom){
    printf("%s", nom);                 //IHM
}
/* ----------------------------------------------------------------------------
Fonction définition du mode de fonctionnement de la broche
SYNTAXE : modeBroche(BROCHE, MODE)
BROCHE  : Port GPIOXX
MODE    : ENTREE = 0, SORTIE = 1 ou DESACTIVEE = 2
eq. pinMode()
---------------------------------------------------------------------------- */
void modeBroche(int broche, int mode){
    char bufferBroche[10];             //buffer de conversion
    sprintf(bufferBroche, "%d", broche);
                                       //conversion int en string
    char commande[50] = "";            //buffer commande

    if(mode == 1){			           //broche en sortie
        //commande bash pour assigner le port
        //echo PIN > /sys/class/gpio/export
        strcpy(commande, "echo ");     //composition commande par concaténation
        strcat(commande, bufferBroche);//composition commande
        strcat(commande, " > /sys/class/gpio/export");
                                       //composition commande
        system(commande);              //envoi commande système
        //commande bash pour assigner le port en sortie
        //echo out > /sys/class/gpio/gpioPIN/direction
        strcpy(commande, "echo out > /sys/class/gpio/gpio");
                                       //composition commande par concaténation
        strcat(commande, bufferBroche);//composition commande
        strcat(commande, "/direction");//composition commande
        system(commande);              //envoi commande système

    } else if(mode == 2){		       //broche déactivée

        //commande bash pour désactiver le port
        //echo PIN > /sys/class/gpio/unexport
        strcpy(commande, "echo ");
        strcat(commande, bufferBroche);
        strcat(commande, " > /sys/class/gpio/unexport");
        system(commande);

    } else {				           //broche en entrée *** en attente ***
//        //commande bash pour assigner le port
//        //echo PIN > /sys/class/gpio/export
//        strcpy(commande, "echo ");     //composition commande par concaténation
//        strcat(commande, bufferBroche);//composition commande
//        strcat(commande, " > /sys/class/gpio/export");
//                                       //composition commande
//        system(commande);              //envoi commande système
//        //commande bash pour assigner le port en entrée
//        //echo in > /sys/class/gpio/gpioPIN/direction
//        strcpy(commande, "echo in > /sys/class/gpio/gpio");
//                                       //composition commande par concaténation
//        strcat(commande, bufferBroche);//composition commande
//        strcat(commande, "/direction");//composition commande
//        system(commande);              //envoi commande système
    }
}
/* ----------------------------------------------------------------------------
Fonction écriture état de sortie de la broche
SYNTAXE : ecritureDigitale(BROCHE, ETAT)
BROCHE  : XX (Port GPIOXX)
ETAT    : HAUT = 1 = 3.3V ou BAS = 0 = 0V
eq. digitalWrite()
---------------------------------------------------------------------------- */
void ecritureDigitale(int broche, int etat){
    char bufferBroche[10];             //buffer de conversion
    sprintf(bufferBroche, "%d", broche);
                                       //conversion int en string
    char commande[50] = "";            //buffer commande
    if(etat == 1){                     //état HAUT
        //commande bash pour état haut
        //echo 1 > /sys/class/gpio/gpioPIN/value
        strcpy(commande, "echo 1 > /sys/class/gpio/gpio");
                                       //composition commande par concaténation
        strcat(commande, bufferBroche);//composition commande
        strcat(commande, "/value");    //composition commande
        system(commande);              //envoi commande système
    } else {                           //état BAS
        //commande bash pour état bas
        //echo 0 > /sys/class/gpio/gpioPIN/value
        strcpy(commande, "echo 0 > /sys/class/gpio/gpio");
                                       //composition commande par concaténation
        strcat(commande, bufferBroche);//composition commande
        strcat(commande, "/value");    //composition commande
        system(commande);              //envoi commande système
    }
}
/* ----------------------------------------------------------------------------
Fonction attente blocante
SYNTAXE : dormir(TEMPS)
TEMPS   : XX (en milli-seconde)
eq. delay()
---------------------------------------------------------------------------- */
void dormir(unsigned int temps){
	temps = temps * 1000;              //temps en micro-seconde
	usleep(temps);                     //attente
}
/* ----------------------------------------------------------------------------
Fonction retourne le temps système
SYNTAXE : TEMPS = mTemps()
TEMPS   : XX (en milli-seconde)
eq. millis()
---------------------------------------------------------------------------- */
unsigned long int mTemps(void){
    unsigned long int temps = 0;       //variable enttière
    double uptime, idleTime;           //variables décimales
    FILE* fp;                          //variable fichier
    fp = fopen("/proc/uptime", "r");   //ouverture fichier en lecture
    fscanf(fp, "%lf %lf\n", uptime, idleTime);
                                       //lecture données
    fclose(fp);                        //fermeture fichier
    temps = (unsigned long int)(uptime * 1000);
                                       //mise en forme sec en msec
    return temps;                      //retour temps
}
/* ------------------------------------------------------------------------- */

Le principe de ce programme est relativement simple puisqu’on appelle des commandes « bash » à partir d’un programme en C (system(commande)).
Les commentaires du programme sont auto-suffisants pour la compréhension.

Programme blink

Pour saisir ce programme blink50.c, il faut faire dans la console :

nano blink50.c

Cette commande ouvre un fichier texte vide appelé blink50.c (pour la sauvegarde faire Ctrl+o et pour sortir 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
os                  : RPi Linux 4.4.13+ (Jessie)
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 entrées/sorties
#include "ipsGPIO.h"                    //bibliothèque ipsGPIO

#define LED 23                          //led sur GPIO23

int main(void){                         //programme principal
    affiche("Led clignotante");         //IHM
    afficheLn(" by icarePetibles");     //IHM
    modeBroche(LED, SORTIE);            //GPIO23 en sortie
    for(;;){                            //boucle infinie
        ecritureDigitale(LED, HAUT);    //allume led
        dormir(1000);                   //attente
        ecritureDigitale(LED, BAS);     //éteint led
        dormir(1000);                   //attente
    }
    return 0;                           //code sortie
}

La syntaxe utilisée est proche de celle de wiringPi ou Arduino mais en français.
La ligne 25 correspondent à la phase « Initialisation ».
L’allumage de la LED se fait ligne 27 suivi d’une attente d’une seconde ligne 28.
L’extinction de la LED se fait ligne 29 suivie de l’attente ligne 30.
Les lignes 23 et 24 transmettent des messages console signalant le démarrage du programme.

Exécution du programme

Pour exécuter ce 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 :

gcc -c ipsGPIO.c
 gcc -c blink50.c

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

gcc -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

Commentaire bibliothèque

Cette bibliothèque n’a rien d’extraordinaire mais montre uniquement que l’on peut arriver à ses fins avec un peu d’imagination et peu de moyens.

Comme souvent les solutions ou les erreurs se trouvent localisées entre la chaise et le clavier.

Cette bibliothèque fera certainement l’objet de mise à jour lors d’une autre « Saga ».

Conclusion intermédiaire

La première partie de notre expérimentation se termine. On aurait pu faire la même chose avec d’autres langages de programmation.
Les programmes réalisés ne me conviennent pas, principalement pour les raisons suivantes :

  • Lorsqu’on sort de la boucle infinie par une sortie sauvage du genre Ctrl+c, on abandonne la boucle en laissant la sortie GPIO dans un état incertain (ce n’est pas très propre)
  • Le temps d’attente dans les boucles est du type bloquant, c’est-à-dire que la tâche attend la fin avant de faire autre chose. On peut admettre ce type de programmation pour une démonstration mais pas dans un programme réel.
  • Si on avait réalisé d’autres traitements informatiques dans la boucle sans fin, ils auraient subit des retards d’exécution à cause des attentes bloquantes de la boucle.

On peut corriger cette situation par les programmes qui suivent.

Organigramme

organigramme2

Figure 5 : Organigramme

Il comporte les différentes étapes qui permettront une transcription dans un langage donné.
Le premier pavé, qui nous intéresse, est « Initialisation » qui consiste à préparer la pin GPIO23 pour qu’elle puisse piloter la LED.
Après cette phase, on teste si un caractère a été saisi au clavier, si c’est le cas, on sort de la boucle sans fin en éteignant la LED et on désalloue la ressource GPIO.
Dans le cas contraire, on teste si la LED a été allumée ou éteinte pendant un temps égal ou supérieur à DUREE.
Si c’est le cas, on permute l’état de la LED.
Dans le cas contraire, on peut traiter une autre tâche, puis on boucle pour refaire les mêmes opérations.

Bash

Programme

Pour cette partie du programme qui traite des valeurs décimales, il y a lieu d’installer le paquet bc pour que bash puisse faire les traitements correspondants.

sudo apt-get update
 sudo apt-get install bc

Pour saisir ce programme, il faut faire dans la console :

nano blink93.sh

Cette commande ouvre un fichier texte vide appelé blink93.sh (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/bin/bash
#Programme classique LED clignotante
#Led rouge sur GPIO23 via une résistance de 330 Ohms
#Ajout Gestion Ctrl-C
#Ajout attente non bloquante
#Ajout vérification mode super utilisateur
#logiciel            : bash
#cible               : raspberry Pi
#date de création    : 18/06/2016
#date de mise à jour : 18/07/2016
#version             : 1.0
#auteur              : icarePetibles
#référence           : 
#Remarques           : Pour fonctionner, il faut être sous super utilisateur
#                      Il faut rendre le fichier exécutable avec
#                      sudo chmod +x blink93.sh
#                      Pour exécuter le fichier, il faut faire
#                      sudo ./blink93.sh
#
LEDPIN=23                                           #GPIO23
OFF=0                                               #variable éteindre
ON=1                                                #variable allumée
DUREE=1000                                          #demi-période
ETATLED=0                                           #led éteinte
#vérification si accès root
#if [ $EUID -ne 0 ]                                  #si $EUID différent de 0
if [ $EUID != "0" ]                                 #si $EUID différent de 0
then                                                #alors
    echo "Il faut être root pour exécuter le script. Essaye sudo $0"
    exit                                            #sortie
fi                                                  #fin if

#Procédure de netoyage, éteind led, désactive la sortie
cleanup()
{
    PIN=$1                                          #paramètre transmis
#    echo $PIN                                       #affiche paramètre transmis
                                                    #dans notre cas 23
    echo $OFF > /sys/class/gpio/gpio$PIN/value      #led éteinte
    echo $PIN > /sys/class/gpio/unexport            #désactive port
    echo                                            #esthétique
    echo Interruption                               #message IHM
    echo Led éteinte et pin désactivée              #message IHM
    echo Fin script                                 #message de fin
    exit                                            #sortie
}
#lecture temps
function mTemps()
{
    ligne=`cat /proc/uptime`                        #lit uptime et idletime
                                                    #valeurs décimales
    mTemps=$(echo "$ligne" | cut -f 1 -d ' ')       #extrait uptime
    mTemps=$(echo "$mTemps*1000" |bc)               #multiplie par 1000 pour
                                                    #avoir des msec
    mTemps=${mTemps%%.*}                            #float to int
    return $mTemps                                  #valeur mTemps
}
#programme principal
echo Led clignotante                                #message de début
echo ctrl-c pour sortir de la boucle                #IHM
#Setup pin et direction - Cature Control-C SIGHUP SIGKILL
echo $LEDPIN > /sys/class/gpio/export               #assigne pin 23
echo out > /sys/class/gpio/gpio$LEDPIN/direction    #pin 23 en sortie
#trap "cleanup $LEDPIN" 1 2 15                       #capture SIGNAL
trap "cleanup $LEDPIN" SIGHUP SIGINT SIGTERM        #capture SIGNAL et lance la
                                                    #la procédure cleanup avec
                                                    #le paramètre 23
mTemps                                              #lecture référence temps
valeurPrecedente=$mTemps                            #sauve temps msec
while true                                          #boucle infinie
  do                                                #faire
    mTemps                                          #lecture référence temps
    valeurActuelle=$mTemps                          #sauve temps msec
    let "diff=$valeurActuelle - $valeurPrecedente"  #calcule durée état
    if [ $diff -ge $DUREE ]                         #si temps écoulé >= DUREE
    then                                            #alors
        valeurPrecedente=$valeurActuelle            #init valeur précédente
        if [ $ETATLED -eq $ON ]                     #si led allumée
        then                                        #alors
            echo $OFF > /sys/class/gpio/gpio$LEDPIN/value
                                                    #éteint led
#            echo Led éteinte                        #affichage console
            ETATLED=$OFF                            #led éteinte
        else                                        #sinon
            echo $ON > /sys/class/gpio/gpio$LEDPIN/value
                                                    #allume led
#            echo Led allumée                        #affichage console
            ETATLED=$ON                             #led allumée
        fi
    fi
    #
    #Autres traitements
    #
  done                                              #fin do
#Fin du script

Les différentes variables sont définies aux lignes 20 à 24, si l’on souhaite modifier la fréquence du clignotement, il suffit de changer la valeur de DUREE (en milli-seconde).
En ligne 27, on teste si on est en mode « sudo » avec le message ad hoc (pas nécessaire dans notre cas).
La fonction cleanup(), ligne 34, permet une sortie « propre » de la boucle sans fin en éteignant la LED et en désactivant le port.
La fonction mTemps(), ligne 48, permet de mesurer le temps écoulé depuis le démarrage du Raspberry PI. Elle permet de mesurer la durée d’allumage/d’extinction de la LED.
Les lignes 62 et 63 correspondent à la phase « Initialisation ».
La ligne 65 capture le signal Ctrl+c et lance la fonction cleanup avec le paramètre correspondant à la LED.
L’allumage (ligne 85) ou l’extinction (ligne 80) de la LED est réalisé lorsque la différence entre valeurPrecedente et valeurActuelle est supérieure ou égale à DUREE.

Exécution du programme

Pour exécuter ce programme bash, il faut le rendre exécutable avec la commande :

sudo chmod +x blink93.sh

Et pour l’exécuter :

sudo ./blink93.sh

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

Python

Rpi.GPIO

Programme

Pour saisir ce programme, il faut faire dans la console :

nano blink04.py

Cette commande ouvre un fichier texte vide appelé blink04.py (pour la sauvegarde faire Ctrl+o et pour sortir 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
Ajout d'une possibilité de sortie de la boucle sans fin
Ajout temporisation non bloquante
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 08/06/2016
date de mise à jour : 19/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : 
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
import RPi.GPIO as GPIO                 #bibliothèque RPi.GPIO
import time                             #bibliothèque time
#-------------------------------------------------------------------------------
if __name__ == '__main__':
    """
    Programme par défaut
    """
#-------------------------------------------------------------------------------
# Constantes
#-------------------------------------------------------------------------------
    DUREE = 0.5                         #durée demi période = 0.5 sec
    LED = 23                            #sortie LED sur GPIO23
#-------------------------------------------------------------------------------
    GPIO.setwarnings(False)             #désactive le mode warning
    GPIO.setmode(GPIO.BCM)              #utilisation des numéros de ports du
                                        #processeur
    GPIO.setup(LED, GPIO.OUT)           #mise en sortie du port GPIO 23 (broche
                                        #16 du connecteur)
    print("\nDébut du programme LED clignotante")
    print("Arrêt du clignotement par ctrl+c")
                                        #messages IHM
    GPIO.output(LED, GPIO.HIGH)         #initialisation sortie 23 allume led
    etatLed = True                      #led allumée
    previousTime = time.time()          #valeur time précédente
    try:
        while True :                    #boucle infinie
            currentTime = time.time()   #sauve time actuel
            if abs(currentTime - previousTime) >= DUREE:
                                        #si temps écoulé >= à DUREE
                previousTime = currentTime
                                        #nouveau time précédent
                if etatLed:             #si led allumée
                    GPIO.output(LED, GPIO.LOW)
                                        #éteind led
                    etatLed = False     #led éteinte
                else:                   #si led éteinte
                    GPIO.output(LED, GPIO.HIGH)
                                        #allume led
                    etatLed = True      #led allumée
    #capture du ctrl+c et sortie boucle
    except KeyboardInterrupt:
        GPIO.output(LED, GPIO.LOW)      #Eteint la LED
        GPIO.cleanup()                  #remet toutes pins en entrée
        print("\nFin du programme\n")   #IHM
#-------------------------------------------------------------------------------

La phase « Initialisation » est faite aux lignes 32 à 36.
L’allumage (ligne 55) ou l’extinction (ligne 51) de la LED est réalisé lorsque la différence entre previousTime et currentTime est supérieure ou égale à DUREE.
La ligne 59 capture le signal Ctrl+c qui éteint la LED et libère les ressources GPIO.

Exécution du programme

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

python3 blink04.py

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

gpiozero

Programme

Je déroge un peu de l’organigramme du chapitre 7, sinon on a toujours la même structure du programme. Il existe dans la bibliothèque gpiozero une fonction blink().
Pour saisir ce programme, il faut faire dans la console :

nano blink25.py

Cette commande ouvre un fichier texte vide appelé blink25.py (pour la sauvegarde faire Ctrl+o et pour sortir 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    : 09/06/2016
date de mise à jour : 19/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : https://gpiozero.readthedoc.io/en/v1.2.0/
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
from gpiozero import LED                #bibliothèque gpiozero
#-------------------------------------------------------------------------------
if __name__ == '__main__':
    """
    Programme par défaut
    """
    DUREE = 0.5                         #durée demi-période
    print("\nDébut du programme LED clignotante")
    print("Arrêter le clignotement - ctrl+c")
                                        #messages IHM
    led = LED(23)                       #instance LED sur GPIO23
    led.blink(DUREE, DUREE)             #clignote avec valeur par défaut
    try:
        while True :                    #boucle infinie
            pass                        #circuler, il n'y a rien à voir
    except KeyboardInterrupt:           #capture ctrl+c
        print("\nFin du programme\n")   #IHM
#-------------------------------------------------------------------------------
# Documentation
#-------------------------------------------------------------------------------
#    led.blink(0.01, 1, 10, True)        #voir Documentation (1)
#pause() (attente signal) est remplacé par la boucle infinie while True  
#(1)
#led.blink(on_time=1, off_time=1, n=None, background=True)
#on_time    = nombre de secondes (float) led allumée
#off_time   = nombre de secondes (float) led éteinte
#n          = nombre de clignotement - None = en continu
#background = True (défaut) - démarre une tâche (thread) de clignotement 
#             d'arrière plan et retour
#background = Flase -retour que si le clignotement et fini (att. avec la valeur
#             par défaut de n, on n'aura jamais de retour
#-------------------------------------------------------------------------------

La structure de ce programme est très simple. La phase « Initialisation » se résume à la ligne 27.
Pour le clignotement de la LED, tout est ligne 28. Le reste n’est que de l’habillage et l’attente de capture du Ctrl+c.
L’utilisation de led.blink() fait clignoter la LED avec les paramètres par défaut, c’est à dire en continu avec une demi-période de 1 seconde.

Syntaxe : Led.blink(on_time=1, off_time=1, n=None, background=True)
	on_time = durée d'allumage led (en sec)
	off_time = durée d'extinction led (en sec)
	n = nombre de clignotement (n=None clignotement continu)
	background = principe d'exécution de la tâche
		True (par défaut) = démarre la tâche et retourne
False = retour après la fin du clignotement (Attention : avec n=None et background=False, on n'aura plus la main).

Exécution du programme

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

python3 blink25.py

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

wiringpi

Programme

Pour l’installation de la bibliothèque voir le paragraphe 4.3.1.
Pour saisir ce programme, il faut faire dans la console :

nano blink62.py

Cette commande ouvre un fichier texte vide appelé blink62.py (pour la sauvegarde faire Ctrl+o et pour sortir 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
Ajout sortie boucle infinie et attente non blocante
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 21/06/2016
date de mise à jour : 19/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : www.wiringpi.com
Remarques           : à exécuter avec les privilèges root
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
import wiringpi                         #bibliothèque wiringpi
#-------------------------------------------------------------------------------
if __name__ == '__main__':
    """
    Programme par défaut
    """
    print("\nDébut du programme LED clignotante")
    print("Arrêter le clignotement - ctrl+c")
                                        #messages IHM
    LED = 4                             #sortie LED sur GPIO23 = 4 mode wiringpi
    DUREE = 500                         #durée demi période = 0.5 sec
    ON = 1
    OFF = 0
    wiringpi.wiringPiSetup()            #mode wiringpi ou "pseudo Arduino"
    wiringpi.pinMode(LED, 1)            #pi en sortie sortie
    wiringpi.digitalWrite(LED, OFF)     #led éteinte
    etatLed = False                     #sauve temps précédent (en msec)
    previousTime = wiringpi.millis()
    try:
        while True:                     #boucle infinie
            currentTime = wiringpi.millis()
                                        #sauve temps actuel
            if (currentTime - previousTime) >= DUREE:
                                        #si temps écoulé >= à DUREE (en msec)
                previousTime = currentTime
                                        #sauve temps précédent (en msec)
                if etatLed:             #si led allumée
                    wiringpi.digitalWrite(LED, OFF)
                                        #éteind led
                    etatLed = False     #led éteinte
                else:                   #si led éteinte
                    wiringpi.digitalWrite(LED, ON)
                                        #allume led
                    etatLed = True      #led allumée
    except KeyboardInterrupt:           #capture ctrl+c
        wiringpi.digitalWrite(LED, OFF) #éteind led
        wiringpi.pinMode(LED, 0)        #pin en entrée
        print("\nFin du programme\n")   #IHM
#-------------------------------------------------------------------------------

La structure de ce programme est identique à ceux que l’on a déjà vu jusqu’à présent.

Exécution du programme

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

sudo python3 blink62.py

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

pigpio

Pour utiliser la bibliothèque pigpio, il faut l’installer au préalable. On trouvera la procédure l’installation sous le lien :
http://abyz.co.uk/rpi/pigpio/download.html

Programme

Ce programme, pour changer, utilise une autre méthode pour sortir de la boucle infinie. La saisie non bloquante d’un caractère clavier est incluse dans un module Python indépendant.
Pour saisir ce programme, il faut faire dans la console :

nano saisieCarac.py

Cette commande ouvre un fichier texte vide appelé saisieCarac.py (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Saisie caractère clavier non blocante
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 08/06/2016
date de mise à jour : 16/06/2016
version             : 1.0
auteur              : icarePetibles
référence           : http://home.wlu.edu/~levys/software/kbhit.py
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
import os                               #système d'exploitation
import sys                              #informations système
import termios                          #interface posix et contrôle I/O tty
import atexit                           #nettoyage et enrégistrement fonctions
from select import select               #accès contrôles I/O plateforme
#-------------------------------------------------------------------------------
# Classe KBHit
#-------------------------------------------------------------------------------
class KBHit:
#-------------------------------------------------------------------------------
    def __init__(self):
        """
        Création d'un objet KBHit que l'on peut appeler pour faire différentes
        choses
        """
        #Remarque : On ne traite pas le cas de windows
        #Sauvegade les paramètres du terminal
        self.fd = sys.stdin.fileno()    #la méthode fileno() renvoie le 
                                        #descripteur de fichier d'un objet de
                                        #type fichier
        self.new_term = termios.tcgetattr(self.fd)
        self.old_term = termios.tcgetattr(self.fd)
                                        #retourne une liste contenant les 
                                        #attributs tty pour le descripteur de
                                        #fichier fd
        self.new_term[3] = (self.new_term[3] ~termios.ICANON ~termios.ECHO)
                                        #ICANON désactivé et ECHO désactivé
        termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term)
                                        #fixe les attributs tty pour le 
                                        #descripteur de fichier fd à partir des 
                                        #attributs, qui est une liste comme 
                                        #celle retournée par tcgetattr()
        #Réinitialisation terminal normal et sortie
        atexit.register(self.set_normal_term)
                                        #enrégistre la fonction à exécuter à la
                                        #fin
#-------------------------------------------------------------------------------
    def set_normal_term(self):
        """
        Reset vers le mode normal du terminal
        """
        #Remarque : On ne traite pas le cas de windows
        termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term)
                                        #fixe les attributs tty pour le 
                                        #descripteur de fichier fd à partir des 
                                        #attributs, qui est une liste comme 
                                        #celle retournée par tcgetattr()
#-------------------------------------------------------------------------------
    def getch(self):
        """
        Renvoi le caractère du clavier après un appel KBHit().
        """
        s = ''
        #Remarque : On ne traite pas le cas de windows
        return sys.stdin.read(1)        #lecture du caractère de stdin
#-------------------------------------------------------------------------------
    def kbhit(self):
        """
        Retourne True si un caractère a été frappé au clavier, sinon False
        """
        #Remarque : On ne traite pas le cas de windows
        dr, dw, de = select([sys.stdin], [], [], 0)
        return dr != []                 #True ou False
#-------------------------------------------------------------------------------
#Test
#-------------------------------------------------------------------------------
if __name__ == "__main__":
    kb = KBHit()                        #instance KBHit()
    print("Début du programme")
    print("Appuyer sur une touche, ou ESC pour sortir")

    while True:                         #boucle sans fin
        if kb.kbhit():                  #si touche clavier
            c = kb.getch()              #lecture touche
            if ord(c) == 27:            #si ESC
                break                   #sortie de la boucle sans fin
            print(c)                    #affiche le caractère

    kb.set_normal_term()                #terminal en mode normal
    print("Fin du programme")           #message HIM
#-------------------------------------------------------------------------------

Les lignes 82 à 95 permettent de tester le programme de saisie.
Pour saisir ce programme blink, il faut faire dans la console :

nano blink41.py

Cette commande ouvre un fichier texte vide appelé blink41.py (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
Le contenu du programme et de ees 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
Ajout sortie boucle infinie
Ajout test pigpiod existe
Ajout temporisation non bloquante
logiciel            : python 3.4.2
cible               : raspberry Pi
date de création    : 09/06/2016
date de mise à jour : 19/06/2016
version             : 1.0
auteur              : icarePetibles
référence           : abyz.co.uk/rpi/pigpio/index.html
Remarques           : 
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
from saisieCarac import *               #saisie caractère non blocante
import time                             #bibliothèque time
import pigpio                           #bibliothèque pigpio
import os                               #bibliothèque os
#-------------------------------------------------------------------------------
if __name__ == '__main__':
    """
    Programme par défaut
    """
#Test si pigpiod existe sinon lance sudo pigpiod
    if os.system('pidof pigpiod >/dev/null') == 256:
        os.system('sudo pigpiod >/dev/null')
        print("'sudo pigpiod' lancé par le programme")
#-------------------------------------------------------------------------------
    kb = KBHit()                        #instance KBHit()
    print("\nDébut du programme LED clignotante")
    print("Arrêter le clignotement - appuyer sur 'q'")
                                        #messages IHM
    LED = 23                            #sortie LED sur GPIO23
    DUREE = 0.5                         #durée demi période = 0.5 sec
    ON = 1                              #esthétique
    OFF = 0                             #esthétique
    pi = pigpio.pi()                    #connection à la tâche pigpiod
    pi.set_mode(LED, pigpio.OUTPUT)     #configure pin en sortie
    pi.write(LED, ON)                   #sortie 23 allume led
    etatLed = True                      #led allumée
    previousTime = pi.get_current_tick()
                                        #valeur time précédente (en micro-sec)
    while True:                         #boucle infinie
        if kb.kbhit():                  #test si touche appuiée
            c = kb.getch()              #lecture de la touche
            if c.lower() == "q":        #touche q ou Q
                break                   #sortie de boucle infinie
        currentTime = pi.get_current_tick()
                                        #sauve time actuel (en micro-sec)
        if pigpio.tickDiff(previousTime, currentTime)/1000000.0 >= DUREE:
                                        #si temps écoulé >= à DUREE (en sec)
            previousTime = currentTime  #nouveau time précédent
            if etatLed:                 #si led allumée
                pi.write(LED, OFF)      #éteind led
                etatLed = False         #led éteinte
            else:                       #si led éteinte
                pi.write(LED, ON)       #allume led
                etatLed = True          #led allumée
        
    pi.set_mode(LED, pigpio.INPUT)      #nettoyage
    kb.set_normal_term()                #rétablie le terminal normal
    print("\nFin du programme\n")       #message IHM
    pi.stop()                           #déconnexion
#-------------------------------------------------------------------------------

Pour exécuter ce programme, il faut lancer au préalable une tâche de fond qui assure le contrôle des autres tâches. Si vous l’oubliez, les lignes 31 à 33 le feront pour vous.
Ligne 21, on importe les fonctions pour la saisie non bloquante d’un caractère au clavier.
Les lignes 50 à 53 permettent de sortir de la boucle infinie si l’on saisie ‘q’ ou ‘Q’ au clavier.
Le reste du programme nous est familier.

Exécution du programme

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

python3 blink41.py

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

Commentaire bibliothèque

La documentation pour cette librairie peut être consultée sur le site :
http://abyz.co.uk/rpi/pigpio/python.html

On peut également avoir quelques informations supplémentaires par les commandes suivantes :

python3
>>> import pigpio
>>> help(pigpio)

Rappel : pour sortir de l’interpréteur Python, il suffit de faire Ctrl+d

Graphique tkinter

Un peu de graphisme pour piloter notre LED.

LED_allumee

Figure 6 : LED allumée

LED_eteinte

Figure 7 : LED éteinte

Programme

Pour saisir ce programme, il faut faire dans la console :

nano blink70.py

Cette commande ouvre un fichier texte vide appelé blink70.py (pour la sauvegarde faire Ctrl+o et pour sortir Ctrl+x).
Le contenu du programme et de ses commentaires sont représentés ci-dessous.

#!/usr/bin/python3
# -*- coding:utf-8 -*-
"""
Programme led clignotante avec interface graphique
os                  : RPi Linux 4.4.13+
logiciel            : python3.4.2
cible               : raspberry Pi
date de création    : 25/06/2016
date de mise à jour : 25/06/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
"""
#-------------------------------------------------------------------------------
# Bibliothèques
#-------------------------------------------------------------------------------
from tkinter import *                  #bibliothèque graphique tkinter
import RPi.GPIO as GPIO                #bibliothèque RPi.GPIO
#-------------------------------------------------------------------------------
#variables et constantes
DUREE = 500                            #1/2 période du clignotement led
largeur = 26                           #largeur canvas
hauteur = 26                           #hauteur canvas

ledOn   = '#ff0000'                    #led allumée couleur rouge
ledOff  = '#B1B1B1'                    #led éteinte couleur grise
etatLed = False                        #led éteinte
#-------------------------------------------------------------------------------
#fonctions
#-------------------------------------------------------------------------------
def maj():
    """Bascule état led en fonction de DUREE"""
    global etatLed                     #variable global - pas très orthodose
                                       #mais pour faire simple
    if(etatLed):                       #si led allumée
        etatLed=False                  #led éteinte
        GPIO.output(23, GPIO.LOW)      #sortie 23 low - led éteinte
        des1.itemconfig(lumiere, fill=ledOff)
                                       #affiche la led éteinte
    else:                              #si led éteinte
        etatLed=True                   #led éteinte
        GPIO.output(23, GPIO.HIGH)     #sortie 23 high - led allumée
        des1.itemconfig(lumiere, fill=ledOn)
                                       #affiche la led allumée
    des1.update_idletasks()            #force le rafraîchissement graphique
    des1.after(DUREE, maj)             #appel maj après écoulement DUREE
#-------------------------------------------------------------------------------
def quitter():
    """Quitte l'application"""
    GPIO.output(23, GPIO.LOW)          #sortie 23 low
    GPIO.setup(23, GPIO.IN)            #GPIO23 en entrée
    quit()                             #sortie de mainloop
    destroy()                          #détruit l'objet ainsi que les enfants
#-------------------------------------------------------------------------------
def initialisation():
    """Initialisation"""
    GPIO.setwarnings(False)            #désactive le mode warning
    GPIO.setmode(GPIO.BCM)             #numérotation ports processeur
    GPIO.setup(23, GPIO.OUT)           #sortie sur GPIO23
    GPIO.output(23, GPIO.LOW)          #sortie 23 low
#-------------------------------------------------------------------------------
#programme pricipal
#-------------------------------------------------------------------------------
fen = Tk()                             #instance Tk
fen.title('La saga Blink')             #titre de la fenêtre
fen.iconbitmap('@framboise.xbm')       #icon de l'application
largApplication = 300                  #largeur de l'application
hautApplication = 110                  #hauteur de l'application
largDisplay = fen.winfo_screenwidth()  #largeur de l'écran en pixels
hautDisplay = fen.winfo_screenheight() #hauteur de l'écran en pixels
posX = int((largDisplay - largApplication)/2)
                                       #position X de l'appli pour être centrer
posY = int((hautDisplay - hautApplication)/2)
                                       #position Y de l'appli pour être centrer
fen.geometry('{}x{}+{}+{}'.format(largApplication, hautApplication, posX, posY))
                                       #taille et position de la fenêtre
fen.resizable(False, False)            #ne permet pas le re-dimensionnement
fen.protocol('WM_DELETE_WINDOW', quitter)
                                       #sortie par la petite croix (X)
#-------------------------------------------------------------------------------
#création objets graphiques
#-------------------------------------------------------------------------------
tex1=Label(fen, text='La saga Blink - Led clignotante', font="Tahoma 12 bold", fg="blue")
                                       #label message
tex1.pack(padx=5, pady=5)              #activation graphique

des1=Canvas(fen, width=largeur, height=hauteur, bd=0)
                                       #canvas pour le dessin de la led
center=int(largeur/2)
r=int((largeur-2)/2)
lumiere=des1.create_oval(center-r+1, center-r+1,center+r, center+r, fill=ledOff, outline="")
                                       #dessine led avec couleur éteinte
des1.pack()                            #activation graphique

bou1=Button(fen, text='Quitter', font="Tahoma 10", command=quitter)
                                       #button pour quitter l'application
bou1.pack(padx=5, pady=5)              #activation graphique

tex2=Label(fen, text='icarePetibles ', font="Tahoma 7")
                                        #label auteur 😉
tex2.pack(side=RIGHT)                  #activation graphique
#-------------------------------------------------------------------------------
initialisation()                       #paramètres de départ
maj()                                  #lance le 'Blink'
fen.mainloop()                         #boucle infinie graphique
fen.destroy()                          #destruction de la fenêtre
#-------------------------------------------------------------------------------

Normalement pour ce type de programme, la logique voudrait que l’on crée une classe pour l’application. Mais pour que le programme soit plus lisible, ce n’est pas le cas.
Notre programme comporte trois fonctions (initialisation, quitter et maj).

initialisation() : déclare et initialise le port GPIO via la bibliothèque RPi.GPIO (on aurait pu faire la même chose avec les autres bibliothèques).

quitter() : éteint la LED, libère la ressource port GPIO, sort de la boucle infinie et détruit le graphique. Cette fonction est appelée par le bouton quitter ou la petite croix (à droite et en haut de la fenêtre graphique).

maj() : cette fonction est appelée toutes les DUREE pour permuter l’état de la LED et l’affichage graphique.

Dans les lignes 65 à 78, on construit le support de notre fenêtre application. A la ligne 79, on capture le clic sur la petite croix.
Dans les lignes 84 à 102, on implémente les labels, bouton, canvas et dessin (LED).

Ligne 104 : on lance l’initialisation.
Ligne 105 : on déclenche le clignotement de la LED.
Ligne 106 : on active la boucle infinie graphique.
Ligne 107 : on détruit l’application graphique.

Exécution du programme

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

python3 blink70.py

Pour sortir de la boucle infinie, il suffit de cliquer sur le bouton Quitter ou sur la petite croix.

Langage C

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

Pour saisir ce programme, il faut faire dans la console :

nano saisieCarac.h

Cette commande ouvre un fichier texte vide appelé saisieCarac.h (pour la sauvegarde faire Ctrl+o et pour sortir 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           :
----------------------------------------------------------------------------- */
#ifndef saisieCarac_h
#define saisieCarac_h
/* -----------------------------------------------------------------------------
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
/* -------------------------------------------------------------------------- */
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
}
/* -------------------------------------------------------------------------- */
#endif

Pour saisir le programme blink, il faut faire dans la console :

nano blink81.c

Cette commande ouvre un fichier texte vide appelé blink81.c (pour la sauvegarde faire Ctrl+o et pour sortir 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
Ajout sortie boucle infinie et attente non blocante
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           : www.wiringpi.com
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
Bibliothèques
----------------------------------------------------------------------------- */
#include <stdio.h>                     //bibliothèque entrées/sorties
#include <wiringPi.h>                  //bibliothèque wiringPi
#include "saisieCarac.h"               //fonction saisie caractère non bloquant
#include <ctype.h>                     //bibliothèque pour tolower()
//------------------------------------------------------------------------------
#define LED 4                          //numéro led = GPIO23
#define DUREE 1000
int main(void){                        //programme principal
    int c;                             //stocke touche clavier
    unsigned int valeurActuelle = 0;
    unsigned int valeurPrecedente = 0;
    int etatLed = FALSE;
    printf("Led clignotante\n");       //IHM
    printf("'q' pour arrêter le clignotement\n");
    wiringPiSetup();                   //numérotation wiringPi ou "pseudo Arduino"
    pinMode(LED, OUTPUT);              //pin en sortie
    digitalWrite(LED, LOW);            //led éteinte
    valeurPrecedente = millis();
    for(;;){                           //boucle infinie
        if(kbhit())                    //si touche saisie
            c = getchar();             //lecture touche
        if(tolower(c) == 'q')          //test si 'q' ou 'Q'
            break;                     //sortie de la boucle
        valeurActuelle = millis();
        if(valeurActuelle - valeurPrecedente >= DUREE){
            valeurPrecedente = valeurActuelle;
            if(etatLed){
                digitalWrite(LED, LOW);
                etatLed = FALSE;
            } else {
                digitalWrite(LED, HIGH);
                etatLed = TRUE;
            }
        }
    }

    digitalWrite(LED, LOW);            //éteint led
    pinMode(LED, INPUT);               //pi en entrée
    printf("\nFin du programme\n");    //IHM
    return(0);                         //code sortie
}
//------------------------------------------------------------------------------

Rien de neuf par rapport à ce que l’on a vu dans les programmes précédents.

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) :

gcc -Wall -o blink81 blink81.c -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

Ce programme se compose d’un fichier blink52.c et de deux bibliothèques externes (saisieCarac.h et ipsGPIO.h). La bibliothèque ipsGPIO.h est la même que celle du paragraphe 5.2.

saisieCarac.h et saisieCarac.c

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

nano saisieCarac.h

Cette commande ouvre un fichier texte vide appelé saisieCarac.h (pour la sauvegarde faire Ctrl+o et pour sortir 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.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    : 26/06/2016
date de mise à jour : 28/06/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 saisieCarac.c, il faut faire dans la console :

nano saisieCarac.c

Cette commande ouvre un fichier texte vide appelé saisieCarac.c (pour la sauvegarde faire Ctrl+o et pour sortir 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
}
/* -------------------------------------------------------------------------- */

ipsGPIO.h et ipsGPIO.c

voir paragraphe 5.2.1.1

blink52.c

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

nano blink52.c

Cette commande ouvre un fichier texte vide appelé blink52.c (pour la sauvegarde faire Ctrl+o et pour sortir 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
Ajout attente non blocante
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : gcc (Raspbian 4.9.2-10) 4.9.2
cible               : raspberry Pi
date de création    : 26/06/2016
date de mise à jour : 28/06/2016
version             : 1.0
auteur              : icarePetibles
référence           :
Remarques           :
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
Bibliothèques
----------------------------------------------------------------------------- */
#include <stdio.h>                      //bibliothèque entrées/sorties
#include <ctype.h>                      //manipulation caractères
#include "ipsGPIO.h"                    //bibliothèque ipsGPIO
#include "saisieCarac.h"                //saisie caractère non blocant

#define DUREE 500                       //1/2 période clignotant
#define LED 23                          //led sur GPIO23

int main(void){                         //programme principal
    int c;                              //caractère clavier
    unsigned long int valeurActuelle = 0;
                                        //sauve temps actuel
    unsigned long int valeurPrecedente = 0;
                                        //sauve temsp précédent
    int etatLed = FAUX;                 //led éteinte
    affiche("Led clignotante");         //IHM
    afficheLn(" by icarePetibles");     //IHM
    afficheLn("'q' ou 'Q' pour sortir");//IHM
    modeBroche(LED, SORTIE);            //GPIO23 en sortie
    ecritureDigitale(LED, BAS);         //éteind led
    valeurPrecedente = mTemps();        //temps
    for(;;){                            //boucle infinie
        if(kbhit())                     //si touche saisie
            c = getchar();              //lecture touche
        if(tolower(c) == 'q')           //test si 'q' ou 'Q'
            break;                      //sortie boucle
        valeurActuelle = mTemps();      //temps
        if(valeurActuelle - valeurPrecedente >= DUREE){
                                        //si temps écoulé supérieure DUREE
            valeurPrecedente = valeurActuelle;
                                        //temps
            if(etatLed){                //si led allumée
                ecritureDigitale(LED, BAS);
                                        //éteind la led
                etatLed = FAUX;         //led éteinte
            }else{                      //si led éteinte
                ecritureDigitale(LED, HAUT);
                                        //éteind la led
                etatLed = VRAI;         //led éteinte
            }                           //fin (etat led)
        }                               //fin test DUREE
    }                                   //fin boucle infinie
    ecritureDigitale(LED, BAS);         //éteind led
    modeBroche(LED, DESACTIVE);         //désactive pin LED
    afficheLn("\nFin du programme");    //IHM
    return 0;                           //code sortie
}                                       //fin programme

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 :

gcc -c ipsGPIO.c
gcc -c saisieCarac.c
gcc -c blink52.c

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

gcc -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 q ou Q au clavier.

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

rm *.o

Node.js

Un langage qui fait beaucoup parler et qui devient de plus en plus populaire (à surveiller). C’est quoi node.js ? C’est simplement du Javascript mais côté serveur contrairement à la version classique qui s’exécute côté client. Pour en savoir plus, il suffit de consulter les tutoriels sur le net ou des ouvrages spécialisés.

Ce langage est séduisant et l’on peut créer un serveur web en 3 à 4 lignes.

Pour ma part, je suis relativement « étanche » à ce langage et, mes vieux neurones ont du mal à s’adapter, aux fonctions avec des fonctions en paramètres qui s’exécutent de manière non bloquantes.

Pour notre application, nous n’utiliserons pas le concept serveur web mais comme un langage traditionnel.

Programme

Le programme utilise un module complémentaire « onoff« . La procédure d’installation ainsi que la documentation sont disponibles sous le lien :
https://www.npmjs.com/package/onoff

Pour les plus curieux, on trouvera sous https://www.npmjs.com/, la liste impressionnante des modules disponibles.

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

nano blink02.js

Cette commande ouvre un fichier texte vide appelé blink02.js (pour la sauvegarde faire Ctrl+o et pour sortir 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
os                  : RPi Linux 4.4.13+ (Jessie)
logiciel            : node v0.12.6
cible               : raspberry Pi
date de création    : 26/06/2016
date de mise à jour : 20/07/2016
version             : 1.0
auteur              : icarePetibles
référence           : https://www.npmjs.com/package/onoff
Remarques           :
----------------------------------------------------------------------------- */
var Gpio = require('onoff').Gpio,      //module onoff
    led = new Gpio(23, 'out');         //led sur GPIO23 et en sortie

DUREE = 500                            //demi-période clignotement (msec)

console.log('Début programme led clignotante');
console.log("'Sortie de la boucle infinie par ctrl+c'");
                                       //IHM

var iv = setInterval(function(){       //appel toutes les x milli-sec
    led.writeSync(led.readSync() === 0 ? 1 : 0)
}, DUREE);                               //durée de répétition

function exit(){                       //sortie de la boucle infinie
    clearInterval(iv);                 //arrêt clignotement
    led.writeSync(0);                  //éteint led
    led.unexport();                    //unexport GPIO et libère la resssource
    console.log('\nFin programme');    //IHM
    process.exit();                    //arrêt node
}
process.on('SIGINT', exit);            //capture du ^C et exécute exit()

Exécution programme

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

node blink02.js

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

Conclusion

La saga pourrait continuer pendant des semaines et des semaines ou des pages et des pages. Finalement on va se trouver dans une situation de bis repetita.

On aurait pu utiliser d’autres langages (console ou graphique) pour commander notre port GPIO, comme Java, Scratch, Node-RED, C++, Pascal, Fortran, PHP, Javascript, etc…

green_blMais tout à une fin.

Peut être à bientôt pour une prochaine saga (pushButton, I2C, SPI, 1-Wire, interruption, etc…)

La saga continue : Complément à la première partie de la saga Blink

Sources

Vous pouvez télécharger l’ensemble des sources ici :
http://psl.ibidouille.net/Images_forum/raspberryPi/sagaBlink.zip

Share Button

67 réflexions au sujet de « La Saga Blink : Un Raspberry pour faire clignoter une LED ! »

  1. Ping : RaspberryPi | Pearltrees

        1. gUI

          plus simple ? tu rappelles comment on calcule les valeurs en fonction de la fréquence du clignotement ?

          c’est plus simple pour celui qui sait, mais c’est pas « universellement » plus simple. par exemple moi je préfère de loin les petits microcontrôleurs à $1, c’est 4 lignes de code, et pas besoin de calculatrice 🙂

          Répondre
    1. icare

      Bonjour,
      Je pense qu’il est dépassé. On trouve, du côté du soleil levant, des petites cartes à microcontrôleur qui seront bientôt moins cher que le NE555.
      On a changé d’époque et ce n’est pas fini. 😉
      🙂

      Répondre
  2. S.POURRE

    Bonjour,

    2 remarques/observations complémentaires:
    – Il me semble que wiringpi est installé d’office avec jessie.
    – On peut utiliser le GPIO sans être SU. Il faut ajouter la ligne suivante à son fichier .profile:
    WIRINGPI_GPIOMEM=1
    Par principe, je n’aime pas travailler en étant SU (surtout en développement).

    Ces 2 remarques mineures étant faites, je tiens à souligner la démarche de l’auteur. Étant assez actif sur le forum, je constate régulièrement que des débutants, qui viennent pour la plupart du monde Windows (ce n’est pas une insulte), veulent se lancer d’emblée dans des projets lourds, avec des cartes d’interface (écran LCD, I2C, 1 wire..).
    Comme les fondamentaux ne sont pas maîtrisés, ils se découragent assez vite ou il faut les guider pas à pas.
    L’auteur nous montre qu’il est possible de rentrer dans les arcanes du Raspberry avec une simple LED (et une résistance).
    Je pense que sa démarche logique consistera à explorer ensuite les bus (I2C, SPI, série, 1 wire) avant de se lancer dans des projets complexes. AMHA, en procédant de la sorte, il a de fortes chances de mener à terme ses projets car il aura compris le fonctionnement de la bête et ne sera pas tributaire de bouts de code glanés à droite et à gauche, péniblement assemblés.

    Sylvain

    Répondre
    1. Patrice SEIBEL Auteur de l’article

      Bonjour,
      Merci pour les infos, dans mon cas wiringpi n’est pas présent avec Jessie.
      Je partage tout à fait tes remarques, oh combien de débutants veulent faire un « drone » en n’ayant pas l’ombre d’une expérience.
      Il y aura une suite mais toujours dans la même démarche (multi-langages), le suivant sera la « saga push button ».
      @+

      Répondre
  3. François MOCQ

    Bonjour Sylvain
    un grand merci pour le forum 🙂 merci aussi pour les remarques qui viennent en complément de l’article
    Patrice, l’auteur de cet article devrait bientôt récidiver avec la lecture d’un inter etc.
    Incroyable non ? A quoi ça peut servir d’allumer une LED avec un inter en passant par un Raspberry Pi… Ce serait tellement simple de relier directement la LED à l’inter 😀 et pourtant je suis tout à fait en phase avec lui !
    à bientôt
    François

    Répondre
    1. gUI

      oui, ces articles sont une excellente idée ! ils resteront je pense une bonne base de référence Francophone (et encore, pas certain que cette collection de méthodes existe ailleurs)

      Répondre
    2. S.POURRE

      Bonsoir François,

      Merci de me dire merci ;-))
      AMHA le succès de ce site est du :
      -) à toi, maître des lieux, pour tes articles et la tonalité que tu donnes.
      -) au travail, souvent ignoré, des modos et admins.
      Cordialement.

      Sylvain

      Répondre
  4. antoin

    Bonjour
    J’avais fait les exercices avec python (raspberrypi.org) mais j’étais resté sur ma faim au niveau de la compréhension. Sur apple 2 avec des peek et des poke on avait les adresses mémoires du controlleur de manettes.

    Le fichier bash, avec la commande echo répond à mon attente:
    echo « 23 » > /sys/class/gpio/export #assigne pin
    echo « out » > /sys/class/gpio/gpio23/direction #en sortie
    echo « 1 » > /sys/class/gpio/gpio23/value #allume led
    echo « 0 » > /sys/class/gpio/gpio23/value #éteint led

    Bien sur que l’intérêt de cet article est pédagogique.
    Dans une réalisation concrète on utilisera par exemple les bibliothèques python.

    Répondre
    1. antoin

      Je reste encore un peu sur ma faim pour comprendre le fonctionnement des broches.
      Que ce soit les echo en bash, les bibliothèques python, celles en C on fait appel à des routines en langage machine.
      Je ne demande pas un programme en langage machine pour programmer des led mais simplement de savoir ce qui se passe au niveau machine pour activer une broche du GPIO en input ou output, etc.
      Si c’est comme appleII cela se faisait par une écriture ou une lecture en mémoire, et elles étaientt même accessible du basic avec des peek et des poke car les adresses mémoires étaient documentées

      Répondre
      1. François MOCQ

        Bonjour
        Venant de cette époque j’ai utilisée les Z80 PIO et autres 8255 à toutes les sauces… Mais avec les Soc on est passé à une échelle supérieure vu le nombre de ports et les registres à prendre en compte. Bon c’est faisable mais justement les bibliothèques permettent d’accéder aux E/S bien plus facilement en restant dans les couches supérieures, sans descendre au niveau du bit de sortie 🙂
        Vous en saurez plus à partir de la page 89 de ce document : http://www.framboise314.fr/docs/BCM2835Datasheet.pdf
        Cordialement
        François

        Répondre
        1. antoin

          Merci bien François, je vais pouvoir satisfaire ma curiosité. Tout à fait d’accord qu’il faille passer ensuite par les bibliothèques.
          cordialement
          Antoin

          Répondre
  5. Bud Spencer

    Bonjour messieurs.

    Voila un bel article très bien écrit et illustré comme on aimerait en voir plus souvent. Toutefois, en termes de programmation, les méthodes utilisées sont l’exemple type de ce qu’il ne faut pas faire, surtout sur un PI aux ressources particulièrement limitées. A l’exception de l’exemple nodejs (qui lui est fondamentalement asynchrone), tous les autres exemples occupent en permanence le thread principal à grand coup de comparaisons incessantes aussi gourmandes qu’inutiles et c’est justement ce qui est à l’origine de l’échec de nombreux projets de débutant. Pour voir ou je veux en venir, essayez donc de mettre une variable qui s’incrémente de 1 à chaque comparaison faites entre 2 changements d’état de la led. Vous allez vous rendre compte que des milliers (voir même millions pour les exemples en c) d’instructions sont exécutées et occupent constamment l’uc pour finalement ne rien faire. Dommage de ne pas profiter de cette belle aptitude rédactionnelle que vous possédez pour faire la démonstration d’un bon exemple qui laisserait l’uc complètement au repos entre 2 changements d’état de la led et qui ne s’inquièterait de la valeur d’un input key que dans le cas d’une interruption clavier.

    Répondre
    1. S.POURRE

      Bonjour,

      L’auteur est conscient de ce problème et le mentionne expressément dans son article qui vise les débutants. On ne peux pas les confronter de suite aux threads et mutex !
      Le Raspberry est fait de compromis, pas toujours heureux ;-(
      L’absence de gestionnaire d’interruptions dans l’espace noyau en est un exemple. Cela implique de gérer un ISR dans l’espace utilisateur. Heureusement la bibliothèque wiringpi le permet mais c’est assez peu documenté et pas trivial.

      Sylvain

      Répondre
      1. Bud Spencer

        Je comprends bien que c’est à titre didactique que Patrice a écrit ce beau topic et c’est justement pour cela, je pense, qu’il n’est pas très judicieux d’orienter les débutants dans ce sens (il suffit de lire les forums pour s’apercevoir qu’ils font déjà tous ce genre d’erreur). Ici, absolument pas besoin de mutex pour faire quelque chose de cohérant et d’explicit pour un débutant puisque l’on n’est pas censé avoir plusieurs threads qui accèderaient au même gpio simultanément. Un simple thread externe (1 ligne de code …) qui appel une void qui gererait le blink (en utilisant des sleep pour la tempo pour ne rien consommer pendant les attentes) et attendre tranquillement sans rien faire l’appuis d’une touche dans le thread principale pour savoir si l’on doit quitter. Au final un programme bien plus simple qui ferait exactement le même boulot mais sans rien consommer et qui laisserait de la ressource pour le gps de la détection d’obstacle de la tondeuse ;). Je n’ai pas de pi sous la main, mais un truc du genre ferait très largement l’affaire :

        int main()
        {
        pthread_t bled;
        //init io
        cout << "Initialisation GPIO …" << endl;
        cout << "Press Enter to Quit." << endl;
        pthread_create(&bled, NULL, &blinkLed,NULL);
        cin.ignore();
        pthread_cancel(tled) ;
        pthread_join(tled,NULL);
        cout << "Liberation GPIO …" << endl;
        return 0;

        }

        Répondre
        1. S.POURRE

          Vous avez raison pour cette usage particulier où on se contente de changer l’état de sortie d’un GPIO, il n’y a pas besoin de mutex.
          Dans le prochain article, lecture de l’état d’un bouton poussoir sur port GPIO, qui correspond à un besoin fondamental (cf. question récurrente des débutants), il sera certainement encore possible de s’en passer. Il est en effet peu probable, avec une action humaine, de provoquer 2 appuis successifs plus rapides que le temps de réaction du programme (c’est d’ailleurs mis à profit dans le filtrage logiciel des rebonds).
          Quand il faudra faire de l’acquisition de données via I2C (ou SPI), il en sera tout autrement.
          Avec une thread écrivain et une thread lecteur qui partagent la même ressource, il faudra mieux éviter de lire pendant une opération d’écriture (et vive versa).
          Avec le bus I2C, c’est encore plus flagrant vu le nombre d’esclaves qu’il peut y avoir. On peut certes faire du polling mais c’est un gaspillage éhonté de ressources (sur ce point aussi je vous rejoins). Les PCF8574 que l’on retrouve sur beaucoup de cartes d’interface ont bien une broche INT et ce n’est pas pour faire joli.
          Mais tout cela n’est pas trivial et dépasse, AMHA, le cadre de l’initiation d’un débutant. J’ai eu l’occasion, sur le forum, de discuter avec un modérateur qui est loin d’être un newby et il y a renoncé.
          Personnellement, j’y travaille car mes projets sont trop lourds pour se contenter du polling ou de la boucle infinie. Ils sont aussi trop lourds pour être développés/compilés sur le Raspberry (surtout que je n’ai qu’un B+). Je n’ai pas envie d’attendre des heures le résultat d’une compil ou de flinguer rapidement la carte SSD par trop d’écritures.
          J’y vais donc aussi « pas à pas ». Pour le moment, j’ai un environnement de cross compilation fonctionnel mais qui ne me satisfait pas à 100 %.
          C’est peut-être le fait de partager cette approche ‘pas à pas » avec l’auteur qui me fait comprendre et admettre sa démarche en n’oubliant pas la cible visée.
          Tout le monde n’a pas le temps ou la fibre rédactionnelle mais je pense que vos contributions seraient très appréciées sur le forum. Au plaisir de vous y retrouver bientôt.

          Sylvain

          Répondre
          1. François MOCQ

            salut Sylvain
            je ne peux qu’aller dans ton sens ! Pour ma part je ne suis pas un dev je suis plutôt un hardeux. Mais le fait de se lancer à écrire un article comme celui-là en sachant qu’on va s’exposer aux critiques est déjà un sacré pas à franchir que beaucoup n’ont pas fait 🙂
            Après, les critiques si elles sont constructives et amènent des éléments au débat, permettent à tout le monde d’avancer. L’auteur en profite pour ses prochains articles et les lecteurs s’aperçoivent que derrière la porte qui vient d’être ouverte il y en a encore beaucoup à explorer….
            Et je pense aussi que c’est ce qui est intéressant dans ce monde de l’informatique. On sait qu’on ne saura jamais tout, qu’à chaque fois qu’on apprend on s’apercevra qu’il y a encore bien plus à apprendre…
            Il faut avoir cette envie de toujours aller plus loin pour progresser et si on ne l’a pas il faut faire autre chose 🙂 enfin… c’est juste mon avis
            cordialement
            François

          2. Bud Spencer

            Soyons clair, il ne s’agit pas ici de remettre en cause l’excellent travail de rédaction de Patrice que je salue une fois de plus. Ma remarque se veut avant tout constructive. Elle n’a pas vocation à dire qu’une méthode est mieux ou moins bien qu’une autre, mais bien de mettre en garde, concernant celles utilisées ici. Soyons pragmatique, quel est l’intérêt d’utiliser un langage très rapide (je parle ici du C) si c’est pour augmenter la consommation de ressources proportionnellement à la vitesse d’exécution des instructions ? C’est exactement à ce paradoxe que nous somme confronté ici. Plus l’exécution des instructions conditionnelles sera rapide et plus on en fera, ce qui forcement augmentera la consommation de ressources. Ne voyez-vous pas une énorme faille face au fait qu’une seule instruction sur plusieurs milliers aura réel un effet sur le déroulement du programme et que ce rapport ne pourrait qu’augmenter si on passait sur un system plus rapide ?
            Une petite suggestion pour Patrice : Si vous tenez absolument à utiliser ces boucles infernales, mettez au moins un usleep de quelques ms dans la partie systématique de vos boucles. Cela aura pour effet de réduire considérablement le nombre d’instructions inutiles. Bien sûr cela se transformera en latence sur l’input key et la précision de blinking sera un peu moins bonne, mais le piège que vous avez creusé est bien trop profond pour que vous puissiez vous en sortir sans payer un tribut 😉

  6. Patrice SEIBEL Auteur de l’article

    Bonjour,
    Merci à tous les deux pour votre retour et précisions.
    Il est vrai que certains programmes sont exigeants en terme de ressources mais rien n’est parfait dans le monde réel. 😉
    Le but de l’article est avant tout initiatique et il ne s’agit pas de décourager les débutants par des notions complexes et compliquées. A un moment donné, il faut faire des choix. Si le débutant commence par faire des minis cahier des charges, des organigrammes et de documenter sa programmation, je pense que j’ai atteint 80% de mon but.

    Maintenant comme tout est perfectible et que j’ai prévu un petit complément à la saga blink.
    Je vais voir pour ajouter quelques notions sur une programmation plus économe en terme de ressources tout en restant dans un cadre initiatique et facilement accessible.

    Cela peu paraître utopique, mais je préfère un programmeur qui programme (même si cela n’est pas l’optimum) qu’un programmeur qui abandonne car c’est incompréhensible pour lui. Il pourra s’améliorer lorsqu’il rencontrera des problèmes et il sera plus résistant face à la difficulté.
    Mais c’est juste mon avis.
    @+

    Répondre
  7. Patrice SEIBEL Auteur de l’article

    Re,
    Le débat est intéressant car il permet d’orienter les articles en fonction des préoccupations des utilisateurs et de fournir de la matière première pour d’autres articles.
    Je me doutais qu’il y aurait des réactions, c’est normal, mais pas sur ce point là. 😉
    Pour revenir au sujet, AMHA, il y a deux approches possibles :
    1) un environnement type carte Arduino ou cartes consœurs. Dans ce cas précis, si la tâche occupe 100% des ressources ce n’est pas un problème car elle tourne pour cela.
    2) un environnement « nano-ordinateur » et, dans ce cas, la gestion des ressources est d’actualité.
    Dans les prochains articles, je préciserais le contexte de mise en œuvre.
    Je reste à votre écoute pour d’autres suggestions, remarques ou propositions.
    @+

    Répondre
  8. fred

    J’adore faire clignoter des DEL (ben oui LED c’est pas francais 🙂 ) et plus je ferais un truc complexe pour le faire plus ca me fera kiffer … (c’est français ça ?) car ou est l’intérêt si c’est pas pour te faire quelques noueds au cerveau

    N’en peche le NE555 même si il est vieu et moche ben il etait bien utile avant …

    Répondre
  9. j2c

    Mais c’est de la tuerie cet article !

    Bien-sur que pour faire clignoter une led on peut faire plus simple avec d’autres outils. Mais là, l’intérêt que je vois à l’article, c’est d’apprendre à exploiter les GPIO du raspberry, avec un prétexte de changement d’état régulier.

    On pourrait très bien s’inspirer de ces exemples pour faire autre chose.

    Merci pour cet article que j’ajoute dans ma liste des trucs à relire quand j’aurais besoin de jouer avec mes GPIO 😉

    Répondre
  10. Romain

    Comme mentionné au-dessus, c’est de la tuerie cet article 🙂 J’ai tout mon kit LED/résistances/breadboard étalé sur le bureau (ce soir c’est sur Arduino, avec le HS Hackable).

    Très content de voir ça sur le Pi ! J’avais commencé avec les articles de PiMag, mais une version très complète en Français avec du C, du Python et… du bash (!) est très appréciable. Je sais ce que je fais demain. Merci !

    Répondre
  11. Bud Spencer

    Ceux qui ont lu les commentaires ont certainement remarqué mon objection concernant les méthodes utilisées par l’auteur de ce premier volet ‘Blink Saga’. J’avais déjà la conviction de ce que j’avançais, mais le doute subsistait malgré tout (par expérience, je sais tant que l’on n’a pas essayé, on n’est jamais sûr de rien …). N’avais-je pas exagéré les défaillances des méthodes utilisées ? Celles que j’avais en tête étaient t’elles réellement fiable ? N’avais-je pas tout simplement apporté une critique futile au risque de décourager un auteur au combien soigneux dans ces présentations ? Il fallait que j’en ai le cœur net. J’ai donc téléchargé les codes sources ‘Blink Saga’ et j’en ai choisi un qui était concerné par ma critique. Je me suis ensuite mis dans la peau d’un débutant et j’ai réalisé les opérations de compilation proposées puis j’ai essayé le programme. Ce que je craignais n’est rien comparé au résultat. Je m’attendais à un niveau de performance médiocre alors que dans la réalité c’est carrément alarmant au point que l’on ne peut pas orienter de jeunes développeurs dans cette direction. Bien que je n’ai pas la prétention de faire un article aussi bien rédigé que celui, je me propose d’en écrire un qui mettrait en évidence les erreurs commises ainsi que leurs conséquences et surtout comment les éviter pour la suite de cette très intéressante ‘Saga’ qui je n’en doute pas doit intéresser beaucoup de débutants francophones. Il appartiendra ensuite à la rédaction en chef de le publier ou pas. Par contre, je ne trouve nulle part le mode opératoire pour écrire un article. Quel format utiliser pour faciliter la publication et à qui l’adresser ?

    Répondre
    1. Patrice SEIBEL Auteur de l’article

      Bonsoir,
      Chic, on va avoir un article d’un pro du développement 😉
      Tous les programmes fonctionnent et ont fait l’objet d’un test sur le B, zéro et le 3.
      Maintenant s’il faut rentrer dans la programmation système pour débuter avec le GPIO, pourquoi pas.
      Concernant les ressources, tant que l’on est dans l’organigramme de la figure 4, on est <8%;
      Pour l'organigramme de la figure 5, on a 100% (mais ce n'est pas un secret) sauf pour tkinter <20% et node <10%.
      @+

      Répondre
    2. Terence Hill

      Bin mince alors … Bud … je te preferais largement en acteur de film spagetti … tu as mal digérè un truc ?

      arrête de te prendre la tête hein … c’est un belle article qui a le mérite d’exister et surtout il est clair

      Quand tu auras fait le 1/4 du boulot que Patrice a fait reviens nous voir et surtout mets toi dans ta caboche d’intello présomptueux et que le débutant que je suis (bon peut etre pas si débutant que ca) à juste envie de te dire …  » hey mec prends du recule on est là pour faire mumuse avec nos joujoux tout en apprennent et les prise de melon c’est pas ici ….va te détendre »

      PS: Désolé Francois et Patrice pour ce petit message (qui n’apporte rien sauf peut etre me détendre ) mais je déteste les Gens comme lui qui n’apporte rien … ca me met hors de moi … Beau travail de vous 2 en tout cas …

      Répondre
        1. Bud Spencer

          Et quel soutient …
          Tu vois, j’avais apprécié la rédaction de ton tuto, je l’avais dit et même répété et pour justement t’en remercier, je me proposais de t’aider à avancer (toi et surtout tous ceux qui vont reproduire tes erreurs). Finalement je constate que ton égo t’importe bien plus que ton besoin d’apprendre et que tu te fouts pas mal des résultats pour les autres. Je me suis couché hiers soir à 2h00 du mat (en devant me lever ce matin à 5h30) pour corriger tes sources et commencer la rédaction d’un article qui évidement te remettais en cause puisque ce sont TES erreurs qui me servaient d’exemple concret à éviter. Mais pour toi toute critique est mauvaise dans le sens où elle te remet en cause. Hé bien soit, je ne t’aiderai pas. A n’en pas douter, d’autres bien moins intentionné que moi finiront bien par te mettre le nez dans … tes erreurs. Vu que tu ne penses pas avoir besoin de conseils pour programmer, prends quand même celui-ci qui se veut plutôt ‘moral’ : Avant de proposer quelque tuto que ce soit, pose toi juste la question de savoir si ce que tu vas écrire est à la hauteur de l’espace qui va te publier et acceptes à l’avance les critiques qui pourraient arriver (à moins que tu ne te penses infaillible). Jusqu’à présent, je pensais être ici sur un site référence du Raspberry Pi Francophone, mais désormais, toi et d’autres m’ont vraiment mis le doute. Pour être carrément honnête, je me demande même pourquoi je perds mon temps à polémiquer avec vous.

          Répondre
      1. icare

        Bonjour,
        Je pense que la contribution de Bud Spencer est constructive car elle aborde un aspect important lorsqu’on fait du partage de temps.
        Par contre, faire de la lévitation magnétique, en écoutant une radio internet, tout en utilisant libreOffice pour rédiger un article et, en prime, consulter des références sur le net.
        Il va se passer quelques choses, la lévitation magnétique va pas fonctionner si elle accapare pas les ressources.
        Les deux approches sont louables, et il y a de la place pour tout le monde.
        Nous on veut juste s’amuser, apprendre de nos mutuelles différences et se coucher moins bête le soir.
        D’après Patrice, il y aura une suite à la saga blink sinon ce ne serait pas une saga.
        @+

        Répondre
        1. Terence Hill

          ce n’est pas forcement le fond qui me gène au contraire toute expérience est toujours bien venu … mais la forme peut etre mieux exprimée genre:
           » J’ai pris les sources et je les ai regardé, on devrait pouvoir amélioré certaines choses pour l’optimisation des ressources comme …. »

          Et non:
          « Ce que je craignais n’est rien comparé au résultat. Je m’attendais à un niveau de performance médiocre alors que dans la réalité c’est carrément alarmant au point que l’on ne peut pas orienter de jeunes développeurs dans cette direction.  »

          euh sérieux on envisage d’allumer des LED pas d’integrer un RPI dans la futur mission sur MARS

          Et pourtant je suis le 1er a râler auprès de développeur qui ne savent pas optimiser les ressources et les cycles faut dire j’ai été à bonne école j’ai fait de l’assembleur sur des truc tellement faible en ressource que l’optimisation etait de rigueur et on rigolait pas avec ça …

          Ah si j’avais eu un RPI à l’époque (dit le vieux)

          Répondre
          1. François MOCQ

            pareil j ai démarré au Z80 et 6800 avec les Exorciser Motorola et on comptait les bits disponibles 🙂 aujourd’hui on entend « ouais mais y a que 4 Go de mémoire » 😀
            effectivement ça ne nous rajeunit pas

          2. Bud Spencer

            « Et pourtant je suis le 1er à râler auprès de développeur qui ne savent … »

            Rassure-nous, tu plaisantes, tu te fouts de nous ou tu tentes de te la jouer la 🙂 🙂 :)
             
            Tu sais de quoi je parle au moins ? Tu as au moins lus ces codes ? Tu les as essayés ? Je ne parle pas de quelques octets perdus de ci de là, mais d’un process qui consomme à lui seul et sans gui, plus que la visu d’un vidéo en streaming sur le net juste pour faire clignoter une led toutes les secondes, et je n’aborde même pas le coté optimisation. Crois-moi, si tu as envie de râler ou d’écrire au moins une chose de constructible sur ce coup, je te prie de croire qu’il y a des quoi alimenter ta grogne et il y en a grand besoin.

        1. François MOCQ

          Pour moi dans un sens ou dans l’autre tous les retours sont positifs car ils montrent la diversité des activités et des préoccupations des utilisateurs de la framboise (et des autres cartes aussi !)
          bon amusement
          François 🙂

          Répondre
      2. Bud Spencer

        Serait-ce des insultes 🙂

        Tu te prétends débutant et c’est très bien de l’admettre et si je peux te donner un conseil, attend toi le rester encore très très longtemps, parce qu’avec une telle objectivité, tu n’es pas près d’avancer.

        Toi tu n’apportes rien, je suis d’accord, en revanche, de mon côté j’ai lu, j’ai analysé et pour confirmer les erreurs critiques que je soupçonnais j’ai testé tous ces exemples puis je les ais corrigés ‘au mieux’ pour ne pas trop les déformer avec pour seul but d’aider patrice à ne pas refaire les mêmes erreurs et pouvoir proposer aux débutants soucieux d’apprendre (l’inverse de toi) des exemples non pas exemplaires mais au minimum acceptable. Lui n’a pas besoin de me dire que c’est un débutant, je le vois bien en lisant ses sources et je les juge avec toute l’indulgence que l’on doit avoir envers quelqu’un de son niveau qui malgré tout essais d’apporter sa pierre à l’édifice. Si je voulais mettre le doigt sur toutes les anomalies que j’arrive à lever dans cet article juste avec mon humble niveau, ce n’est plus un article que je devrais écrire, mais carrément un bouquin entier. Commence par apprendre que la seule chose que l’on tirer d’une erreur, c’est justement d’apprendre. Au lieu d’insulter, lis, analyses, expérimentes, comprends et quand tu penseras avoir le niveau ou au moins l’intelligence pour te joindre à un débat qui se veut avant tout technique, reviens me voir et là on pourra peut-être discuter.

        Répondre
  12. Patrice SEIBEL Auteur de l’article

    Re,
    @Bud Spencer
    En attendant ton topo, tu peux essayer le programme en C ci-dessous :

    1: #include //stdio.h
    2: #include //stdlib.h
    3: #include //pthread.h
    4: #include //unistd.h
    5: #include //wiringPi.h
    6:
    7: #define LED 4
    8:
    9: volatile char theCar = ‘\0’;
    10:
    11: void* blink(){
    12: wiringPiSetup();
    13: pinMode(LED, OUTPUT);
    14: while(theCar != ‘q’){
    15: digitalWrite(LED, HIGH);
    16: delay(500);
    17: digitalWrite(LED, LOW);
    18: delay(500);
    19: }
    20: return NULL;
    21: }
    22:
    23: void* sortie(){
    24: while(theCar != ‘q’){
    25: printf(« q pour sortir ! »);
    26: theCar = getchar();
    27: }
    28: return NULL;
    29: }
    30:
    31: int main(void){
    32: pthread_t filsA, filsB;
    33:
    34: if(pthread_create(&filsA, NULL, blink, NULL)){
    35: perror(« pthread_create »);
    36: exit(EXIT_FAILURE);
    37: }
    38:
    39: if(pthread_create(&filsB, NULL, sortie, NULL)){
    40: perror(« pthread_create »);
    41: exit(EXIT_FAILURE);
    42: }
    43:
    44: if(pthread_join(filsA, NULL))
    45: perror(« pthread_join »);
    46:
    47: if(pthread_join(filsB, NULL))
    48: perror(« pthread_join »);
    49:
    50: digitalWrite(LED, LOW);
    51: pinMode(LED, INPUT);
    52:
    53: printf(« Fin blink\n »);
    54: }

    Pour l’instant cela fonctionne pour C, C++ et python mais je n’ai pas trouver la solution pour le bash.
    Tu vois que tes remarques n’étaient pas vaines.
    Rq1: je sais j’ai utilisé une variable locale pour éviter de passer une structure en paramètre.

    Rq2: je n’y connaît rien en programmation 😉
    @+
    [edit]
    Pour compiler :
    gcc nomFichier.c -lpthread -lwiringPi -o nomFichier
    Pour exécuter :
    sudo ./nomFichier

    Répondre
  13. Bernard B

    Bonjour Francois
    Article intéressant suivi d’une non moins intéressante passe d’armes pour une poignée de dollars.
    Il faut juste espérer que ça ne découragera pas des gars comme Patrice Seibel de publier car en publiant on s’expose nécessairement à des avis qui ne font pas toujours plaisir.

    Pendant les années ou je travaillais à l’assistance informatique d’une grande administration, j’étais aussi moniteur sur Multiplan (ça fait longtemps) 😉 puis sur Excel et quelques SGBD comme Dbase IV et Foxpro. J’ai été souvent confronté à des stagiaires qui essayaient de me déstabiliser et parfois en savait plus que moi mais ça m’a permis d’avancer et d’apprendre qu’on ne sait jamais et surtout de rester modeste.

    Bonne fin de juillet

    Répondre
    1. fred

      Mais non il ne va pas se décourager … Non parce que sinon je vais venir lui botter le train arrière car je le veux mon article sur l’I2C … d’ailleurs je comprends pas pourquoi c’est pas déjà en ligne il fait quoi ? et qu’on me dise pas c’est les vacances, c’est du boulot, ou encore tu sais il a aussi un travail …. ce se serait

      😉

      Répondre
      1. Patrice SEIBEL Auteur de l’article

        Bonjour à tous,
        Tu l’auras ton article sur l’I2C en version « saga ».
        Pour l’instant, je termine la « saga Push Button » et le complément à la « saga Blink ».
        Par contre, je cherche des volontaires pour une pétition pour augmenter la durée légale de la journée. L’idéal serait de passer de 24 à 48. 🙂
        @ bientôt
        Patrice

        Répondre
        1. S.POURRE

          Bonjour Patrice,

          Je constate avec plaisir que je ne m’étais pas trompé en analysant ta démarche . Dès mon premier post je soulignais qu’il serait cohérent, après le GPIO de base (LED, BP), d’aborder les bus série.
          Je trouve sain et légitime qu’un article provoque des réactions car c’est reconnaître le travail de l’auteur. Je regrette juste la tournure de cet échange où l’on a vu apparaîtrent, cas très rare sur ce site, des attaques personnelles.
          Il me reste à souligner, une fois encore, la cohérence et la pédagogie de ta démarche. Je ne pense pas me tromper mais je n’ai pas vu beaucoup d’articles d’initiation présentant le C comme langage de programmation permettant d’arriver assez facilement à un résultat. Par facilité ou par paresse intellectuelle, on trouve les sempiternels langages interprétés.
          Les remarques techniques d’optimisation étaient certes justifiées mais je crains que l’appel aux threads n’ait brouillé le message pour un débutant qui risque d’avoir du mal à déchiffrer ce programme.

          Quant à la pétition pour la durée de la journée, normalement celle-ci fait 24 h + la nuit 😉
          Merci et félicitations pour ton travail
          Cordialement
          Sylvain

          Répondre
          1. Patrice SEIBEL Auteur de l’article

            Bonjour,
            Merci 🙂
            Concernant les threads cela peut être déroutant pour les débutants et n’avait pas sa place dans mon approche. Maintenant que c’est fait, je ferai quelque chose de « very lite » sur le sujet dans mon complément.
            Effectivement les critiques et remarques constructives font progresser les sujets.
            Vu le nombre d’heures de vol de l’auteur, les attaques personnelles, dénigrements ou autres sarcasmes ne m’atteignent pas.
            @ bientôt
            Patrice

  14. Yann

    Bonjour à tous
    Merci pour ce site…et pour ce super tuto ! Quel travail ! Il a bien pour objet l’utilisation des GPIO et est parfaitement didactique pour moi débutant en Raspberry…Etonnant cette polémique sur le multitache qui est hors sujet selon moi, même si sur le fond c’est intéressant. La critique est aisée mais l’art est difficile…
    Comme je suis flemmard je fais mes tests avec mon multimetre….et la librairie gpiozero me plait bien !

    Bonne journée et encore bravo à ceux qui donnent leur temps pour partager leurs connaisssances !

    Yann

    Répondre
  15. Lucien Dupré

    Bonjour,

    Je suis un vieux à la retraite (70 ans) qui s’est intéressé à la framboise pour épater ses petits enfants …
    J’ai donc passé l’examen de la led qui clignote, comme tout le monde, mais je n’ai pas eu le courage de faire aussi bien que l’auteur de cet article que je félicite pour son travail pédagogique, même si certains le trouvent perfectible.
    Je suis allé plus loin dans cette saga, mais de manière perso et je n’ai pas la force de produire un article aussi bien structuré. Voici mon expérience, programmée à ma manière, forcément contestable, mais qui pourrait donner des idées à l’évolution de la saga blink.

    La seconde étape de maîtrise du GPIO consiste à détecter une température au moyen d’un DS18B20 (moins de 3 euros pour une précision de 0.5 degré sans calibrage !!).
    J’ai donc voulu faire clignoter ma led lorsque la température dépassait un certain seuil critique et l’arrêter en dessous d’un autre seuil. On peut faire l’inverse pour du froid.
    J’ai construit un petit programme qui teste la température en faisant un petit démon (un thread) qui n’occupe les ressources que lorsqu’il devient actif, qui lance éventuellement l’allumage du blink de la led, ou bien l’extinction du blink de la led, et puis meurt. J’ai tenté aussi d’activer ce programme par CRON.

    Je dirige mon PI depuis le net et j’ai voulu construire en PHP le service web qui me dit quel est l’état de la led, sans donner au serveur web les droits de SU.

    Et voila, je suis parti sur une immense chose ! Je ne suis pas certain que mes programmes « bidouillesques » soient diffusables mais je soumets l’idée à faire développer par des puristes de la programmation pour mettre en place un canevas (un framework) qui aiderait les débutants à travailler proprement du premier coup … sans avoir à passer par les deux cent étapes possibles pour développer en DIY !

    Encore toutes mes félicitations pour cet article.
    L.D.

    Répondre
    1. François MOCQ

      Bonjour Lucien
      je ne suis pas un developpeur non plus mais un vieux hardeux qui a commencé avec des tubes 🙂
      lorsque j’écris un programme je reste modeste et je sais qu’un dev. professionnel aurait sans doute fait mieux mais quoi ? on fait comme on sait et ça permet à d’autres de commencer, à d’autres d’améliorer ou de critiquer (pour moi une critique technique est toujours à prendre avec modestie et humilité)
      alors si vous souhaitez publier ce que vous avez fait ce sera avec plaisir.
      Pas facile d’exposer son travail à la vue de tous j’en sais quelque chose mais c’est aussi un moyen de mettre à plat ce qu’on a bien compris (Ce qui se conçoit bien s’énonce clairement – Et les mots pour le dire arrivent aisément – Nicolas Boileau) et souvent de s’apercevoir de ses lacunes et d’identifier ce qu’on a moins bien pigé 😉 )
      alors les pages de framboise314 vous sont ouvertes comme à tous ceux qui ont envie de décrire un montage, une programme, une réalisation !
      bonne fin de journée
      cordialement
      François
      ps pour moi la retraite… c’est DANS UNE SEMAINE 😀

      Répondre
    2. fred

      Allez Lucien, fais passer ton code

      Juste comme ca l’idée je la trouve super mais aviez vous une idée d’application pratique en faisant ca ? ou c’etait juste pour le FUN

      Ce qui m’étonne toujours c’est les idées qui sortent de la tête des gens … parce que moi ca sort pas …
      Quand je vois les différents inventeurs ou les personnes qui créent des concepts à partir d’une feuille blanche ca me … enfin ca … Bon je suis béa d’admiration en faite … il doit me manquer un truc!?!

      PS: désolé pour le tutoiement du début c’était pour le FUN

      Répondre
      1. François MOCQ

        Bonjour Fred
        les applications pratiques elles sont dans la tête des utilisateurs.
        Il FAUT savoir allumer et éteindre une LED. C’est TOUJOURS la première chose qu’on fait quand on prend en main une carte et ça depuis des lustres (et je sais de quoi je parle, je suis très… lustré). Mais pourquoi ? bin… si on remplace le LED par un relais on peut commander… une cafetière, un volet roulant, un portail, une porte de garage…. en industriel faire tourner un moteur , faire sortir ou rentrer un vérin, chauffer une cuve, la vidanger ….
        Lidée de Lucien d’allumer une LED au dessus d’une certaine température ? Super ! ça permet par exemple de déclencher une ventilation dans une serre quand il fait trop chaud… Et l’éteindre quand c’est trop chaud ? binnn si j’ai un aquarium et que je ne veux pas faire bouillir mes poissons, j’arrête le chauffage quand la température programmée est atteinte…
        La LED c’est le premier pas vers les utilisations d’actionneurs externes. Savoir allumer et éteindre une LED c’est pouvoir agir sur le monde extérieur !
        voili voilou
        @+
        François

        Répondre
        1. icare

          Bonjour,
          « … si on remplace le LED par un relais on peut commander… une cafetière, un volet roulant, un portail, une porte de garage…. en industriel faire tourner un moteur , faire sortir ou rentrer un vérin, chauffer une cuve, la vidanger ….
          La LED c’est le premier pas vers les utilisations d’actionneurs externes. »
          Et la saga push button fera le pendant « capture des inter-actions extérieur »
          @+

          Répondre
        2. fred

          Effectivement … Vendredi je devais pas être en phase avec mon cerveau (mon quoi?) la semaine fut longue … Bref, ça me parait si évident aujourd’hui En plus j’y avait pensé quand j’ai monté mon RPI avec commande via radio de prises et de volets roulants au départ pour faire de la simulation de présence et surtout parce que j’ai une baie vitrée qui prend le soleil en plein l’après midi, pour réguler un peu la température …

          Bon ca veut donc dire que j’ai besoin de vacances 🙂

          Répondre
  16. Ping : Technologie | Pearltrees

  17. Ping : Raspberry Pi | Pearltrees

  18. Ping : Un Raspberry pour faire clignoter une LED ! - Steve Fuchs

  19. Ping : Penser ‘Thread’ pour simplifier vos programmes | Framboise 314, le Raspberry Pi à la sauce française….

  20. Ping : Plongez dans le Go | Framboise 314, le Raspberry Pi à la sauce française….

  21. Bastien

    Bonjour,
    tout d’abord merci beaucoup pour ce tuto très complet.
    J’ai une question concernant la photo :
    http://www.framboise314.fr/wp-content/uploads/2016/07/LED_GPIO.jpg
    J’aimerais acheter le même type de connexion broches/resistances pour me fabriqué un câble vidéo pour mon Atari ST :p
    j’ai cherché cobbler mais je trouve que des accessoires avec PCB alors que sur la photo on dirait un fil avec de la gaine thermo.
    Auriez-vous un lien ?
    D’avance merci

    Répondre
    1. Patrice SEIBEL Auteur de l’article

      Bonjour,
      Merci.
      L’accessoire de la photo est une réalisation personnelle. Il ne faut pas grand chose et très facile à faire.
      Une led + une résistance + un lien femelle/femelle du commerce + un bout de gaine thermorétractable.
      Les liens femelle/femelle se trouvent facilement, pour qq cents, par paquet de 10, 50 ou 100 du côté du soleil levant. Le reste n’est que quelques soudures et la gaine pour des questions d’isolement.
      Peut être en cherchant sur les sites chinois, tu trouveras des cordons fil vers connecteur femelle.
      @+

      Répondre

Laisser un commentaire

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

Complétez ce captcha SVP * Time limit is exhausted. Please reload CAPTCHA.