CHECK-UP BATTERIE: PROGETTO EVO (2° puntata)

Proseguono le riflessioni sul progetto EVO (evoluzione). Questa seconda puntata è dedicata prevalentemente al software.

E’ utile capire come il software interagisce con l’hardware, perchè ne derivano conseguenze importanti circa l’hardware da mettere in campo.

Il calcolo delle tensioni viene fatto rapportando a 5 volt la tensione massima da leggere. Per misurare tensioni superiori a 5 volt occorre utilizzare un divisore di tensione.

Se dobbiamo leggere 16 volt – tensione massima ipotizzata in ingresso – dobbiamo calcolare le 2 resistenze del divisore in questo modo:

vmax / 5 = divisore

Per 16 volt il divisore “minimo” è di 3,2 (16 / 5).

Se impostiamo la resistenza che va a massa (R7) = 1k la resistenza sul ramo della tensione positiva (R4) viene calcolata come segue:

R4 = (divisore – R7) / R4

Nel nostro caso R4 = (3,2 – 1) / 1 = 2,2k,

In realtà dovremo mettere una resistenza un poco più alta come 2,7k, ma su questo sorvoliamo per proseguire i nostri calcoli.

Bene. A questo punto il software cosa fa ?

Usiamo questa istruzione:

volt_INPUT = analogRead(A0);

Poniamo che mi restituisca il valore 425

Questo numero NON indica alcuna tensione; indica semplicemente quanti segmenti sono stati rilevati, tra i 1024 della scala che va da zero a 5 volt.

Pertanto dobbiamo utilizzare questa formula:

volt_INPUT = (volt_INPUT * 500 / 1024) / 1000;

Nell’esempio proposto i volt diventano 2,0751. Questi sono volt veri, ma sono i volt nel punto centrale del divisore; occorre considerare la riduzione del divisore e dobbiamo quindi moltiplicare questo valore x 3,20 (nell’esempio, naturalmente):

volt_INPUT = volt_INPUT * 3.20:

Il risultato è 6,640625 e questo è il dato vero della tensione al capo positivo del divisore di tensione.

Se anzichè 425 scatta lo “scalino” successivo, cioè 426 segmenti, la tensione diventa 6,65625

Lo scalino tra 6,65625 e 6,640625 è un valore molto modesto, poco sopra al centesimo di volt, che certifica la validità di questo metodo di rilevazioni. Ma c’è un però, nella teoria, ma anche nella pratica.

Occorre osservare che un divisore alto penalizza la sensibilità delle rilevazioni.

Il dato diventa critico nella determinazione dei milliamper di carica, che vengono conteggiati per differenza di tensione ai capi della resistenza di shunt. Occorre che i divisori di tensione relativi (R5=R6 e R8=R9) siano identici con tolleranza minima delle resistenze. Infatti la formula è questa:

mAmper = (volt_INPUT – volt_SHUNT);

Questa formula dà i millivolt di caduta di tensione ai capi della resistenza di shunt e NON i milliamper. Dobbiamo fare una rettifica, in base alla legge di ohm:

mAmper = mAmper * 10 / resistenza di shunt;

Con i dati impostati, qualora lo “scalino”  cioè il segmento rilevato passi da 425 a 424 abbiamo una variazione di tensione pari a 0,015 volt che su un carico di 1 ohm comporta una corrente di carica pari a 15 milliamper. Non è molto, ma possiamo far meglio, per avere informazioni più precise sulla intensità della carica con batterie di capacità modesta. Spiego come.

Occorre diminuire il valore del divisore di tensione e aumentare  (quando possibile) la resistenza di shunt.

Circa quest’ultima è stato già previsto un deviatore e con resistenza da 5 ohm (quella per scala da 500 milliamper), In questo caso  abbiamo “scalini” da 3 milliamper, anzichè i 15 con resistenza da un solo ohm (scala da 2 amper).

Possiamo agire anche sul divisore di tensione posto a valle della batteria con divisore pari a 2 anzichè 3,2 conseguentemente tutti i valori migliorano di un 60% circa.

A valle della batteria possiamo utilizzare un divisore di tensione più “leggero” perchè le tensioni sono minori in quanto ridotte dalla tensione della batteria.

Tutto ciò considerato si è deciso di modificare lo schema elettrico e collocare la resistenza di shunt a valle della batteria da caricare, cioè tra la batteria e il Mosfet.

Con divisore 2 ai lati della resistenza di shunt (cioè R5, R6, R8 e R9 ciascuna da 1k) gli scaglioni dei milliamper sono i seguenti:

