Lipo überwachung

Hallo Arduino Gemeinde,
läst sich ein LiPo 5S mit einen UNO überwachen? - die einzelnen Zellen haben ja max 4,2V - mein Problem ist dass ich nur ein GND habe - eine Zelle ist kein problem - was mache ich mit den anderen ?

mfg
Alex

Hallo Alex,

Ich habe mir 2 Möglichkeiten ausgedacht.

Benutze 5 Analogeingänge und messe mit dem 1. die erste Zelle, mit dem 2. die erste und zweite, mit dem 3. die erste zweite und drite und so fort.
dann braucht man nur jeweil die Differenz zwische den Eingängen berechnen.
Frage ist ob die Genauigkeit bei den letzten Zellen reicht. 5*4,2/1024 ergibt ca. 20 mV für die letzte Zelle.

  1. Möglichkeit für jede Zelle einen Komperator und Optokoppler zu verwenden, da kann man aber nur feststellen 4,2 V erreicht oder nicht.

Soll eine Anregung sein
Karl

Hi Alex

Das Problem ist doch das dass bei Allen, außer der Ersten Zelle, die jeweiligen Spannungen nicht auf Masse bezogen sind .
Der Ardu die Spannungsmessung aber gegen Masse macht.

Wenn Du die einzelnen Zellen mittels eines Operationsverstärker misst und den Ausgang dann mit dem Eingängen des Arduinos misst.
Der OPV misst die Differenzspannung zwischen seinen zwei Eingängen und gibt diese Spannung ( wenn seine Verstärkung auf 1 eingestellt ist ) am Ausgang gegen Masse aus.
Es währe auch möglich die Spannung der ersten Zelle gegen Masse messen -> Zellenspannung Zelle 1

die Spannung der ersten und der zweiten Zelle gegen Masse messen und die
Spannung der ersten Zelle abziehen-> Zellenspannung Zelle 2

u.s.w.

Aber Achtung die Spannung am Eingang darf 5V nicht überschreiten also mit Spannungsteilern arbeiten.

Brauchst Du eigentlich die Spannung aller Zellen. Genügt es nicht die erste Zelle bzw des Akkus zu messen da diese ähnlich der anderen sein wird und so auf den Ladungszustand des Akkus schließen.
Bei Ladung macht das ja das Ladegerät und bei Etladung sollten alle Zelen gleichmäßig sich entladen. Ist das nicht der Fall ist der Akku sowieso defekt.

Grüße Uwe

Uwe genau dass interessiert mich - wie der Akku beim entladen beansprucht wir (ich möchte 60-100A Ziechen) dabei treten Schwankungen der einzelnen Zellen im Bereich von 0,15V und mehre auf.

da ich vor kurzen mit Arduino angefangen habe , bitte ich euch mir etwas zu helfen

das währe der Code für eine Zelle - Eingang 0 gegen Masse

const float referenceVolts = 5.0; 
const int batteryPin = 0;       

void setup()
{
   Serial.begin(9600);
}

void loop()
{
   int val = analogRead(batteryPin);  
   float volts = (val / 1023.0) * referenceVolts;  
   Serial.println(volts);  
}

mfg
Alex

hallo Alex,
ich habe dir mal einen sketch für einen lifepo4 4s2p drangehängt, müsstest deinen Bedürfnissen entsprechend abändern
der sketch ist aufgeteilt in 2 Teile
gruß ardubu
Teil1

/*
  8+2 Kanal Spannungesmesser und Strommesser mit SD card Datenlogger
 inkl. Kapazitätsberechnung mit Ausgabe auf LCD + SD
 Alle Belegungen sind für den Mega 2560, sowie LCD 2004 mit I2C und SD Plus Shield
 Dieser Sketch speichert die Daten von 10 analogen Eingängen auf der SD Karte und zeigt sie auf dem LCD an
 	
 Die Schaltung:
  8 Spannungsteiler an den analogen Pins 8 bis 15
  2 ACS 715 an den analogen Pins 2 + 3
 
 Pinbelegung der RTC über I2C
 
  Pinbelgung für die SD Karte: 
   MOSI - pin 50
   MISO - pin 51
   CLK - pin 52
   CS - pin 53
 
 Die Schaltung für das LCD:
  Adresse 27 hex
  LCD GND an GND
  LCD VCC an 5V
  LCD SCL an Pin 21
  LCD SDA an Pin 22
 
 
 Created  6. Juni 2012
 geändert 9.März 2013
 by B. K.
 	 
 */

#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h> // benutzt den library code:
LiquidCrystal_I2C lcd(0x27,20,4); // initialisiert die library mit der I2C Adresse 0x27

