Sheet Arduino n.6 (charge/discharge of a capacitor)¶
[Lezione del 26 nov 2019]
carica/scarica di un condensatore¶
La scheda della esercitazione n.6, richiede di misurare il voltaggio di un condensatore durante il processo di carica, per poter avere l’andamento nel tempo della tensione.
Siccome nel seguito poi si chiede di usare altre resistenze/capacità (ovvero: provare con circuiti che hanno diverse costanti RC) e di misurare anche la fase di scarica, mi sono organizzato come segue.
Prima di tutto ho provato la sola carica con RC=0,1s. Campioni misurati: 101, ogni 200ms.
Osservato che il tempo di campionamento (elevato) non permetteva di tracciare una curva dettagliata (questo è il relativo risultato:

) ho:
diminuito il tempo di campionamento a 20ms;
raddoppiato il buffer delle misure per includere la scarica; ma osservando comportamenti strani dell’Arduino, evidentemente generati da degli overflow in aree di memoria:
ho diminuito il numero di campionamenti da 101*2 a 71*2 (carica e successiva scarica);
quindi tracciato per rc=0,1s e successivamente per
RC=0,47s.
Il seguente video sintetizza quanto detto:
Il dettaglio dello sketch è:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | /* Embedded Systems Architecture - hardware
* application on sheet 06
*
* charge and discharge of a capacitor
*/
#define TO_V (5.0 / 1024.0) // convert an analog UNO unit to V
#define CHARGE_PIN 2
#define ANALOG_PIN A0
#define BUF_SZ 71
#define DELTA_TIME 20
#define FOREVER 1
#define Vin 5
double t[2*BUF_SZ]; // times values
double vout[2*BUF_SZ]; // measured tension(s)
void setup() {
pinMode(CHARGE_PIN, OUTPUT); // this is our power to capacitor
digitalWrite(CHARGE_PIN, LOW); // and setting it to low to be sure capacitor is discharged
Serial.begin(9600); // init the serial at 9600 baud
}
void loop() {
Serial.println("Discharging capacitor: 30s");
delay(30000);
Serial.println("Starting capacitor charge. Measuring:");
digitalWrite(CHARGE_PIN, HIGH); // powering capacitor
for(int i=0; i<BUF_SZ; i++){
Serial.print(".");
t[i] = millis();
vout[i] = analogRead(ANALOG_PIN) * TO_V;
delay(DELTA_TIME);
}
Serial.println("");
Serial.println("Starting capacitor discharge. Measuring:");
digitalWrite(CHARGE_PIN, LOW); // unpowering capacitor (discharge starts)
for(int i=BUF_SZ; i<2*BUF_SZ; i++){
Serial.print(".");
t[i] = millis();
vout[i] = analogRead(ANALOG_PIN) * TO_V;
delay(DELTA_TIME);
}
Serial.println("");
/* printing measure to serial monitor*/
Serial.println("Print start: Time (s), measured voltage (V)");
for(int i=0;i<2*BUF_SZ;i++){
Serial.print((t[i]-t[0])/1000, 3);
Serial.print(", ");
Serial.println(vout[i], 4);
}
Serial.println("Print end");
while(FOREVER){}; // halting ops
}
|
Come si vede abbiamo tre cicli in successione.
I primi due catturano le misure. Il primo durante la carica, il secondo durante la scarica.
Il terzo ciclo stampa sul monitor della seriale i risultati collezionati.
Analogamente a quanto fatto per l’esercizio precedente, il plottaggio di questi dati si può fare con questo programma python utilizzando la libreria matplotlib:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
help = '''python plot.py datafile
where datafile is: t, vout
'''
import csv
import os
from matplotlib import pyplot as plt
import sys
FN = 'v-220-470-200.txt'
PLOT = 'v=f(t)'
HTITLE = 'condenser charge/discharge'
HLENGTH = 6
def main(filename, plot):
#read t, vout values from csv file
with open(filename, 'r') as f:
v = list(csv.reader(f, delimiter=',')) # t, vout
v = v[HLENGTH:-1] # no header(s) and tail
v = [[float(e) for e in row] for row in v] # convert elements from string to float
#sys.exit(0)
x = [v[r][0] for r in range(len(v))] # t as x axis
y = [v[r][1] for r in range(len(v))] # vout as y axis
plt.plot(x, y, '+') # plot t-vout
plt.title(HTITLE+ ' ' + plot) # set plot title
plt.xlabel('t (s)') # set x axis limits
plt.ylabel('vout (V)') # set x axis limits
plt.grid(True)
#plt.show() # show interactively
plt.savefig(os.path.splitext(filename)[0]+'.png', format='png') # show to file
if __name__=='__main__':
#print(len(sys.argv))
if len(sys.argv) > 1:
FN = sys.argv[1][:]
if len(sys.argv) > 2:
HTITLE = sys.argv[2][:]
main(FN, PLOT)
|
In pratica otteniamo i seguenti grafici. Per RC=0,1s (R=220 Ohm, C=470 microF) campionando ogni 20 ms, abbiamo:

Come si vede il condensatore carica completamente in meno di 1 secondo, come ci possiamo attendere con una costante di tempo di 1 decimo di secondo. Quindi la successiva scarica parte da 5V per arrivare a 0V. Anche in questo caso in meno di 1 secondo.
Invece per RC=0,47s (R=1 KOhm, C=470 microF), sempre campionando ogni 20 ms, abbiamo:

Qui la costante di tempo di circa mezzo secondo non permette la completa carica del condensatore in poco meno di 1,5s. Siamo comunque oltre il 90% di carica (2,2*RC).