resistenza = 1 ohm       milliamper = 9,76

resistenza = 2 ohm       milliamper = 4,88

resistenza = 5 ohm       milliamper = 1,95

Lo schema elettrico viene rimodulato come segue:

Il positivo della batteria è collegato direttamente al generatore di tensione, tramite selettore a 4 posizioni (potrebbe però essere un commutatore a sei posizioni con i 6 volt in posizione 1, i 9 volt in posizione 2, i 12 volt in posizione 4 e ultimi i 12 volt in posizione 6. Con ciò si può ottenere il reset automatico quando si passa sulle posizioni 3 e 5 contigue ai 12 e ai 16 volt “pericolosi”. E’ molto semplice, perchè basta portare a livello basso – 0 Volt – il pin Reset del microcontrollore, ma occorre un commutatore a 2 vie 6 posizioni).

Si notano in basso i 3 potenziometri con cui si definiscono i parametri di tensione, intensità e durata carica. Vanno bene da 10k cadauno.

Si notano gli Zener sugli ingressi A1 e A2, non previsti inizialmente. Nel disegno è sfuggita la resistenza da 1k che va al microcontrollore, di sicurezza.

Il selettore, doppio, di selezione resistenza di shunt, è collocato tra batteria e Mosfet. Una porzione del selettore è collegato agli ingressi digitali del microcontrollore Atmel 328 NANO.

Se abbiamo afferrato come “lavora” il software sappiamo come regolarci per avere informazioni precise in sede di check-up della batteria da testare.

Occorre utilizzare sempre la scala milliamper più bassa, in rapporto alla carica programmata.

La rimodulazione del progetto ha però qualche conseguenza negativa. Abbiamo 2 selettori che modificano di molto le tensioni in gioco; dobbiamo evitare che ai capi di A1 e A2 arrivino tensioni superiori ai 5 volt, che potrebbero anche danneggiare il microcontrollore; abbiamo pertanto deciso di mettere 2 zener da 5,6 volt e anche una resistenza da 1k tra divisore e ingresso microcontrollore.

Si pone inoltre qualche altro problema:

  1. se carichiamo una batteria Ni MH da 1,20 volt selezionando i 16 volt di ingresso (assurdo, ma potrebbe accadere) ai capi della resistenza di shunt avremo un valore superiore a 10 volt (massimo ammissibile con divisore 2) e la gestione pwm diventa critica;
  2. la stessa cosa accade qualora durante la carica venga selezionata una tensione di ingresso superiore che provoca anche l’inconveniente di “sparare” sulla batteria una corrente immediata molto superiore a quella programmata. Quest’ultimo problema si può verificare anche quando si modifica la scala milliamper durante la carica.
  3. accade anche qualora, per errore, vengano cortocircuitati i morsetti della batteria.

Possiamo risolvere questi problemi via software con un reset immediato e un warning con cicalino.

Con batteria da 1,2 volt e 3,7 volt è opportuno utilizzare 6 volt di ingresso. I 12 e i 16 volt sono da evitare.

I 9 volt possono servire per caricare pacchi di batterie Ni Mh e batterie al piombo da 6 volt.

I 12 volt possono servire per pacchi di batterie attorno ai 9 volt.

I 16 volt servono per le batterie al piombo da 12 volt.

I calcoli che abbiamo fatto possono sembrare macchinosi, e lo sono, ma il software sarà organizzato per farci scegliere la condizione migliore di carica e di check-up.

Premesso che il check-up deve essere realizzato sulla base delle informazioni circa la batteria da testare, per impostare i valori limite di tensione, intensità della carica e tempo abbiamo dei potenziometri allacciati con un capo a massa e l’altro ai 5 volt positivi.

Con la solita istruzione software analogRead(Ax) otteniamo un numero che va da zero a 1024, a seconda della posizione del cursore centrale. E’ facile trasformare questo numero nella scala che ci interessa, con queste semplici linee di codice:

//

limite_tensione = analogRead(A3) * 1.37; // massimo 14 volt (con 2 decimali):
//
limite_corrente = analogRead(A4) * 1.93; // massimo 2000 milliamper con 1024 segmenti, cioè posizioni intermedie:
//
limite_durata_carica = analogRead(A5); // arriva massimo a 1024 minuti, che sono circa 17 ore:

//

I valori vengono evidenziati a video, ad ogni reset e vengono ripetuti durante la carica, a cadenza programmata; possono essere modificati durante la carica.

Vale la pena di soffermarci ora sulla gestione del duty-cycle che nel nostro caso corrisponde alla variabile numerica ciclopwm.

