+1 500 000 prodotti nell’offerta
7000 pacchi giornalmente
+300 000 clienti da 150 paesi
Data di pubblicazione: 23-07-2021 Data di aggiornamento: 16-04-2026 🕒 11 min di lettura
Il dispositivo finito è costituito da blocchi funzionali, che spesso possono essere utilizzati ripetutamente. Ad esempio, se costruiamo un misuratore di frequenza con un microcontrollore, a parte il blocco dell'amplificatore, avremo bisogno di quasi gli stessi componenti utilizzati per la costruzione di un relè temporizzato. Ci riferiamo al microcontrollore assieme all' "ambiente circostante" (resistori, condensatori, quarzo e altri componenti), display, pulsanti e connettori. Naturalmente, il frequenzimetro non avrà bisogno di un relè per accendere un dispositivo esterno, mentre il relè temporizzato non necessiterà di un amplificatore di ingresso a banda larga, ma il nucleo rimarrà lo stesso. Pertanto, la chiave per la creazione autonoma di applicazioni è la comprensione delle regole di funzionamento di ciascun blocco funzionale e successivamente la combinazione delle loro funzionalità.
Piattaforme come Arduino non richiedono all'utente la conoscenza delle norme di funzionamento dei singoli componenti. È sufficiente collegare la scheda base al modulo/shield di estensione e realizzare un'applicazione funzionante. D'altra parte, se non abbiamo nemmeno una conoscenza base dei componenti, in caso di problemi con il funzionamento del nostro dispositivo saremo costretti a procedere a tastoni. Nel frattempo scegliendo i componenti Arduino il più delle volte ci aspettiamo un effetto rapido. È difficile conciliare tali attesecon la necessità di acquisire le giuste conoscenze, poiché è sufficiente digitare alcuni comandi per vedere i primi effetti sul display, ma comprendere perché ciò è accaduto a volte richiede molto tempo.
In considerazione delle discrepanze sopra descritte, ciascuno degli articoli di questo ciclo sarà suddiviso in due parti. Nel primo indicheremo come raggiungere l'effetto descritto nell'articolo. La seconda parte presenterà il funzionamento del componente o della soluzione.
Inizieremo con il modulo display LCD, poiché grazie ad esso è possibile vedere il prima possibile l'effetto del lavoro svolto. Successivamente, presenteremo altri elementi dell'interfaccia utente e successivamente circuiti esterni selezionati: sensori ed attuatori. Nel frattempo presenteremo anche alcuni trucchi e metodi di programmazione. Il tutto sulla base della piattaforma Arduino, economica, facilmente accessibile e che inoltre permette di utilizzare le conoscenze acquisite per costruire dispositivi già pronti o loro prototipi.
L'interfaccia base tra il microcontrollore e l'utente è solitamente composta da un display e da un pulsante o pulsanti. Come possiamo immaginare, il primo viene utilizzato per informare l'utente delle operazioni svolte dal microcontroller, mentre con l'aiuto di pulsanti - a volte sostituiti da un impulsatore - è possibile inserire comandi o dati. Nell'offerta sono disponibili molti display (inclusi quelli dotati di touchscreen), tuttavia i display dei caratteri con un controller di tipo HD44780 sono diventati uno standard non ufficiale.
Display con controller HD44780
Nel primo esempio di programmazione utilizzeremo una scheda Arduino UNO R3, una basetta millefori (breadboard), un modulo di display LCD a caratteri a 2 linee da 16 caratteri e diversi cavi di collegamento. Naturalmente, questa è solo una proposta: il display può essere collegato liberamente, anche saldandolo alla scheda. In questo caso è stato utilizzato un metodo che consente elevate possibilità di modifica e cambiamento del layout dei collegamenti.
Se il modulo display dispone di goldpin saldati, potremo semplicemente collegarli alla basetta millefori. Successivamente collegheremo il display alla scheda Arduino UNO, come descritto nella tabella 1.
Tabella 1. Collegamenti del display a caratteri alla scheda Arduino UNO
| Numero del pin del display | Nome del segnale del display | Nome del connettore Arduino | Nome del segnale Arduino |
|---|---|---|---|
| 1 | VSS | Power | GND |
| 2 | VDD | Power | +5V |
| 3 | V0 | Power | GND |
| 4 | RS | Analog In | A4 (PC4) |
| 5 | R/W | Power | GND |
| 6 | E | Analog In | A5 (PC5) |
| 7 | DB0 | – | – |
| 8 | DB1 | – | – |
| 9 | DB2 | – | – |
| 10 | DB3 | – | – |
| 11 | DB4 | Analog In | A0 (PC0) |
| 12 | DB5 | Analog In | A1 (PC1) |
| 13 | DB6 | Analog In | A2 (PC2) |
| 14 | DB7 | Analog In | A3 |
| 15 (facoltativo) | LED+ | Power | 3.3V |
| 16 (facoltativo) | LED- | Power | GND |
Dobbiamo ricordare che ad es. se si dispone della massa GND dal connettore Power alla basetta millefori, è possibile eseguire i collegamenti sulla basetta millefori e non sarà necessario ogni volta collegarsi al connettore Power.
L'utilizzo del connettore Power è necessario in quanto mediante quest'ultimo alimenteremo il display. Il connettore Analog In è montato proprio accanto ad esso, quindi per comodità si è deciso di utilizzare le uscite del microcontroller disponibili su di esso. Tuttavia, non bisogna farci indurre in errore dal nome: per la gestione del modulo display sono necessarie le uscite digitali, non gli ingressi / le uscite analogiche. Il connettore è chiamato Analog In poiché ad esso sono stati condotti ingressi analogici opzionali, che tuttavia possono essere configurati per funzionare anche in altre modalità, incluse la modalità come uscite digitali. Pertanto, l'ingresso analogico A0 è costituito dalla porta PC0, A1 - PC1, ecc. (vedi: uscite del microcontroller ATmega328PU).
Tra le numerose opzioni dei driver software disponibili per Arduino, per la gestione del display è stata scelta la libreria LiquidCrystal. Dopo aver creato uno sketch inseriremo la libreria nella prima riga del programma, utilizzando il comando #include. Dopo aver collegato il display al microcontroller come descritto in precedenza, saremo pronti per realizzare il primo sketch di controllo del modulo display LCD.
Alla porta USB del nostro PC collegheremo la scheda Arduino. Nel menu Arduino sceglieremo File e successivamente Nuovo (Ctrl+N). Sul display apparirà una finestra simile a quella presentata nella figura 1. La parola chiave void ci informa che in questo punto verrà creata una funzione che non restituisce alcun valore. Dopo la parola void viene inserito il nome della funzione e la parentesi graffa che apre "{" indica l'inizio della funzione e la parentesi di chiusura "}" indica la fine della funzione.
Quando si crea un nuovo sketch, Arduino informa della necessità di definire due funzioni speciali: void setup(), che descrive la configurazione del microcontroller e contiene le istruzioni eseguite una volta all'inizio del programma, e void loop(), contenente le operazioni eseguite in un loop infinito.
Figura 1. Finestra del nuovo sketch di Arduino
Perché il programma dell'applicazione deve essere eseguito in un loop infinito? Le applicazioni Windows o Linux vengono eseguite con il controllo del sistema operativo. Se eseguiamo l'applicazione su Windows, una volta terminato il funzionamento questa torna al luogo da cui è stata richiamata, il più delle volte per visualizzare il cosiddetto desktop, la riga di comando e così via. Da questo momento in poi il sistema operativo assume il controllo del funzionamento del processore. Il microcontroller sulla scheda Arduino UNO non dispone di alcun sistema operativo preinstallato, pertanto lo sviluppatore deve assicurarsi che il funzionamento dell'applicazione termini in modo sicuro. Ciò può essere effettuato spegnendo il microcontroller (ad es. impostandolo in modalità di stand-by) o realizzando un loop nell'esecuzione delle istruzioni per impedire l'esecuzione di istruzioni al di fuori dell'intervallo richiesto in memoria. Ciò può essere effettuato nella funzione void loop() o in qualsiasi altro modo, il cui esempio verrà riportato di seguito.
Prima di poter visualizzare le informazioni sul display è necessario configurare il microcontroller. In questo esempio, tutto ciò che bisogna fare è configurare adeguatamente le uscite di comando del display.
All'inizio del nostro sketch includiamo la libreria di funzioni del display:
#include <LiquidCrystal.h>
Successivamente, per la nostra comodità e leggibilità del software, utilizzando il comando #define, definiremo i nomi dei pin - uscite della porta C del microcontroller:
//porta PC
#define pc0 A0
#define pc1 A1
#define pc2 A2
#define pc3 A3
#define pc4 A4
#define pc5 A5
Ora informeremo il microcontroller a cui è collegato il display. Quest'operazione viene effettuata tramite la funzione lcd(), in cui l'elenco degli argomenti indica al processore dove vengono indirizzati i singoli segnali. Nell'elencare le uscite è necessario rispettare la sequenza appropriata: LiquidCrystal lcd(RS, Enable, D4, D5, D6, D7).Nel creare l'elenco di argomenti verrà utilizzata la tabella 1, che contiene l'elenco dei collegamenti tra Arduino e il modulo display LCD: LiquidCrystal lcd(pc4, pc5, pc0, pc1, pc2, pc3).
Ora sarà necessario impostare la modalità di funzionamento delle uscite: è necessario impostare queste ultime per il funzionamento come uscite digitali. Questa configurazione viene salvata all'interno della funzione void setup():
pinMode(pc0, OUTPUT);
pinMode(pc1, OUTPUT);
pinMode(pc2, OUTPUT);
pinMode(pc3, OUTPUT);
pinMode(pc4, OUTPUT);
pinMode(pc5, OUTPUT);
Successivamente inizializziamo la visualizzazione del display, impostando il numero di colonne, righe e nel primo passaggio pulendo lo schermo. Dopo l'inizializzazione, il display LCD dovrebbe essere vuoto, tuttavia per sicurezza e per il corretto inizio del funzionamento, vale la pena seguire questa istruzione:
lcd.begin(16, 2);
lcd.clear();
Dopotutto, è sufficiente un solo comando per visualizzare il messaggio:
lcd.print("Hello!");
Nella funzione loop() non inseriremo alcun comando. Il software, dopo la visualizzazione del messaggio, semplicemente eseguirà un ciclo infinito, facendo perdere tempo alla CPU. In linea di principio, a questo punto, ad es. sarebbe possibile entrare in modalità di risparmio energetico, poiché il messaggio sullo schermo comunque non cambierebbe, ciò richiederebbe ulteriori analisi delle risorse hardware, non consigliabili in questa fase.
L'intero programma che visualizza il messaggio "Hello!" può essere trovato nei materiali aggiuntivi a questo articolo. Se la descrizione precedente e l'effetto ottenuto sono soddisfacenti, puoi saltare la lettura del resto del testo. Nel prossimo articolo ci occuperemo di alcune operazioni più avanzate sul contenuto visualizzato, oltre alla semplice visualizzazione del messaggio.
Un'analisi più approfondita dell'argomento dovrebbe iniziare con la presentazione della struttura del microcontroller presente sulla scheda Arduino, tuttavia si tratta di un argomento molto ampio. Pertanto, prima di tutto affronteremo il principio di funzionamento del modulo display LCD.
Per comprendere come viene gestito il modulo display LCD è essenziale la conoscenza base dei sistemi di memoria e dei circuiti digitali in generale. È necessario conoscere notevoli concetti come livello logico alto e basso, forma d'onda, dati, numero a 8 bit, byte, bit, fronte di salita o di discesa. Ciò è necessario poiché dal punto di vista del programma di gestione, il modulo display è visto come un tipo di memoria digitale con cui il microcontroller può comunicare in modo bidirezionale. Nel frattempo, infatti, il modulo display LCD dispone di un proprio microcontroller (il modello HD44780 menzionato precedentemente o simili) che non solo riceve i dati da visualizzare, ma esegue anche comandi relativi al funzionamento del modulo LCD e gestisce il display. A causa del fatto che il microcontroller integrato nel modulo display dispone di una funzione altamente specializzata e autonoma, spesso si dice che tali sistemi sono subordinati o eseguono funzioni slave. Il microcontroller integrato nella scheda Arduino svolge una funzione di controllo, master. In genere, tali circuiti vengono denominati di livello superiore o master. Questi concetti possono essere trovati ripetutamente nelle descrizioni di vari dispositivi collegati al microcontroller.
Torniamo per un po' alle basi. Nei circuiti CMOS, e la maggior parte dei circuiti integrati moderni sono eseguiti in tale tecnologia, il valore logico "1" è pari ad almeno il 95% della tensione di alimentazione del sistema, mentre il valore logico "0" è inferiore o uguale a 0,3 V. Se il circuito del processore dispone di un alimentatore integrato, cosa che spesso accade nei processori più complessi, il valore logico "1" viene determinato in riferimento alla sorgente di alimentazione interna. Può essere diversamente - se il circuito CMOS ha ingressi conformi ai livelli TTL, allora il valore logico "1" rappresenta una tensione superiore a 2,4 V. Pertanto, in caso di dubbi, vale la pena di dare un'occhiata alla scheda catalogo di un determinato circuito. Potremo trovarla facilmente in rete.
Il cambiamento del livello logico comporta un cambiamento del valore di tensione. Questo cambiamento si verifica in salti, ma comunque, in un determinato intervallo di tempo. Quando un livello passa da "0" a "1", parleremo di fronte di salita, e quando da "1" a "0" di fronte di discesa. La durata della transizione viene quindi chiamata, rispettivamente, il tempo di salita o di discesa. Di solito ci vogliono alcuni nanosecondi, ma questa non costituisce una regola.
In un microcontroller una singola linea che presenta un livello di "0" o "1" è chiamata bit di dati. 8 linee simili formano un byte. Il microcontroller AVR come quello integrato in una scheda Arduino UNO, dispone di una parola di dati a 8 bit, pertanto può elaborare parole a 1 byte, decimali nell'intervallo di 0... 255. Se il numero è maggiore di 255, richiederà la suddivisione in "porzioni", l'esecuzione di operazioni su di esse e successivamente la compilazione del risultato. Tuttavia, non dobbiamo preoccuparci di ciò, poiché tale operazione viene effettuata in background dal compilatore del linguaggio Arduino. Tuttavia, è necessario essere consapevoli del fatto che maggiore è il numero di bit che devono essere memorizzati per una variabile, più a lungo questa verrà elaborata dal microcontroller.
In questo esempio il microcontroller master controlla il modulo display LCD utilizzando dei segnali di uscita. Modificando i suoi segnali di uscita, controlla i livelli logici sugli ingressi del modulo display. Ciò consente di selezionare il momento della registrazione dei dati e l'area di memoria in cui verranno memorizzati:
Per il controllo del funzionamento del modulo display LCD abbiamo a disposizione due modalità di funzionamento: di solito sono chiamate a 8 bit e 4 bit. Nel primo caso la gestione del display richiede almeno 10 linee di dati (RS, E, D0...D7). Dal punto di vista del software di gestione, questa modalità è molto efficace se al sistema superiore è possibile collegare il display come memoria su un bus dati a 8 bit. L'indirizzamento del modulo display comporterà in questo caso l'impostazione di un livello alto sull'ingresso Enable, basso o alto (a seconda che si tratti di un comando o di dati da visualizzare) sull'ingresso RS, esponendo i dati sul bus e modificando il livello su Enable a basso. In alcuni sistemi ciò semplifica notevolmente il software di gestione.
In modalità a 4 bit continueremo ad utilizzare parole a 8 bit, ma al sistema superiore saranno collegati solo gli ingressi D4...D7 del modulo display, e le parole di dati a 8 bit saranno suddivise in due porzioni, ciascuna da 4 bit. Ciò complica il software di gestione e non consente di collegare facilmente il modulo display al sistema master, ma consente di risparmiare 4 linee GPIO del microcontroller.
Nei software di gestione per moduli LCD semplificati, che non utilizzano linee R/W a priori, si presuppone che il modulo display funzioni correttamente. Viene impostato un tempo predefinito, ad es. l'esecuzione del comando eseguito più a lungo (in genere circa 2 millisecondi) e si presuppone che dopo tale tempo il display abbia eseguito il comando o abbia visualizzato un carattere e sia possibile inviare ulteriori dati. Di solito il microcontroller integrato nel modulo display è più veloce: solo l'esecuzione del comando clear (pulizia dello schermo) richiede persino 2 millisecondi. D'altra parte, se, come in questo esempio, abbiamo 2 righe di 8 caratteri sullo schermo, se inviamo 16 byte in 32 millisecondi o 100 microsecondi non ha eccessiva importanza. Nessun utente sarà in grado di notarlo. Ciò cambia solo quando abbiamo a che fare con display grafici cui viene trasmessa una quantità di dati nettamente superiore.
Arduino non ci offre un elevato margine di manovra durante la gestione del display. Il microcontroller ATmega328 integrato all'interno di Arduino UNO non dispone di linee di indirizzo esterne, pertanto la gestione del display in modalità 8 bit con l'indirizzamento in questa modalità, nonché la memoria esterna, non sono possibili. Tuttavia, se utilizziamo una porta GPIO per gestire il segnale R/W, in tal caso possiamo testare il flag busy del bus e leggere il contenuto dei registri e della memoria del modulo LCD.
Per configurare la modalità di collegamento del display nella libreria LiquidCrystal.h, è possibile utilizzare una funzione con lo stesso nome, ossia LiquidCrystal (). La modalità di collegamento del display è determinata dall'elenco di argomenti per il richiamo della funzione:
Il controller HD44780 è un chip universale, progettato per supportare schermi LCD con un numero diverso di caratteri (colonne e righe). In questo modo, quando l'alimentazione è accesa, il controller "non sa" quale schermo è collegato e per il corretto funzionamento è necessario procedere alla configurazione. Nella suite Arduino per fare ciò viene utilizzata la funzione begin(), i cui argomenti sono il numero di colonne e il numero di righe. Ad esempio, se si dispone di uno schermo con 2 righe di 16 caratteri, digiteremo begin(16, 2).
Il software nell'esempio utilizza ancora la funzione clear() per pulire lo schermo. È una buona pratica usarlo come primo comando, dopo aver inizializzato il modulo LCD, in quanto possiamo trovare display che, dopo l'inizializzazione, mostrano caratteri casuali. Inoltre abbiamo utilizzato la funzione print(). Gli argomenti per l'inizializzazione sono costituiti dai dati da visualizzare, ad es. un numero o testo, e nel caso dei numeri, la base per i numeri decimali è pari a "DEC", per i binari "BIN", gli esadecimali "HEX", gli ottali "OCT". La funzione print() viene utilizzata per convertire i numeri se è necessario visualizzarli in diversi sistemi numerici:
Il comando Print posiziona i caratteri visualizzati dalla posizione corrente del cursore. In genere, dopo il comando clear(), il cursore si trova nell'angolo superiore sinistro dello schermo LCD.
La libreria della funzione LiquidCrystal.h contiene molte altre funzionalità utili, tuttavia ne parleremo nel prossimo articolo. Sebbene siamo agli inizi, abbiamo fornito una solida porzione di nozioni.
Transfer Multisort Elektronik (TME) è uno dei maggiori distributori mondiali di componenti elettronici, parti elettrotecniche, attrezzature da laboratorio e automazione industriale. Il catalogo include oltre 1.500.000 di prodotti di 1.300 produttori leader. I moderni centri logistici di TME a Łódź e Rzgów (Polonia), con una superficie complessiva di oltre 40.000 m², spediscono quasi 6.000 pacchi al giorno a clienti in più di 150 paesi.
TME investe anche nello sviluppo delle conoscenze e competenze di giovani ingegneri e appassionati di elettronica attraverso il progetto TME Education e supporta la comunità tecnologica organizzando la serie di eventi TechMasterEvent, promuovendo l’innovazione e lo scambio di esperienze.