Mese: Giugno 2021


Lezione 3

By lapinig,

Operazioni di controllo (mascherature)

In questa terza lezione passiamo ad analizzare la parte essenzialmente di “controllo” svolta da un microcontrollore. Una volta acquisite le situazioni in cui si trovano gli ingressi, collegati al mondo esterno, il microcontrollore può effettuare una serie di controlli, spesso andando a verificare lo stato di un singolo bit, tramite una sequenza di “mascherature” per eliminare, di volta in volta, i bit non influenti ed isolare solo quelli necessari.

Esercitazione 7: Uso di mascherature di controllo

Con la piattaforma TinkerCad realizziamo questo circuito

Si vuole realizzare il seguente funzionamento:

  1. Il dip switch 1 accende/spenge il Led Verde
  2. Il dip switch 2 accende/spenge il Led Rosso
  3. Quando il dip switch 3 è alto allora il terzo led (Blu) si accenderà quando i primi due led hanno stati diversi, altrimenti resterà spento
  4. Quando il dip switch 4 è alto allora il terzo led (Blu) si accenderà quando il primi due led hanno il medesimo stato, altrimenti resterà spento.

Nella richiesta non sono state prese in esame le altre due possibili combinazioni del 3° e 4° dip-switch, eventualmente si potrebbe prevedere l’ipotesi che il Led Blu sia sempre spento quando i suddetti dip-switch sono entrambi bassi ovvero sempre acceso quando i due dip-switch sono entrambi alti.

Il codice sorgente completo per ottenere questa comportamento lo trovate qui.

Esercitazione 8: Uso del controllo switch()

Con la piattaforma TinkerCad realizziamo questo circuito

Il microcontrollore di Arduino pilota, tramite sette (od otto) uscite un display a 7 segmenti LED. Si vuole realizzare quindi un convertitore binario-decimale con relativo visualizzatore. Come ci siamo accorti ben presto durante la lezione, le combinazioni possibili sul dip-switch a 4 contatti sono 16, ben oltre le dieci combinazioni della numerazione decimale.

Il display utilizzato ha una struttura come indicato di seguito

Il display da noi utilizzato è però del tipo a catodo comune, quindi tutti e otto i led sono invertiti ed il piedino comune (Common) è collegato a tutti i catodi e pertanto, per poter accendere il segmento, andrà collegato a GND (alimentazione negativa), mentre il pin di uscita di Arduino porterà al singolo segmento il positivo.

I singoli segmenti hanno una sigla indicata con le lettere alfabetiche dalla A fino G, partendo dal segmento in alto e proseguendo in senso orario. Il punto decimale (Decimal Point) è indicato dalla sigla DP.

Mentre è abbastanza ovvio capire quali segmenti vanno accesi per ottenere le combinazioni numeriche da 0 fino a 9 (numerazione decimale), un po’ meno chiaro è cosa fare con le combinazioni da 10 a 15. Utilizzeremo per la visualizzazione sul display la codifica esadecimale, faremo quindi un visualizzatore in base 16. I simboli ,da sempre utilizzati in ambiente elettronico/informatico per visualizzare queste combinazioni, sono le lettere dell’alfabeto dalla A fino alla F.

Per visualizzare questi ulteriori simboli utilizzeremo a volte le lettere maiuscole e a volte le lettere minuscole, poichè questo tipo di display, molto semplice e con pochi piedini è nato ben prima di queste esigenze. Qui sotto potete vedere alcuni esempi di visualizzazione di caratteri alfabetici

Per la cronaca esistono altri modelli di display che arrivano fino a 14/16 segmenti e che riescono a visualizzare qualsiasi carattere alfabetico.

Il codice sorgente completo per ottenere questa comportamento lo trovate qui.

