Linux Embedded

Le blog des technologies libres et embarquées

Électronique simple (pour GPIO)

Nous avons tous eu envie, un jour, d'utiliser notre ordinateur pour allumer et éteindre des diodes ou pour prendre le contrôle de petits circuits. La plupart de nos lecteurs auront les compétences nécessaires pour programmer le logiciel qui rendrait un tel système intelligent, mais quelques notions simples d’électronique peuvent s'avérer bien utiles. Cet article va servir d'introduction aux principes de base pour connecter une Raspberry Pi à des systèmes simples. Si vous connaissez la loi d'Ohm vous devriez pouvoir suivre.

Les GPIO, qu'est que c'est.

Les GPIO (pour General Purpose Input Output) sont des connecteurs sur votre carte qui permettent de parler directement au CPU. Pas de timing, pas de protocole : une tension sur le GPIO est lu comme un '1' par  le CPU et un '1' écrit dans le registre de commande met une tension sur le GPIO. Ces connexions sont donc parfaites pour bricoler des petits circuits électroniques. La Raspberry Pi exporte un grand nombre de GPIO et la plupart sont accessibles sur le connecteur P1 (celui qui exporte également le port série)

[caption id="" align="aligncenter" width="450"] Le connecteur P1[/caption]

Voici la signification de chacune des pins

[caption id="" align="aligncenter" width="254"] Les différentes pin du connecteur P1[/caption]

 

GPIO : les pièges à éviter

Une GPIO est donc une connexion directe sur le processeur. Le processeur est une petite chose fragile et il est important de ne pas trop le fatiguer. Le risque de détruire votre carte existe et il faudra faire un peu plus attention que d'habitude lorsque vous travaillerez.

Tout d'abord les GPIO de la raspberry pi travaillent en 3.3v et la carte dispose à la fois de sources  3.3v et de 5v. Les GPIO ne sont pas protégés contre les surtensions.

Ensuite, il ne faut pas tirer trop de courant des GPIO. Le maximum autorisé est de l'ordre de 16mA. Il faudra protéger les GPIO avec des résistances pour ne pas tirer plus de courant. En particulier il ne faudra pas court-circuiter les GPIO sur la masse.

Comment contrôler une LED.

Notre première petite aventure dans le monde des GPIO va être l'équivalent électronique de "hello world", nous allons allumer une LED.

L'électronique

Notre GPIO peut produire du 3v3, nous avons un connecteur GND sur P1, l'approche naïve voudrait que l'on fasse le circuit suivant diode_naif Malheureusement ce montage fonctionnera... quelques secondes avant de griller votre processeur. Réfléchissons ensemble à ce qui se passe. Lorsque le GPIO fournit une tension de 3v3  le courant qui est tiré de notre GPIO peut être facilement déduit de la célèbre loi d'Ohm : U=RI. Quelle est la résistance d'une LED ? Négligeable. Qu'est que ça donne dans notre équation ? I= infini... Pas bon. Il va falloir limiter le courant. Pour cela nous allons augmenter la résistance de la diode, ou plutôt ajouter une résistance dans le circuit. diode_res Quelle valeur pour la résistance ? Demandons à Ohm... La diode  a besoin d'avoir une tension de l'ordre de 2v à ses bornes (la valeur précise dépends de la diode)  Pour avoir une intensité de 10mA avec un voltage de 3v3, il nous faut : R=(3.3-2)/0.01=130Ω Et voila. Nous avons un circuit sécurisé pour allumer notre diode...   Avant de nous tourner vers Linux pour contrôler notre GPIO, regardons le schéma suivant diode_inverse   Ce schéma est le symétrique du précédent sauf que l'on utilise une source externe 3v3 et que le GPIO nous sert de masse. La LED s'allume donc lorsque le GPIO est à 0 et s'éteint lorsqu'il est à 1. Nous avons inversé la logique. On parle ici de GPIO "Active Low", c'est à dire que l'état actif correspond à la valeur logique 0

Piloter un GPIO sous Linux

Pour contrôler facilement les GPIO, Linux fournit une interface sysfs qui est très simple d'utilisation. Tout d'abord rendons-nous dans le répertoire de gestion des GPIO

