Utilizzare un display LCD a caratteri con CircuitPython

In questo articolo vi parlo di come utilizzare un display LCD a caratteri da CircuitPython sulla scheda Maker Pi Pico di cui vi ho parlato nell’articolo precedente, che vi invito a leggere qualora non l’aveste fatto dato che qui ometterò le cose già dette, soprattutto la questione dell’installazione delle librerie.

Sponsor

La scheda Maker Pi Pico è stata gentilmente offerta da Cytron Technologies

Display LCD a caratteri con backpack

Non mi dilungo nel parlare dei display LCD a caratteri dato che qui su settorezero ho scritto numerosi tutorial tempo fa, in particolare questo. Parlo però di un accessorio oserei dire indispensabile: il backpack I2C. Si tratta di un piccolo circuiti basato su un IO expander che, agganciati sul retro del display, permette di pilotarlo in I2C, risparmiando tantissimi pin. E’ possibile acquistare questi display con già il backpack montato oppure potete fare come ho fatto io: dato che ho tantissimi display LCD basati sul controller HD44780 e compatibili, ho comprato solo una confezione di backpack per convertirli. Si trovano su Amazon a due spicci:

In genere, questi qui che si trovano su Amazon, utilizzano l’IO Expander PCF8574 ma è possibile trovarli anche con l’MCP23008 o MCP23017 (e probabilmente altri). Chiaramente poi bisognerà utilizzare delle librerie per pilotare gli IO del display attraverso lo specifico expander, ma io qui parlerò solo del modello linkato che usa il PCF8574.

Sul corpo del PCB sono presenti:

  • un trimmer, per la regolazione del contrasto
  • 3 pad aperti nominati A0, A1, A2 che servono, eventualmente, per cambiare l’indirizzo I2C
  • un jumper per mantenere fissa la retroilluminazione
  • l’header maschio a 4 pin per il collegamento al bus I2C e la tensione. Le linee I2C hanno già le resistenze di pull-up a bordo verso la VCC.

I 3 pad di selezione indizzo chiudono le linee A0, A1, A2 dell’expander verso GND e normalmente sono aperti lasciando quei 3 pin a livello alto (non sono richieste resistenze di pull-up perchè sono interne) e dotando quindi il dispositivo di indirizzo I2C slave 0x27.

Il backpack va montato sull’LCD in questo verso, con l’header che fuoriesce verso la sinistra del display:

Modifica del BackPack per usare display a 5V con 3.3V

Il PCF8574 è fatto per lavorare in un range di tensioni da 2.5 a 6V per cui va bene sia con i display che operano a 3.3V, sia per quelli che operano a 5V. Il problema nasce nel momento in cui bisogna montarlo su un display 5V e interfacciarlo ad una logica a 3.3V : il problema non è tanto sulla retroilluminazione (che si potrebbe bypassare chiudendo una resistenza sul PCB del display che porta la corrente al led) ma è sulla logica.

Ho provato molti display in mio possesso, che sono tutti vecchi e funzionanti a 5V, e nessuno riesce a funzionare a 3.3V per cui ho pensato ad una modifica spicciola.

La modifica che illustro, però, può portare comunque il PCF8574 a danneggiarsi, per cui prendetela con le pinze: non mi assumo nessuna responsabilità per eventuali danni. Io la sto comunque usando da parecchio senza problemi, vi spiego di seguito in cosa consiste.

Fermo restando che la parte di interfacciamento verso il microcontrollore deve rimanere a 3.3V (sul VCC del backpack daremo la 3.3V in modo che le linee I2C abbiano il pull-up verso tale tensione non danneggiando gli IO del microcontrollore), possiamo dare i 5V soltanto al display.

Praticamente dal backpack dobbiamo rimuovere i pin 2 e 15 che si collegano, rispettivamente, al pin VCC e al pin Anodo-Retroilluminazione del display in modo che il PCF8574 abbia un’alimentazione separata (3.3V)da quella del display (5V). Facendo in questo modo il backpack si verrà a trovare con questi due pin mancanti e isolati dal display.

