Lcd i2c PCF8574 new library

In passato ho già dedicato un articolo all’lcd i2c PCF8574, la possibilità di controllare un display Lcd con protocollo I2C.

lcd i2c PCF8574 new library mauroalfieri genuino

Se letto il mio articolo dedicato all’expander PCF8574 per il controllo dei display lcd in i2c sei già aggiornato sull’argomento.

Qualche settimana fa alcuni utenti mi hanno segnalato che il mio sketch si comportava in modo errato: solo il primo carattere del testo compariva sul display e tutti gli altri sembravano sparire nel nulla.

Dopo alcuni commenti scambiati con coloro che lamentavano il problema siamo riusciti a definire che il problema si presenta con le ultime versioni dell’IDE.

La soluzione dell’LCD i2c pcf8574 new labrary

La soluzione è arrivata da Alessandro, che ringrazio, per aver trovato la libreria scritta da Marco Schwartz che con il suo display funzionava alla perfezione risolvendo il problema.

Tuttavia altri appassionati, come Aldo, lamentano ancora il problema nonostante la libreria suggerita.

Ho quindi deciso di provare la libreria di Marco su una scheda I2C autocostruita per aver chiaro non solo il modo in cui lavora ma anche i collegamenti e per farlo ho usato un prototipo realizzato dall’amico Luca Dentella ( www.lucadentella.it ) e donatomi per dei test.

Il primo test che ho eseguito mostrava un display con tutti i blocchi caratteri della prima linea accesi e la seconda linea vuota, spenta.

Ho quindi indagato sulle possibili cause, facendomi aiutare dall’amico Nicola S., che già in passato aveva studiato a fondo il funzionamento dei display LCD con controllo a 4bit, la differenza evidenziata è principalmente nei collegamenti:

lcd i2c PCF8574 new library schema

infatti indagando nel codice della libreria scritta da Marco ho potuto leggere, miracoli dell’open-source, che il motivo per cui si comporta così con il mio display è la modalità in cui usa i pin del”expander PCF8574.

I pin del PCF86574 con la LiquidCrystal_I2C

In pratica il display testato da Marco, usa la configurazione:

PCF8574 Pin su PCF8574 Lcd HD44780
P0 4 Rs
P1 5 R/W
P2 6 En
P3 7 BL
P4 9 D7
P5 10 D6
P6 11 D5
P7 12 D4

mentre quello che ho provato io usa:

PCF8574 Pin su PCF8574 Lcd HD44780
P0 4 D4
P1 5 D5
P2 6 D6
P3 7 D7
P4 9 En
P5 10 R/W
P6 11 Rs
P7 12 BL

ho dedotto il tipo di connessione presente nel display utilizzato da Marco dalla libreria stessa, quindi potrebbe non essere perfettamente coincidente.

Ho quindi creato un fork della libreria di marco in modo da poter lavorare sulle differenze e modificato sia il .h sia il .cpp come ti mostro in seguito:

Modifiche alla LiquidCrystal_I2C.h

/*** 4bit data / 4bit control ***

// flags for backlight control 4bit data / 4bit command
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En B00000100  // Enable bit
#define Rw B00000010  // Read/Write bit
#define Rs B00000001  // Register select bit

*/

/*** 4bit control / 4bit data ***/

// flags for backlight control 
#define LCD_BACKLIGHT 0x00
#define LCD_NOBACKLIGHT 0x80

#define En B00010000  // Enable bit
#define Rw B00100000  // Read/Write bit
#define Rs B01000000  // Register select bit

In cui ho invertito i primi 4 bit da destra ( meno significativi ) con gli ultimi 4 bit ( più significativi ) usati dal collegamento del mio expander per consentire il corretto controllo del display lcd i2c pcf8574 con la libreria LiquidCrystal_I2C.

Modifiche alla LiquidCrystal_I2C.cpp