Riepilogo dei contenuti della lezione:

  1. Abbiamo creato una funzione separata Visualizza() per cercare di non “intasare” la funzione loop() facendola diventare estremamente lunga. Questo modo di procedere è consigliato perchè permette di mantenere “leggibile” il codice sorgente e permette anche di creare funzioni che, tramite il copia/incolla, possono essere facilmente riutilizzate in altri programmi (non bisogna mai “riscoprire l’acqua calda” tutte le volte).
  2. Abbiamo i vari tipi di controllo if()/else anche con più ramificazioni if()/elseif()/else.
  3. Abbiamo utilizzato il controllo switch() quando il numero di ramificazioni del controllo if() cominciare a diventare insostenibile.
  4. Abbiamo utilizzato le “mascherature” con le funzioni AND (&) ed OR (|). Qui potete vedere alcuni esempi che abbiamo visto durante la lezione. Anche qui potete vedere altri esempi.
  5. Abbiamo utilizzato la scrittura delle maschere in esadecimale (0x5B ad esempio) per poter passare direttamente e velocemente da numeri binari a numeri facilmente leggibili da noi “umani”.

Alla prossima lezione…

Lezione 2

By lapinig,

Operazioni di INPUT

In questa seconda lezione passiamo ad analizzare l’altra operazione che permette al microcontrollore che governa Arduino di interagire con il mondo “esterno”.

Si tratta dell’operazione di INPUT. L’operazione viene definita di “ingresso” (input) poichè i dati del mondo esterno “entrano” all’interno del microcontrollore.

A differenza della scorsa lezione si tratta quindi di operazioni di lettura.

Esercitazione 4: Uso di interruttori

Con la piattaforma TinkerCad realizziamo questo circuito

Quello che si vuole realizzare è un funzionamento di questo tipo:

  1. Commutando lo switch S1 si deve accendere/spengere il Led Verde
  2. Commutando lo switch S2 si deve accendere/spengere il Led Rosso

Il programma è quindi molto facile da realizzare… il codice lo trovate qui.

Scritto quasi ad “occhi chiusi” perchè tanto è semplice… ma, ma… andando in simulazione ci accorgiamo che non funziona. O meglio, qualcosa fa, ma non esattamente quello che volevamo. All’inizio a volte i led sono spenti, ma spesso sono accesi, in ogni caso facendo scorrere la slitta dell’interruttore si accendono e non si spengono più.

Per controllare meglio proviamo a collegare un multimetro, impostato come voltmetro, all’ingresso del microcontrollore. In effetti ci accorgiamo che la tensione passa da 5 volt (alimentazione positiva) a quasi zero, ma non zero, ovvero a poco più di 50 mV. Inoltre l’interruttore su cui abbiamo collegato il voltmetro adesso funziona perfettamente, ossia accende e spenge regolarmente il Led Rosso.

Cosa succede?

Quando spostiamo la slitta dell’interruttore e scolleghiamo il piedino del microcontrollore dalla tensione di +5 volt, il filo connesso al piedino rimane scollegato, libero, ossia non connesso a nessun potenziale elettrico, in gergo si dice che è “flottante”. Un conduttore lasciato libero in aria funziona come da antenna e riesce a captare piccoli segnali elettrici o a mantenere per lungo tempo il potenziale che aveva in precedenza, prima di riuscire a disperderlo. In sostanza in genere si comporta spesso come se fosse collegato ad una sorgente di tensione, in ogni caso il potenziale a cui si pone è assolutamente aleatorio.

Per evitare questo problema ogni conduttore deve essere sempre e comunque legato ad un potenziale alto (alimentazione positiva) o basso (alimentazione negativa o massa). Nel nostro caso possiamo risolvere collegando un resistore da 10 Kohm verso il negativo (resistore di pull-down), riprovando con il medesimo programma di prima vedremo che il problema non si ripresenta e tutto funziona correttamente. Vedremo anche che la tensione sul piedino andrà da +5 volt a 0 volt.

Esercitazione 5 e 6: Uso di pulsanti

Con la piattaforma TinkerCad realizziamo questo circuito

