Archivi categoria: i miei allievi

Arduino – misurare tensioni continue fino a 5V

La misurazione di una tensione con Arduino è un esercizio standard utilizzato per spiegare come funziona il convertitore Analogico Digitale sulla scheda. Nell’esempio che segue verrà mostrato come visualizzare sulla Serial Monitor la tensione di una batterie da 1,5V ma in generale di una tensione non superiore ai 5V, seguono poi una serie di esercizi per i miei studenti.
Nella prossima lezione mostreremo come misurare una tensione superiore ai 5V.

ATTENZIONE
E’ essenziale ricordare che non bisogna in alcun modo inserire tensioni superiori a 5V sui pin di Arduino, in quanto potreste distruggere irrimediabilmente la scheda.

Per la rilevazione di una tensione elettrica su un pin analogico viene utilizzata la funzione analogRead, che come più volte indicato su questo sito, è in grado di convertire una tensione tra 0V e 5V continui in un valore numerico intero con risoluzione di 10 bit tra 0 e 1023, operazione svolta dal convertitore A/D.

Ricordo che l’analogRead(pin) legge il valore di tensione (compreso tra 0 e 5V) applicato sul piedino analogico ‘pin’ con una risoluzione di 10 bit e la converte in un valore numerico compreso tra 0 e 1023, corrispondente quindi ad un intervallo di 1024 valori, pertanto il valore unitario corrisponde a:

Vu = 5V/1023 = 4,89 mV

Per conoscere il valore di tensione rilevato sarà sufficiente moltiplicare la tensione unitaria Vu per il valore restituito dalla funzione analogRead(pin), quello che chiamiamo valore quantizzato Vq compreso tra 0 e 1024, il valore misurato Vm sarà:

Vm = Vu x Vq

e sapendo che Vu corrisponde a 4,89 mV possiamo scrivere:

Vm = 4,89 x Vq

Nota per i miei allievi: riprenderemo questo semplice calcolo qundo utilizzeremo ad esempio i sensori di temperatura.

Il semplice schema di collegamento è riportato nell’immagine che segue:

Per stampare sulla Serial Monitor la tensione ai capi della batteria, useremo valori di tipo float (in virgola mobile), che come indicato nel mio post: “Arduino: tipi di dati – ripasso” possiamo esprime valori compresi tra –3.4028235E+38 e 3.4028235E+38.
La stampa di numeri in virgola mobile sula Serial Monitor verrà rappresentata con numeri che hanno al massimo con due cifre decimali, riprenderemo questo aspetto nel secondo esempio di questa lezione.

// Prof. Maffucci Michele
// Esempio 01: Misura di tensioni continue non superiori a 5V
// utilizzando variabili di tipo float
// Data: 01.10.2021

// tensione di riferimento predefinita sulla scheda
const float tensioneDiRiferimento = 5.0;

// batteria connessa al pin analogico 0
const byte pinBatteria = A0;

void setup() {
  // inizializzazione della porta seriale
  Serial.begin(9600);
}

void loop() {
  // legge il valore della batteria e lo trasforma
  // in un valore numerico tra 0 e 1023
  int valoreLetto = analogRead(pinBatteria);

  // calcolo della proporzione
  // volt:tensioneDiRiferimento = valoreLetto:1023.0
  // da cui si ricava la formula che segue
  float volt = (valoreLetto/1023.0) * tensioneDiRiferimento;

  // stampa sulla Serial Monitor la tensione misurata
  Serial.println(volt);
}

Per evitare spreco di memoria dovuto ai calcoli che utilizzano i tipi di dati float che occupano maggiore memoria, è possibile utilizzare al posto del tipo float il tipo long, ovvero un int lungo rappresentato da 4 byte in grado di rappresentare numeri interi tra –2147483648 a 2147483647.

Vediamo come modificare lo sketch precedente per rilevare tensioni espresse in millivolt in cui però si utilizzano variabili intere di tipo long:

// Prof. Maffucci Michele
// Esempio 02: Misura di tensioni continue non superiori a 5V
// utilizzando variabili di tipo float
// Data: 01.10.2021

// batteria connessa al pin analogico 0
const byte pinBatteria = A0;

