Ein Batteriemonitor für Strom und Spannung mit dem INA226 und dem Arduino Uno

Ich möchte einen Batteriemonitor bauen. Dazu muß die Batteriespannung gemessen werden mit 12V oder 24V und der entnommene oder geladene Strom. Für die Strommessung wird ein Shunt Widerstand verwendet. Für hohe Ströme von einigen Ampere bis hin zu mehreren Hundert Ampere werden Shunt Widerstände angeboten die einen Spannungsabfall von ca. 60mV bis 75 mV beim Maximalstrom haben.

Ich brauche also einen AD Wandler der -+75mV genauso gut messen kann wie 12V oder 24V. Das ist mit zwei langsamen aber hochauflösenden AD Wandlern machbar. Dazu kann man einen Spannungsteiler für 24V und eine OP Verstärker für +-75 mV vorschalten. Hierbei sind dann noch die Toleranzen der Widerstände und der OP Schaltung zu beachten.

Einfacher ist es man nimmt gleich ein Batteriemonitor IC das beide Bereiche abdeckt. Hier bietet sich das INA226 IC von Texas Instruments an. Es hat einen Spannungsmeßbereich von 0V bis 36V und eine Shunt Spannungsbereich von +-82 mV. Damit erfüllt es die Anforderungen.

Integriert ist ein 16 Bit AD Wandler für beide Bereiche. Das reicht auch gut aus. Das Gehäuse ist sehr klein, ein 10-Pin DGS VSSOP, und damit schwer zu löten. Hier bietet sich eine fertige Schaltung auf einer Platine an. Auf der Platine sind schon die zwei I²C PullUp Widerstände integriert und es ist ein 0,1 Ohm Widerstand als SMD Shunt mit theoretischen 3W aufgelötet. Der Widerstand sollte für einen ersten Test ausreichen.

I = U / R = 0,082 Volt / 0,1 Ohm = 0,82 A = 820 mA
Er kann also Ströme bis +- 820mA direkt einlesen.

Der Maximalstrom für den 3W Shunt mit 0,1 Ohm wird so berechnet:
P = U * I
mit U=R*I eingesetzt ergibt sich
P = R * I²Umgestellt nach I ergibt das:
I = Wurzel aus (P/R) = Wurzel aus (3W / 0,1 Ohm) = 5,4 A
Das gilt aber nur bei optimaler Kühlung des Shunts. Auf meiner Platine kann ich von ca. 1/4 ausgehen, also etwa 1,3 A maximaler Strom. Damit sind die meßbaren 820mA von oben erlaubt und bis 1,3A geht auch bei dauerhafter Überlastung nichts kaputt.

Später wird der SMD Shunt durch einen massiven Shunt für höhere Ströme ersetzt.

Schön ist auch, daß der Shunt an den -Pol oder den +Pol der Batterie angeschlossen werden kann, dem AD-Wandler ist das egal solange er keine 40V bekommt.

Die Spannungsmessung bis 36V ist für 1 oder 2 Autobatterien sehr gut geeignet.

Bei meiner Platine sind beide Adressleitungen A0 und A1 über einen Widerstand auf Masse gelegt. Dadurch hat das IC die Adresse 0x40 (INA226 Datenblatt Seite 18).

Das INA226 könnte auch den Strom und die Leistung direkt ausgeben, wenn es vorher über eine kleine Rechnung mit den Shunt Daten versorgt wird. Das ist aber hier nicht notwendig, das macht der Arduino mit links nebenbei.

Das INA226 kann mit 3,3V oder 5V betrieben werden, ich habe mich für 3,3V vom Arduino Uno entschieden. Dann noch GND verbinden und die beiden I²C Leitungen auf A4 und A5 anschließen.
Der zu messende Strom wird an IN+ und IN- angeschlossen und die Plus Batteriespannung an VBS. Batterie Minus ist GND.

Das Configuration Register muß mit einem Wert geladen werden. Ich habe mich einfach für eine dauerhafte AD Wandlung mit Mittelung über 16 Werte entschieden. Das kann er leicht in der Sekunde erledigen. Dazu wird der Wert 0x4427 ins Register 0x00 geschrieben. Siehe INA226 Datenblatt Seite 22.

Die Batteriespannung wird aus dem Register 0x02 gelesen und die Shunt Spannung aus dem Register 0x01. Die Leistung ergibt sich aus P = U * I

Alle 3 Werte werden am PC in der Konsole ausgegeben.