Memori dell’esperienza precedente questa volta mettiamo subito i resistori di pull-down sul piedino del microcontrollore.

Prima di effettuare i collegamenti occorre puntualizzare il tipo di pulsante da noi utilizzato. In questo tipo di pulsante i quattro terminali sono collegati a coppie: i piedini 1 e 2 sono collegati insieme tra loro, così come i piedini 3 e 4, quando viene premuto il pulsante queste due coppie 1-2 e 3-4 vengono a sua volta collegate fra loro.

Guardando lo schema realizzato con TinkerCad i piedini sulla sinistra ed etichettati con 1a e 1b costituiscono una coppia, mentre quelli con etichetta 2a e 2b costituiscono l’altra coppia. Per visualizzare l’etichetta basta posizionare il puntatore del mouse sul piedino ed attendere un istante.

La funzione da realizzare richiesta al programma è la seguente:

  1. All’inizio tutti i Led sono spenti.
  2. Premendo il pulsante di sinistra una volta il Led Verde si accende (poichè era spento)
  3. Premendo il pulsante di sinistra una volta ancora il Led Verde si dovrà spengere e così via.
  4. Il pulsante destro si comporterà come il precedente, però attivando/disattivando l’accensione del Led Rosso.

Come abbiamo visto durante la lezione, da adesso in poi converrà strutturare la sequenza del programma in questo modo:

  1. Il programma deve “leggere” lo stato di TUTTI gli ingressi e lo memorizza temporaneamente in memoria (RAM) per gli usi successivi. In pratica il microcontrollore fa una “foto” dello stato del mondo esterno.
  2. Il microcontrollore, tramite il programma, elabora questi dati e prende delle “decisioni”, in pratica crea altri dati.
  3. Il microcontrollore emette in uscita alcuni dati (risultati dalle elaborazioni precedenti e quindi dagli ingressi letti), “scrive” cioè verso il mondo esterno.

Il programma creato (che trovate qui), che a prima vista non presenta errori, però non si comporta come desiderato. Durante la simulazione a volte la pressione del pulsante fa cambiare di stato al Led associato ma, molto più spesso lo lascia invariato. Nel corso della lezione abbiamo visto che introducendo un certo ritardo nell’esecuzione della funzione loop(), si ottiene un miglioramento, ma il programma non funziona ancora correttamente. Inoltre vi ho già “intimato” di non utilizzare mai l’istruzione delay() poichè essa provoca un blocco totale del microcontrollore (in questo caso per 100 msec) durante il quale esso non fa altro che attendere…

Occorre modificare sostanzialmente il programma, impostandolo in modo che il microcontrollore in ogni momento sappia com’è lo stato di un ingresso, com’era in precedenza e quanto tempo è trascorso dall’ultima variazione di quell’ingresso. La procedura a prima vista potrebbe sembrare un’inutile complicazione, in realtà il tutto si traduce in una maggior sicurezza ed affidabilità del funzionamento, inoltre viene risolto anche un altro problema, quello dei “rimbalzi” a cui ho accennato durante la lezione.

In questo documento potete trovare spiegato l’argomento in maniera più dettagliata. Mentre a questo link trovate il programma definitivo che risolve anche i problemi presentatisi fino ad ora.

All’interno del programma trovate anche un ulteriore quesito. Prossimamente troverete qui sotto la soluzione da me proposta.