void setup() {
  // inizializzazione della porta seriale
  Serial.begin(9600);
}

void loop() {
  // legge il valore della batteria e lo trasforma
  // in un valore numerico tra 0 e 1023
  // valoreLetto è di tipo long
  long valoreLetto = analogRead(pinBatteria);

  // stampa sulla Serial Monitor la tensione misurata
  // in millivolt

  Serial.println((valoreLetto*(500000/1023L))/100);
}

Quindi per evitare di effettuare calcoli con numeri di tipo float (in virgola mobile) senza perdere precisione, il trucco consiste nell’operare sui valori in millivolt invece che  sui valori in volt. Ricordo che 1 volt corrisponde a 1000 millivolt.

Come detto all’inizio di questa lezione sappiamo che un valore numerico di 1023 restituito dall’analogRead, corrisponde al valore massimo di 5000 millivolt, allora ogni unità rappresenta 5000/1023 millivolt, che corrisponde a 4,89 millivolt. Come detto nell’esempio precedente, la stampa su Serial Monitor di un numero in virgola mobile mostrerà al massimo due decimali, pertanto l’eliminazione dei decimali nel secondo esempio possiamo farlo moltiplicando per 100, nel codice: 5000×100=500000, questo valore verrà poi moltiplicato per il rapporto tra il valore letto e 1023 ed il tutto ancora diviso per 100, così facendo otterremo il valore in millivolt. Questo calcolo permette di far effettuare al compilatore solamente calcoli tra interi e non tra float, rendendo quindi la computazione più veloce e riducendo la quantità di memoria utilizzata.

Si noti che al fondo del numero 1023 è stata aggiuta una L, cioè 1023L, che indicare al compilatore che il numero rappresentato è di tipo long (4 byte).

Esercizi per i miei studenti

Esercizio 1
Utilizzare un Trimmer per regolare la tensione in ingresso ad A0 tra 0 e 5V, in questo caso si prenda la tensione di 5V dal pin di Arduino.

Esercizio 2
Nel primo sketch proposto utilizzare la funzione map per convertire il valore restituito dall’ analogRead in un valore di tensione. In questo caso nascono dei problemi sulla precisione della misura, sapresti indicarmi quali?

Esercizio 3
Visualizzare il valore di tensione regolato dal Trimmer sul Plotter Seriale.

Esercizio 4
Utilizzando uno qualsiasi dei due sketch indicati sopra e visualizzare la tensione misurate sul un display 16×2

Esercizio 5
Aggiungere all’esercizio precedente l’indicazione di carica data da un grafico costituito da 5 quadrati che ne indicano il livello di carica, non appena il livello di carica raggiunge 1 volt il quadrettino inizia a lampeggiare.

Buon Making a tutti 🙂

Raspberry Pi Pico – controllare lo stato di un pin digitale

Propongo in questa breve lezione due esempi di base sull’uso del Raspberry Pi Pico: identificare lo stato di un pulsante e realizzazione di un interruttore mediante un pulsante.

Per questo esempio utilizzeremo il pin 14 a cui connetteremo un pin del pulsante, così come rappresentato nell’immagine che segue. Come sapete molti dei pulsanti disponibili nei kit elettronici sono costituiti da 4 pin, connessi frontalmente a due a due.
Proseguiamo connettendo il secondo pin del pulsante al positivo sulla breadboard (3,3V). Ricordiamoci inoltre la connessione del 3,3V del PiPico al positivo della breadboard.

E’ molto importante ricordare che una simile connessione del pulsante con il PiPico potrebbe causare problemi di cortocircuito alla pressione del pulsante, perché non presente una resistore di PULL-UP o di PULL-DOWN fisico. Per evitare di utilizzare un resistore, attiviamo la resistenza di PULL-DOWN sul pin 14, ATTENZIONE ricordate di fare questa operazione altrimenti rischiate di distruggere irrimediabilmente  il vostro microcontrollore.

Aprite l’editor Thonny e digitate il seguente programma:

# Prof. Maffucci Michele
# Controllo dello stato sul pin 14 (una sola volta)
# 18.09.2021

# libreria che permette di utilizzare MicroPython con il RaspyMicro
import machine