File datei;  // test datei
//const uint8_t SD_CS = 53; // SD chip select
RTC_DS1307 RTC;  // define the Real Time Clock object
//------------------------------------------------------------------------------
// call back for datei timestamps
void dateTime(uint16_t* date, uint16_t* time) {
  DateTime now = RTC.now();

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(now.year(), now.month(), now.day());

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}
//------------------------------------------------------------------------------
const int chipSelect = 53;
const float mb =16.0; //Messbereich
const int tm = 1023.0; // Teiler Messbereich (10 Bit)
float (strom1)=0;
float (strom2)=0;
float C1=0;
float C2=0;
byte a=0;
byte b=0;
int c=0;
char d;// 8. Buchstabe des Dateinamens
char(dateiname)[13]="datalog0.csv";

//========================================================================================================================================================
void setup() {
  Serial.begin(9600);
  Wire.begin();
  if (!RTC.begin()) {
    Serial.println("RTC fehlt");
    while(1);       }
  DateTime now = RTC.now();
  lcd.init();
  lcd.begin(20,4); // gibt die Zeichenanzahl und Zeilenzahl des LCD's vor:
  lcd.backlight();
  pinMode(chipSelect, OUTPUT); //CS

  // setzt die date time callback function
  SdFile::dateTimeCallback(dateTime); 
  
if (!SD.begin(chipSelect)) {  // prüft ob die SD Karte eingeschoben ist und initialisiert werden kann
    Serial.println();
    Serial.print("Karte Fehlt");
    Serial.println();   
    lcd.print("Karte fehlt");
    delay(2000);
    lcd.clear();
    return;}
   
    while (SD.exists(dateiname)) {//püft ob der Datiename schon vergeben ist
    c=c++;
    if (c >9){Serial.println("Bereits 10 Dateien auf SD Karte");return;}
    d= c+'0'; //Umwandlung von int in char
    dateiname[7]=d;              }

    lcd.home();
    lcd.print("Hallo ");
    lcd.setCursor(0,1);
    lcd.print("Messen und loggen");
    lcd.setCursor(0,2);
    lcd.print("Timestamp + RTC ");
    lcd.setCursor(0,3);
    lcd.print("U_8 I_2 C_2");
    delay(3000);
    
    File datei = SD.open(dateiname, FILE_WRITE);
     datei.println();
     datei.print(now.day()); datei.print("."); datei.print(now.month()); datei.print("."); datei.print(now.year()); Serial.print("  ");
     datei.println();
     datei.println("Zeit,U1,U2,U3,U4,U5,U6,U7,U8,I1,I2,C1,C2"); // schreibt eine Kopfzeile auf den seriellen Monitor
     datei.close(); 
   
       Serial.println();
       Serial.print(now.day()); Serial.print("."); Serial.print(now.month()); Serial.print("."); Serial.print(now.year()); Serial.print("  ");
       Serial.println();
       Serial.println("Zeit,U1,U2,U3,U4,U5,U6,U7,U8,I1,I2,C1,C2"); // schreibt eine Kopfzeile auf den seriellen Monitor
    
}//setup ende
//===============================================================================================================================================================

Teil2