Riepilogo dei contenuti della lezione:

  1. L’istruzione digitalRead() effettua delle “letture” dagli ingressi ovvero il mondo “esterno” entra nel microcontrollore.
  2. Abbiamo visto che l’istruzione if() permette al microcontrollore di prendere delle decisioni (o effettuare scelte), essa può essere legata (opzionalmente) anche all’istruzione else che permette di effettuare decisioni alternative.
  3. Abbiamo utilizzato il simbolo “! che in linguaggio C significa negazione ovvero il contrario di…
  4. Abbiamo utilizzato il simbolo “>” ossia maggiore di (ovviamente esiste anche il contrario “<“) che può essere utilizzato nei confronti per prendere delle decisioni. Esiste anche il simbolo comparativo di uguaglianza “==” ed il simbolo di disuguaglianza “!=” (diverso da…) come anche i simboli “>=” e “<=” (maggiore o uguale a… e minore o uguale a...)
  5. Abbiamo utilizzato il simbolo “&&” per legare due condizioni (entrambe da verificare cioè devono essere entrambe vere) nel costrutto if().

Alla prossima lezione…

Lezione 1

By lapinig,

Operazioni di OUTPUT

Partiamo dalle più semplici operazioni gestibili con un microcontrollore come quello utilizzato nella scheda Arduino.

Esercitazione 1: Lampeggio Verde/Rosso

Con la piattaforma TinkerCad realizziamo questo circuito

Il funzionamento richiesto deve essere il seguente (con temporizzazioni fisse di 0,5 sec ovvero 500 msec):

  1. Si deve accendere il solo Led Verde
  2. Quindi si accende anche il Led Rosso insieme al Verde
  3. Si spenge il Led Verde (ma rimane acceso il Rosso)
  4. Si spegne anche il Led Rosso
  5. Il ciclo si ripete all’infinito

Il codice completo lo trovate qui (utilizzatelo solo dopo aver provato da soli).

Esercitazione 2: Semaforo semplificato a due vie

Come seconda prova propongo questo circuito

Immaginiamo di dover realizzare la gestione di una sequenza semaforica costituita da due gruppi di luci (rosso/giallo/verde) presenti in un incrocio di due vie. Per semplificare le due direzioni NS (Nord-Sud) e EW (Est-Ovest) hanno le stesse luci a coppie ossia il Rosso Nord si accenderà insieme al Rosso Sud, il Verde Nord insieme al Verde Sud, ecc.

Chiaramente quando nella direzione NS è acceso il colore Verde oppure Giallo, nella direzione ortogonale EW dovrà obbligatoriamente essere acceso il colore Rosso. Per questa ragione prendiamo in considerazione solo le sequenze di accensione dei colori Verde e Giallo, il Rosso opposto sarà acceso di conseguenza.

Le temporizzazioni richieste, inizialmente, sono di 5 secondi per il Verde e di 2 secondi per il Giallo. In seguito verrà chiesto di differenziare la tempistica per una delle due direzioni.

Il funzionamento richiesto è il seguente:

  1. Si accende il Verde nella direzione NS per 5 secondi (e quindi il Rosso EW)
  2. Si accende il Giallo nella direzione NS per 2 secondi (e quindi rimane acceso il Rosso EW)
  3. Si accende il Verde nella direzione EW per 5 secondi (e quindi anche il Rosso NS)
  4. Si accende il Giallo nella direzione EW per 2 secondi (e quindi rimane acceso il Rosso NS)
  5. Si ripete la sequenza dall’inizio

Nota: Le luci non indicate dovranno essere spente in ogni singolo punto, consiglio quindi di pilotare TUTTE le volte TUTTE le uscite, alcune saranno accese mentre altre spente.

Il codice completo lo trovate qui (utilizzatelo solo dopo aver provato da soli).

Esercitazione 3: Lampeggio “Real Time”

Come ultima prova di questa lezione propongo questo circuito

La funzione richiesta questa volta sembra molto semplice:

  1. Il Led Verde deve lampeggiare con un ritmo di 2 sec. ON / 2 sec. OFF
  2. Il Led Rosso deve lampeggiare con un ritmo di 0,5 sec. ON / 0,5 sec. OFF
  3. Il tutto ripetuto all’infinito

