Nuova sezione libri disponibile!

Un laboratorio di Fisica con Arduino e Python

Ludovico Russo

lettura in 8 minuti

Premessa

Recentemente sono stato contattato dalla mia ex scuola (Liceo G. Stampacchia di Tricase) per aiutare a creare un corso di robotica e automazione per i nuovi studenti del liceo. Ho preso molto a cuore l'iniziativa e sto supportando i professori e il preside nell'implementazione. Da questo progetto è nata, tra le varie cose, l'idea di iniziare a sperimentare l'accoppiata Python + Arduino (magari su un raspberry pi) per realizzare in modo semplice esperimenti di Fisica e Matematica. Dal mio punto di vista i vantaggi di questo approccio sono molteplici, ecco quelli che mi vengono in mente adesso:

  • l'approccio è veramente multidisciplinare, invece del classico laboratorio di fisica, in cui gli studenti dovevano prendere ed elaborare a mano i dati, qui è richiesto allo studente di sviluppare il circuito di misura, scrivere codice Arduino a basso livello e utilizzare Python ad alto livello per l'elaborazione
  • super divertente (almeno secondo me)
  • molto economico da realizzare.

Come primo spunto, propongo un semplicissimo esperimento per la misura della carica di un condensatore in un circuito RC.

Nota: ho realizzato questo esperimento per dare alcuni spunti ai miei ex professori su cosa si può fare sfruttando queste tecnologie. Ancora non so se (e in che modo) si può proporre un'esperienza del genere agli studenti, ma credo fortemente che questi strumenti possano essere fortemente istruttivi!

iPython e pyLab

iPython è un'interfaccia di comando per Python molto semplice da utilizzare e potente. In accoppiata con la libreria matplotlib permette di ottenere un perfetto tool di lavoro per l'analisi dei dati scientifico, comprendente tool per la visualizzazione grafica dei dati. Una volta installato, è possibile lanciare il tool con il comando bash

ipython --pylab

Teoria sul circuito RCRC

Il circuito RCRC è un semplice circuito elettronico composto da un condensatore (di capacità CC) in serie ad una resistenza (di valore RR). Lo scopo dell'esperimento è misurare l'evoluzione carica QQ del condensatore nel tempo, cioè l'andamento della differenza di potenziale VV ai terminali del condensatore quando il circuito viene alimentato. Si ricordi, infatti che Q=CVQ=CV.

Noti i parametri RR e CC, sappiamo che la differenza di potenziale v(t)v(t) ai capi del consatore, al variare del tempo, è data da

v(t)=V(1etRC)v(t) = V_\infty \cdot \left(1-e^{-\frac{t}{RC}}\right)

dove VV_\infty è la tensione a cui viene alimentato il circuito RCRC, solitamente V=5VV_\infty = 5V.

Implementazione

L'esperimento realizzato permette, sfruttando Arduino, di misurare l'andamento della tensione v(t)v(t) ai due capi del condensatore e mandare (sfruttando la comunicazione seriale) a Python questi dati. Una volta acquisiti i dati possono venire elaborati sfruttando le potenzialità di iPython.

Circuito

Il circuito sviluppato è mostrato nella figura seguente. Materiale:

  • Arduino UNO.
  • Condensatore (nel mio caso un elettrolitico con C=100μFC=100\mu F).
  • Resistore (nel mio caso con R=10kΩR=10k\Omega).
  • Breadboard.

Importante: dato che Arduino (specialmente quando comunica in seriale) non è capace di acquisire dati ad una frequenza molto elevata, per riuscire a prendere un numero adeguato di dati conviene scegliere valori di RR e CC abbastanza elevati, in modo da avere constanti di tempo dell'ordine di qualche di qualche secondo. Nel mio caso, ho scelto τ=RC=1s\tau=RC=1s nominale.

RC-Scheme

Essendo il condensatore che ho utilizzato elettrolitico, i suoi terminali sono polarizzati, ossia è necessario collegare il terminale positivo (anodo) ad un punto del circuito avente potenziale più elevato rispetto al punto di collegamento del terminale negativo (catodo). Nel caso si utilizzi un condesatore ceramico, non è importante la polarità!

Colleghiamo quindi il catodo (-) del condensatore al PIN GND di Arduino ,e l'anodo (++) tramite breadboard al pin A0A0. Colleghiamo inoltre, per mezzo di una resistenza, l'anodo del condensatore al PIN 22 di Arduino.

