Un laboratorio di Fisica con Python e Arduino - Circuito RC v2

Ludovico Russo

7 mins min read

Come premesso, ripropongo oggi l'esperimento sul circuito RCRC presentato in questo post e rivisto utilizzando l'IDE di programmazione scientifica Spyder e la libreria per sviluppare programmi Arduino in Python nanpy.

Spyder + Nanpy + RC

Per info sull'accoppiata e su come installare il tutto, rimando al mio precedente post.

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).

Quando un circuito RCRC inizialmente spento viene alimentato ad una tensione VV_\infty, si può verificare che l'andamento nel tempo della tensione ai capi del condensatore rispetta la legge

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

Il valore τ=RC\tau = RC è anche detto costante di tempo.

Tolleranze dei Componenti

Nell'esperimento che proponiamo oggi, considereremo anche le tolleranze che abbiamo sui componenti elettronici che useremo. In fisica è noto e accettato dalla comunità l'impossibilità di ottenere misure esatte. Ogni misura ottenuta si trova quindi all'interno di un insieme numerico (range di incertezza) di valori accettabili.

Similmente, riguardo ai componenti elettronici commerciali, è impossibile per i produttori creare componenti sempre uguali: per questo motivo, al valore nominale di un componente è sempre associato una tolleranza, che ne definisce il range di incertezza.

Facciamo un esempio: se prendiamo un resistore RR di valore nominale 100kΩ100k\Omega e tolleranza 5%5\%, sappiamo che la misura reale della resistenza del componente sarà all'interno del range 100Ω±5%=[95105]Ω100\Omega\pm5\% = [95 - 105]\Omega.

Scopo dell'esperimento

Lo scopo dell'esperimento è verificare che la legge delle carica del condensatore è rispettata. Il procedimento adottato sarà il seguente:

  • Utilizziamo la legge della carica del condensatore per simulare l'andamento (considerando le tolleranze dei componenti).
  • Misuriamo la carica di un condensatore di un circuito RCRC reale.
  • Confrontiamo la simulazione con i dati reali verificando che la misura ricade all'interno del range di incertezza dei componenti.
  • Otteniamo una misura più precisa della costante di tempo τ\tau utilizzando Python.

Circuito

Il circuito sviluppato è mostrato nella figura seguente. Il materiale utilizzato è qui riportato:

  • Arduino UNO.
  • Condensatore Elettrolitico C=100μF±50%C=100\mu F \pm 50\%).
  • Resistore (nel mio caso con R=200Ω±5%R=200\Omega\pm5\%).
  • 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 decina di millisecondi. Nel mio caso, ho scelto τ=RC=0.02s\tau=RC=0.02s 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 condensatore 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.

Simulazione

Per simulare l'andamento della tensione v(t)v(t) dobbiamo considerare il parametro τ=RC\tau = RC. Date le tolleranze dei due circuiti, possiamo stimare la costante di tempo come

τ=0.02s±55%[0.09,0.31]s\tau = 0.02s \pm 55\% \in [0.09, 0.31]s

Andremo, quindi, a simulare 3 curve, rappresentate dalla τ^=0.02s\hat{\tau} = 0.02s nominale, e dai valori minimo e massimo che essa può assumere: τm=0.009s\tau_m = 0.009s e τM=0.031s\tau_M = 0.031s. In questo esperimento non andremo a considerare le altre incertezze, come quella sulla tensione di carica VV_\infty o dell'incertezze sulle misure dei sensori.

Per disegnare le tre curve, implementiamo una funzione in Python che calcola i valori della curva data i campioni di tempo in forma di vettore e il valore di tautau da utilizzare

def v_s(t, tau):
    return 5*(1-np.exp(-1/tau * t))

Andremo quindi ad utilizzare questa funzione all'interno di uno script in Spyder.

from pylab import *
import numpy as np

def v_s(t, tau):
    return 5*(1-np.exp(-1/tau * t))

t = arange(0,0.2,0.0001)
tau = 0.02
eps_tau = 0.55
tau_m, tau_M = tau-eps_tau*tau, tau+ eps_tau*tau

plot(t, v_s(t, tau), 'k-')
plot(t, v_s(t, tau_m),'k--')
plot(t, v_s(t, tau_M),'k--')

Il cui output sarà il seguente

Simulazione RC

Si noti che la simulazione viene fatta fino a 0.2s0.2s. Questo valore è calcolato in modo da essere molto più grande (circa 10 volte) la costante di tempo stimata.

Campionamento del Circuito RC

A questo punto, utilizziamo nanpy per campionare i dati utilizzando il seguente script


from datetime import datetime
from nanpy import ArduinoApi, SerialManager
from time import sleep

# connessione ad arduino sulla porta seriale specifica
connection = SerialManager(device='/dev/cu.usbmodem1461')
a = ArduinoApi(connection=connection)

# scarichiamo il condenatore
a.pinMode(2, a.OUTPUT)
a.digitalWrite(2, a.LOW)
sleep(2)

