Nel precedente articolo tecnico "Smart Display RS485 Introduction" abbiamo introdotto i concetti di base relativi all'interfaccia RS485 e al protocollo Modbus. In questo articolo approfondiremo alcune tecniche comunemente utilizzate nello sviluppo con Smart Display attraverso un esempio basato su più pagine, tra cui:
- Come passare da una pagina all'altra utilizzando il Button widget.
- Come aggiornare i valori dei widget dopo il cambio di pagina.
- Come generare segnali acustici di diversa durata tramite il buzzer.
- Come utilizzare il Graph widget.
Materiale necessario
- Uno Smart Display con interfaccia RS485. In questo esempio utilizzeremo uno Smart Display da 3.5".
- Arduino (Uno o Mega2560).
- Scheda di espansione RS485 per Arduino (Link a DFRobot).
- Potenziometro (VR).
Collegamenti
- Potenziometro: collegare Vcc a 5V, GND a GND e l'uscita ad Arduino A0.
- Collegare il terminale A della scheda di espansione RS485 a RS485+ dello Smart Display.
- Collegare il terminale B della scheda di espansione RS485 a RS485- dello Smart Display.
Struttura dell'esempio
Il progetto è composto da tre pagine, tra le quali è possibile passare utilizzando il Button widget. Di seguito sono descritte la struttura e le funzioni di ciascuna pagina.
Pagina 1:
Sul lato destro è presente un pulsante per passare alla pagina successiva, mentre nella parte inferiore è disponibile un Horizontal Slider per regolare la luminosità dello schermo. Di seguito è riportata l'anteprima della pagina.

Pagina 2:
Sul lato sinistro è presente un pulsante per tornare alla pagina precedente, mentre sul lato destro è disponibile un pulsante per passare alla pagina successiva. Nella parte inferiore sono inoltre presenti tre pulsanti che consentono di generare segnali acustici di durata breve, media e lunga.

Pagina 3:
Sul lato sinistro è presente un pulsante per tornare alla pagina precedente. Un potenziometro viene utilizzato per simulare un ingresso analogico e la variazione dei dati viene visualizzata tramite il Graph widget.

Poiché in questo esempio viene utilizzata una scheda di espansione RS485, prima di iniziare la programmazione è necessario scaricare la libreria richiesta tramite il Library Manager.

Creazione dei contenuti delle pagine
Per prima cosa, utilizziamo GUI Builder per creare i contenuti delle pagine. Il testo può essere inserito direttamente nel Text widget di ciascuna pagina, senza doverlo definire nel programma.

La configurazione dettagliata dei widget è riportata nella tabella seguente.

È possibile scegliere il modello di Smart Display in base al materiale disponibile e utilizzare widget diversi per creare interfacce grafiche differenti. È importante, tuttavia, che il widget ID e il type di ciascuna pagina corrispondano alle definizioni utilizzate nel programma. Per semplificare la configurazione, si consiglia di creare i contenuti delle pagine utilizzando i widget ID e i type indicati nella tabella.
Passiamo ora alla parte relativa alla programmazione.
Spiegazione del programma di esempio
(1) File include
Dopo aver scaricato la libreria ModbusMaster, assicurarsi di includerla utilizzando la direttiva #include:

Inoltre, per semplificarne la gestione, alcune costanti relative allo Smart Display sono state raccolte nel file SmartDisplayModbus.h. Assicurarsi di includere anche questo file.
(2) Conversione del Widget ID in indirizzo di registro
Nel precedente articolo abbiamo illustrato il metodo per convertire il widget ID nel relativo indirizzo di registro, come mostrato di seguito.

Questa tabella, tuttavia, è stata definita quando ogni pagina poteva contenere al massimo 10 widget. Attualmente è possibile utilizzare fino a 64 widget per pagina. La tabella rimane valida per i primi 10 widget, mentre dall'undicesimo widget in poi è necessario utilizzare una nuova area di registri. Per questo motivo sono state definite le seguenti macro:

Per semplificare l'utilizzo, viene definita una funzione che consente di eseguire le operazioni di lettura e scrittura in base al widget ID, effettuando al suo interno la conversione nell'indirizzo di registro.

(3) Widget ID e progettazione della GUI
Durante la creazione dei contenuti delle pagine con GUI Builder, abbiamo già evidenziato che i widget ID devono rimanere coerenti. Per questo motivo, nel programma vengono definite le seguenti costanti per i widget ID.

Queste costanti consentono di identificare più facilmente il tipo di widget e di confrontarlo con la configurazione effettiva della pagina. Se in futuro viene modificata la progettazione della GUI, è importante verificare anche questi valori per evitare errori.
(4) Buzzer
Il firmware genera il segnale acustico utilizzando un contatore per introdurre un determinato ritardo, quindi invia un segnale 0/1 al buzzer. Altri contatori vengono utilizzati per controllare i tempi di attivazione e disattivazione del segnale acustico. Per attivare il buzzer è necessario scrivere nei seguenti quattro registri.