Il file .cpp deve essere modificato per consentire il corretto invio delle sequenze di bit all’expander pcf8574 che a sua volta li trasferisce al display, la prima modifica:

       /*** 4bit data / 4bit control ***

        // we start in 8bit mode, try to set 4 bit mode
        write4bits(0x03 << 4);
        delayMicroseconds(4500); // wait min 4.1ms
  
        // second try
        write4bits(0x03 << 4);
        delayMicroseconds(4500); // wait min 4.1ms
  
        // third go!
        write4bits(0x03 << 4);
        delayMicroseconds(150);
  
        // finally, set to 4-bit interface
        write4bits(0x02 << 4);

        /*** 4bit control / 4bit data ***/

        // we start in 8bit mode, try to set 4 bit mode
        write4bits(0x03);
        delayMicroseconds(4500); // wait min 4.1ms

        // second try
        write4bits(0x03);
        delayMicroseconds(4500); // wait min 4.1ms

        // third go!
        write4bits(0x03);
        delayMicroseconds(150);

        // finally, set to 4-bit interface
        write4bits(0x02);

si trova all’interno del metodo begin il cui scopo è inizializzare l’Lcd.

Poiché i valori dei bit di comando sono traslati rispetto a quelli di “dati” usati dalla versione originale della LiquidCrystal è necessario invertirli nella fase di inizializzazione.

Puoi quindi commentare le linee  originali in cui i bit venivano traslati di 4 posizioni: write4bits(0x03 << 4); e sostituirle con quelle riportate nel riquadro precedente: write4bits(0x03); in modo che al display arrivi 00000011 e non 00110000.

La seconda modifica riguarda il metodo send, richimato dalla printIIC che a sua volta viene richiamato dalla write4bit:

/************ low level data pushing commands **********/

/*** 4bit data / 4bit control ***

// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
        uint8_t highnib=value&0xf0;
        uint8_t lownib=(value<<4)&0xf0;
       write4bits((highnib)|mode);
        write4bits((lownib)|mode);
}

/*** 4bit control / 4bit data ***/

// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
        uint8_t highnib=value>>4;
        uint8_t lownib=value & 0x0F;
        write4bits((highnib)|mode);
        write4bits((lownib)|mode);
}

anche in questo caso la modifica riguarda lo shift dei bit dati rispetto a quelli di controllo.

I bit HIGH li estrai con la formula value>>4 per cui un valore 10010011 diventa 00001001;

I bit LOW li estrai con una operazione di AND mascherato a 0F = 00001111 da cui un valore simile a 10010011 diventa 00000011;

La funzione resta invariata nelle linee successive.

Download della libreria modificata

Trovi la libreria sul mio GitHub come fork della libreria di Marco Schwartz ma adatto a display che utilizzano come collegamenti tra l’LCD i2c PCF8574 quelli della seconda tabella del paragrafo “I pin del PCF86574 con la LiquidCrystal_I2C”.

lcd i2c PCF8574 new library git

Il video demo del display con la libreria adattata

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/lcd-i2c-pcf8574-new-library.html

12 commenti