Hier das Programm

// Batteriemonitor mit dem INA226 IC und dem Arduino Uno
// Messbereich: Batteriespannung 0-36VDC und Shuntspannung +-82mV zur Strommessung
// beide mit 16 Bit Auflösung und hier mit 16 Mittelungen für 1 Messung pro Sekunde
// SMD Shunt 0,1 Ohm / 3 W ist aufgelötet und kann hier bis 820mA messen
//
// Anschlüsse:
// 3,3V und GND
// INA226 - Uno - Mega
// SCL    - A5  - 21
// SDA    - A4  - 20
//
// Matthias Busse 30.12.2016 Version 1.0

#include <Wire.h>

float rShunt=0.1; // Shunt Widerstand festlegen, hier 0.1 Ohm
const int INA226_ADDR = 0x40; // A0 und A1 auf GND > Adresse 40 Hex auf Seite 18 im Datenblatt

void setup() {
  Wire.begin();
  Serial.begin(38400);
  // Configuration Register Standard Einstellung 0x4127, hier aber 16 Werte Mitteln > 0x4427
  writeRegister(0x00, 0x4427); // 1.1ms Volt und Strom A/D-Wandlung, Shunt und VBus continous
}

void loop(){
  // Bus Spannung, read-only, 16Bit, 0...40.96V max., LSB 1.25mV
  Serial.print(" Volt: ");
  float volt = readRegister(0x02) * 0.00125; 
  Serial.print(volt,3);
  Serial.print(" V, Current: ");
  // Seite 24: Shunt Spannung +- 81,92mV mit 16 Bit, LSB 2,5uV
  int shuntvolt = readRegister(0x01);
  if (shuntvolt && 0x8000) {// eine negative Zahl? Dann 2er Komplement bilden
    shuntvolt = ~shuntvolt; // alle Bits invertieren
    shuntvolt += 1;         // 1 dazuzählen
    shuntvolt *= -1 ;       // negativ machen
  }
  float current = shuntvolt * 0.0000025 / rShunt; // * LSB / R
  Serial.print(current,3);
  Serial.print(" A, Power: ");
  float power=abs(volt*current);
  Serial.print(power,3);
  Serial.print(" W");
  Serial.println();
  delay(1000);
}

static void writeRegister(byte reg, word value) {
  Wire.beginTransmission(INA226_ADDR);
  Wire.write(reg);
  Wire.write((value >> 8) & 0xFF);
  Wire.write(value & 0xFF);
  Wire.endTransmission();
}

static word readRegister(byte reg) {
  word res = 0x0000;
  Wire.beginTransmission(INA226_ADDR);
  Wire.write(reg);
  if (Wire.endTransmission() == 0) {
    if (Wire.requestFrom(INA226_ADDR, 2) >= 2) {
      res  = Wire.read() * 256;
      res += Wire.read();
    }
  }
  return res;
}

Eine Fehlerbetrachtung zur Spannungsmessung
Der Fehler ist im Datenblatt mit max. 0,1% und typisch 0,02% angegeben. 36V * 0,001 = 36mV max.
Der Fehler über die Temperatur ist mit max. 50ppm/°C und typisch 10ppm angegeben. Bei +- 10 Grad Temperaturänderung ( also 10-30°C ) sind das 100 ppm oder 0,1 % typisch, also auch ca. 36mV
Das LSB ist 1,25mV (letztes Bit oder Schrittweite der AD Wandlung)
Zusammen ergibt das 73mV als Fehler oder 0,2%.

Eine Fehlerbetrachtung zur Strommessung, ähnlich wie oben
Der Fehler ist im Datenblatt mit max. 0,1% und typisch 0,02% angegeben. 0,082V * 0,001 = 82uV max.
Der Fehler über die Temperatur ist mit max. 50ppm/°C und typisch 10ppm angegeben. Bei +- 20 Grad Temperaturänderung ( also 0-40°C ) sind das 100 ppm oder 0,1 % typisch, also auch ca. 82VmV
Das LSB ist 2,5uV (letztes Bit oder Schrittweite der AD Wandlung)
Zusammen ergibt das 167uV als Fehler.
Das heißt z.B. für meinen 0,1 Ohm Shunt einen Strommessfehler von
I = U/R = 167uV / 0,1 Ohm = 1,67mA. Das sind ca. 0,2% vom Endausschlag.
Ein Shunt hat eine Toleranz von typisch 0,5%, was bei 820mA einen maximalen Fehler von 4,1 mA ergibt. Hier liegt der Fehler des Shunts deutlich über dem Fehler des IC. Man kann zusammenfassend sagen daß die Strommessung einen Fehler von 0,7 % haben kann.