void loop() 
{
      DateTime now = RTC.now();
      int (zeit10) = ((now.second())%10);
      int (zeit5) = ((now.second())%5);
      a=a++;
      b=b++;
  float korrFakt[8]= {(1.002725956),(0.998),(1.000068),(0.998),(1.00214),(0.99751),(0.998851),(0.996)}; //Korrekturfaktoren für die 8 Eingänge
  float zw;
  int mwdu1;
  int mwdu2;
  
   
     if (zeit10==0 && a==1) 
    {
     datei = SD.open(dateiname, FILE_WRITE);
     datei.print(now.hour()); datei.print(":"); 
           if (now.minute()<10) {datei.print("0");}
     datei.print(now.minute()); datei.print(":"); 
           if (now.second()<10) {datei.print("0");}
     datei.print(now.second());
     datei.print(",");
                                                                     
     Serial.print(now.hour()); Serial.print(":"); 
            if (now.minute()<10) {Serial.print("0");}
     Serial.print(now.minute()); Serial.print(":"); 
            if (now.second()<10) {Serial.print("0");}
     Serial.print(now.second());
     Serial.print(",");
    }
    
    for (int analogPin = 8; analogPin < 15; analogPin+=2) {
     mwdu1 = analogRead(analogPin); // liest die Eingänge 1, 3, 5, 7
     mwdu2 = analogRead(analogPin+1);// liest die Eingänge 2, 4, 6, 8
     mwdu1=map(mwdu1,10,1023,12,1023);
     mwdu2=map(mwdu2,10,1023,12,1023);
     if(mwdu1<=5) {mwdu1=0;}
     if(mwdu2<=5) {mwdu2=0;}
     float(U1) = (((mwdu1 *mb) / tm ) * korrFakt[analogPin-8]);//wandelt den digitalen Messwert in einen analogen, rechnet den Spannungsteiler und den Korrekturfaktor ein
     float(U2) = (((mwdu2 *mb) / tm ) * korrFakt[analogPin-7]);                                                     
     float u1 = U1;
   //  float u2 = U2;
     
    if (analogPin == 10 || analogPin == 14) {
        U1 = U1 - zw;}// zieht 3. und 7. Messwert den vorherigen ab, wenn eine Spannung anliegt
    zw = U2; //Zwischenwert für das Abziehen
        U2 = U2 - u1; //zieht vom Messwert den vorherigen ab
                   
    //Strommessung
    int(mwIu1) = analogRead(2); //liest den 1. Stromeingang
    int(mwIu2) = analogRead(3); //liest den 2. Stromeingang
    float(Iu1) = (((mwIu1-101.0)*30.4)/750);
    float(Iu2) = (((mwIu2-101.0)*30.4)/750);
    
    //Ausgabe
    if (zeit10==0 && a<=1) {
      Serial.print (U1,5 ); //schreibt den Messwert 6 stellig auf den seriellen monitor
      Serial.print (" ");
      Serial.print (U2,5 ); //schreibt den Messwert 6 stellig auf den seriellen monitor
      Serial.print (" ");
      Serial.print (mwdu1 ) ;//schreibt den Messwert 6 stellig auf den seriellen monitor
      Serial.print (" ");
      Serial.print (mwdu2 ) ;//schreibt den Messwert 6 stellig auf den seriellen monitor
      Serial.print (" ");
      //Serial.print (zw); //schreibt den Messwert 6 stellig auf den seriellen monitor
      //Serial.print (" ");

      datei.print(U1);// schreibt den Messwert auf die SD Karte
      datei.print (",");// schreibt hinter den Messwert ein Komma
      datei.print(U2);
      datei.print (",");
      
      if (analogPin==14) {
      Serial.print (Iu1,6);
      Serial.print (",");
      Serial.print (Iu2,6);
      Serial.print (",");
      Serial.print (mwIu1);
      Serial.print (",");
      Serial.print (mwIu2);
      Serial.print (",");
      Serial.print (C1);
      Serial.print (",");
      Serial.print (C2);
      Serial.println();
      
      datei.print(Iu1,1);
      datei.print(",");
      datei.print(Iu2,1);
      datei.print(",");
      datei.print(C1,1);
      datei.print(",");
      datei.print(C2,1);
      datei.println();
                          }
    }
       
        // Ausgabe auf LCD
        if (zeit10 == 0 && a<=1){
          
        int(zeile);
        if (analogPin==8){zeile=0;lcd.clear();}
        if (analogPin==10){zeile=1;}
        if (analogPin==12){zeile=2;}
        if (analogPin==14){zeile=3;}
        lcd.setCursor(0,zeile);
        lcd.print("U") ;
        lcd.print(analogPin-7);// zeigt welche Spannung angezeigt wird;
        lcd.print("=");
        lcd.print(U1); // zeigt den Messwert;
        lcd.print("V ");// zeigt hinter dem Messwert V;
        lcd.setCursor(10, zeile);
        lcd.print("U") ;
        lcd.print(analogPin-6); // zeigt welche Spannung angezeigt wird;
        lcd.print("=");
        lcd.print(U2); // zeigt den Messwert;
        lcd.print("V ");// zeigt hinter dem Messwert V;
        
        }
        if (zeit10!=0){a=0;}

        if ((zeit5==0) && (zeit10!=0) && (b<=1))
        {
          if (analogPin==14) {
   
             //-------------------------------------------------------------------------------------           
      //Kapazitätsberechnung
      
      strom1=strom1+Iu1;
      strom2=strom2+Iu2;
      C1=(strom1/360); // Berechnung der ge- oder entladenen Amperstunden.
      C2=(strom2/360); // Berechnung der ge- oder entladenen Amperstunden.
   //--------------------------------------------------------------------------------------      
      
            //LCD Ausgabe 2.Seite
           lcd.clear(); // löscht das LCD
           lcd.print("I1="); 
           lcd.print(Iu1,1);
           lcd.print("A");
           lcd.setCursor(10, 0);                 
           lcd.print("I2=");
           lcd.print(Iu2,1);
           lcd.print("A");
           lcd.setCursor(0,1);
           lcd.print("C1=");
           lcd.print(C1,1);
           lcd.print("Ah");
           lcd.setCursor(10,1);
           lcd.print("C2=");
           lcd.print(C2,1);
           lcd.print("Ah");
           lcd.setCursor(0,3);
           lcd.print(now.day());lcd.print(".");lcd.print(now.month());lcd.print(".");lcd.print(now.year());
           lcd.setCursor(13,3);
           lcd.print(now.hour());lcd.print(":");
           if (now.minute() < 10){lcd.print("0");}
           lcd.print(now.minute());
                          }
        }
          if (zeit5 !=0){b=0;}
   
}
datei.close();
}//ende loop