Guidé par le magazine « Linux Inside – Raspberry pour les débutants » dans la découverte de ce nano ordinateur, l’un des tutoriels proposait l’utilisation d’un écran LCD pour afficher les informations météo de sa ville… Ce tutoriel me paraissant accessible, je me suis donc orienté sur l’utilisation de l’écran LCD HD44780 1602 (16 caractères x 2 lignes) pour la première expérimentation des GPIOs de mon Raspberry Pi.
L’art. 1/2 s’intéresse aux aspects « bas niveau » du reverse engineering de la Chuck Norris Joke Machine. Ici sont détaillées toutes les notions nécessaires avant d’aborder, dans le second article, le code python qui pilotera la machine.
Bon, la météo c’est chouette mais pas passionnant et on se lasse assez vite du contenu affiché. En revanche, une bonne blague Chuck Norris, c’est nettement plus drôle (si tant est que les blagues Chuck Norris vous fassent marrer) et davantage adapté pour promouvoir son projet une fois finalisé qu’une température/hygrométrie. Parallèlement, j’ai découvert l’utilitaire « fortune » disponible sur les systèmes de type Unix et l’idée était lancée… nom de code : « Chucky Project ».
(Rétro)Spécification des exigences
La devise : Laugh and go ! Pour ce projet, il est question d’afficher, une blague Chuck Norris choisie aléatoirement parmi un gisement de Chuck Norris Fact. Selon la qualité de la blague, l’utilisateur peut (ou non) en demander l’impression.
Préambule : Rappel sur les GPIOs
Commençons par la signification des ces 4 lettres : GPIO est un acronyme pour Global Purpose Input Output : il s’agit des 40 broches (40 à partir du modèle B+) situées sur le bord du Raspberry. Ces broches sont des portes d’entrée/sortie qui permettent de communiquer avec « le monde réel » (LED, capteurs,…).
Les deux modes de fonctionnement des GPIOs
En se plaçant côté Raspberry, on peut les voir comme des prises de courant pour lesquels 2 modes sont possibles :
- INPUT (ou mode lecture) : le Raspberry lit l’état (0 ou 3.3V) des broches ;
- OUTPUT (ou mode écriture) : le Raspberry « allume » (toggle de 0V à 3.3V) ou « éteint » (toggle de 3.3V à 0V) les broches.
Numérotation des GPIO

Lorsque l’on développe un programme, il y a deux façons de se référer aux GPIOs :
- La numérotation BCM : numérotation logique des GPIOs telles qu’elles sont « vues » par le Raspberry (une mappe vous sera utile pour repérer l’emplacement) ;
- La numérotation BOARD : numérotation physique des GPIOs selon leur emplacement sur la carte.
Pour être tout à fait exact, parmi les 40 broches , certaines présentes des fonctions particulières (voir cartographie des GPIO ci-dessus) :
- des pins d’alimentation (deux 3.3V, deux 5V, huit masses) ;
- des pins proposant une liaison série UART (Universal Asynchronous Receiver Transmitter), SPI (Serial Peripheral Interface), I2C…
Connecter l’écran LCD Hitachi HD44780 1602 sur le Raspberry Pi
Tout d’abord, décrivons rapidement le périphérique d’affichage. Il s’agit d’un écran LCD 16×2 avec le contrôleur HD44780, très répandu, peu cher (moins de 5 €) et il fonctionne en 5V.
Les broches de l’écran