# carichiamo il condensatore e misuriamo l'andamento
a.digitalWrite(2, a.HIGH)
ts = datetime.now()
vm, tm = [], []
for i in range(0,50):
    vm.append(5.0*a.analogRead(14)/1023.0)
    tm.append(datetime.now())
print 'stop'

# convertiamo i dati in numpy
tm = [(i-ts).total_seconds() for i in  tm]
tm = np.array(tm)
vm = np.array(vm)

# plot
plot(tm,vm, '.')

Questo semplice script, dopo aver scaricato il condensatore, prevede a misurare la carica sul condensatore nel tempo, salvando anche i valori temporali in cui questi dati vengono campionati.

Alla fine, plotta i valori misura nel tempo, ottenendo questo risultato.

Misura RC

Come si può vedere dal grafico, l'andamento dei campioni è molto simile ad una curva esponenziale negativa.

Come sopra, abbiamo fatto in modo che il campionamento vada avanti per circa 10 volte la stima della costante di tempo. Questo viene fatto modificando il numero di campioni all'interno del ciclo for.

Verifica della legge della carica del circuito e misura sperimentale di τ\tau

Non ci resta che verificare se la legge fisica di carica del condensatore è effettivamente verificata. Per fare questo, per prima cosa è necessario verificare che i campioni siano all'interno delle due curve simulate con i valori limite di τ\tau considerando le tolleranze. Per fare questo, basta eseguire di seguito i due script ripostati sopra in modo da sovrapporre i plot, ottenendo un risultato simile a questo:

Verifica RC

In cui si può effettivamente vedere che l'andamento stimato è rispettato.

Per ultimo, verifichiamo che l'andamento dei campioni sia effettivamente ben approssimato da una curva esponenziale decrescente, e calcoliamo il tautau^* che meglio approssima questi campioni.

Per far questo, possiamo utilizzare un interessante modulo chiamato from scipy.optimize ed in particolare la funzione curve_fit contenuta al suo interno.

Con le seguenti linee di codice, chiediamo alla funzione curve_fit di calcolare il miglior tau che meglio approssima i dati campionati (tm e vm), utilizzando la funzione v_s implementata prima.

from scipy.optimize import curve_fit
popt, pcov = curve_fit(v_s, tm, vm)

La funzione ritorna due valori:

  • popt è un array contenente il set di parametri di v_s che meglio approssima i dati (in questo caso, dato che l'unico parametro utilizzato è τ\tau, popt conterrà un solo elemento).
  • pcov contiene l'errore di approssimazione

Possiamo quindi utilizzare questi dati per estrapolare una misura più precisa del tau reale τ\tau^* e quindi la curva che meglio approssima i valori ottenuti.

Otteniamo quindi

  • τ=0.028[0.09,0.31]\tau^* = 0.028 \in [0.09, 0.31] compatibile con il range di valori stimato all'inizio
  • Un errore molto piccolo ϵ=1.62107\epsilon = 1.62\cdot 10^{-7}

Che producono la curva rossa nel seguente grafico

Stima tau RC

Codice Completo

Di seguito vi riporto il codice completo utilizzato nel tutorial

# -*- coding: utf-8 -*-

from pylab import *
import numpy as np
from nanpy import ArduinoApi, SerialManager
from time import sleep

def v_s(t, tau):
    return 5*(1-np.exp(-1/tau * t))

t = arange(0,0.2,0.0001)
tau = 0.02
eps_tau = 0.55
tau_m, tau_M = tau-eps_tau*tau, tau+ eps_tau*tau

plot(t, v_s(t, tau), 'k-')
plot(t, v_s(t, tau_m),'k--')
plot(t, v_s(t, tau_M),'k--')

connection = SerialManager(device='/dev/cu.usbmodem1461')
a = ArduinoApi(connection=connection)

a.pinMode(2, a.OUTPUT)
a.digitalWrite(2, a.LOW)
sleep(2)

print 'start'

from datetime import datetime

a.digitalWrite(2, a.HIGH)
ts = datetime.now()

vm, tm = [], []
for i in range(0,50):
    vm.append(5.0*a.analogRead(14)/1023.0)
    tm.append(datetime.now())
print 'stop'

tm = [(i-ts).total_seconds() for i in  tm]

tm = np.array(tm)
vm = np.array(vm)

plot(tm,vm, '.')

from scipy.optimize import curve_fit
popt, pcov = curve_fit(v_s, tm, vm)

tau_star = popt[0]
epsilon = pcov[0]
plot(t, v_s(t, tau_star),'r')

Conclusioni

Come potete vedere, utilizzando questi strumenti si può, in pochissimo tempo e con pochissimo materiale, sviluppare un esperimento di elettrotecnica semplice ma completo. È ovviamente possibile complicare a piacere questo esperimento aggiungendo nuovi componenti elettrici al circuito o utilizzando componenti di valori diversi.

Come al solito, gli interessati possono contattarmi sulla mia pagina facebook per commenti e/o consigli.