Gestion de l'afficheur SSD1306 OLED 128x32
publication: 10 février 2022 / mis à jour 22 février 2022

Appel à collaboration
Vous développez des montages, simples ou complexes avec ESP32 et ESP32forth.
Partagez-les ici sur ce site.
ESP32forth ne pourra se développer qu'avec la collaboration active de toutes les bonnes volontés.
Vos montages peuvent aider d'autres développeurs.
Les montages des autres développeurs peuvent vous aider.
Pour proposer un article ou un montage, cliquez ici
Listing complet des commandes OLED: Manage commands for OLED SSD1306 128x32 display
Utilisation de la librairie Wire
Ceci est la première utilisation du port I2C géré à partir de la librairie Wire. ici, nous allons voir en détail comment gérer un afficheur OLED SSD1306 128x32 pixels.
Tous les mots nécessaires à la gestion du port I2C sont disponibles dans le vocabulaire
Wire
. Accès à ce vocabulaire:
--> Wire vlist Wire.flush Wire.peek Wire.read Wire.available Wire.write Wire.requestFrom Wire.endTransmission Wire.beginTransmission Wire.getTimeout Wire.setTimeout Wire.getClock Wire.setClock Wire.begin
Dans ce vocabulaire, les mots essentiels pour notre application sont
Wire.begin
, Wire.beginTransmission
,
Wire.endTransmission
et Wire.write
.
Sur la carte ESP32, les deux ports GPIO dédiés à la transmission sur le port I2C sont:
- G21 I2C SDA
- G22 I2C SCL
L'affectation de ces ports GPIO au bus I2C s'effectue en exécutant le mot
Wire.begin
:
21 22 wire.begin drop
Chaque séquence de transmission sur le bus I2C est encadrée par les mots
Wire.beginTransmission
et Wire.endTransmission
.
Exemple:
addrSSD1306 Wire.beginTransmission
CTRL_COMMANDS Wire.tx
\ ....here transmission of command
addrSSD1306 Wire.endTransmission drop
La transmission des commandes ou données s'effectue à l'aide du mot
Wire.write
. Ce mot accepte en entrée une zone mémoire pointée
par l'adresse de début de cette zone et la longueur de cette zone.
Nous verrons plus loin comment définir de telles zones de données.
Branchement de l'afficheur OLED SSD1306 128x32
Voici le branchement de notre afficheur OLED à la carte ESP32:

La très faible consommation de cet afficheur OLED permet de l'alimenter à partir de la carte ESP32.
Commande de l'afficheur OLED
Nous aurions pu gérer cet afficheur à partir d'une librairie ARDUINO en l'intégrant au code source de ESP32Forth et recompiler ce code avec ARDUINO IDE. Il nous semble plus intéressat de repartir de zéro et créer nos propres définitions, indépendemment des libraries du langage C:- d'une part, pour montrer qu'il est possible de se passer de certaines librairies du langage C;
- d'autre part, pour définir des mots plus souples et limités à l'usage que nous souhaitons.
On commence d'abord par définir quelques constantes essentielles:
\ for SSD1306_128_64 \ 128 constant SSD1306_LCDWIDTH \ 64 constant SSD1306_LCDHEIGHT \ for SSD1306_128_32 128 constant SSD1306_LCDWIDTH 32 constant SSD1306_LCDHEIGHT \ definition of SSD1306 display dimensions in pixels SSD1306_LCDWIDTH constant DISPLAY_WIDTH SSD1306_LCDHEIGHT constant DISPLAY_HEIGHT $91 constant SSD1306_SETCONTRAST $a4 constant SSD1306_DISPLAYALLON_RESUME $a5 constant SSD1306_DISPLAYALLON $a6 constant SSD1306_NORMALDISPLAY $a7 constant SSD1306_INVERTDISPLAY $a8 constant SSD1306_SETMULTIPLEX $ae constant SSD1306_DISPLAYOFF $af constant SSD1306_DISPLAYON $d3 constant SSD1306_SETDISPLAYOFFSET $da constant SSD1306_SETCOMPINS $db constant SSD1306_SETVCOMDETECT $d5 constant SSD1306_SETDISPLAYCLOCKDIV $d9 constant SSD1306_SETPRECHARGE \ $00 constant SSD1306_SETLOWCOLUMN \ $10 constant SSD1306_SETHIGHCOLUMN $40 constant SSD1306_SETSTARTLINE $20 constant SSD1306_MEMORYMODE $21 constant SSD1306_COLUMNADDR $22 constant SSD1306_PAGEADDR $c0 constant SSD1306_COMSCANINC $c8 constant SSD1306_COMSCANDEC $a0 constant SSD1306_SEGREMAP $8d constant SSD1306_CHARGEPUMP $01 constant SSD1306_EXTERNALVCC $02 constant SSD1306_SWITCHCAPVCC \ Scrolling constants $2f constant SSD1306_ACTIVATE_SCROLL $2e constant SSD1306_DEACTIVATE_SCROLL $a3 constant SSD1306_SET_VERTICAL_SCROLL_AREA $26 constant SSD1306_RIGHT_HORIZONTAL_SCROLL $27 constant SSD1306_LEFT_HORIZONTAL_SCROLL $29 constant SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL $2a constant SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL \ Addressing modes $00 constant HORIZONTAL_ADDRESSING_MODE $01 constant VERTICAL_ADDRESSING_MODE $02 constant PAGE_ADDRESSING_MODE \ control: $00 for commands \ $40 for datas $00 constant CTRL_COMMANDS $40 constant CTRL_DATAS \ set adress of OLED SSD1306 display 128x32 pixels $3c constant addrSSD1306
Nous avons repris les les mêmes noms de constantes que les codes en langage C:
#define SSD1306_MEMORYMODE 0x20 #define SSD1306_COLUMNADDR 0x21 #define SSD1306_PAGEADDR 0x22 #define SSD1306_SETCONTRAST 0x81 #define SSD1306_CHARGEPUMP 0x8D #define SSD1306_SEGREMAP 0xA0 #define SSD1306_DISPLAYALLON_RESUME 0xA4 #define SSD1306_DISPLAYALLON 0xA5 #define SSD1306_NORMALDISPLAY 0xA6 #define SSD1306_INVERTDISPLAY 0xA7 #define SSD1306_SETMULTIPLEX 0xA8 #define SSD1306_DISPLAYOFF 0xAE #define SSD1306_DISPLAYON 0xAF #define SSD1306_COMSCANINC 0xC0 #define SSD1306_COMSCANDEC 0xC8 #define SSD1306_SETDISPLAYOFFSET 0xD3 #define SSD1306_SETDISPLAYCLOCKDIV 0xD5 #define SSD1306_SETPRECHARGE 0xD9 #define SSD1306_SETCOMPINS 0xDA #define SSD1306_SETVCOMDETECT 0xDB #define SSD1306_SETLOWCOLUMN 0x00 #define SSD1306_SETHIGHCOLUMN 0x10 #define SSD1306_SETSTARTLINE 0x40 #define SSD1306_EXTERNALVCC 0x01 #define SSD1306_SWITCHCAPVCC 0x02 #define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 #define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 #define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 #define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A #define SSD1306_DEACTIVATE_SCROLL 0x2E #define SSD1306_ACTIVATE_SCROLL 0x2F #define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3
Certaines de ces constantes ont une action complexe. Le fait de reprendre les mêmes noms du code source en langage C pour définir nos constantes en langage FORTH permet de rechercher la documentation dorrespondant à ces constantes utilisées comme commandes pour l'afficheur OLED.
Ici, nous avons trois constantes essentielles:
addrSSD1306
, valeur $3c, qui est l'adresse de l'afficheur OLED sur notre bus I2C. Cette adresse est détectée parWire.detect
dans cet article:
Détection d'un périphérique I2C.CTRL_COMMANDS
, valeur $00, qui indique que les octets qui suivent sont des octets de commande;CTRL_DATAS
, valeur $40, qui indique que les octets qui suivent sont des données à afficher.
On définit ensuite un certain nombre de mots qui vont simplifier l'envoi d'une séquence de commandes ou de données vers notre afficheur OLED:
\ begin I2C transmssion to SSD1306 OLED display : SSD1306beginTransmission ( -- ) addrSSD1306 Wire.beginTransmission ; \ memoryze transmitted bytes, interval [00..31] variable maxBytesSended \ end I2C transmssion to SSD1306 OLED display : SSD1306endTransmission ( -- ) -1 Wire.endTransmission drop 0 maxBytesSended ! ; \ if sended bytes > 32 end and restart transmission : incrementMaxBytes ( -- ) 1 maxBytesSended +! maxBytesSended @ 31 > if SSD1306endTransmission SSD1306beginTransmission then ; \ Send code c to I2C bus : Wire.send ( c -- ) >r 0 <# r> hold #> Wire.write drop incrementMaxBytes ; \ send a data array to SSD1306 connected via I2C bus \ CAUTION: array size max 32 bytes : sendStringToSSD1306 ( addr len -- ) SSD1306beginTransmission Wire.write drop SSD1306endTransmission ;
ATTENTION
Au cours du développement et essai de nos définitions, nous avons découvert que le tampon d'envoi de données sur le bus I2C est limité à 32 octets.
Les données sont placées dans ce tampon et transmises seulement quand le mot
SSD1306endTransmission
est exécuté.
Passons maintenant aux choses sérieuses.
On va définir une structure de données, créée à l'aide des mots
streamCreate:
et ;endStream
:
\ define a command or data stream for SSD1306 : streamCreate: ( comp:| exec: -- addr len ) create here \ leave current dictionnary pointer on stack 0 c, \ initial lenght data is 0 does> dup 1+ swap c@ toSSD1306 ; \ store ataddr length of datas compiled beetween \and here : ;endStream ( addr-var len ---) dup 1+ here swap - \ calculate cdata length \ store c in first byte of word defined by streamCreate: swap c! ;
A l'aide de ces mots, on définit deux structures, dispSetup
et
dispReset
permettant l'initialisation de l'afficheur OLED:
\ Initialize SSD105 128x32 display streamCreate: dispSetup CTRL_COMMANDS c, SSD1306_DISPLAYOFF c, SSD1306_SETDISPLAYCLOCKDIV c, $80 c, SSD1306_SETMULTIPLEX c, DISPLAY_HEIGHT 1- c, SSD1306_SETDISPLAYOFFSET c, $00 c, SSD1306_SETSTARTLINE $00 or c, SSD1306_CHARGEPUMP c, $14 c, ( CHARGE_PUMP_ON ) SSD1306_SEGREMAP $01 or c, ( Reverse mapping ) SSD1306_COMSCANDEC c, SSD1306_SETCOMPINS c, $02 c, SSD1306_SETCONTRAST c, $7f c, SSD1306_SETPRECHARGE c, $22 c, SSD1306_SETVCOMDETECT c, $40 c, \ SSD1306_MEMORYMODE c, HORIZONTAL_ADDRESSING_MODE c, SSD1306_DISPLAYALLON_RESUME c, SSD1306_NORMALDISPLAY c, SSD1306_DISPLAYON c, ;endStream \ Reset SSD105 128x32 display streamCreate: dispReset CTRL_COMMANDS c, SSD1306_DISPLAYOFF c, SSD1306_MEMORYMODE c, HORIZONTAL_ADDRESSING_MODE c, SSD1306_COLUMNADDR c, \ $21 $00 c, \ start $7f c, \ end SSD1306_PAGEADDR c, \ $22 $00 c, \ start $07 c, \ end SSD1306_DISPLAYON c, ;endStream \ main INITialization for SSD1306 128x32 OLED display : dispInit ( -- ) \ start the I2C interface using pin 21 and 22 on ESP32 DEVKIT V1 \ with 21 used as sda and 22 as scl. 21 22 wire.begin drop dispSetup dispReset ;
Exécution de dispInit
. L'affichage de ces pixels indique que
l'initiatialisation de l'afficheur OLED s'est exécutée avec succès:

Voici d'autres commandes utilisables ensuite pour contrôler l'affichage:
streamCreate: dispOn \ toggle display on CTRL_COMMANDS c, $af c, \ DISPLAYON ;endStream streamCreate: dispOff \ toggle display off CTRL_COMMANDS c, $ae c, \ DISPLAYOFF ;endStream \ store normal | inverse display state SSD1306_NORMALDISPLAY value _SSD1306_DISPLAY \ set display mode normal : dispNormal ( -- ) SSD1306beginTransmission CTRL_COMMANDS Wire.send SSD1306_NORMALDISPLAY Wire.send SSD1306endTransmission SSD1306_NORMALDISPLAY to _SSD1306_DISPLAY ; \ invert display mode : dispInvert SSD1306beginTransmission CTRL_COMMANDS Wire.send SSD1306_INVERTDISPLAY Wire.send SSD1306endTransmission SSD1306_INVERTDISPLAY to _SSD1306_DISPLAY ; : OledInvert ( -- ) \ test if actual display mode is normal _SSD1306_DISPLAY SSD1306_NORMALDISPLAY = if dispInvert else dispNormal then ;
Commandes avec paramètres
Le souci, avec les mots définis par streamCreate:
, c'est que leur contenu
n'intègre pas de paramètre. On va contourner ceci en créant le mot Wire.tx
qui transmet un seul code binaire intégré dans une pseudo-chaine de texte:
\ Send code c to I2C bus : Wire.send ( c -- ) >r 0 <# r> hold #> Wire.write drop incrementMaxBytes ;
On peut maintenant définir ces mots:
: setLine { page -- } SSD1306beginTransmission CTRL_COMMANDS Wire.send SSD1306_COLUMNADDR Wire.send $00 Wire.send \ start $7f Wire.send \ end SSD1306_PAGEADDR Wire.send page Wire.send \ start page Wire.send \ end SSD1306endTransmission ; \ pointer for current page [0..3] 0 value currentPage \ move pointer to next page : crLine ( ---) currentPage 1+ 3 and to currentPage currentPage setLine ; \ Reset SSD105 128x32 display streamCreate: dispReset CTRL_COMMANDS c, SSD1306_MEMORYMODE c, HORIZONTAL_ADDRESSING_MODE c, SSD1306_COLUMNADDR c, \ $21 $00 c, \ start $7f c, \ end SSD1306_PAGEADDR c, \ $22 $00 c, \ start $03 c, \ end ;endStream \ send 32x 0 value streamCreate: sendBlock32bytesWith0 ( -- ) CTRL_DATAS c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, $00 c, ;endStream \ clear a complete line : lineCLS ( -- ) 4 for aft sendBlock32bytesWith0 then next ; \ clear complete screen : OledCLS ( -- ) dispReset DISPLAY_HEIGHT 8 / for aft lineCLS then next ;
Le mot LineCLS
vide l'afficheur de son contenu.
Le mot crLine
force l'affichage vers la ligne suivante. Ce mot
boucle sur la ligne 0 après la ligne 3.
Le mot setContrast
ajuste la luminosité de l'afffichage.
Dans l'article suivant, on expliquera l'affichage de texte.
Legal: site web personnel sans commerce / personal site without seling