Voici donc l’écran : comme vous pouvez le voir sur la photo ci-dessus, 16 broches sont disponibles. Passons en revue la fonction de chacune d’entre elles en indiquant au passage sur quelle GPIO du Raspberry effectuer la connexion.
ID | Pin LCD HD44780 | Fonction | GPIO Raspberry (BCM) |
---|---|---|---|
1 | VSS | Masse | GND |
2 | VDD | Alimentation (+5V) | +5V |
3 | V0 | Contraste de l'affichage 0V = High contrast 5V = Low contrast | GND |
4 | RS | Register Select RS = 0 : commande RS = 1 : donnée | GPIO 7* |
5 | RW | Read/Write : permet de lire (High) ou écrire (Low) | GND |
6 | E | Enable (Clock) cadencement transmission, validation R/W | GPIO 8* |
7 | D0 | Entrée numérique | Not Used |
8 | D1 | Entrée numérique | Not Used |
9 | D2 | Entrée numérique | Not Used |
10 | D3 | Entrée numérique | Not Used |
11 | D4 | Entrée numérique | GPIO 25* |
12 | D5 | Entrée numérique | GPIO 24* |
13 | D6 | Entrée numérique | GPIO 23* |
14 | D7 | Entrée numérique | GPIO 18* |
15 | A | Anode pour alimenter le rétroéclairage (backlight) | +5V |
16 | K | Cathode pour alimenter le rétroéclairage (backlight) | GND |
ID | Pin RED Switch | Fonction | GPIO Raspberry (BCM) |
17 | Pin + | RED Switch LED + | 26* |
18 | Pin - | RED Switch LED - | GND |
19 | IN/OUT | Entrée/sortie de l'interrupteur | 21* |
20 | IN/OUT | Entrée/sortie de l'interrupteur | GND |
ID | Pin GREEN Switch | Fonction | GPIO Raspberry (BCM) |
21 | Pin + | GREEN Switch LED + | 4 |
22 | Pin - | GREEN Switch LED - | GND |
23 | IN/OUT | Entrée/sortie de l'interrupteur | 12* |
24 | IN/OUT | Entrée/sortie de l'interrupteur | GND |
ID | Pin Thermal Printer | Fonction | GPIO Raspberry (BCM) |
25 | VH | Alimentation + 5V | Power Adapter |
26 | GND | Alimentation GND | Power Adapter + GND du Raspberry |
27 | RX | Receive Data | 14** |
28 | TX | Transmit Data | Not Used |
29 | DTR | GND | Not Used |
* Pour rappel, c’est la numération BCM qui a été retenue ici. Vous auriez pu choisir n’importe quelle autre GPIO libre sur votre Raspberry.
** Pour la transmission de données, la GPIO 14 (BCM) est la liaison série UART0_TXD. Des modifications de la configuration du Raspberry sont nécessaires pour utiliser la liaison série : voir art. 2/2.
Le schéma de câblage de l’ensemble est le suivant :

ATTENTION : Il est nécessaire de placer des résistances (ici 330 ohms) entre les switch, LED et le backlight de l’écran. De manière générale, l’idée à retenir est que le courant qui sort du Raspberry (soit depuis les pins d’alimentation +3.3V ou +5V soit depuis les GPIOs) DOIT traverser une certaine résistance avant de boucler le circuit sur la masse du Raspberry. A défaut, vous créez en quelque sorte un court-circuit.
En images, de quoi se donner une idée du câblage à réaliser.
Les modes d’utilisation du LCD HD44780 1602
Dans le tableau du paragraphe précédent, nous avons vu que les broches D0 à D3 n’étaient pas connectées au Raspberry. Il faut savoir que l’écran LCD HD44780 1602 propose 2 modes de communication :
- mode 8 bits : les données et les commandes sont envoyées sur les pins broches D0 à D7. Avec ces 8 bits, l’octet codant chaque caractère à afficher est envoyé en une seule fois ;
- mode 4 bits : seules les pins D4 à D7 sont utilisées pour commander l’afficheur. Ne disposant que de 4 lignes pour envoyer un octet (codant le caractères à afficher), on transmet séquentiellement l’octet en 2 quartets : d’abord les 4 bits de poids fort suivis des 4 bits de poids faible. La ligne E (pin 6) doit être « pulsée » (impulsion d’au moins 450 ns d’après la documentation technique de l’écran, pour passer de 0 à 1 puis retour à 0) pour marquer le début et la fin de chaque demi-octet et ainsi cadencer la transmission.
Opter pour le mode 4 bits permet de ne pas hypothéquer 8 GPIOs côté Raspberry mais seulement 4 et simplifie d’autant le câblage.
Les mémoires du LCD HD44780 1602
Chaque ligne de l’écran est composée 16 matrices de 8×5 pixels qui peuvent être individuellement allumé ou éteint. Pour afficher ce que nous percevons comme un caractère, le contrôleur de l’écran doit donc, pour chaque matrice appliquer des patterns prédéfinis et stockées en mémoire.
Il existe (au moins) deux modèles : le HD44780UA00 dont la CGROM contient un set de caractères japonais et le HD44780UA02 dont la CGROM contient un set de caractères européen.
Pour ma part, je dispose du modèle japonais, pour lequel la CGRAM et la CGROM sont organisées de cette façon :