# creazione dell'oggetto pulsante che include il pin 14 impostato come input
# su cui viene attivata il resistore di PULL-DOWN
pulsante = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

# la lettura del pulante viene fatta usando l'API machine
# usando la funzione value

print(button.value())

Salvate il programma sulla vostra scheda, assegnate ad esempio il nome pulsante1.py
Se mandate in esecuzione il programma lo stato del pin verrà mostrato immediatamente sulla Shell una sola volta.

Se non premete il pulsante verrà mostrato sulla Shell il valore logico 0 in quanto abbiamo utilizzato una resistenza di PULL-DOWN, nel momento in cui, all’avvio premete il pulsante lo stato logico visualizzato sulla Shell sarà 1.

Per leggere lo stato del pulsante in modo continuo bisognerà aggiungere un loop all’interno del programma che segue che chiameremo pulsante2.py

# Prof. Maffucci Michele
# Controllo dello stato sul pin 14 (in modo continuo)
# 18.09.2021

# libreria che permette di utilizzare MicroPython con il RaspyMicro
import machine

# per la gestione del tempo
import utime

# creazione dell'oggetto pulsante che include il pin 14 impostato come input
# su cui viene attivata il resistore di PULL-DOWN
pulsante = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

# la lettura del pulante viene fatta usando l'API machine
# usando la funzione value

# while True definisce un loop infinito al cui interno
# troviamo il controllo dello stato del pulsante
while True:
    # se la condizione è vera viene stampato
    # il messaggio mediante la print
    # e fermato il programma per 1 secondi
    if pulsante.value() == 1:
        print("Hai premuto il pulsante")
        utime.sleep(1)

Premete sul pulsante di Run nell’IDE, vedrete che fino a quando non premete il pulsante non accade nulla. Non appena il pulsante viene premuto viene stampata sulla Shell la strina “Hai premuto il pulsante”.

Attenzione che senza la brevissima pausa di 1 secondo verrebbe stampato continuamente il messaggio “Hai premuto il pulsante”.

Vedrete quindi la stampa del messaggio ogni secondo. Se mantenete premuto il pulsante per un tempo superiore a 1 secondi verrà stampato nuovamente il messaggio e ciò si ripeterà ogni secondo fino a quando non rilasciamo il pulsante.

Vediamo ora un programma che, oltre ad inviare un messaggio sulla Shell, accende un LED esterno connesso al pin 15 ogni volta che premiamo il pulsante, chiamiamo il programma pulsante3.py.

# Prof. Maffucci Michele
# Controllo dello stato sul pin 14 (in modo continuo)
# eaccensione di un led alla pressione del pulsante
# 18.09.2021

# libreria che permette di utilizzare MicroPython con il RaspyMicro
import machine

# per la gestione del tempo
import utime

# creazione dell'oggetto pulsante che include il pin 14 impostato come input
# su cui viene attivata il resistore di PULL-DOWN
pulsante = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

#pin 15 dichiarato come OUTPUT
ledEsterno = machine.Pin(15, machine.Pin.OUT)

# while True definisce un loop infinito al cui interno
# troviamo il controllo dello stato del pulsante
while True:
    # se la condizione è vera viene stampato
    # il messaggio mediante la print
    # e fermato il programma per 1 secondi
    if pulsante.value() == 1:
        ledEsterno.value(1)    # imposta il livello logico 1 sul pin 15
        print("Hai premuto il pulsante")
        utime.sleep(0.5)       # imposta una pausa di mezzo secondo
        ledEsterno.value(0)    # imposta il livello logico 0 sul pin 15

Vediamo ora come realizzare un programma che realizza la funzione di un interruttore, cioè il mantenimento dello stato al rilascio del pulsante. Chiamiamo il programma interruttore1.py. Il circuito è il medesimo dell’esempio al passo precedente.

# Prof. Maffucci Michele
# realizzazione di un interruttore
# mediante pulsante connesso al Pin 14 con antirimbalzo software
# con accensione di un LED connesso al pin 15
# 18.09.2021

# libreria che permette di utilizzare MicroPython con il RaspyMicro
import machine

# per la gestione del tempo
import utime