Vai al modulo dei commenti

    • gianni il 9 Marzo 2016 alle 17:00
    • Rispondi

    Per impieghi grafici dovrei usare un Glcd. Necessitereì avere HW e SW per l’ impiego con I12c o Spi.
    Mi puoi dare indicazioni in merito ?
    Grazie

    1. Ciao Gianni,
      trovi tutorial per entrambe le modalità sul blog.

    • Alice il 16 Maggio 2016 alle 17:08
    • Rispondi

    Ciao Mauro,
    Sono Alice e sono una dottoranda a Ingegneria. Mi sono approcciata da poco ad Arduino ma quanto basta per scrivere uno sketch per pilotare un motore passo passo con telecomando ad infrarossi. Ora ho acquistato uno schermo lcd con relativo driver e vorrei usarlo per visualizzare di volta in volta gli steps e nome del tasto. Come potrei implementare il mio sketch di base? Fammi sapere se ti servono altre informazioni
    Alice

    1. Ciao Alice,
      sono certo che hai già in mente come procedere e quello che ti occorre è solo una conferma/confronto prima di procedere.
      Io ti suggerirei di dividere l’informazione per il display giocando con due linee: la prima per riportare il numero di step ed una seconda per riportare il pulsante premuto.
      Ogni volta che il motore compie uno step invii alla linea corrispondente il nuovo valore;
      Ogni volta che ricevi un codice dal telecomando e lo decodifichi ne invii il valore alla linea corrispondente del display;

  1. Buongiorno Mauro,
    E’ da poco che sono venuto a conoscienza del tuo blog, lo trovo molto interessante, quello che pubblichi è spiegato molto bene e si denota la tua esperienza hardware e software.
    Volevo domandare se fosse possibile avere una library che possa funzionare anche con i convertitori dotati di integrato PCF8574 che si trovano in internet o su Futura Shop.
    Sotto riporto pinout di questi convertitori, grazie, Giorgio.

    quello che si acquista in internet o su Futura Shop
    2846-LCDI2CINTERFACE usa:
    PCF8574 Lcd HD44780
    P0 – 4 – Rs
    P1 – 5 – R/W
    P2 – 6 – En
    P3 – 7 – BL
    P4 – 9 – D4
    P5 – 10 – D5
    P6 – 11 – D6
    P7 – 12 – D7

    1. Ciao Giorgio,
      ho scritto e rilasciato sul mio gitHub ( https://github.com/Mauroalfieri/LiquidCrystal_I2C ) una versione che usa i pin con definizione:
      BlackLight = P7
      Enable = P4
      Read/Write = P5
      Register select = P6
      Data4 = P0
      Data5 = P1
      Data6 = P2
      Data7 = P3

      invertendo i pin usati da Marco Schwartz che mi sembra corrispondano ai pin che segnali, prova a verificare come funzionano per comprendere le differenze e quale può essere adatta al tuo progetto.

  2. Grazie Mauro per la risposta, i pin che ho segnalato sono diversi da quelli di Marco, i 4 bit dati sono invertiti tra di loro e purtroppo non sono pratico nel variare i parametri nei 2 file .h e .ccp, speravo in un tuo aiuto, grazie, Giorgio.
    Pin di Marco:
    P0 4 Rs
    P1 5 R/W
    P2 6 En
    P3 7 BL
    P4 9 D7
    P5 10 D6
    P6 11 D5
    P7 12 D4
    Miei pin:
    P0 – 4 – Rs
    P1 – 5 – R/W
    P2 – 6 – En
    P3 – 7 – BL
    P4 – 9 – D4
    P5 – 10 – D5
    P6 – 11 – D6
    P7 – 12 – D7

    1. Ciao Giorgio,
      posso provare a scriverti una libreria adatta su commissione modificando la mia.
      Ho bisogno che mi invii almeno uno dei display da testare per provarla.
      Ti invio via email l’indirizzo ed i costi della commissione.

    • Ettore il 29 Maggio 2018 alle 14:53
    • Rispondi

    Buongiorno, vorrei farmi del male usando il terminale da raspberry usando i comandi i2cget e i2cset non saprei come utilizzare la logica e il datasheet PCF85741 e del display 16×02 (non saprei dove reperire il datasheet), accetto suggerimenti anche su periferiche semplici.
    Grazie Saluti
    Ettore

    1. Ciao Ettore,
      il datasheet puoi cercarlo su Google e sempre sullo stesso strumento puoi cercare esempi dei comandi che desideri utilizzare.
      Io purtroppo ho utilizzato il PCF8574 solo come descritto in questo articolo.

    • Andrea il 30 Giugno 2018 alle 17:46
    • Rispondi

    Ciao Mauro, so che l’articolo è vecchio , ma non trovo una soluzione. Il problema della stampa di un solo carattere, il primo di Hello World, rimane anche dopo aver scaricato la tua libreria modificata.
    Ho controllato 2000 volte i collegamenti ed è tutto corretto. il display è HD 44780 , io ho aggiunto il PCF8574PA.
    In passato avevo già testato il funzionamento, non vorrei che il problema fosse la nuova versione dell’ide, ma mi sembra strano.
    Potresti spiegarmi perchè viene stampato solo un carattere? a livello libreria intendo.
    Grazie della disponibilità

    1. Ciao Andrea,
      la mia versione della libreria, come ho spiegato, è legata ad un particolare tipo di connessione tra il display ed il PCF8574PA che usa i 4bit dati invertiti rispetto ai 4bit comandi.
      Ti consiglio di provare la libreria I2C di Marco S. il cui link è nell’articolo.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.