L’écran dispose au total de 3 types de mémoires :
- CGROM (Character Generator ROM) : espace mémoire préprogrammé et non modifiable ;
- CGRAM (Character Generator RAM) : 16 premiers emplacements (octets) de la CGROM dont les 8 premiers sont personnalisables ;
- DDRAM (Display Data RAM) : contient les caractères affichés à l’instant t à l’écran. Pour être affiché à l’écran, le message doit se trouver dans la DDRAM. Par exemple, pour afficher « Hello » à l’écran, il faut charger le pattern de H de la CGROM vers la DDRAM et faire pareil pour « e », « l », « l », »o ». L’adressage de la DDRAM dépends de la taille de l’écran LCD, pour le 16×2 :
Row1 0x80 0x81 0x82 0x83 0x84 0x85 0x86 … 0x8F
Row2 0xCO 0xC1 0xC2 0xC3 0xC4 0xC5 0xC6 … 0xCF
Alors concrètement, comment demander l’affichage d’un caractère sur l’écran depuis un script Python ? Et bien le mécanisme utilisé dans l’API HD44780 est très simple. Lorsque l’on demande l’affichage du caractère « a » par exemple, Python le convertit en binaire soit 0110 0001. Ensuite, la fonction d’affichage demandera à l’écran d’afficher le pattern stocké à l’adresse 0110 0001 (0110 étant les bits de poids forts identifiant la colonne dans la map CGRAM et 0001 étant les bits de poids faibles identifiant la ligne dans la map CGRAM). Et quel caractère est enregistré à cette adresse… le caractère « a » ! Plus précisément, chaque caractères (qu’on identifie par une adresse sur 1 octet) pointe lui-même sur une séquence de 8 octets qui définissent par des 0 et des 1 si les 8 lignes de 5 pixels sont allumés (1) ou non (0). C’est ce que nous allons voir dans le chapitre suivant…
Génération de caractères personnalisés
Comme on l’a vu précédemment, chaque caractère est dessiné grâce à une matrice de 8×5 pixels. Chacune des 8 lignes est encodée sur 1 octets :
- les 3 bits de poids forts sont placés à 0 ;
- les 5 bits suivants sont placés à 0 ou 1 selon l’état attendu du pixel de la colonne correspondante (allumé ou éteint).
On résume : 1 caractère correspond donc à un espace mémoire d’un octet dans la CGROM (lui-même identifié par une adresse sur un octet). Cet espace mémoire contienr une adresse qui pointe à son tour vers une suite de 8 octets permettant de décrire le pattern correspondant au caractère attendu.
Pour dessiner de nouveaux patterns et obtenir rapidement les séquences hexadécimales à charger dans l’écran, rendez-vous sur le site : http://www.quinapalus.com/hd44780udg.html. Par exemple, si on dessine un smiley :

Ainsi, pour charger ce nouveau caractère en CGRAM, il serait nécessaire d’enregistrer la séquence 0x1b,0x0,0xa,0x0,0x4,0x11,0xe,0x0 (du haut vers le bas) dans l’espace mémoire pointé par l’adresse du caractère à créer.
Pour plus de détail sur la fonctionnement technique de l’écran, je vous invité à consulter la documentation technique.
Connecter l’imprimante thermique CSN-A2-T sur le Raspberry
Alimentation électrique de l’imprimante
Pour tester le bon fonctionnement de l’imprimante, il est possible d’imprimer une page de test en maintenant le bouton enfoncé lors de la mise sous tension.

