Chuck Norris Machine : LCD HD44780 et thermal printer

Chuck Norris Facts Machine

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.

Chuck Norris Joke Ticket
Chuck Norris Joke Ticket
L’Interface Homme Machine se fait par l’intermédiaire d’un écran d’affichage LCD 16×2 et de deux switch momentanés, 1 rouge et 1 vert. En matière d’ergonomie, on reste pas loin du principe disant que : « Une bonne interface ne devrait avoir qu’un seul bouton ». Côté impression, le choix de l’imprimante thermique est un excellent compromis coût/rétention de l’information. Et puis, pouvoir repartir avec sa petite blague sur un ticket de caisse, ça claque !

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
Cartographie des GPIOs du Raspberry
Cartographie des GPIOs du Raspberry

Lorsque l’on développe un programme, il y a deux façons de se référer aux GPIOs :

  1. 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) ;
  2. 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
Ecran LCD Hitachi HD44780 1602
Ecran LCD Hitachi HD44780 1602

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.

IDPin LCD HD44780FonctionGPIO Raspberry (BCM)
1VSSMasseGND
2VDDAlimentation (+5V)+5V
3V0Contraste de l'affichage
0V = High contrast
5V = Low contrast
GND
4RSRegister Select
RS = 0 : commande
RS = 1 : donnée
GPIO 7*
5RWRead/Write : permet de lire (High) ou écrire (Low)GND
6EEnable (Clock)
cadencement transmission, validation R/W
GPIO 8*
7D0Entrée numériqueNot Used
8D1Entrée numériqueNot Used
9D2Entrée numériqueNot Used
10D3Entrée numériqueNot Used
11D4Entrée numériqueGPIO 25*
12D5Entrée numériqueGPIO 24*
13D6Entrée numériqueGPIO 23*
14D7Entrée numériqueGPIO 18*
15AAnode pour alimenter le rétroéclairage (backlight)+5V
16KCathode pour alimenter le rétroéclairage (backlight)GND
IDPin RED SwitchFonctionGPIO Raspberry (BCM)
17Pin +RED Switch LED +26*
18Pin -RED Switch LED -GND
19IN/OUTEntrée/sortie de l'interrupteur21*
20IN/OUTEntrée/sortie de l'interrupteurGND
IDPin GREEN SwitchFonctionGPIO Raspberry (BCM)
21Pin +GREEN Switch LED +4
22Pin -GREEN Switch LED -GND
23IN/OUTEntrée/sortie de l'interrupteur12*
24IN/OUTEntrée/sortie de l'interrupteurGND
IDPin Thermal PrinterFonctionGPIO Raspberry (BCM)
25VHAlimentation + 5VPower Adapter
26GNDAlimentation GNDPower Adapter
+ GND du Raspberry
27RXReceive Data14**
28TXTransmit DataNot Used
29DTRGNDNot 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 :

Schéma de câblage de l'ensemble Raspberry + HD44780 + Thermal Printer + Switch
Schéma de câblage de l’ensemble Raspberry + HD44780 + Thermal Printer + Switch (Cliquez pour agrandir)

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 :

  1. 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 ;
  2. 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 :

CGRAM Map du HD44780 UA00 (Japanese standard font)
CGRAM Map du HD44780 UA00 (Japanese standard font)

L’écran dispose au total de 3 types de mémoires :

  1. CGROM (Character Generator ROM) : espace mémoire préprogrammé et non modifiable ;
  2. CGRAM (Character Generator RAM) : 16 premiers emplacements (octets) de la CGROM dont les 8 premiers sont personnalisables ;
  3. 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 :

Custom pattern smiley
Custom pattern 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.

Test d'impression sur l'imprimante thermique
Test d’impression sur l’imprimante thermique

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.

Adaptateur jack femelle DC 5.5 x 2.1 mm
Adaptateur jack femelle DC 5.5 x 2.1 mm

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.

2 réflexions sur « Chuck Norris Machine : LCD HD44780 et thermal printer »

Laisser un commentaire

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