SchedulerLCD: Libreria per stampare su un LCD senza bloccare Arduino

Cosa vuol dire scrivere su un LCD senza bloccare Arduino? Cosa vuol dire scrivere “codice no blocking”??
Vediamo di capire di cosa stiamo parlando…

SchedulerLCD
Download Library SchedulerLCD

Quando aggiungiamo un display LCD ad un progetto Arduino, probabilmente è perché ci interessa informare l’utente dei vari cambiamenti di stato del sistema o per un semplice feedback dopo una operazione esterna compiuta dall’utente stesso… beh, fin qua niente di particolare direte voi.. Faccio l’include nel mio sketch di una qualche libreria per gestire l’LCD come ad esempio la nota LiquidCrystal e dopo aver istanziato e inizializzato un oggetto lancio una chiamata del genere: lcd.print(“Evento sistema…!”).

..e se abbiamo più eventi? E per eventi intendiamo ad esempio:
la variazione di temperatura e umidità, il cambio di stato di un sensore pir ecc… come faccio ad informare l’utente su più eventi anziché uno??????
Qualcuno potrebbe dire: è semplice, basta fare così:

lcd.print(“TEMP…!”);
lcd.print(“HUMI…!”);
lcd.print(“PIR…!”);
// e via dicendo…

… ma c’è una cosa da tenere presente, con un clock di 16MHz l’utente davanti al display non distinguerebbe nemmeno un puntino con una velocità così alta tra un informazione e l’altra! Penserà che il sistema sia impazzito!!!!! Quindi facciamo così: aggiungiamo un delay tra una print e la successiva:

lcd.print(“TEMP…!”);
delay(2000);
lcd.print(“HUMI…!”);
delay(2000);
lcd.print(“PIR…!”);
delay(2000);

Adesso ogni informazione sul display sarà visualizzata per 2 secondi, quindi l’utente avrà tutto il tempo per leggere le varie informazioni.
Sorge un problema però! A questo punto, facendo dei semplici calcoli: 2 * 3 = 6 … cioè, se per ogni print blocchiamo Arduino per 2 sec. con sole 3 print stiamo bloccando Arduino per ben 6 secondi … e questo non va bene!

Come risolvere il problema?
Tempo addietro scrissi un articolo dove dimostrai e spiegai come fosse possibile evitare di bloccare Arduino abbandonando la funzione delay a favore della funzione millis.
Basandomi su quella logica ho scritto SchedulerLCD una libreria per stampare su display lcd senza bloccare Arduino. Forse chiamarla libreria è un parolone, si tratta di 100 righe di codice, niente di che, ma andateveli a leggere 😉

Come funziona SchedulerLCD?
Andiamo a vedere l’esempio che ho preparato insieme alla libreria:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SchedulerLCD.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
SchedulerLCD<LiquidCrystal_I2C> schedule(&lcd);

String mystring;
float temp = 30.5;

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


  // è possibile saltare questa chiamata
  // di default viene settato un timer di 2000 millisecondi cioè 2 secondi
  schedule.setTimer(1000); // tempo tra una print e la successiva in milliSecondi
}

void loop()
{
  mystring = "Temp: " + (String)temp;

  schedule.print("Rilevata", mystring.c_str(), "\0");
  schedule.print("Prima riga", "\0");
  schedule.print("", "Seconda riga", "\0");
  schedule.print("AreaCom", "SchedulerLCD", "\0");
  schedule.print("Hello", "World!", "\0");

  schedule.reset();
}

Questa libreria non reimplementa un set di funzioni per gestire gli LCD, ma vuole essere una sorta di scheduler per gestire le stampe sul display.
In che modo vuole gestirle? Assegnando un certo tempo di visualizzazione sul display senza bloccare Arduino con la funzione delay. Il tempo di visualizzazione sul display potete sceglierlo voi ovviamente altrimenti di default è settato a 2000 millisecondi ovvero 2 secondi.
Non implementando funzioni per la gestione del display, la SchedulerLCD si appoggia alla ben nota LiquidCrystal.
Nello sketch quindi includiamo normalmente la LiquidCrystal ed ovviamente la SchedulerLCD.
Cosa c’è di nuovo nel codice quindi? Analizzare lo sketch.
Iniziamo andando ad istanziare un oggetto della SchedulerLCD per poterla usare ed andremo a farlo in questo modo:

SchedulerLCD<LiquidCrystal_I2C> schedule(&lcd);

Avete notato il parametro &lcd che viene passato al costruttore??? Quello che abbiamo passato è l’indirizzo puntanto dall’oggetto LiquidCrystal_I2C creato in precedenza, ecco perché vi dicevo che la libreria si appoggia alla LiquidCristal. Una cosa da sottolineare è che avremmo potuto usare anche la LiquidCristal per i display senza “convertitore seriale”, basta andare a sostituire LiquidCrystal_I2C con LiquidCrystal in questo modo:

SchedulerLCD<LiquidCrystal> schedule(&lcd);

Adesso che abbiamo creato il nostro oggetto dobbiamo settare la durata di visualizzazione per le informazioni che dovranno apparire sul display. Per fare questo useremo il metodo setTimer.
Ed andremo a farlo dentro la funzione setup in questo modo:

schedule.setTimer(1000);

Con questa istruzione andremo a decidere quindi la durata di ogni singola visualizzazione in millisecondi, in questo caso avremmo una durata di 1 secondo.
Se questa chiamata viene omessa, non succede niente perché di default è già impostato un tempo di 2 secondi.

A questo punto possiamo stampare uno oppure una serie di messaggi sul nostro LCD e guardare come vengono scanditi nell’ordine in cui li abbiamo scritti allo scadere del tempo che abbiamo impostato.
Per farlo andiamo a scrivere nel loop:

schedule.print(“Hello”, “World!”, “\0”);

perché ho scritto “Hello” “World!” invece di “Hello World!” ??? Ipotizzando di avere sottomano un lcd a 2 righe in questo modo sto stampando sulla prima riga Hello e sulla seconda Word!
E se fosse stato un display a 4 righe e avrei deciso di stampare su 4 righe??? Semplicemente avrei fatto così:

schedule.print(“Hello”, “World!”, “Ciao”, “Mondo!”, “\0”);

volendo lasciare vuota la seconda riga invece avrei fatto così:

schedule.print(“Hello World!”, “”, “Ciao”, “Mondo!”, “\0”);

allo stesso modo avremmo fatto volendo lasciare vuota la prima riga invece che la seconda:

schedule.print(“”, “Hello World!”, “Ciao”, “Mondo!”, “\0”);

ma cos’è quel “\0” che passiamo ogni volta come ultimo argomento?? Serve a “terminare” la funzione, ed è obbligatorio per ogni chiamata.

In fine, in fondo al loop dobbiamo eseguire questa riga:

schedule.reset();

fondamentale per il corretto funzionamento della libreria.

Adesso vediamo invece come passare una stringa:
mettiamo di avere un tipo di dato float, che immaginiamo possa essere ad esempio un valore di temperatura o umidità o quello che volete voi, andremo a fare una cosa del genere:

float temp = sensor.getTemp();
String mystring = “Temp: ” + (String)temp;

schedule.print(mystring.c_str(), “\0”);

notate come viene chiamato il metodo c_str che serve a convertire l’oggetto String in un const char*.

Download Library SchedulerLCD

A questo punto non vi resta che collegare il vostro display lcd ed iniziare a sperimentare 🙂
Vi lascio con un articolo dove ho descritto come creare dei caratteri personalizzati per questi display lcd.

Come sempre per ogni dubbio problema lasciate pure un commento.
Un saluto e alla prossima 😉