Codice Arduino

Il codice Arduino che andremo ad implementare sfrutta il PIN 22 per caricare e scaricare il condensatore. In fase di carica, utilizzando il PIN A0A0 misura il valore di carica sul considerare e invia i dati in seriale. Il codice che ho sviluppato raccoglie 50 campioni intervallati da un periodo di campionamento Tc=100msTc =100ms.

È importante scegliere il tempo TcTc in modo da avere abbastanza campioni per valutare riuscire a ricostruire correttamente l'andamento del segnale.

Apro una piccola parantesi ingegneristica, esiste il Teorema di Nyquist che impone che il tempo di campionamento di un qualisasi segnale temporale deve essere Tc<12τminT_c < \frac{1}{2}\tau_{min}, dove τmin\tau_{min} è la più piccola costante di tempo di segnale stesso. In questo caso abbiamo una sola costante di tempo τ=RC=1s\tau=RC=1s, quindi dobbiamo scegliere Tc<0.5sT_c< 0.5s.

All'atto pratico, il mio consiglio è scegliere sempre Tc=τ10Tc =\frac{\tau}{10}. Nel mio caso ho τ=1s\tau = 1s e quindi ho scelto Tc=100msTc = 100ms.

Una volta scelto TcTc possiamo implementare il codice Arduino. Lo scopo del codice è:

  • Scaricare il condensatore per un tempo appropriato T=50TcT=50\cdot Tc.
  • Iniziare il ciclo di carica.
  • Campionare i dati di v(t)v(t) e mandarli in seriale.

Il codice implementato è riportato di seguito.

# define POWER_PIN 2

int cnt = 0;
int sensorPin = A0;

int Tc = 100; // 100ms

int N_campioni = 50;

void setup() {
  Serial.begin(9600);
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, LOW);
  delay(N_campioni*Tc);
  digitalWrite(POWER_PIN, HIGH);
  Serial.println("START");
}

void loop() {
  if (cnt < N_campioni) {
      int sensorValue = analogRead(sensorPin);
      Serial.println(sensorValue);
      cnt++;
    } else if (cnt == N_campioni){
      Serial.println("END");
      cnt++;
    }
  delay(Tc);
}

Testiamo il codice

Una volta implementato e lanciato il codice in Arduino, possiamo testare il programma attraverso il serial monitor. Apriamo il serial monitor e resettiamo la scheda, il programma inizierà a scaricare il condensatore e poi a prendere i dati. Il tutto dovrebbe durare circa 10s10s. Sul serial monitor dovreste vedere i valori misurati, come nella foto seguete

Se tutto funziona correttamente, possiamo passare all'utilizzo di Python per salvare i dati ed analizzarli.

Utilizzo di Python e pyLab

Per utilizzare questi strumenti, è necessario installare sul computer le seguenti librerie

  • iPython
  • matplotlib
  • pySerial

Le prime due servono per utilizzare in modo efficace e semplice tutta la potenza di pylab, l'ultima è una libreria che ci permette di sfruttare la comunicazione seriale per parlare con Arduino.

Scriviamo il codice per loggare i dati in seriale da Arduino

Creiamo un file chiamato rc.py in una cartella vuota, e implementiamo il seguente codice nel nuovo file.

from serial import Serial
import time

def get_data(port):
    print 'RESET CONDENSATORE....'
    times = []
    values = []
    ser = Serial(port)
    data = ser.readline().rstrip()
    while data != "START":
        data = ser.readline().rstrip()
    print 'STARTING....'
    while data != "END":
        data = ser.readline().rstrip()
        try:
            m = float(data)/1024.0 * 5
            times.append(time.time())
            values.append(m)
        except:
            continue
    print 'STOP....'
    ser.close()

    times = [t - times[0] for t in times]

    return times, values

Salviamo il file e apriamo la cartella all'interno del terminale.

Utilizzo di pyPlot

All'interno del terminale lanciamo iPython con PyLab utilizzando il seguente comando.

ipython --pylab

A questo punto, accedendo alla linea di comando di pyPlot, dovreste vedere una schermata simile alla seguente

iPython

Campionamento dei Dati

Perfetto, ora possiamo iniziare ad usare pyPlot in modo interattivo. Per prima cosa, bisogna importare il file rc.py ed utilizzarlo. Per farlo, eseguiamo i seguenti comandi:

Importiamo il file con il comando

import rc

Campioniamo i dati.