Per regolare la durata del segnale acustico, viene creata una funzione che utilizza SMARTDISPLAY_BUZZER_HIGH come parametro. Di seguito è riportato un esempio della funzione.

Il buzzer viene attivato solo quando il valore di SMARTDISPLAY_BUZZER_ACTIVE è diverso da quello scritto in precedenza. Per questo motivo, il valore viene mantenuto come variabile static all'interno della funzione e invertito a ogni chiamata.
Infine, nella funzione di gestione della pagina è possibile generare segnali acustici di diversa durata in base allo stato dei pulsanti.

(5) Cambio di pagina
Prima di cambiare pagina è necessario passare a CONFIG_MODE. Dopo aver impostato la nuova pagina, si passa a DISPLAY_MODE. Durante il cambio di pagina, lo Smart Display ricarica tutti i widget presenti nella nuova pagina. Per evitare operazioni di lettura o scrittura prima che il caricamento sia completato, normalmente viene inserito un breve ritardo. La durata necessaria dipende dalla complessità della pagina. Se dopo il cambio di pagina si verificano comportamenti anomali, è possibile aumentare il tempo di attesa e verificare se il problema viene risolto.

Dopo il cambio di pagina, i widget della nuova pagina assumono i valori predefiniti. Viene quindi implementata una procedura che gestisce il cambio di pagina, memorizza i valori dei widget e li ripristina quando necessario.
Per prima cosa, definiamo un puntatore a funzione per la gestione delle pagine, in modo da poter creare una tabella delle pagine e associare a ciascuna pagina la relativa funzione di gestione.

Successivamente, creiamo la tabella delle pagine.

La costante MAX_WIDGETS_PER_PAGE definisce il numero di widget per i quali vengono memorizzati i valori in ciascuna pagina. Se in futuro vengono aggiunti altri widget, è necessario aggiornare di conseguenza anche questo valore.
Infine, la gestione del cambio di pagina e dei widget viene eseguita nella funzione loop().

Se la pagina corrente _curPage è diversa dalla pagina successiva _nextPage, il flag di cambio pagina newPage viene impostato su true. In questo modo, la funzione di gestione della pagina può rilevare che è necessaria l'inizializzazione. Prendiamo Page0 come esempio.

Se il parametro init è true, significa che si è appena entrati nella pagina. In questo caso, il valore di WIDGET_P0_BUTTON_NEXT viene impostato su 0. Quando si passa a una nuova pagina, il valore predefinito del pulsante è 0 e vogliamo eseguire un comando specifico (in questo esempio, il passaggio a PAGE_1) solo quando il pulsante viene premuto, ovvero quando il valore passa da 0 a 1. È quindi necessario reimpostare il valore su 0, poiché potrebbe essere già stato impostato su 1 da un'operazione precedente.
Anche il valore iniziale del Slider widget è 0 al momento del caricamento. Tuttavia, la luminosità potrebbe essere stata modificata in precedenza; è quindi necessario ripristinare il widget al valore di luminosità corrente _brightness.
Negli altri casi (quando init è false), i widget vengono gestiti in base alla variazione dei rispettivi valori. Infine, i valori di tutti i widget vengono memorizzati per essere utilizzati come riferimento nel ciclo di elaborazione successivo.
Per impostare la pagina successiva _nextPage viene utilizzata la seguente funzione:

La funzione di gestione della pagina controlla il contenuto dei widget a ogni esecuzione, ad eccezione della prima. Quando rileva che il valore di un pulsante è passato da 0 a 1, richiama la funzione seguente per richiedere il cambio di pagina.

(6) Graph Widget
Il Graph widget consente di rappresentare graficamente i valori ricevuti. In questo esempio utilizziamo un potenziometro collegato ad A0 per simulare un ingresso analogico e visualizziamo l'andamento dei dati tramite il Graph widget. Poiché l'ingresso analogico di Arduino ha un intervallo da 0 a 1023, mentre il Graph widget accetta valori da 0 a 100, è necessario utilizzare la funzione map() per adattare l'intervallo dei valori.
Il Graph widget aggiorna la visualizzazione solo quando il valore cambia. Per ottenere un aggiornamento periodico, è possibile controllare il valore a intervalli regolari e, se il nuovo valore è uguale a quello letto in precedenza, modificarlo leggermente aggiungendo o sottraendo 1. In questo modo è possibile ottenere un effetto di aggiornamento dinamico a intervalli regolari.

Conclusioni
Con questo si conclude la spiegazione del programma di esempio. Ci auguriamo che questo articolo possa contribuire a una migliore comprensione delle modalità di sviluppo con Smart Display. L'esempio può inoltre essere utilizzato come base di partenza per progetti futuri, contribuendo a ridurre i tempi di sviluppo. Il programma completo può essere scaricato dal seguente link: Modbus-MultiPageOperation on GitHub.
Se non si ha familiarità con RS485 / Modbus, è possibile consultare anche il precedente articolo per maggiori informazioni: Smart Display RS485 Introduction.