# creazione dell'oggetto pulsante che include il pin 14 impostato come input
# su cui viene attivata il resistore di PULL-DOWN
pulsante = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

#pin 15 dichiarato come OUTPUT
ledEsterno = machine.Pin(15, machine.Pin.OUT)

# val usato per conservare lo stato del pulsante
val = 0

# vecchio_val per conservare lo stato del pulsante al passo precedente
vecchio_val = 0

# ricorda lo stato in cui si trova il LED,
# stato = 0 led spento, stato = 1 led acceso
stato = 0

# while True definisce un loop infinito al cui interno
# troviamo il controllo dello stato del pulsante
while True:
    val = pulsante.value()                   # legge il valore del pulsante e lo conserva
    if (val == 1) and (vecchio_val == 0):    # controlla se è accaduto qualcosa
        stato = 1 - stato
        utime.sleep(0.15)	             # attesa di 15 millisecondi
    vecchio_val = val;
    if (stato == 1):
        ledEsterno.value(1)    # imposta il livello logico 1 sul pin 15
    else:
        ledEsterno.value(0)    # imposta il livello logico 0 sul pin 15

Modifichiamo ora il programma precedente inviando sulla Shell il messaggio che indica lo stato del LED, chiamiamo il programma interruttire2.py. Il circuito è il medesimo dell’esempio al passo precedente.

# Prof. Maffucci Michele
# realizzazione di un interruttore
# mediante pulsante connesso al Pin 14 con antirimbalzo software
# con accensione di un LED connesso al pin 15
# e stampa dello stato del LED sulla Shell
# 18.09.2021

# libreria che permette di utilizzare MicroPython con il RaspyMicro
import machine

# per la gestione del tempo
import utime

# creazione dell'oggetto pulsante che include il pin 14 impostato come input
# su cui viene attivata il resistore di PULL-DOWN
pulsante = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)

#pin 15 dichiarato come OUTPUT
ledEsterno = machine.Pin(15, machine.Pin.OUT)

# val usato per conservare lo stato del pulsante
val = 0

# vecchio_val per conservare lo stato del pulsante al passo precedente
vecchio_val = 0

# ricorda lo stato in cui si trova il LED,
# stato = 0 led spento, stato = 1 led acceso
stato = 0

# stampare una sola volta il messaggio 'LED acceso' o 'LED spento' sulla Shell
abilitaMessaggio = 0

# while True definisce un loop infinito al cui interno
# troviamo il controllo dello stato del pulsante
while True:
    val = pulsante.value()                    # legge il valore del pulsante e lo conserva
    if (val == 1) and (vecchio_val == 0):     # controlla se è accaduto qualcosa
        stato = 1 - stato
        utime.sleep(0.15)		      # attesa di 15 millisecondi
    vecchio_val = val;
    if (stato == 1) and (abilitaMessaggio == 0):
        ledEsterno.value(1)                   # imposta il livello logico 1 sul pin 15
        abilitaMessaggio = 1
        print("LED acceso")                   # stampa il messaggio
        utime.sleep(1)
    elif (stato == 0) and (abilitaMessaggio == 1):
        ledEsterno.value(0)                   # imposta il livello logico 0 sul pin 15
        abilitaMessaggio = 0
        print("LED spento")                   # stampa il messaggio
        utime.sleep(1)

Buon Coding a tutti 🙂

Arduino: stampare più funzioni sulla serial plotter

L’attività di progetto di questa mattina: progettazione di dispositivi elettronici che rispondono a diverse necessità per la salute umana: cura della persona, disabilità, sicurezza sul lavoro, strumenti medici/laboratorio, accessibilità dei luoghi pubblici, ecc…

Con mio piacere ne è nata un’intensa attività di ricerca che ha coinvolto l’intero gruppo classe. Molte le necessità e tra queste ne evidenzio uno, semplice, che riguarda la programmazione, che in più occasioni gli studenti affrontano durante le sperimentazioni e di cui mi sono reso conto di non avere documentato adeguatamente, ovvero: il plot di più funzioni su uno stesso piano cartesiano con Arduino.

