
![]() | #1 (permalink) Top |
User Data registr.: 12-05-2012 Residenza: asti
Messaggi: 6.979
| Misuratore di Resistenza Interna con ARDUINO
Ciao, volevo presentarvi un progetto che sto portando avanti. Mi sono cimentato un poò su ARDUINO e la prima cosa che ho sentito la necessità di realizzare è un misuratore di Resistenza Interna delle nostre lipo. Perchè questo strumentino? Molto semplice : non tutti i cb misurano la Ri, tra quelli che la misurano, non tutti la misurano cella per cella, tra questi ancora meno sono quelli che mi danno la possibilità di archiviare i dati in un file sul pc per mantenere lo storico. Al momento ho già superato la fase embrionale ed il progetto è quasi in via definitiva. NON VUOLE essere uno strumento di precisione, ma mi sono reso conto che confrontato con altri strumenti e con calcoli fatti a mano per misurare la Ri, i valori riportati sono affidabili. Questa foto è per dare l'idea delle dimensioni : ![]() Questo è stato il primo esperimento usando la scheda LEONARDO che è molto piccola; poi ho dovuto cambiarla con una MEGA perchè il codice sorgente era troppo grande. Poco male : una scheda ARDUINO la si recupera sempre e non sono mai soldi buttati via. La spesa è del tipo 18 il display e 40 la MEGA, ma se si vuole risparmiare su HK ci sono i cloni a pochi dollari ma io preferisco rimanere nell'ambito dell'originale. In pratica come funziona il progetto? La scheda ARDUINO si basa (come i nostri multifunzione più famosi tipo questo Radio Control Planes, Helicopters, Cars, Boats, FPV and Quadcopters - Hobbyking* o questo che è molto più preciso ACME LiPo Voltage Monitor con misura Resistenza interna cella a diversi carichi) sugli stessi circuiti integrati della serie ATMEL che in pratica sono dei piccoli microprocessori programmabili con una dozzina di IN analogici e digitali e con dei convertitori ADC abbastanza precisi a 10 bit. ll codice scritto fino ad ora fa le seguenti operazioni : -> lettura voltaggio per singola cella a riposo -> tramite un mosfet, applico un carico da 10 ohm 100W sui cavi di potenza della lipo -> dopo aver aspettao qualche secondo per stabilizzare il carico, rileggo il voltaggio di ogni singola cella -> stacco il carico -> conoscendo Voltaggio a riposo e sottocarico e conoscendo la resistenza di carico, calcolo la Ri -> scrivo sul display tutti i valori con sfondo coloraro in base alla tensione Il risultato finale è questo : ![]() Il calcolo della percentuale residua di carica si basa, ovviamente, sul voltaggio. Per la misurazione del voltaggio di ogni singola cella, all'entrata c'è un partitore resistivo che divide la tensione per 2,3,4,5,6,7 e 8 in base alla cella di riferimento. TUTTE le resistenze che ho usato sono con tolleranza 0,1% Questo il codice scritto : Codice: // Include le librerie #include <SPI.h> #include <SD.h> #include <TFT.h> // Arduino LCD library // Definizione pin di collegamento lcd arduino mega #define sd_cs 4 #define lcd_cs 10 #define dc 9 #define rst 8 //MOSFET IRF540 //inizializzazione LCD TFT TFTscreen = TFT(lcd_cs, dc, rst); void setup() { TFTscreen.begin(); //inizializza il display TFTscreen.background(255, 255, 255); //cancella tutto il display TFTscreen.stroke(0,0,255); //definisce colore di scrittura TFTscreen.print("Prove lettura Ri"); TFTscreen.print(""); } void loop () { // Legge le tensioni sui singoli PIN int Cella1 = analogRead(A0); int Cella2 = analogRead(A1); int Cella3 = analogRead(A2); int Cella4 = analogRead(A3); int Cella5 = analogRead(A4); int Cella6 = analogRead(A5); int Cella7 = analogRead(A6); int Cella8 = analogRead(A7); float voltage1; float voltage2; float voltage3; float voltage4; float voltage5; float voltage6; float voltage7; float voltage8; TFTscreen.stroke (0,0,0); //definisce colore di scrittura int voltage_limite = 1.50; //imposto il limite in Volt al di sotto del quale la cella viene azzerata TFTscreen.background(255, 255, 255); // Converte la CellaX in Volt moltiplicando per il valore di divisione del partitore resistivo, poi sottrae la tensione delle celle precedenti int R=0; int G=0; int B=0; voltage1 = Cella1 * (5.0 / 1023.0); TFTscreen.setCursor (3,7); TFTscreen.print ("C1"); if (voltage1 < voltage_limite) {voltage1 = 0;} if (voltage1 > 4.10) {R=0;G=255;B=0;} //verde if (voltage1 < 4.10 and voltage1 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage1 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage1 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,4,29,14);//rettangolo TFTscreen.setCursor (20,7);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage1,2); //scrive dentro rettangolo float Volt_T = voltage1; // Cella2 voltage2 = (Cella2 * (5.0 / 1023.0))*2 - Volt_T; TFTscreen.setCursor (3,22); TFTscreen.print ("C2"); if (voltage2 < voltage_limite) {voltage2 = 0;} if (voltage2 > 4.10) {R=0;G=255;B=0;} //verde if (voltage2 < 4.10 and voltage2 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage2 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage2 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,19,29,14);//rettangolo TFTscreen.setCursor (20,22);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage2,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage2; //Cella3 voltage3 = (Cella3 * (5.0 / 1023.0))*3 - Volt_T; TFTscreen.setCursor (4,37); TFTscreen.print ("C3"); if (voltage3 < voltage_limite) {voltage3 = 0;} if (voltage3 > 4.10) {R=0;G=255;B=0;} //verde if (voltage3 < 4.10 and voltage3 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage3 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage3 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,34,29,14);//rettangolo TFTscreen.setCursor (20,37);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage3,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage3; //Cella4 voltage4 = (Cella4 * (5.0 / 1023.0))*4 - Volt_T; TFTscreen.setCursor (4,52); TFTscreen.print ("C4"); if (voltage4 < voltage_limite) {voltage4 = 0;} if (voltage4 > 4.10) {R=0;G=255;B=0;} //verde if (voltage4 < 4.10 and voltage4 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage4 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage4 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,49,29,14);//rettangolo TFTscreen.setCursor (20,52);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage4,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage4; //Cella5 voltage5 = (Cella5 * (5.0 / 1023.0))*5 - Volt_T; TFTscreen.setCursor (4,67); TFTscreen.print ("C5"); if (voltage5 < voltage_limite) {voltage5 = 0;} if (voltage5 > 4.10) {R=0;G=255;B=0;} //verde if (voltage5 < 4.10 and voltage5 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage5 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage5 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,64,29,14);//rettangolo TFTscreen.setCursor (20,67);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage5,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage5; //Cella6 voltage6 = (Cella6 * (5.0 / 1023.0))*6 - Volt_T; TFTscreen.setCursor (4,82); TFTscreen.print ("C6"); if (voltage6 < voltage_limite) {voltage6 = 0;} if (voltage6 > 4.10) {R=0;G=255;B=0;} //verde if (voltage6 < 4.10 and voltage6 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage6 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage6 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,79,29,14);//rettangolo TFTscreen.setCursor (20,82);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage6,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage6; //Cella7 voltage7 = (Cella7 * (5.0 / 1023.0))*7 - Volt_T; TFTscreen.setCursor (4,97); TFTscreen.print ("C7"); if (voltage7 < voltage_limite) {voltage7 = 0;} if (voltage7 > 4.10) {R=0;G=255;B=0;} //verde if (voltage7 < 4.10 and voltage7 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage7 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage7 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,94,29,14);//rettangolo TFTscreen.setCursor (20,97);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage7,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage7; //Cella8 voltage8 = (Cella8 * (5.0 / 1023.0))*8 - Volt_T; TFTscreen.setCursor (4,112); TFTscreen.print ("C8"); if (voltage8 < voltage_limite) {voltage8 = 0;} if (voltage8 > 4.10) {R=0;G=255;B=0;} //verde if (voltage8 < 4.10 and voltage8 > 3.60) {R=255;G=255;B=0;} //giallo if (voltage8 < 3.60) {R=255;G=0;B=0;} //rosso if (voltage8 == 0) {R=255;G=255;B=255;} //bianco TFTscreen.fill (R,G,B);//colore definito prima TFTscreen.rect (17,109,29,14);//rettangolo TFTscreen.setCursor (20,112);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (voltage8,2); //scrive dentro rettangolo Volt_T = Volt_T + voltage8; //conta il numero di celle int num_celle = 0; if (voltage2 == 0) {num_celle = 1; goto fineconteggio;} if (voltage3 == 0) {num_celle = 2; goto fineconteggio;} if (voltage4 == 0) {num_celle = 3; goto fineconteggio;} if (voltage5 == 0) {num_celle = 4; goto fineconteggio;} if (voltage6 == 0) {num_celle = 5; goto fineconteggio;} if (voltage7 == 0) {num_celle = 6; goto fineconteggio;} if (voltage8 == 0) {num_celle = 7; goto fineconteggio;} {num_celle = 8;} fineconteggio : //disegna rettangolo e scrive dentro la Vtot della lipo TFTscreen.fill (193,255,255); TFTscreen.setTextSize(2); TFTscreen.rect (85,4,70,44); TFTscreen.setCursor (91,9); TFTscreen.print ("Vtot"); TFTscreen.setCursor (91,29); TFTscreen.print (Volt_T,2); //disegna 2° rettangolo per scrivere numero celle TFTscreen.rect (85,49,70,44); TFTscreen.setCursor (91,55); TFTscreen.print (num_celle); TFTscreen.setCursor (105,55); TFTscreen.print ("S"); // calcola percentuale residua lipo float media_celle; float Vmin_rif; float Vmax_rif; float carica_rimanente; Vmin_rif = 3.50; //limite inferiore minimo a cui corrisponde lo 0% Vmax_rif = 4.20; media_celle = (voltage1 + voltage2 + voltage3 + voltage4 + voltage5 + voltage6 + voltage7 + voltage8)/num_celle; carica_rimanente = (media_celle - Vmin_rif)/((Vmax_rif - Vmin_rif)/100); TFTscreen.setCursor (91,73); TFTscreen.print (carica_rimanente,0); TFTscreen.setCursor (130,73); TFTscreen.print ("%"); TFTscreen.setTextSize(1); //TFTscreen.setCursor (91,97); //TFTscreen.print (media_celle); int led = 5; pinMode (led,OUTPUT); digitalWrite (led,HIGH); int mosfet = 6; pinMode (mosfet,OUTPUT); digitalWrite (mosfet,HIGH); delay (1000); //definisce e legge le celle sottocarico int Cella1C = analogRead(A0); int Cella2C = analogRead(A1); int Cella3C = analogRead(A2); int Cella4C = analogRead(A3); int Cella5C = analogRead(A4); int Cella6C = analogRead(A5); int Cella7C = analogRead(A6); int Cella8C = analogRead(A7); float voltage1C; float voltage2C; float voltage3C; float voltage4C; float voltage5C; float voltage6C; float voltage7C; float voltage8C; TFTscreen.fill (255,255,255); //definisce il colore bianco dentro i riquadri per scrivere i Volt sotto carico voltage1C = Cella1C * (5.0 / 1023.0); if (voltage1C < voltage_limite) {voltage1C = 0;} float Volt_T_C = voltage1C; voltage2C = (Cella2C * (5.0 / 1023.0))*2 - Volt_T_C; if (voltage2C < voltage_limite) voltage2C = 0; Volt_T_C = Volt_T_C + voltage2C; voltage3C = (Cella3C * (5.0 / 1023.0))*3 - Volt_T_C; if (voltage3C < voltage_limite) voltage3C = 0; Volt_T_C = Volt_T_C + voltage3C; voltage4C = (Cella4C * (5.0 / 1023.0))*4 - Volt_T_C; if (voltage4C < voltage_limite) voltage4C = 0; Volt_T_C = Volt_T_C + voltage4C; voltage5C = (Cella5C * (5.0 / 1023.0))*5 - Volt_T_C; if (voltage5C < voltage_limite) voltage5C = 0; Volt_T_C = Volt_T_C + voltage5C; voltage6C = (Cella6C * (5.0 / 1023.0))*6 - Volt_T_C; if (voltage6C < voltage_limite) voltage6C = 0; Volt_T_C = Volt_T_C + voltage6C; voltage7C = (Cella7C * (5.0 / 1023.0))*7 - Volt_T_C; if (voltage7C < voltage_limite) voltage7C = 0; Volt_T_C = Volt_T_C + voltage7C; voltage8C = (Cella8C * (5.0 / 1023.0))*8 - Volt_T_C; if (voltage8C < voltage_limite) voltage8C = 0; Volt_T_C = Volt_T_C + voltage8C; //definisce le variabili per il calcolo della Resistenza Interna float RI1; float RI2; float RI3; float RI4; float RI5; float RI6; float RI7; float RI8; //calcola la RI per singola cella e la scrive (12 è il valore in ohm della resistenza che uso) float Rcarico; Rcarico = 12,1; RI1 = ((voltage1 - voltage1C)*Rcarico)/voltage1C; if (voltage1C == 0) RI1 = 0; RI2 = ((voltage2 - voltage2C)*Rcarico)/voltage2C; if (voltage2C == 0) RI2 = 0; RI3 = ((voltage3 - voltage3C)*Rcarico)/voltage3C; if (voltage3C == 0) RI3 = 0; RI4 = ((voltage4 - voltage4C)*Rcarico)/voltage4C; if (voltage4C == 0) RI4 = 0; RI5 = ((voltage5 - voltage5C)*Rcarico)/voltage5C; if (voltage5C == 0) RI5 = 0; RI6 = ((voltage6 - voltage6C)*Rcarico)/voltage6C; if (voltage6C == 0) RI6 = 0; RI7 = ((voltage7 - voltage7C)*Rcarico)/voltage7C; if (voltage7C == 0) RI7 = 0; RI8 = ((voltage8 - voltage8C)*Rcarico)/voltage8C; if (voltage8C == 0) RI8 = 0; TFTscreen.rect (49,4,33,14);//rettangolo TFTscreen.setCursor (52,7);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI1*1000,0); //scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,19,33,14);//rettangolo TFTscreen.setCursor (52,23);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI2*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,34,33,14);//rettangolo TFTscreen.setCursor (52,37);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI3*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,49,33,14);//rettangolo TFTscreen.setCursor (52,52);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI4*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,64,33,14);//rettangolo TFTscreen.setCursor (52,67);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI5*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,79,33,14);//rettangolo TFTscreen.setCursor (52,82);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI6*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,94,33,14);//rettangolo TFTscreen.setCursor (52,97);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI7*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente TFTscreen.rect (49,109,33,14);//rettangolo TFTscreen.setCursor (52,112);//posizione cursore per scrivere dentro rettangolo TFTscreen.print (RI8*1000,0);//scrive dentro rettangolo il valore della Ri della cella corrispondente digitalWrite (mosfet,LOW); digitalWrite (led, LOW); //definisco ciclo di lettura del pulsante per ricominciare int attesa = 3; pinMode (attesa, INPUT); //void loop () //{ //digitalRead (attesa); //while (attesa == HIGH); {}; //} delay (10000); TFTscreen.background(255,255,255); } Al momento la visualizzazione avviene solo su display ma è possibile, modificando opportunamente il codice, scrivere anche sul pc oppure solo sul pc evitando l'acquisto del display. In futuro aggiungerò del codice per usarlo anche come servo tester. Se vi vengono in mente modifiche di qualunque genere, sono gradite ![]() Il prosismo passo è quello, per avere una precisione ancora più elevata, di eliminare i partitori resistivi all'entrata e sostituirli con degli op-amp. Ovviamente, sempre per l'entrata, è in fase di realizzazione un pcb apposito per ospitare tutte le resistenze compresa quella di carico anzichè usare un millefori come adesso di cui vi risparmio la foto...
__________________ Goblin 500 miniVbar Compass 7HV ULTIMATE miniVbar Mai discutere con un idiota, ti trascina al suo livello e ti batte con l'esperienza. RC Dreams Ultima modifica di mgaproduction : 19 luglio 14 alle ore 10:38 |
![]() | ![]() |
![]() | #3 (permalink) Top |
User Data registr.: 03-09-2012 Residenza: Gubbio-Ravenna
Messaggi: 1.771
|
Interessante il progetto, ma che tipo di display hai usato?
__________________ Divertirsi insieme e con poco? Prova il combat! Curtman Squadron Combat Sito Web: https://sites.google.com/site/curtmansquadroncombat/ ![]() |
![]() | ![]() |
![]() | #4 (permalink) Top |
User Data registr.: 12-05-2012 Residenza: asti
Messaggi: 6.979
|
La colonna di sinistra riporta i Volt di ogni singola cella, la colonna di fianco riporta i milliohm corrispondenti, a destra i Volt totali, il numero di celle e la percentuale di carica residua. Quest'ultima si basa su dei limiti, ovviamente variabili da codice, che sono : 0% 3.5V e 100% 4.2V Il display è quello originale ARDUINO ;)
__________________ Goblin 500 miniVbar Compass 7HV ULTIMATE miniVbar Mai discutere con un idiota, ti trascina al suo livello e ti batte con l'esperienza. RC Dreams |
![]() | ![]() |
![]() | #8 (permalink) Top | |
User Data registr.: 29-09-2014 Residenza: campoformido
Messaggi: 29
| Citazione:
Per quello ho provato a crivere se qualcuno mi può aiutare. Saluti Pauli | |
![]() | ![]() |
![]() | #9 (permalink) Top |
User Data registr.: 15-09-2014
Messaggi: 412
|
Esclusa la parte del mosfet, non è difficile. Serve solo pazienza per progettare i collegamenti e fare i calcoli. Se qualcuno riuscisse a spiegare la parte mosfet si potrebbe lavorare insieme e progettare da 0 questo sistema... Purtroppo sembra che l'utente sia inattivo da un po'.. speriamo comunque che legga |
![]() | ![]() |
![]() | #10 (permalink) Top |
User Data registr.: 25-07-2004 Residenza: Trieste
Messaggi: 5.670
|
Se volete fare esercizio di programmazione, va bene farsi da soli questo strumento. Ma se vi serve questo strumento, il suo prezzo da Hobby King è inferiore al costo del solo materiale per costruirselo in proprio. Le molte ore di programmazione che dovrete impiegare per far funzionare uno strumento simile, possono essere impiegate meglio per la costruzione di un nuovo modello. Naraj. |
![]() | ![]() |
![]() |
Bookmarks |
| |
![]() | ||||
Discussione | Autore discussione | Forum | Commenti | Ultimo Commento |
Resistenza interna delle LiPo con carico dinamico | Paolo Gx | Batterie e Caricabatterie | 5 | 24 aprile 14 21:27 |
Lipo resistenza interna | levens | Batterie e Caricabatterie | 6 | 07 agosto 13 21:52 |
Misuara la resistenza interna | telix636 | Batterie e Caricabatterie | 22 | 07 marzo 10 17:58 |
resistenza interna batterie | antoniog222 | Aeromodellismo Volo Elettrico | 5 | 21 agosto 05 23:54 |
Calcolo Resistenza Interna | Hannibal | Aeromodellismo Volo Elettrico | 15 | 06 maggio 05 18:44 |