$cd /sys/class/gpio

Ce répertoire contient deux fichiers export et unexport. Nous allons les utiliser pour réserver la pin qui nous intéresse auprès du noyau. Par exemple pour le GPIO numéro 4:

$echo 4 > export

Si cette pin était utilisé par un autre sous-système, le noyau pourrait refuser de l'exporter (la plupart des pin correspondant aux GPIO peuvent être utilisés pour d'autres périphériques, comme les port séries ou le bus I2C, le noyau sert donc d'arbitre) nous voyons qu'un nouveau répertoire est apparu, il correspondant au  GPIO que nous venons de réserver. Voyons ce qu'il contient :

$cd gpio4

$ls
active_low direction edge power subsystem uevent value

$cat active_low
0

$cat direction
in

$cat edge 
none

$cat value
0

Les répertoires et fichiers power subsystem et uevent sont des fichiers standards pour tous les périphériques. Le fichier direction nous permets de décider si notre GPIO est en lecture (in) ou en écriture (out) et le fichier value nous permet de choisir la valeur (ou de la lire si nous sommes en mode lecture). Configurons correctement notre GPIO

echo out > direction

echo 1 > value

Et nous avons allumé notre diode. Enfin, lorsque nous utilisons le circuit inversé nous pouvons prévenir le noyau

echo 1 > active_low

et la signification logique de value sera inversée.

 Lire la position d'un interrupteur.