Poi unire sul display questi due pin con uno spezzone di filo:

Infine su uno di questi due pin saldiamo un altro filo che useremo per dare la 5V al display: la logica del display funzionerà a 5V, mentre l’IO expander invierà alle linee dati del display segnali con livello logico a 3.3V, che saranno interpretati correttamente.

Il display sappiamo che funziona normalmente in sola scrittura (gli IO normalmente sono tutti ingressi ad alta impedenza) e soltanto in un caso (la lettura dello stato) alcuni IO si portano in uscita presentando un livello logico, che in questo caso sarà 5V: questi 5V andranno verso l’IO expander che è alimentato a 3.3V.

L’expander può si funzionare fino a 6V, ma sul datasheet è dichiarato che gli IO possono sopportare fino a Vcc + 0.5V, ovvero 3.8V nel nostro caso dato che l’expander sta funzionando a 3.3V… Quindi il rischio è questo: l’istante in cui il display eventualmente restituisce lo stato e riporta su un pin una tensione di 5V verso l’expander, evento che dura comunque una frazione di secondo. Perchè ho detto eventualmente?

In un vecchio articolo ricorderete che abbiamo presentato una libreria di gestione display per i microcontrollori PIC che faceva uso di questa feature: la lettura del flag di Busy per correggere i problemi di temporizzazione che si hanno con controllers di diversa marca. Per fare questa operazione si porta il pin R/W a livello logico alto e si cambiano in ingresso gli IO collegati alle linee dati del display 7,6,5 e 4 e si attende che sulla linea D7 arrivi un livello logico alto mentre gli altri rimangono bassi: segno che il display è “pronto” per accettare altri comandi. Ecco è questo il momento in cui i 5V da D7 (o dalle altre 3 linee dati) possono arrivare ad un GPIO dell’expander, danneggiandolo perchè da datasheet, essendo alimentato a 3.3V, può accettare fino a 3.8V.

La libreria che ho utilizzato io non fa uso di questa feature (controllate anche voi perchè la vecchiaia potrebbe farmi sbagliare): nei comandi inviati infatti non leggo comandi in cui R/W viene portato a 1 e si legge dagli IO o si porta l’expander coi pin in ingresso anzichè in uscita. Difatti  la lettura dello stato non è strettamente necessaria ed è probabile che alcune librerie non la implementino proprio: controllate voi stessi. In molti magari collegano il pin di R/W ma lo tengono sempre a livello logico zero mantenendo il display sempre in scrittura : questo evita che il display vada in lettura e possa quindi inviare 5V sulle linee dati verso il dispositivo che lo controlla.

Quindi: se fate questa modifica, non è detto che il backpack duri in eterno: dovreste fare farie considerazioni come appena spiegato (ed è anche possibile che mi sia perso qualcosa per strada). Per stare più sicuri, magari, si potrebbero aggiungere delle resistenze dai pin del BackPack verso il display, o, molto meglio, acquistare un display fatto apposta. Insomma io sono qui per passione, per portare avanti un Hobby con quello che mi ritrovo e ritrovandomi a riciclare cose che ho in giro è chiaro che non sempre le cose possono andare bene!

Mi è capitato soltanto un frangente in cui il display non funzionava più e ho temuto il peggio: per prova l’ho collegato ad Arduino e ha funzionato, ho quindi formattato il Pico rimettendo tutto daccapo e ha tornato a funzionare. Il problema era dato da qualche strano malfunzionamento della libreria, probabilmente perchè avevo salvato i files non utilizzando un editor “sicuro” come specificato nell’articolo precedente.

Collegamento del display alla Maker Pi Pico

A questo punto collegheremo normalmente il backpack, montato sul display, ad un connettore Grove dotato di I2C (utilizzeremo il connettore Grove 4), mentre il filo singolo della 5V andrà collegato su VBUS del Raspberry Pi Pico, che presenta la 5V dalla porta USB. Il pin di VBUS è il primo in alto alla destra del connettore USB con il connettore USB in alto.

