Come usare un display LCD 16x2 I2C con Arduino

Il display LCD 16x2 I2C è il classico LCD da 16 colonne e 2 righe con un piccolo adattatore già montato sul retro. Il vantaggio è immediato: invece di molti fili servono normalmente solo GND, VCC, SDA e SCL. Vediamo prima come funziona, poi i pin e infine la libreria Arduino.

Componenti necessari:

  • 1x Arduino UNO
  • 1x Display LCD 16x2 con I2C
  • Cavi jumper (breadboard opzionale)

Immagine del display

Foto del display LCD con I2C

Come funziona un LCD 16x2 I2C

Il display vero e proprio usa normalmente un controller compatibile con HD44780. Sul retro, il cosiddetto I2C backpack contiene spesso un espansore di porte come il PCF8574. Arduino invia i dati tramite il bus I2C; il backpack li converte nei segnali paralleli richiesti dal display.

Il bus I2C usa due linee: SDA per i dati e SCL per il clock. Ogni dispositivo possiede inoltre un indirizzo I2C. Nei backpack LCD 16x2 è molto comune 0x27, ma esistono anche moduli con indirizzo diverso, per esempio 0x3F.

A cosa servono i 4 pin I2C

GND

Massa del modulo: collegala a GND di Arduino.

VCC

Alimenta display e backpack. I comuni moduli per Arduino UNO sono normalmente usati a 5 V.

SDA - Serial Data

Linea dati I2C. Su Arduino UNO e Nano classico corrisponde al segnale A4/SDA. Sulle schede con pin SDA dedicato puoi usare direttamente quello.

SCL - Serial Clock

Linea di clock I2C. Su Arduino UNO e Nano classico corrisponde a A5/SCL. Su altre schede la posizione può cambiare.

Trimmer, backlight e indirizzo

Il piccolo trimmer sul backpack regola il contrasto. Se la retroilluminazione si accende ma non leggi nulla, ruotalo lentamente. Molti moduli hanno anche un jumper per la retroilluminazione e piazzole A0, A1 e A2 che possono modificare l'indirizzo I2C.

Collegare un LCD I2C ad Arduino UNO

Collegamento del display LCD I2C ad Arduino UNO
  • GND → GND
  • VCC → 5V
  • SDA → SDA / A4
  • SCL → SCL / A5

Sull'UNO R3 i pin SDA/SCL dedicati riportano gli stessi segnali di A4/A5: non serve collegare entrambe le coppie.

Libreria Arduino LiquidCrystal_I2C

Per questi moduli viene comunemente usata la libreria LiquidCrystal_I2C. Se non è installata, apri il Library Manager dell'Arduino IDE e installa una libreria compatibile con l'header LiquidCrystal_I2C.h. Le varie implementazioni possono avere piccole differenze, ma l'API seguente è una delle più diffuse.

LiquidCrystal_I2C lcd(0x27, 16, 2);

0x27 è l'indirizzo, 16 il numero di colonne e 2 il numero di righe.

Primo codice: scrivere sul display

lcd_16x2_i2c.ino
// https://nemiatools.com
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {{
  lcd.init();
  lcd.backlight();

  lcd.setCursor(0, 0);
  lcd.print("Hello Arduino!");

  lcd.setCursor(0, 1);
  lcd.print("NEMIA TOOLS");
}}

void loop() {{
}}

lcd.init() inizializza il modulo e lcd.backlight() accende la retroilluminazione. Da quel momento puoi usare print() e setCursor() quasi come nella versione parallela.

Comandi LiquidCrystal_I2C più utili

  • lcd.init() inizializza il display.
  • lcd.backlight() e lcd.noBacklight() controllano la retroilluminazione.
  • lcd.print() scrive testo o numeri.
  • lcd.setCursor() sceglie la posizione.
  • lcd.clear() cancella il display.
  • lcd.home() riporta il cursore all'inizio.
  • lcd.cursor(), lcd.noCursor(), lcd.blink() e lcd.noBlink() controllano il cursore.

Esempio: mostrare un valore che cambia

lcd_i2c_counter.ino
// https://nemiatools.com
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {{
  lcd.init();
  lcd.backlight();
  lcd.print("Tempo acceso:");
}}

void loop() {{
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
  lcd.print(" s    ");
  delay(200);
}}

Se 0x27 non funziona: I2C scanner

Se il display è cablato correttamente ma non risponde, cerca il suo indirizzo con uno I2C scanner:

i2c_scanner.ino
// https://nemiatools.com
#include <Wire.h>

void setup() {{
  Wire.begin();
  Serial.begin(9600);
}}

void loop() {{
  for (byte address = 1; address < 127; address++) {{
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {{
      Serial.print("I2C device: 0x");
      if (address < 16) Serial.print("0");
      Serial.println(address, HEX);
    }}
  }}
  delay(3000);
}}

Se il Monitor Seriale mostra, per esempio, 0x3F, usa LiquidCrystal_I2C lcd(0x3F, 16, 2);.

Perché scegliere I2C

La versione I2C occupa soltanto due linee di comunicazione, lasciando liberi molti pin Arduino per sensori, pulsanti e attuatori. Più dispositivi I2C possono inoltre condividere SDA e SCL se possiedono indirizzi compatibili.

Problemi comuni

Backlight acceso ma nessun testo: regola il trimmer e verifica l'indirizzo. Scanner senza dispositivi: controlla alimentazione, GND, SDA e SCL. Codice compilato ma display vuoto: verifica che la libreria installata usi la stessa API dell'esempio.