Pour lire la valeur d'un GPIO nous pouvons, à nouveau tenter une approche naïve : bouton_naif   Ce circuit ne marche évidement pas. Lorsque l'interrupteur est fermé le voltage lu par le GPIO est 0, mais lorsque l'interrupteur est ouvert, le voltage du GPIO est... indéterminé. Ce n'est pas dangereux mais ce n'est pas bon. Il faut améliorer ceci en tirant le voltage du GPIO vers 3v3. Un deuxième circuit (tout aussi naïf, mais plus dangereux) serait le suivant: bouton_naif2 Ici, lorsque l'interrupteur est ouvert, le GPIO lit bien un voltage de 3.3v. Lorsque l'interrupteur est fermé... on court-circuite directement l'alimentation de la carte. Au mieux cela reboot la raspberry pi, au pire... On ne va pas essayer. Pour éviter le court-circuit nous allons installer une résistance entre la source d'alimentation et le GPIO. Cela nous donne le circuit suivant: bouton_pullupIci tout se passe bien. Lorsque l'interrupteur est ouvert, le voltage du GPIO est proche de 3v3 (il y a un peu de courant qui entre dans le GPIO mais c'est négligeable) lorsque l'interrupteur est fermé, le GPIO est relié à la masse et la résistance est traversée par un courant mais protège la source d'alimentation. Quelle valeur pour la résistance ? Le calcul précis est un peu compliqué, mais il faut une "grosse" résistance, typiquement 10kΩ. Cette résistance sert à "tirer" le voltage vers le haut lorsque l'interrupteur est ouvert. Elle est appelée "pull-up" Il y a encore un petit risque dont il faudrait se protéger. Si le GPIO est accidentellement configuré en mode out et mis à 3.3v nous aurons un court circuit potentiel entre le GPIO et la masse. Ce n'est pas bon. En insérant une petite résistance (1kΩ) sur le chemin, nous pouvons facilement nous protéger. Voici donc le circuit final bouton_complet La lecture depuis Linux n'est pas compliqué

$cd /sys/class/gpio/gpio4
$echo in > direction
$echo value
1

Fermez l'interrupteur

$cat value
O

Enfin, pour compléter, voici le même circuit en logique inversée bouton_inverse

Un peu de puissance

Jusqu'à maintenant nous avons travaillé en 3v3. C'est le voltage du coeur de la Raspberry Pi mais les périphériques sont en 5v. Si vous voulez piloter autre chose que des diodes il vous faudra rapidement vous occuper de voltages un peu plus élevé et protéger vos GPIO un petit peu mieux. Voyons tout cela.

Lire une forte tension

Pour lire une tension plus forte, la configuration la plus simple est la suivante

level_shifter

Si le point du haut est à 0v, nous aurons bien 0v sur le GPIO. Si il est à 5v R1 et R2 doivent être paramétrés pour que le GPIO soit à 3v3.

3v3 = R2.I
5v = (R1+R2)I
...
R1/R2 = 5v/3v3 -1
R1/R2 = 0.5

Le rapport entre les deux résistance doit donc être 1/2 et la valeur doit rendre le courant de fuite négligeable. Des valeurs typiques seraient R1=18k R2=33k

Piloter une vrai charge

Intéressons nous maintenant au problème inverse : nous voulons piloter un petit moteur grâce à un GPIO. Notre moteur sera alimenté en 5v et nécessite une intensité importante par rapport à ce que peut supporter le GPIO. Nous utiliserons donc un montage comme celui ci-dessous.

load_simple

 

La résistance sert à éviter le court-circuit, la base du transistor étant reliée à la masse.

Les caractéristiques exactes du transistor dépendront de votre charge et du voltage à contrôler mais sachez qu'on peut trouver des transistors capable de piloter plusieurs dizaines de volts et de laisser passer une centaine de milliampères. C'est suffisant pour des petits moteurs mais si vous voulez contrôler un petit peu plus, il vous faudra un relais.

Avant de parler des relais, il va nous falloir protéger notre transistor un petit peu mieux. Un moteur étant un élément mécanique, il a la mauvaise habitude d'envoyer des pics de voltage parasites lorsqu'il démarre. Le bas du moteur peut avoir des pics de voltage supérieur au voltage de la source ou inférieur la masse. ce n'est pas bon. Nous allons nous protéger contre ça...

load_protected

La diode du haut est normalement bloquante, mais devient passante si le voltage au pied de notre moteur devient supérieur à Vcc, la seconde diode joue un rôle similaire si le voltage devient inférieur à Gnd.

Parlons maintenant un peu des relais. Un relais est (pour simplifier) un interrupteur piloté par un électroaimant. Cette séparation mécanique permet d'isoler fortement le circuit de commande du circuit de puissance. C'est parfait si vous voulez piloter des prises électriques.

relay

Nous avons vu tous les éléments qui composent ce schéma :

  • La diode protège le transistor des piques de courant
  • la résistance protège le GPIO des courts-circuits
  • Le relais a besoin d'être commandé en 5V, d'où le transistor de commande
  • Les deux circuits n'étant pas couplés électriquement il n'est pas nécessaire de relier les deux masses

Commander les GPIO depuis Linux, un peu plus en détail

Nous avons rapidement parlé de sysfs, qui permet de piloter les GPIO de façon générique. Si c'est bien pratique pour des problèmes simples, ce n'est pas ce qu'il y a de mieux pour développer un programme C. De plus, le CPU de la raspberry pi offre plus de possibilités que celles disponibles via sysfs.

  • Génération d'interruption par les GPIO (disponible via poll sur sysfs)
  • Génération d'horloge sur le GPIO 4
  • résistance pull-up et pull-down intégrés

Pour accéder à toutes ces fonctionnalités il faut lire la documentation Broadcom... ou utiliser une bibliothèque qui le fait pour vous.

  • wiringpi permet d'accéder facilement aux GPIO en C, C++, java, perl python et quelques autres langages. Cette bibliothèque couvre la plupart des fonctionnalités dont vous aurez besoin
  • raspdbusgpio est un daemon système qui envoie des messages dbus sur événement GPIO. Pratique pour une approche plus "système" de la gestion des GPIO

Conclusion

Les GPIO ne sont pas compliqués à utiliser. Avec un peu de prudence on peut facilement utiliser une Raspberry Pi pour piloter des petits circuits... Voire des gros. Un peu de recherche sur internet vous permettra de dénicher pleins de projets hardware facile à réaliser et les bases fournies par cet article vous permettront de comprendre les principes derrière les schémas.

Liens

    • le 06 juillet 2014 à 22:10

      Très rafraîchissant et bien écrit ! Merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.