t_meas, v_meas = rc.get_data("/dev/ttyUSB0")

Nota 1: dobbiamo passare alla funzione get_data il nome della porta a cui Arduino è collegato. Per trovarla, basta verificare a quale porta è collegato Arduino sfruttando l'IDE di Arduino stesso.

Nota 2: Ricordate di chiudere il serial monitor dall'IDE di Arduino prima di eseguire il comando, altrimenti il canale di comunicazione risulterà occupato.

Una volta eseguita la funzione, dovremo aspettare la fine della procedura di acquisizione. A questo punto, troveremo i dati campionati all'interno delle due variabili t_meas e v_meas, che conterranno, rispettivamente, i tempi e i valori del dati campionati.

Per verificare che la procedura sia andata a buon fine, possiamo semplicemente digitare il nome di una delle due variabili e premere invio per stampare a schermo i valori contenuti all'interno.

Disegniamo i dati campionati

Per disegnare i dati possiamo eseguire il seguente comando

plot(t_meas, v_meas, 'ro')

A questo punto, dovrebbe apparire istantaneamente una nuova finestra con il grafico dei dati campionati

graph1

Nota: plot prende due parametri più un parametro opzionale. I primi due sono due vettori contenenti i dati da disegnare rispettivamente sull'asse xx e yy. Il terzo parametro (opzionale) è una stringa che definisce lo stile del disegno. In questo caso "ro" significa "disegna i valori in rosso (r) con dei pallini (o)".

Verifichiamo la legge fisica

A questo punto, non ci resta che verificare la legge fisica che regola la carica del circuito RCRC. Per farlo, proviamo a simulare l'andamento della carica sfruttando la legge e sovrapponiamo la simulazione ai dati campionati, per vedere se combaciano.

Per farlo, creiamo prima di tutto una sequenza di valori di tempo da 0s0s a 5s5s abbastanza densa, con il comando

t_sim = arange(0,5,0.01)

Tramite il comando, abbiamo generato una sequenza di numeri da 00 a 55 a intervalli di 0.010.01.

A questo punto, possiamo simulare l'equazione. Prima di tutto, bisogna definire le variabili RR, CC e VV_\infty.

Utilizzamo per farlo la notazione scientifica per definire i numeri.

R=10e3
C=100e-6
Vinf=5

A questo punto, possiamo implementare la legge e simulare i dati:

v_sim = Vinf*(1-exp(-t_sim/(R*C)))

Per finire, plottiamo i dati utilizzando il comando plot (questa volta su una linea continua di colore blu).

plot(t_sim, v_sim, 'b')

E, riaprendo la finestra dell'immagine, otterremo un grafico simile a questo

graph2

Conclusioni

Ho ricevuto molti segnale interesse per questo esperimento da parte dei professori della mia scuola. Spero che questo tutorial, che non è perfetto e che andrà migliorato, possa aiutare qualcuno a fare didattica in modo più divertente.

Se avete suggerimenti, trovate errori o volete semplicemente contattarmi, mi trovate su facebook.

Ringraziamenti

Alla stesura di questo documento hanno contribuito

  • Prof. Michele Maffucci
  • Prof. Giorgio de Nunzio

Ti è piaciuto questo post?

Registrati alla newsletter per rimanere sempre aggiornato!

Ci tengo alla tua privacy. Leggi di più sulla mia Privacy Policy.

Ti potrebbe anche interessare