Avevo mostrato in più occasioni come effettuare il plot di grandezze variabili nel tempo utilizzando la Serial Plotter dell’IDE di Arduino, uno degli ultimi articoli si riferisce alla realizzazione di uno strumento per la rilevazione di vibrazioni, un semplice sismografo realizzato con un sensore piezoelettrico.

Alcuni studenti questa mattina, si stavano cimentando nella progettazione di un guanto da utilizzare per la movimentazione di un braccio robot industriale della hyundai con l’obiettivo di simulare la movimentazione a distanza di sostanze chimiche pericolose. Nelle prime attività di ricerca si è manifestata la necessità di visualizzare su tre grafici diversi le componenti X, Y, Z dell’accelerazione fornite da un accelerometro connesso ad Arduino.

Come sicuramente saprete l’avvio della Serial Plotter avviene, così come per la Serial Monitor dal menù Tools. Ricordo che Serial Monitor e Serial Plotter non possono essere avviate contemporaneamente.

La Serial Plotter prende i valori che giungono dalla seriale (connessione USB) e li grafica su un piano cartesiano. I dati numerici vengono anche visualizzati nella parte in alto a sinistra della finestra della Serial Plotter.

I valori massimi e minimi rappresentati sull’asse Y vengono regolati automaticamente, mentre la dimensione dell’asse X è fissato a 500 punti e l’aggiornamento del grafico avviene ogni qual volta nel vostro sketch viene eseguita una Serial.println().

Ricordate inoltre di fissare il Baud Rate del Serial Plotter in modo che corrisponda a quello che avete indicato nel codice.

Per tracciare contemporaneamente forme d’onda è possibile agire in due modi:

inserendo uno spazio tra due istruzioni di stampa

Serial.print(temperatura);
Serial.print(" ");
Serial.println(umidita);

oppure inserendo una tabulazione tra due istruzioni di stampa

Serial.print(temperatura);
Serial.print("\t");
Serial.println(umidita);

In questo caso le due grandezze, temperatura e umidità, saranno rappresentate da due funzioni separate e tracciate contemporaneamente sullo stesso piano cartesiano.

A titolo di esempio consideriamo il mio post in cui mostravo come utilizzare un DHT11 e visualizzeremo sulla Serial Plotter le due grandezze fisiche temperatura ed umidità. Di seguito schema di collegamento, sketch e grafici.

// Prof. Maffucci Michele
// Visualizzazione della pressione e dell'umidità rilevata da un DHT11
// sulla Serial Plotter
// 16.09.2021

// Libreria DHT
#include "DHT.h"

// Pin digitale di arduino connesso al DHT
#define DHTPIN 2

// tipo del sensore: DHT 11
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

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

void loop() {
  // Attesa di 1 millisecondo prima di fornire la misura.
  delay(1);

  // Lettura dell'umidità
  float h = dht.readHumidity();
  // Lettura della temperatura in gradi Celsius
  float t = dht.readTemperature();

  // Verifica se le si presenta un errore di lettura (e riprova nuovamente)
  if (isnan(h) || isnan(t)) {
    Serial.println(F("Impossibile leggere dal sensore DHT!"));
    return;
  }

  // Stampa del valore dell'umidità
  Serial.print(h);
  Serial.print(' ');
  // Stampa del valore della temperatura
  Serial.println(t);
}

Il plot delle due grandezze è:

Per completezza realizziamo un semplice sketch che permette di rappresentare 3 funzioni sinusoidali sfasate di 90 gradi una rispetto all’altra con ampiezze diverse:

// Prof. Maffucci Michele
// Visualizzazione di tre funzioni siusoidali
// di ampiezza diversa e sfasate di 90 gradi
// 16.09.2021

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

void loop() {

  // M_PI è la macro definita nell'header math.h
  // che definisce il pi greco che ha il valore di:
  // 3.14159265358979323846
  for(int i = 0; i < 360; i += 2) {
    float ValoreY1 = 1 * sin(i * M_PI / 180);
    float ValoreY2 = 2 * sin((i + 90)* M_PI / 180);
    float ValoreY3 = 4 * sin((i + 180)* M_PI / 180);

    Serial.print(ValoreY1);
    Serial.print(' ');         // deve essere stampato spazio ' ' o  tab '\t' tra due valori.
    Serial.print(ValoreY2);
    Serial.print(' ');         // deve essere stampato spazio ' ' o  tab '\t' tra due valori.
    Serial.println(ValoreY3);  // l'ultimo valore deve avere un ritorno a capo

    delay(1);
  }
}

