Le registre à décalage PISO
Le registre à décalage entrées parallèles => sortie série (ou en anglais shift register Parallel In Serial Out) est un petit circuit intégré très pratique pour augmenter le nombre d’entrée d’un Arduino.
A quoi ça sert?
Imaginons un tableau de bord avec ses touches (boutons poussoirs) et trop de touches pour les entrées de l’Arduino. Il existe plusieurs façons de connecter pleins de boutons poussoir à un Arduino sans utiliser trop de fil (et donc d’entrées). Dans ces façons, il y a la matrice et pour une matrice il faut gérer plusieurs ligne et plusieurs colonnes, les activer et les désactiver pour scanner l’ensemble du clavier (c’est généralement ce qui est utilisé pour des claviers 3×3 ou 3×4). Il y a aussi l’utilisation d’un multiplexeur (plusieurs entrées, une sortie) qui permet de lire une de ses entrées, sélectionnée par commande, sur sa sortie. Et nous avons aussi la possibilité d’utiliser un registre à décalage et c’est cette solution qui est expliquée plus bas.
Comment ça marche?
Comme son nom l’indique, ce circuit possède plusieurs entrées en parallèle et une sortie série. Bien pratique pour avoir plusieurs entrées séparées, les sérialiser dans le temps, et les présenter sur une seul pin de l’Arduino. Le principe est simple, le circuit récupère les valeurs qu’il y a sur les entrées parallèles grâce à un ordre qui lui est envoyé et les restitue une à une sur la sortie série en fonction d’un signal de commande (une horloge).
L’enchainement des étapes pour récupérer un octet
Étape 1 : charger les valeurs présentes sur les entrées parallèles dans le registre interne
Étape 2 : lire 8 fois la valeur sur la sortie série en envoyant à chaque lecture un coup d’horloge pour faire décaler les données. Ceci permet de lire l’entrée 8 puis l’entrée 7 ainsi de suite.
Étape 3 : faire ce qu’on veut avec les 8 bits (l’octet) récupérés
La mécanique interne d’un registre PISO :
Des registres à décalage, il en existe quelques uns avec le même principe de base mais avec quelques fonctionnalités différentes. Nous allons voir le CD4021BE (mais vous auriez pu tout a fait prendre un 74HC165, attention le câblage n’est pas le même).
Comment brancher un CD4021E?
Le CD4021E se présent sous la forme d’un composant à 16 broches en boitier DIP (traversant en photo) ou en version CMS (composant de surface).
Voici la correspondance des pins.
[pastacode lang= »c » manual= »–%20pin%20out%20du%20CD4021%0A%20%20%20%20%20%20%20%201___o___16%20%20%20%20%0API-8%20-%3E%20%20%7C%20%20%20%20%20%7C%20%3C-%20Vcc%20(%2B5v)%0A%20%20Q6%20%3C-%20%20%7C%20%20C%20%20%7C%20%3C-%20PI-7%0A%20%20Q8%20%3C-%20%20%7C%20%20D%20%20%7C%20%3C-%20PI-6%0API-4%20-%3E%20%20%7C%20%204%20%20%7C%20%3C-%20PI-5%0API-3%20-%3E%20%20%7C%20%200%20%20%7C%20-%3E%20Q7%0API-2%20-%3E%20%20%7C%20%202%20%20%7C%20%3C-%20entr%C3%A9e%20s%C3%A9rie%20(provenant%20par%20exemple%20de%20la%20sortie%20Q8%20d’un%20autre%20CD4021)%0API-1%20-%3E%20%20%7C%20%201%20%20%7C%20%3C-%20entr%C3%A9e%20de%20l’horloge%20(CLOCK)%0A%20GND%20-%3E%20%20%7C_____%7C%20%3C-%20chargment%20des%208%20inputs%20paralelles%20(LOAD)%0A%20%20%20%20%20%20%20%208%20%20%20%20%20%20%209%0AQ8%20est%20la%20sortie%20s%C3%A9rie%0AQ6-7%20sont%20des%20sorties%20interm%C3%A9diaires%20″ message= » » highlight= » » provider= »manual »/]
L’alimentation se fait avec les pin 8 GND et pin 16 Vcc (+5v).
les pins de contrôles sont :
- la pin 9 Load qui permet de charger les données sur front haut et de les figer dans le registre interne sur front bas
- la pin 10 Clock, chaque front montant décale les valeurs dans le registre interne et présente la nouvelle valeur sur la sortie série de PI 1 vers PI 8
les pins d’entrée sont les pins PI 1 à PI 8 et la pin de sortie série est la sortie Q8 (la pin 3).
Comment utiliser le CD4021E avec une carte Arduino?
Au moment du chargement des valeurs dans le registre interne, celles-ci ne seront plus perturbées par un changement d’état sur les pins jusqu’au nouveau chargement. Il faut donc charger une fois et récupérer les 8 bits avant de charger à nouveau.
Dès le chargement, la première valeur, (celle de l’entrée Pi8, soit la pin 1) devient disponible sur la sortie série Q8 (pin 3). Puis ensuite il faut envoyer un coup d’horloge pour mettre le prochain bit (soit celui présent sur la PI7 au moment du chargement) sur la sortie Q8. Et ainsi de suite pour récupérer les bits restants.
Voici un exemple de code qui permet de récupérer l’octet d’un CD4021E. Attention à la façon dont vous enregistrez les bit LSB (Less Significant Bit) ou MSB (Most Significant Bit), l’exemple de code enregistre le premier bit lu comme le MSB et le dernier lu comme le LSB.
[pastacode lang= »c » manual= »%2F%2F%20d%C3%A9finition%20des%20pin%0A%23define%20CLOCK%20%20%2010%0A%23define%20LOAD%20%20%20%209%0A%23define%20IN%20%20%20%20%20%203%0A%23define%20BLINK%20%20%2013%0A%0Abyte%20serieVal%20%3D%20231%3B%20%20%2F%2Fmettre%20un%20valauer%20non%20nulle%0Abool%20blinkStatus%3Dtrue%3B%0A%0A%0Avoid%20setup()%20%7B%0A%20%20%2F%2Finitialisation%20de%20la%20liaison%20s%C3%A9rie%0A%20%20Serial.begin(9600)%3B%0A%0A%20%20%2F%2Fd%C3%A9finition%20du%20mode%20des%20pin%0A%20%20pinMode(BLINK%2C%20OUTPUT)%3B%0A%20%20pinMode(CLOCK%2C%20OUTPUT)%3B%0A%20%20pinMode(LOAD%2C%20OUTPUT)%3B%20%0A%20%20pinMode(IN%2C%20INPUT)%3B%0A%0A%7D%0A%0Avoid%20loop()%20%7B%0A%0A%20%20%2F%2F%20clignotement%20de%20la%20led%20pin%2013%20%C3%A0%20chaque%20lecture%20de%20donn%C3%A9es%0A%20%20digitalWrite(BLINK%2CblinkStatus)%3B%0A%20%20blinkStatus%3D!blinkStatus%3B%0A%0A%20%20%2F%2F%20mise%20%C3%A0%20un%20du%20pin%20LOAD%20pour%20le%20chargment%20de%20chaque%20PI%0A%20%20digitalWrite(LOAD%2C1)%3B%0A%20%20%2F%2F%20attente%20du%20chargement%20des%20donn%C3%A9es%0A%20%20delayMicroseconds(20)%3B%0A%20%20%2F%2F%20verrouillage%20des%20donn%C3%A9es%20avant%20de%20les%20transmettre%20par%20la%20liaison%20s%C3%A9rie%0A%20%20digitalWrite(LOAD%2C0)%3B%0A%0A%20%20serieVal%3D%20shiftSerialInChar(CLOCK%2CIN)%3B%0A%0A%20%20Serial.println(serieVal%2C%20BIN)%3B%2F%2Faffichage%20de%20la%20valeur%20en%20binaire%20%3D%3E%2010110010%0A%20%20Serial.println(%22——————-%22)%3B%0A%20%20%2F%2Fdelay%20pour%20chaque%20r%C3%A9cup%C3%A9ration%20de%20donn%C3%A9es%20%0A%20%20delay(1000)%3B%0A%7D%0A%0Abyte%20shiftSerialInChar(int%20pinClock%2C%20int%20pinData)%7B%0A%20%20byte%20temp%3D0%3B%0A%20%20byte%20valTemp%3D1%3B%0A%20%20%2F%2F%20d%C3%A9calage%20de%208%20fois%20pour%20r%C3%A9cup%C3%A9rer%20les%208%20bits%20du%20registre%0A%20%20for(int%20i%3D0%3Bi%3C8%3Bi%2B%2B)%7B%0A%20%20%20%20%2F%2F%20l’horloge%20est%20mise%20%C3%A0%20z%C3%A9ro%0A%20%20%20%20digitalWrite(pinClock%2C%200)%3B%0A%20%20%20%20%2F%2F%20lecture%20de%20la%20valeur%20sur%20le%20port%20s%C3%A9rie%20du%20CD4021%0A%20%20%20%20temp%20%3D%20digitalRead(pinData)%3B%0A%20%20%20%20valTemp%20%3D%20valTemp%20%3C%3C%201%3B%20%2F%2F%20d%C3%A9calage%20pour%20le%20nouveau%20bit%20qui%20arrive%0A%20%20%20%20valTemp%20%3D%20valTemp%20%7C%20temp%3B%20%2F%2F%20ajout%20du%20nouveau%20bit%20dans%20l’octet%20en%20derni%C3%A8re%20position%0A%20%20%20%20%2F%2F%20l’horloge%20est%20mise%20%C3%A0%201%20pour%20d%C3%A9caler%20les%20donn%C3%A9es%20du%20registre%0A%20%20%20%20digitalWrite(pinClock%2C%201)%3B%0A%20%20%7D%0A%20%20return%20valTemp%3B%0A%7D » message= » » highlight= » » provider= »manual »/]
Utiliser plusieurs CD4021E
Le principe est assez simple, comme il s’agit d’une liaison série avec un décalage, il suffit de mettre les CD4021E en série. Pour se faire on raccorde la sortie Q8 du premier sur l’entrée série (pin 11) du deuxième et on lit la sortie Q8 du deuxième. Il faut également relier les LOAD et CLOCK de chacun des éléments. Au bout du 8eme top d’horloge c’est les données du premier élément qui seront accessibles.
Ce montages série est très intéressant car il permet toujours de n’utiliser que 3 pins de la carte Arduino quelque soit le nombre de registres en série. En revanche, plus il y a de registres en série plus il faudra de temps pour récupérer les données.
Vous trouverez des informations complémentaires sur le site Arduino (voir lien en fin d’article).
Note
Il existe aussi plus simplement la fonction shiftIn d’Arduino 🙂
https://www.arduino.cc/en/Tutorial/ShiftIn
Et il doit y avoir un ou 2 sites dont j’ai pu m’inspirer mais j’ai oublié lesquels (merci à eux quand même).
Bonjour,
Merci beaucoup pour cet article, qui a été pour le moi le plus clair sur ce sujet. Du coup, j’ai a peu près tout compris, mais je me pose une dernière question.
Pour avoir plus de 8 entrées, vous suggérez de mettre plusieurs CD4021E en série. Mais le fait que nous récupérerions 8 bits ne permet-il pas de déjà recevoir plus de 8 entrée?
Avec votre exemple, on se contente de récupérer « un seul 1 », limitant effectivement le nombre d’entrées à 8, mais si on branche 2 départs d’un interrupteur vers 2 entrées parallèles du CD4021E, on peut bien récupérer deux 1, non? On peut donc imaginer que l’on peut en théorie mettre 11111111 (soit 255) entrées sur le CD4021E?
Y aurait-il une limitation électrique ou électronique à ce raisonnement? J’ai tenté vite fait le montage avec un interrupteur et 2 départs, et cela a l’air de fonctionner.
Merci pour votre retour (je cherche à programmer un lecteur mp3 commandé par une trentaine de boutons :))
bonjour,
merci pour le retour 🙂
pour répondre à votre question, effectivement quand on parle d’un octet il peut avoir 256 possibilités de 0 à 255.
le module CD4021E (8 entrées parallèle pour 1 sortie série) permet de faire 8 branchements en direct (donc huit boutons par exemple) ce qui permet de récupérer simplement un octet complet ou chacun des bits correspond l’état (0 ou 1) pour chacun des boutons. On pourrait imaginer un codage spécifique sur 256 (en décimal) mais le problème c’est que question branchement ça risque d’être compliqué et surtout il ne sera plus possible de savoir quel bouton à vraiment été appuyé.
par exemple 1 pour un bouton allumé et 0 pour un bouton éteint et on ajoute le résultat de tout les boutons.
imaginons 30 boutons, les premiers 20 appuyés (donc 1 à chaque fois ce qui donne 20) et les 10 derniers non appuyés donc éteints (0 pour chacun ce qui donne 0), j’ai donc un total de 20, je sais que 20 bouton sont appuyés. Maintenant si j’ai les 10 premiers qui sont éteints et les 20 derniers qui sont allumés, j’aurai aussi 20 mais ce ne sera pas les mêmes boutons allumés pour la même valeur de l’octet et je pense que vous devez savoir quels boutons ont été appuyés pour votre lecteur.
donc 4 module PISO en série et ça marchera pour 32 boutons.
Maintenant il existe d’autres solutions pour augmenter les entrées, des matrices (grand classique quand il s’agit de boutons), des multiplexeurs ou encore des extension d’entrée/sortie en IC par exemple.
en espérant avoir répondu à votre question.
Bonjour je m interrogé dans le cadre de la réalisation d’un joystick de l avantage d un registre vs une matrice exemple en 12 boutons je map ça en 3×4 ce qui me fait 7 fils contre 12 sur le registre du coup quel sont les avantage inconvénients du registre comparé à une matrice ?