HB Cloud Tutorial #1 - Uso dei Led
Iniziamo ad utilizzare la piattaforma di Cloud Robotics
HB Cloud Tutorial #2 - Uso dei Bottoni
Rieccomi con il secondo tutorial legato all'uso dei bottoni per il robot **DotBot-ROS**. In questo tutorial, vedremo come configurare ed utilizzare in Python un bottone attaccato ad un pin GPIO del Raspberry Pi 3.
HB Cloud Tutorial #3 - I Motori
I Motori sono una delle parti essenziali dei robot. In questo tutorial, vederemo come è possibile in modo semplice ed intuitivo implementare un programma in Python che controlla i motori in base a comandi inviati via Wifi al Robot.
Inviare Goals alla Navigation Stack - versione nodo ROS Python
Inviare un goal all ROS navigation stack utilizzando un nodo Python
Controllare siBOT dalla piattaforma HBR
Come controllare il manipolatore siBOT utilizzando la piattaforma HBR
Sviluppare un rilevatore di fiamma con la visione artificiale
Sviluppare un rilevatore di fiamma con la visione artificiale
Scriviamo un Blog in Python e Flask
Tutorial su come implementare, a partire da zero, un blog personale utilizzando Python e Flask! Prima parte!
Un IDE web Arduino sviluppato in Python e Flask
Un mio progetto dell'estate del 2015 che permette di programmare Arduino da un'interfaccia Web esposta da un Raspberry Pi
Canopy: una Pythonica alternativa a Matlab
Presento questo interessante tool python che può essere considerato una buona alternativa a Matlab per l'analisi dei dati!
Spyder, un'altra alternativa in Python a Matlab
Una velocissima prova del tool interattivo Spyder per l'analisi scientifica in Python
Simuliamo il moto parabolico in Python e Spyder
Un piccolo tutorial per iniziare ad utilizzare Spyder con Python
Python + Arduino = Nanpy
Programmare Arduino in Python con Nanpy
Utilizzo di Nanpy con il sensore di temperatura/umidità della famiglia DHT
Come utilizzare Nanpy col sensore DHT di temperatura e Umidità
Pasqua al Liceo Stampacchia di Tricase: Corsi di Arduino e Stampa 3D
In occasione delle vacanze di Pasqua 2017, il Liceo G. Stampacchia organizza due corsi tenuti da me su Arduino e stampa 3D.
Accendere led con Arduino e Telegram
Un bot telegram in grado di controllare Arduino realizzato da 3 ragazzi del Liceo Stampacchia
Implementiamo un bot Telegram con Python
Una semplice guida per iniziare a muovere i primi passi nello sviluppo di chatbot Telegram con Python
Pillole di Python: pyscreenshot
Una semplice tutorial che mostra il funzionamento della libreria pyscreenshot
Sviluppiamo un'app in Electron per controllare la scheda Arduino - parte 2
In questo tutorial, vediamo come sviluppare un oscilloscopio con Node.js, Electron e Typescript
Python Decorators
Introduzione ai decoratori in Python
TDD con Flask e PyTest per lo sviluppo di API REST. Parte 1
Tutorial su come usare il Test Driver Development (TDD) con Flask e PyTest per sviluppare delle semplici API REST
Implementiamo un bot Telegram con Python - I Comandi
Vediamo come gestire i comandi del nostro bot in Telegram
4 (+1) Libri su Python (in Inglese) da cui imparare
Una lista di libri su Python (in Inglese) da cui ho imparato a programmare
Virtualenv: gestiamo meglio le dipendenze in Python
A cosa servono e come si utilizzano i virtualenv Python
Leggere i codici a barre con OpenCV e zbar in Python
Come usare Python per leggere i codici a barre degli alimenti e ricavarne alcune informazioni utili
TDD con Flask e PyTest per lo sviluppo di API REST. Parte 2
Tutorial su come usare il Test Driver Development (TDD) con Flask e PyTest per sviluppare delle semplici API REST
Sviluppiamo un bot Telegram che legge i codici a barre degli alimenti
Implementiamo un bot Telegram in grado di leggere ed analizzare le immagini per la lettura ed interpretazione dei codici a barre
TDD con Flask e PyTest per lo sviluppo di API REST. Parte 3
Tutorial su come usare il Test Driver Development (TDD) con Flask e PyTest per sviluppare delle semplici API REST
Divertiamoci sviluppando UI da terminale con ASCIIMATICS
Le UI da terminale fanno molto anni '80, però sono sempre diventerti da implementare. Oggi vi voglio introdurre ad una semplice libreria per creare questo tipo di applicazione.
Sviluppiamo un Robot con tecnologie Open Source
Inizio una serie di videoguide, in cui voglio introdurvi al mondo della robotica di servizio in modo pratico, facendo vedere come è possibilile, sfruttando tecnologie completamente Open Source, quali Arduino, Raspberry Pi, ROS e Docker, costruire un piccolo robot di Servizio.
Parliamo come GMaps: come creare file audio con gtts (Google Text to Speech) in Python
gtts è una libreria in Python per sfruttare le API di Google Text to Speech per generare file audio dal testo
Robot Open Source - Introduzione a Docker
È disponibile il video "Introduzione a Docker".
I chatbot possono Parlare? Sviluppiamo un bot telegram che manda messaggi vocali
Usiamo le API di sintesi vocale di google per creare un bot in grado di mandare messaggi vocali
Robot Open Source - Docker e Raspberry
È disponibile il video "Docker e Raspberry".