La page de test nous renseigne sur le jeu de caractères imprimables et les caractéristiques de l’imprimante. Côté transmission de données, il s’agit d’une interface TTL avec une vitesse de 9600 Bauds. Côté alimentation électrique… pour avoir perdu beaucoup de temps sur ce point, je vais peut-être vous en faire gagner énormément…
L’ayant lu sur le site Adafruit, j’ai tout d’abord tenter de faire fonctionner l’imprimante avec un chargeur 5V 4A… rien de rien, le bouton feed paper restait sans effet, même la diode verte ne clignotait pas. Premier problème identifié, mon connecteur jack femelle DC 5.5 x 2.1 mm (voir photo ci-dessous) était défectueux, le courant ne passait pas.

Ce problème résolu, la diode verte de l’imprimante clignote à la mise sous tension et le bouton feed paper déroule correctement le papier mais à ce stade, toujours impossible d’imprimer une page de test : lors du test, le papier sort selon une vitesse qui laisse imaginer que l’imprimante imprime effectivement quelque chose… mais le papier reste définitivement vierge ! Là, je commence à m’interroger sur l’imprimante. Après un contrôle visuel des composants internes (visibles en démontant le cache inférieur), tout semble OK.
L’imprimante étant livrée avec une page de test (imprimée par le fabricant pour s’assurer que le matériel fonctionne avant envoi), je cherche la solution ailleurs. Je teste un autre rouleau de papier, toujours pareil… Après (longue) réflexion, j’ai une piste : pas assez d’ampérage. Je branche un chargeur 5V 6A et là : BINGO !
Connexion de l’imprimante sur le port série du Raspberry Pi
L’imprimante peut envoyer et recevoir des données. Pour cela, elle dispose d’un pin TX et d’un pin RX. Nous n’enverrons pas de données Raspberry depuis l’imprimante, le pin TX de l’imprimante ne sera donc pas connecté. La pin RX de l’imprimante est connectée à la GPIO 14 du Raspberry. Les broches VH et GND sont reliées à l’adaptateur d’alimentation.
Il est nécessaire relier la masse de l’imprimante à celle du Raspberry pour garantir la synchronisation de la transmission de données du entre le Raspberry et l’imprimante.
Si les masses ne sont pas reliées, des bits seront perdus aléatoirement lors de la transmission des données, ce qui produira un décalage dans la réception des bits côté imprimante. Ce décalage aura pour effet de remplacer certains caractères par des symboles Chinois ou Japonais. Ayant rencontré ce problème, lors de mes investigations, j’avais pu contourner le problème en insérant un time.sleep(3) entre chaque caractères envoyés.
Référez-vous au tableau ainsi qu’au schéma de câblage ci-dessus pour connecter l’imprimante. Si besoin, la documentation technique de l’imprimante thermique.
Good job !
BIEN JOUE MON PETCH !!!!!!!!!
Bonjour,
Je cherche à réaliser ce projet, mais sans écran lcd, y a t’il possibilité de se passer de table de prototypage ?
Merci d’avance !
Robin
Bonjour,
Oui, il est tout à fait possible de se passer du support de prototypage.
Sans l’écran, cela fait 6 fils en moins. Ne restent plus que les boutons (on peut en mettre un seul, sans LED) à connecter. De plus, ce projet remonte à mes débuts dans le programmation des GPIOs en Python et on peut s’affranchir des résistances (physiques) pull-up ou pull-down de manière logicielle avec la librairie RPi.GPIO.
Et enfin, vous pouvez également opter pour une imprimante thermique USB : la connexion sera d’autant simplifiée.
C’est d’ailleurs ce que j’ai fait une version épurée, avec un bouton d’arrêt d’urgence.
N’hésitez pas si vous avez d’autres questions.
Chucky