A prima vista, ripeto, potrebbe sembrare molto semplice da realizzare. In realtà è impossibile (o quasi) da ottenere con le tecniche viste finora, cioè con semplici sequenze lineari di istruzioni. Impossibile no, perchè prendendo il programma della prima esercitazione e modificandolo, con un numero di righe di istruzione circa 4-5 volte più grande si può ottenere il risultato richiesto. Ma se vi dicessi che va aggiunto un terzo Led, lampeggiante anch’esso e magari con un numero di volte che sta in rapporto di numero primo con gli altri ?

Il codice completo lo trovate qui (utilizzatelo solo dopo aver provato da soli).

I più attenti fra voi avranno notato un terzo Led di colore Blù che non è stato citato nel testo e non è utilizzato. A cosa serve? A complicare ancora di più le richieste:

  1. Ad ogni 5 lampeggi del Led Rosso il Led Blu si deve accendere per 1 secondo e quindi spengersi.

Il codice completo lo trovate qui (utilizzatelo solo dopo aver provato da soli).

Riepilogo dei contenuti della lezione:

  1. Le righe che iniziano con il simbolo // sono commenti e sono ignorate dal compilatore in linguaggio C. Usatele per chiarire i punti critici.
  2. Nel software della piattaforma Arduino la funzione setup() viene eseguita per prima ed una sola volta. Usatela per impostare le condizioni iniziali della macchina.
  3. Nel software della piattaforma Arduino la funzione loop() viene richiamata in continuo (in loop appunto) dopo la funzione setup() e non ha mai termine (solo con lo spengimento della macchina).
  4. La funzione pinMode() serve per impostare la modalità di funzionamento del piedino del microcontrollore della scheda di Arduino: INPUT o OUTPUT. Abbiamo visto per adesso solo la seconda possibilità.
  5. La funzione digitalWrite() serve per impostare un valore digitale su di un piedino di Arduino. Scrivendo HIGH o 1 sul pin saranno presenti 5 volt ed eventuali componenti connessi verranno “accesi”, mentre scrivendo LOW o 0 sul pin saranno presenti 0 volt ed eventuali componenti connessi verrano “spenti”. Il piedino deve essere definito come OUTPUT in precedenza.
  6. La dichiarazione #define non è una funzione del linguaggio C (manca infatti della coppia di parentesi tonde), ma bensì una direttiva o comando del preprocessore del linguaggio C. In pratica si può utilizzare per definire delle costanti utilizzate nel nostro programma. In realtà è molto più potente.
  7. La funzione if() esegue un controllo, in genere fra variabili utilizzate nel programma, per determinare se eseguire un pezzo di codice oppure (else) un altro pezzo di codice. La parte che segue subito la funzione if(), contenuta nella prima coppia di parentesi graffe, viene eseguita se il risultato del controllo è vero (true), altrimenti (else) viene eseguita la parte contenuta nella seconda coppia di parentesi graffe. Notare che, mentre la prima parte è obbligatoria la parte con else e seconda coppia di parentesi può anche mancare.

Alla prossima lezione

Corso Microcontrollori (Arduino)

By lapinig,

Queste pagine saranno utilizzate per fornire i materiali necessari per poter seguire il modulo 11.2 Microcontrollori (Arduino) del Corso AUTOMA20 di ITS PRIME, tenuto dal sottoscritto.

A causa delle ormai note ragioni questo modulo si terrà, almeno in questa parte iniziale, con didattica a distanza e, pertanto, utilizzeremo supporti di virtualizzazione delle esercitazioni di laboratorio per poter comprendere meglio la programmazione dei microcontrollori.

Verrà utilizzata la piattaforma TinkerCad (TM) fornita gratuitamente da AutoDesk (TM) sul sito https://www.tinkercad.com.

Qui potete trovare i primi consigli per registrarvi e poter così accedere a questa piattaforma.

Per comprendere i circuiti che verranno di volta in volta realizzati (virtualmente per adesso) occorre sapere che cos’è una BreadBoard.

Corso ITS – AUTOMA20

Gualtiero Lapini