Come indicato nello schema elettrico il segnale pwm di uscita è sul pin D9.

Questo è il codice, molto semplice:

//
if (volt_batterie > limite_tensione)
{
ciclopwm = ciclopwm – 2;
}
else
{
ciclopwm = ciclopwm + 1;
}
if (mAmper > limite_corrente) ciclopwm = ciclopwm – 3; // limitatore a xxx mAmper definito in testa al listato:
//
if (ciclopwm > 254) ciclopwm = 254;
if (ciclopwm < 0) ciclopwm = 0;
analogWrite (9, ciclopwm);

//

Altra cosa interessante e la rilevazione delle tensioni che viene fatta con molte letture (100):

//

somma_INPUT = 0;
somma_SHUNT = 0;
somma_MOSFET = 0;
//
for (int cicli = 0; cicli < 100; cicli++)
{
volt_INPUT = analogRead(A0);
somma_INPUT = (somma_INPUT + volt_INPUT);
//
volt_SHUNT = analogRead(A1);
somma_SHUNT = (somma_SHUNT + volt_SHUNT);
//
volt_MOSFET= analogRead(A2);
somma_MOSFET = (somma_MOSFET + volt_MOSFET);
//
delay(2);
}
// poi le somme vengono ovviamente divise per 100:

Circa la visualizzazione dati sul display la soluzione più semplice è un dispay 16 x 2 e una gestione seriale I2C. Ma mi piacerebbe optare piuttosto per un 16 x 4 che consente di avere più informazioni contestuali. Potrebbe indicare: 1.tensione batteria; 2.corrente di carica; 3.energia cumulata; 4.tempo trascorso.

Interessanti i conteggi cronometro in ore, minuti e secondi e l’indicazione dei volt con 2 decimali (Sibilla_1_2_3.ino):

// Visualizzo il messaggio sul display
lcd.begin(16, 2);
lcd.print(“hh-mm-sec V-Batt”);
lcd.setCursor(0, 1);
lcd.print(” : : “);
durata = millis()/1000;
if (durata > limite_durata_carica * 60) stop_carica = 1;
//
if (durata >= 3600)
{
ore = durata/3600;
durata = durata – (ore * 3600);
}
if (durata < 3600)
{
minuti = durata/60;
durata = durata – (minuti * 60);
}
if (durata < 60) secondi = durata;
lcd.setCursor(0, 1);
lcd.print(ore);
lcd.setCursor(3, 1);
lcd.print(minuti);
lcd.setCursor(6, 1);
lcd.print(secondi);
lcd.setCursor(11, 1);
lcd.print(volt_batterie);
if (volt_batterie > 999) lcd.setCursor(12, 1);
else lcd.setCursor(11, 1);
lcd.print(“,”);
lcd.setCursor(10, 1);
lcd.print(volt_batterie/100);
conta1 = 0;
delay(250);
//

E’ egualmente interessante la visualizzazione dei milliamper cumulati da inizio carica e i milliamper di carica in corso:
//
lcd.begin(16, 2);
lcd.print(“mAmperora mAmper”);
lcd.setCursor(0, 1);
lcd.print(” “);
lcd.setCursor(2, 1);
stop_millis_nuovo = millis();
millesimi_trascorsi = stop_millis_nuovo – stop_millis_vecchio;
carica = carica + (mAmper * millesimi_trascorsi);
stop_millis_vecchio = stop_millis_nuovo;
if (carica > 3600000000)
{
Amperora = Amperora + 1;
carica = 0;
}
lcd.print((Amperora*1000) + (carica/3600000));
lcd.setCursor(12, 1);
lcd.print(mAmper);
conta2 = 0;
delay(250);
if (stop_carica == 1)
{
analogWrite (9, 0);
delay(1000000000); // stop carica a fine durata carica:
}
//

Un problema con software arduino per microcontrollore Atmel 328 è la definizione delle variabili numeriche. Se non si impostano correttamente si superano i limiti di memoria e i conteggi non sono esatti.

Ricordo infine che il software Sibilla_1_2_3.ino è scaricabile gratuitamente dal sito:

https://github.com/FaenzaSoft

alla sezione DRIVE-IN

E’ evidente che questo software, di riferimento, andrà aggiornato sulla base delle modifiche apportate al progetto hardware.

La prossima puntata sarà dedicata al prototipo di questa versione EVO del CHECK-UP batterie, derivato dal progetto DRIVE-IN.

Ricordo che hardware e software del progetto EVO sono Made in Italy.