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:

_images/v-220-470-200.png

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

_images/v-220-470-20-cd.png

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:

_images/v-1k-470-20-cd.png

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