PC Epd 1.54"V1 - 2018 |
Bibliothèque de gestion d'afficheur e-paper |
Téléchargements
|
Aperçus d'écrans
|
Documentation
|
Bugs connus
|
Anciennes versions
|
Objet
Cette bibliothèque est destinée à être utilisée avec un afficheur e-paper 3 couleurs, sans rafraichissement partiel, de 1,54 pouces (e-paper display (EPD) 1.54 200x200, type B fabriqué par Good Display (http://www.good-display.com/) et distribué par Waveshare (www.Waveshare.com) avec des microcontrôleurs disposant d’une faible quantité de mémoire RAM (typiquement, 2ko dans le cas des modules Arduino).
Abstract: This library can managed a 1.54 inch e-paper display type B (no partial refresh) with a low memory microcontroller (typically: some Arduino with 2kb RAM). The functionalities of the library are:
- display management (init..., see Waveshare)
- clear the display
- fill the display
- draw horizontal lines
- write text
The RAM used for data is lower than 300 bytes (temporary RAM).
Téléchargement
Version 1 : pour Arduino (2018/02)
Quelques rappels
Pour comprendre l’intérêt de cette bibliothèque, il est nécessaire de rappeler quelques particularités de fonctionnement des deux familles disponibles en 2018 :
- Afficheurs 2 couleurs (blanc et noir) : rafraichissement partiel (il est possible d’écrire à une position particulière en (X, Y) de la mémoire écran.
- Afficheurs 3 couleurs (blanc, noir, rouge) : pas de rafraichissement partiel, il faut réécrire la mémoire écran depuis la position 0x0 jusqu’au dernier pixel à modifier (ou au moins, jusqu'au dernier pixel modifié par rapport à l'affichage courant) et ceci, en général, sur deux bancs mémoire.
Cette bibliothèque concerne les afficheurs 3 couleurs sans rafraichissement partiel.
Dans les bibliothèques proposées par Waveshare, le programme utilisateur doit disposer d’une image de la mémoire écran de l’afficheur de façon à positionner les pixels à écrire et faire ensuite un transfert de cette image mémoire dans la mémoire de l’afficheur.
Avec une résolution de 200x200, il faut donc 40000 bits (en fait 80000 comme on verra plus loin) soit 5ko de mémoire. On ne dispose pas d’une telle capacité de RAM dans un Arduino pro micro (2ko). ni dans bon nombre d'autres microcontrôleurs. Et parfois, on ne dispose pas non plus d'assez de mémoire flash pour stocker une image statique.
Pour s’en sortir, il est donc nécessaire de remplir la mémoire « à la volée » sans stocker d’information dans une image de la mémoire écran. C’est ce que permet de réaliser cette bibliothèque.
Avant d’aller plus loin, je vais décrire le cas d’usage pour lequel j’ai créé cette bibliothèque. Cela vous permettra de voir si vous êtes dans un cas similaire et si donc, cette bibliothèque est susceptible de vous intéresser.
Cas d’usage
Vous trouverez sur ce site quelques réalisation de compteurs Geiger Muller très basse consommation (de l’ordre de 30µA).
Ils utilisent un afficheur LCD à segments pour l’affichage du comptage et de quelques autres informations.
Pour un nouveau modèle, je souhaitais pouvoir afficher plus d’informations. Pour cela, j’avais les possibilités suivantes :
- Utiliser un afficheur LCD à segment disposant des possibilités d’affichage correspondantes. Ça n’existe pas tout fait. Quant à le faire réaliser, c’est trop coûteux pour un montage d’amateur et de plus, il n’est pas certain que cela soit réalisable sans qu’il y ait un nombre de signaux à gérer prohibitif.
- Utiliser un afficheur LCD graphique : à part peut-être un écran chez Toshiba, tous les écrans LCD graphiques consomment trop pour que cela réponde au cahier des charges (plusieurs centaines de µA pour les meilleurs, quelques mA pour la plupart).
- Utiliser un afficheur epaper dont la consommation est certe élevée lors du rafraichissement (quelques mA) mais nulle une fois le rafraichissement terminé.
C’est donc cette troisième solution que j’ai expérimentée. Problème, le temps d’écriture et de rafraichissement est très long (environ 6 secondes). Outre la consommation lors de cette opération, ce type d’afficheur n’est pas utilisable pour afficher des informations variant souvent.
Dans le cas présent, je l’ai donc dédié à l’affichage des alarmes, du niveau de la batterie, des valeurs min, max et moyenne du comptage : toutes ces informations varient très peu en régime permanent. Dans mon cas, je peux envisager une mise à jour de l’affichage une fois toute les heures (ou toutes les 24heures, ou en cas d’alarme) si les informations affichées ont changé depuis le dernier affichage.
Voici deux images qui illustrent trois cas d’affichage typiques :
- Première image : pas d’alarme, une batterie est pleine, l’autre presque pleine.
- Deuxième image : une batterie est presque vide.
- Troisième image : une batterie est presque vide et il y a une alarme (dépassement du maximum).
Fonctionnement de l’afficheur
L’EPD comporte deux bancs mémoire : un pour le blanc et noir (nommé BLACK par la suite), l’autre pour le rouge (nommé RED par la suite).
Chaque ligne comporte 200 pixels. Il y a 200 lignes.
Il faut 2 bits pour écrire un pixel sur le banc BLACK et 1 bit pour écrire un pixel sur le banc RED.
On ne peut pas revenir en arrière lorsque l’on commence à écrire (pas de rafraichissement partiel i.e. pas de positionnement à un point quelconque de la mémoire écran).
Les coordonnées du premier point de chaque banc sont 0x0.
La couleur rouge (banc RED) se superpose aux couleurs blanches et noires. Lorsque l’on écrit du rouge sur blanc, la couleur résultante est rouge vif. Lorsque l’on écrit du rouge sur noir, la couleur résultante est rouge foncé.
Si l’on veut afficher du blanc, il faut écrire sur le banc BLACK avec le paramètre UNCOLORED (cf. bibliothèque).
Si l’on veut afficher du noir, il faut écrire sur le banc BLACK avec le paramètre COLORED.
Si l’on veut afficher du rouge, il faut écrire sur le banc RED avec le paramètre COLORED.
On ne peut pas afficher du blanc avec le banc RED. Si l’on écrit sur ce banc avec le paramètre UNCOLORED, le pixel correspondant est transparent.
Cette bibliothèque est-elle utilisable avec un afficheur 2.13 pouces ou 2.9 pouces du même fabricant ? En théorie oui, en pratique, non. En effet, pour une curieuse raison, la largeur correspond au petit côté de l'afficheur et la hauteur au grand côté. Sauf à vouloir utiliser l'afficher dans ce sens, la bibliothèque ne sera pratiquement pas utilisable puisqu'elle écrit des lignes dans le sens de la largeur.
Principe de la bibliothèque
Imaginez une imprimante à aiguille de l’ancien temps. La tête d’imprimante comporte 8 aiguilles verticales (en général) et se déplace de la gauche vers la droite. Lorsqu’un caractère doit être imprimé, les aiguilles impriment les premiers pixels verticaux du caractère, puis les second, puis etc. jusqu’à avoir imprimé la largeur complète du caractère. Le processus redémarre pour le caractère suivant, et ce, jusqu’à la fin de la ligne.
La bibliothèque fonctionne selon le même principe sauf que la tête ne comporte qu’une seule aiguille. L’impression d’un caractère se fera donc ligne de pixel par ligne de pixel sur toute la ligne et le processus se répètera sur la ligne suivante jusqu’à ce que l’on ait imprimé toute la hauteur des caractères.
Un processus d’affichage suivra donc l’enchaînement suivant :
- Réveil de l’afficheur (s’il était en mode SLEEP) => EpdInit().
- Sélection du banc BLACK => EpdSessionStart(BLACK) Le pointeur dans la mémoire du banc RED est à 0x0.
- Affichage de lignes colorées ou non, de caractères, remplissage de zones, etc., toujours à partir de la position courante du curseur (i.e. du pointeur dans la mémoire du banc BLACK de l’afficheur).
- Sélection du banc RED => EpdSessionStart(RED) Le pointeur dans la mémoire du banc RED est à 0x0
- Affichage de lignes colorées ou non, de caractères, remplissage de zones, etc., toujours à partir de la position courante du curseur (i.e. du pointeur dans la mémoire du banc RED de l’afficheur).
- Affichage effectif (REFRESH) => EpdSessionClose()
Les primitives disponibles
Les programmes
En suivant ce lien, vous trouverez un exemple d'utilisation des primitives décrites ci-après. Les affichages générés se trouve dans la section Aperçus d'écrans.
Les sources de l'ensemble des fichiers sont disponibles dans la section téléchargement
Les principales variables d'état et constantes
- EPD_WIDTH, largeur de l'afficheur en pixel (200)
- EPD_HEIGHT, hauteur de l'afficheur en pixel
- RED, utilisé dans l'appel de certaines primitives pour désigner le banc à sélectionner (ici, RED)
- BLACK, utilisé dans l'appel de certaines primitives pour désigner le banc à sélectionner (ici, BLACK)
- INVERTED, utilisé dans la primitive d'écriture d'une string pour indiquer une inversion (fond noir, caractères blancs pour le banc BLACK et fond rouge, caractères transparents pour le banc RED
- NOTINVERTEDutilisé dans la primitive d'écriture d'une string pour indiquer une écriture normale (fond blanc, caractères noir pour le banc BLACK et fond transparent, caractères rouges pour le banc RED
- COLORED, utilisé dans l'appel de certaines primitives pour indiquer que les pixels doivent être affichés en noir pour le banc BLACK et en rouge pour le banc RED
- UNCOLOREDutilisé dans l'appel de certaines primitives pour indiquer que les pixels doivent être affichés en blanc pour le banc BLACK et en transparent pour le banc RED
Les primitives
int EpdInit(int cs, int dc, int rst, int busy);
Initialisation de l’afficheur avec l’attribution des pins pour les signaux CS, DC, RST et BUSY. Réveille l’afficheur s’il était en mode SLEEP. Doit être appelé au moins une fois.
void EpdReset(void);
Réveil de l’afficheur s’il était en mode SLEEP
void EpdSleep(void);
Passage en mode SLEEP. L’afficheur ne consomme plus d’énergie et ne répond plus aux commandes sauf à un signal RESET.
bool EpdSessionStart(int Bank);
Initialisation d’une session d’affichage sur le banc "Bank" (RED ou BLACK). La fonction rend faux si l’on essaye de sélectionner le banc BLACK alors que l’on a démarré une session sur le banc RED.
void EpdSessionFill(bool Color);
Remplissage de l’écran depuis la position courante du curseur jusqu’à la fin de la mémoire écran. Color = UNCOLORED pour la couleur blanche (banc BLACK) ou transparente (banc RED).
"Color" = COLORED pour la couleur noire (banc BLACK) ou rouge (banc RED).
Effectue le REFRESH (fait un EpdSessionClose)
void EpdSessionClose();
Fin de la session d’affichage. Effectue un REFRESH (affichage effectif). Après cette commande, il est possible de sélectionner de nouveau le banc BLACK.
void EpdSessionClearDisplay();
Effacement total de l’écran (banc BLACK et RED). À la fin de la commande, l’écran est blanc.
void EpdSessionWriteString(unsigned int nrSpace, const char * text, int nrFont, bool InvertedChar, bool InvertedFill);
Écriture d’une chaine de caractère (terminée par NULL).
- "nrSpace" est le nombre de caractères « Espace » à afficher avec le premier caractère du texte.
- "text" est la chaine de caractère à afficher
- "nrFont" est le numéro de la fonte à utiliser. La bibliothèque est fournie avec une fonte 20 et une font spéciale de 2 pixel de haut pour faciliter certains dessins (voir l’exemple).
- "InvertedChar" : vrai si on inverse la couleur du fond avec la couleur du caractère. Attention, la signification est différente selon le banc :
- Banc BLACK : écriture blanc sur noir si InvertedChar = true, Noir sur blanc sinon.
- Banc RED : écriture d’un caractère transparent si InvertedChar=true, rouge sinon.
- "InvertedFill" : la fonction remplie automatiquement la fin de la ligne avec la couleur blanche (banc BLACK) ou transparente (banc RED). Si InvertedFill = true, le remplissage se fera avec la couleur noire (banc BLACK) ou rouge (banc RED).
bool EpdSessionGoToLineAbs(unsigned int L, bool Color);
Positionnement à la ligne "L" de l’afficheur. "L" doit être supérieure à la ligne courante (on ne peut pas revenir en arrière). "Color" indique la couleur à utiliser depuis la position courante du curseur jusqu’à la fin de la ligne qui précède la ligne "L". "Color" peut valoir COLORED ou UNCOLORED.
La fonction rend faux si la ligne est supérieure à 200.
bool EpdSessionGoToLineRel(unsigned int L, bool Color);
Positionnement à la ligne courante + "L". Pour le reste, le fonctionnement est le même que la fonction EpdSessionGoToLineAbs.
La fonction rend faux si la ligne devient supérieure à 200.
int EpdSessionGetFontWidth(int nrFont);
Donne la largeur de la fonte "nrFont" (0 si la fonte n’existe pas).
int EpdSessionGetFontHeight(int nrFont);
Donne la hauteur de la fonte "nrFont" (0 si la fonte n’existe pas).
void EpdDisplayFrame(const unsigned char* frame_buffer_black, const unsigned char* frame_buffer_red);
Cette fonction provient de la bibliothèque Waveshare et permet d’afficher une image (située en flash pour les microcontrôleurs ne disposant pas de suffisamment de mémoire RAM).
Aperçus d'écrans
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 1 du programme donné en exemple (EpdSessionClearDisplay()). |
|
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 2 du programme donné en exemple. | |
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 3 du programme donné en exemple. | |
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 4 du programme donné en exemple. | |
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 5 du programme donné en exemple. | |
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 6 du programme donné en exemple. | |
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 7 du programme donné en exemple. | |
L'image ci-contre représente l'état de l'afficheur après exécution de l'exemple 8 du programme donné en exemple. |
Informations sur la version 1 de la bibliothèque
Environnements et plateforme cible
- Testé sur Arduino Pro micro 3.3V 8Mhz.
- Développé sur l'environnement prévu pour Arduino.
- Langage C. Il est possible de porter la bibliothèque en C++
Fichiers
- Programme : PC_Epd_154_low_memory.cpp et PC_Epd_154_low_memory.h
- Includes : font20.c et font2line.c
Bugs connus et évolutions
Vous pouvez signaler les bugs des programmes en utilisant le contact indiqué sur la page d'accueil. "m" pour mineur, "M" pour majeur, "A" pour amélioration.
Version 1.0
Néant