Per il collegamento al connettore Grove useremo un cavetto jumper Grove / Dupont femmina: 

  • Giallo: SCL
  • Bianco: SDA
  • Rosso: VCC
  • Nero: GND

Libreria

Nell’articolo precedente vi ho parlato del bundle librerie Adafruit, bene è presente una libreria per poter utilizzare il backpack I2C con i display a caratteri (adafruit_character_lcd), ma purtroppo è fatta per un prodotto Adafruit che utilizza un IO expander differente. Per fortuna su Github c’è tanta roba e ho trovato questa libreria che funziona alla perfezione: Dhalbert/CircuitPython_LCD.

Questa libreria, dice l’autore, deriva da quest’altra, che a me pare più completa in quanto supporta diversi tipi di IO expander, ma l’autore dice che qui ha apportato dei miglioramenti, per cui non ho indagato ulteriormente dato che mi ha funzionato al primo colpo e mi sta bene così.

Scarichiarmo la libreria dal tasto Code > Download Zip. Estraiamola, viene fuori una cartella chiamata lcd. Copiamo questa cartella, così com’è, dentro la cartella lib del Raspberry Pi Pico. Nella cartella lib dovremo includere anche la cartella adafruit_bus_device che troviamo nel bundle delle librerie Adafruit come ho spiegato nel precedente articolo.

Siamo pronti per un pezzetto di codice:

Codice

Con un editor di testo incolliamo questo codice:

# Test display HD44780 with PCF8574 Backpack by @cyb3rn0id
# Library by Dan Halbert:
# https://github.com/dhalbert/CircuitPython_LCD
 
import board
import busio
import time
from lcd.lcd import LCD
from lcd.i2c_pcf8574_interface import I2CPCF8574Interface
from lcd.lcd import CursorMode
 
# I2C interface on Grove 4 connector
# of Maker Pi Pico
i2c = busio.I2C(board.GP7, board.GP6)  # SCL (yellow), SDA (white)
 
# Talk to the LCD at I2C address 0x27 (default on PCF8574 backpacks)
# using the i2c interface previously created
# The number of rows and columns defaults to 4x20, so those
# arguments could be omitted in this case.
lcd = LCD(I2CPCF8574Interface(i2c, 0x27), num_rows=4, num_cols=20)
lcd.clear()
 
# set_cursor_pos(line, column) - 0-based index
lcd.set_cursor_pos(0,0)
lcd.print("LCD HD44780 test")
lcd.set_cursor_pos(1,0)
lcd.print("with I2C backpack")
lcd.set_cursor_pos(2,0)
lcd.print("on Maker Pi Pico")
lcd.set_cursor_pos(3,0)
lcd.print("by @CyB3rn0id")
time.sleep(2)
 
lcd.clear()
 
fl = 3.14
nu = 76832
 
lcd.set_cursor_pos(0,0)
lcd.print(str(fl))
lcd.set_cursor_pos(1,0)
lcd.print(str(nu))
 
# Make the cursor visible as a line.
lcd.set_cursor_mode(CursorMode.LINE)
 
while True:
    continue

e salviamo il file come code.py. Un po’ di spiegazioni:

La linea:

i2c = busio.I2C(board.GP7, board.GP6) # SCL (yellow), SDA (white)

inizializza l’I2C sul connettore Grove 4 della Maker Pi Pico, dove ci sono i GPIO 7 e 6. La linea :

lcd = LCD(I2CPCF8574Interface(i2c, 0x27), num_rows=4, num_cols=20)

avvia la libreria LCD tramite l’interfaccia PCF8574 (file di libreria i2c_pcf8574_interface.py) utilizzando l’interfaccia I2C creata prima che abbiamo semplicemente chiamato i2c (minuscolo) e l’indirizzo slave 0x27. Gli altri due parametri sono chiari: numero di righe e di colonne del display.

Il resto è spiegato nelle note. Non ci sono funzioni per scrivere numeri perchè in Python potete utilizzare la funzione str() che converte un numero in stringa, per questo dopo la schermata iniziale ho messo un ritardo di 2 secondi per poi cancellare il display e scrivere due numeri come stringa.

Links

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)