Buon Coding a tutti 🙂

Raspberry Pi Pico – come cancellare un file dalla memoria del microcontrollore

Come avrete notato durante le prime sperimentazioni con il PiPico, possiamo depositare all’interno della memoria del microcontrollore più programmi in MicroPython e decidere quali di questi mandare in esecuzione. Nel caso in cui si desideri rendere l’avvio automatico e continuo uno programma non appena il PiPico  viene connesso ad una fonte di alimentazione, è sufficiente rinominate il file in main.py.
Può accadere quindi che le nostre sperimentazioni ci portino a memorizzare più programmi all’interno della memoria del PiPico pertanto si potrebbe avere la necessità di dover cancellare o rinominare alcuni di questi.
In questo breve tutorial vedremo come cancellare un file usando i comandi che inseriremo nella shell di Thonny.

Come aprire un programma memorizzato nel PiPico

Per poter consultare la lista di file memorizzati all’interno del microcontrollore con l’IDE Thonny, fate clic su “Apri” (seconda icona)

Si aprirà un pannello che richiede la selezione dell’unità da aprire: sul computer o sul PiPico, selezionare il Raspberry Pi Pico

Ciò aprirà la finestra di seguito indicata da cui poter visionare la lista dei file e con cui potrete aprire uno dei file per poi modificarlo o eseguirlo.

Cancellare un file memorizzato nel PiPico

Posizionate il cursore nella prima riga della Shell e digitate il comando. Inseriremo una serie di comandi terminali in Python:

import os

in Python “import os” consente di importare i moduli necessari per interfacciarsi con il sistema operativo sottostante su cui Python è in esecuzione ed eseguire una serie di operazioni sui file, come ad esempio la cancellazione, lo spostamento dei file, rinominare file, creare directory e molto altro. Poichè con MicroPython non si ha nessun sistema operativo il modulo os fornisce tutte quelle funzioni relative alla gestione del semplice del file system e le informazioni relativo al sistema.

Continua a leggere

Dove prelevare tutte le versione del Firmware per il Raspberry Pi Pico e come installarlo

L’installazione del Firmware sul Raspberry Pi Pico è descritta nel primo post pubblicato, rispetto alla prima pubblicazione del mio post, le pagine della documentazione di Raspberry Pi Fundation sono state modificate, il clic sul file INDEX.HTM all’interno del vostro PiPico rimandava direttamente alla pagina di download, ora invece rimanda alla home page della documentazione. Per rendere più agevole il download, quindi, così come segnalato sul mio profilo Facebook, segnalo il link diretto alla pagina e alla sezione specifica di download.

Successivamente clic su: Download the MicroPython UF2 file.

Ciò che scaricherete è l’ultima versione (stable), ma nel caso in cui abbiate necessità di avere l’ultima versione, oppure desiderate sperimentare l’uso dell’ultima versione beta o ancora avere tutte le versioni passate del firmware, il sito di riferimento è https://micropython.org

recatevi nella sezione: Download

Selezionate: Raspberry Pi RP2040 microcontroller boards

Nella pagina troverete tutte le versioni, un clic sul link corrispondente per effettuare il download

L’installazione può avvenire tramite REPL, oppure premendo il pulsante sulla scheda BOOTSEL e procedere come descritto nel mio post.

L’installazione del Firmware può avvenire in una modalità ancora più comoda utilizzando anche l’editor Thonny che abbiamo iniziato a conoscere.

Connettete il PiPico al computer mantenendo premuto il pulsante BOOTSEL, dopo non più di 3 secondi rilasciate il pulsante, comparirà l’unità USB sul vostro computer. Avviate Thonny comparirà la seguente finestra:

Clic sul “Installa”

Al termine comparirà il messaggio “Done!”

Se fate clic su “Done!” si aprirà la finestra di stato che vi dirà su quale porta USB è connesso il vostro PiPico:

Un clic su “Chiudi” per iniziare a programmare.

Buon Making a tutti 🙂