Noch ein Hinweis:
Die Spannung kann vor den Shunt (an der Batterie) abgegriffen werden bei einem Batteriemonitor. Dann wird der Batteriezustand angezeigt.
Die Spannung kann aber auch hinter dem Shunt (am Verbraucher) abgegriffen werden, wenn der Verbraucher und dessen Leistung angezeigt werden soll.
Alternativ kann der Spannungsabfall am Shunt in der Rechnung berücksichtigt werden, da der Strom durch den Shunt und den Verbraucher fließt und der Shunt Widerstand bekannt ist. Am Shunt können je nach Strom und Widerstand im Normalbetrieb immerhin 60mV, 75mV oder gar 82mV abfallen.
Wird das nicht berücksichtigt, kann sich der Spannungsfehler von oben leicht verdoppeln.

Verwendet wurden:
Arduino Uno
Arduino 1.8.0 Software
INA226 IC auf dem Board MJMCU-226
Ein kleines Steckbrett und 6 Jumper Kabel
Der Strom kommt aus einem regelbaren Netzteil mit geregelter Strombegrenzung
Die Spannung kommt aus einen einfachen 12V Netzteil

von Matthias Busse

11 Gedanken zu „Ein Batteriemonitor für Strom und Spannung mit dem INA226 und dem Arduino Uno

  1. Stefan Schmitt

    Hallo OM Christian,

    ein anderer OM hat mich auf diese Site gebracht. Wir haben hier ein Projekt, bei dem eine Anwendung 24/7 läuft. Dazu ist angedacht einen einen TRX entweder von einer Batterie/Solar-Akku oder einem Netzteil zu betreiben und sofern der beschriebene Sensor auch die Möglichkeit der Stromerfassung bietet auch eine Überwachung zu implementieren.

    Zu meiner Frage, im Artikel ist ein externer Shunt beschrieben. Wie verhält es sich denn dann mit dem internen SMD Shunt? Wird dieser einfach ausgelötet und gegen einen externen ausgetauscht?

    Grüße vom Niederrhein

    Antworten
      1. admin Beitragsautor

        Den Shunt auf der Platine kann man auslöten und dann in der Berechnung den externen Shunt berücksichtigen. Der Abgriff der Spannung am externen Shunt muß zur Platine geführt werden. Im Datenblatt gibt es die Anschlußbelegung des ICs.
        Zur Sicherheit eine Strommessung mit einem Multimeter machen ob alles richtig berücksichtigt ist, fertig.

        Antworten
  2. Florian

    Hello,

    Your code is also working well with an ESP8266, I added MQTT to it so as to integrate it with home automation system.
    Could I publish the modified code (your code + MQTT management) under Open Source MIT licence on github?

    Regards

    Antworten
  3. Peter

    Hallo,

    ich beschäftige mich gerade mit dem Sensor und als Info zur Fehlerbetrachtung möchte hier den Link betragen http://www.ti.com/product/INA226. Dort kann man mit Hilfe der Vorgaben den Fehler im Diagramm betrachten. Also vorsichtig mit einfachen Berechnungen. Es gibt auch schöne Dokus hierüber von Ti.

    Gruß P

    Antworten
  4. Andreas

    Hallo!
    Hast du den originalen Shunt schon gegen einen Anderen ersetzt?
    Bin auf der Suche nach einem 0,05 Ohm, kann aber leider nichts finden…
    Müsste +/- 20VDC und +/-3-5 Ampere messen

    lg

    Antworten
  5. Frank

    Hallo;

    ich meinen einen kleinen Fehler im Code gefunden zu haben.
    Zeile 22 und 23 : … hier aber 16 Werte Mitteln > 0x4427

    Sollte 0x4527 sein, sonst verändert sich die Bus Voltage Conversion Time auf 140us.

    Korrigiert mich , wenn ich einen Denkfehler drin habe.

    Gruß, Frank

    Antworten
    1. Sven

      Sollte richtig sein! Habe eben das Datenblatt des INA 226 angeschaut und mit dem 0x4427 mittelt er statt 16 Werte 128 Werte, weil er dadurch an D8 eine 1 statt ner 0 hat und somit mittelt er mehr als er, laut Kommentar, sollte.

      Gruß, Sven

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.