INA219 Strom- und Leistungssensormodul

Über den Beitrag

In diesem Beitrag möchte ich das Strom- und Leistungs-Sensormodul INA219 und meine dazugehörige Bibliothek INA219_WE vorstellen.

Bei meinen Recherchen habe ich neben dem INA219 verschiedene andere Stromsensormodule wie den ACS712 oder den MAXIM471 ausprobiert. Der INA219 gefiel mir aber am besten, weil er auch Ströme von wenigen Milliampere zuverlässig erfasst. Außerdem ermittelt das Modul neben dem Strom die Leistung und den Spannungsabfall über dem zu messenden System. Den INA226, sozusagen der Bruder des INA219, werde ich in einem anderen Beitrag behandeln.

Bibliotheken für den INA219 gab es schon einige, aber ich war mit keiner richtig glücklich. Entweder fehlten mir bestimmte Optionen wie z.B. der Triggered-Modus oder ich fand die Funktionen etwas unhandlich zu benutzen. Aber die Geschmäcker sind ja verschieden. Wenn ihr alternative Bibliotheken probieren wollt, dann findet ihr einige davon in der Arduino Bibliotheksverwaltung oder bei Github (Suchbegriff INA219).

Messprinzip des INA219

INA219 Module aus verschiedenen Quellen
Verschiedene INA219 Module

Das Messprinzip des INA219 basiert schlicht auf dem Ohmschen Gesetz. Der zu messende Strom wird über einen Widerstand geleitet und die darüber abfallende Spannung ermittelt. Da man möglichst wenig in das zu messende System eingreifen möchte, ist der Widerstand sehr klein. So ein Strommesswiderstand wird als Shunt bezeichnet. Im Falle des INA219 Moduls hat der Shunt eine Größe von 0,1 Ohm (R100).

Der Shunt des INA219 wird wie unten abgebildet in den Stromkreis des Verbrauchers integriert. Um die Größe des Stroms zu errechnen, muss man dann im Grunde lediglich den Spannungsabfall über dem Shunt mit 10 multiplizieren. Wozu benötigt man dann überhaupt so etwas Komplexes wie den INA219? Nun, zum einen sind die zu messenden Spannungen recht klein. Man braucht also eine Verstärkung und – das sowieso noch – einen A/D-Wandler. Zum anderen kann der INA219 ja noch ein bisschen mehr als einfach nur den Strom messen.

Der INA219 ermittelt neben der Shuntspannung auch den Spannungsabfall über dem Verbraucher („Bus“) zwischen VIN- und GND. Daraus und aus der Größe des Stroms berechnet der INA219 die Leistung des Verbrauchers.

Der Stromkreis über Shunt und Verbraucher ist vom Versorgungsstrom des INA219 getrennt. Wichtig ist aber, dass beide ein gemeinsames GND haben. 

Wie ihr den INA219 in den zu messenden Stromkreis integriert
Wie ihr den INA219 in den zu messenden Stromkreis integriert

Typische Schaltung

Typische Schaltung für den INA219
Typische Schaltung für den INA219

Der INA219, genauer gesagt der Shunt, muss vor den Verbraucher in den Stromkreis eingesetzt werden, sonst funktioniert die Messung der Busspannung nicht. Diese Positionierung nennt man High-Side.

Die Beschaltung ist simpel. Es ist dabei egal, ob ihr die Anschlussklemmen oder die Pins für VIN+ und VIN- benutzt.

Wenn ihr in der oben abgebildeten Schaltung VIN- und VIN+ vertauscht, bekommt ihr übrigens negative Werte für den Strom und die Shuntspannung.

Einige technische Daten des INA219 Moduls

Hier die wichtigsten Daten des INA219 Moduls:

  • Busspannung: 0 – 26 Volt
  • maximaler Busstrom: 3,2 Ampere
  • Versorgungsspannung: 3 – 5.5 Volt
  • Stromverbrauch (selbst ermittelt):
    • kontinuierlicher Modus: 0,7 mA 
    • Power-Down Modus: 9,5 µA 
  • 4 Verstärkungsstufen (1-, 2-, 4-, 8-fach)
  • Messmodi: kontinuierlich („continuous“) oder on-Demand („triggered“);
  • Datenregister:
    • Shunt Spannung (shunt voltage register)
    • Bus Spannung (bus voltage register)
    • Strom (current register)
    • Leistung (power register)
  • Kommunikation über I2C, 4 Adressen einstellbar:
    • 0x40: A0, A1 offen
    • 0x41: A0 geschlossen, A1 offen
    • 0x44: A0 offen, A1 geschlossen
    • 0x45: A0, A1 geschlossen

Falls ihr die I2C Adresse überprüfen wollt, könnt ihr dazu meinen I2C Scanner verwenden.

Weitere technische Angaben findet ihr im Datenblatt zum INA219. 

Ihr bekommt den INA219 für wenige Euro in den meisten Online Elektronikshops, z.B. hier bei Amazon. Teurer sind Module von Adafruit. Ob sich der Preisunterschied in besserer Qualität widerspiegelt, kann ich nicht beurteilen.

Gebrauch der INA219_WE Bibliothek

Ihr installiert die Bibliothek entweder über die Arduino Bibliotheksverwaltung oder ladet sie hier von Github herunter. 

Kontinuierlicher Modus

Baut eure Schaltung wie weiter oben abgebildet auf. Dann ladet den Beispielsketch „Continuous.ino“ hoch: 

#include <Wire.h>
#include <INA219_WE.h>
#define I2C_ADDRESS 0x40

INA219_WE ina219(I2C_ADDRESS);
// INA219_WE ina219 = INA219_WE(); // Alternative: sets default address 0x40

void setup() {
  Serial.begin(9600);
  Wire.begin();
  ina219.init();

  /* Set ADC Mode for Bus and ShuntVoltage
  * Mode *            * Res / Samples *       * Conversion Time *
  BIT_MODE_9        9 Bit Resolution             84 µs
  BIT_MODE_10       10 Bit Resolution            148 µs  
  BIT_MODE_11       11 Bit Resolution            276 µs
  BIT_MODE_12       12 Bit Resolution            532 µs  (DEFAULT)
  SAMPLE_MODE_2     Mean Value 2 samples         1,06 ms
  SAMPLE_MODE_4     Mean Value 4 samples         2,13 ms
  SAMPLE_MODE_8     Mean Value 8 samples         4,26 ms
  SAMPLE_MODE_16    Mean Value 16 samples        8,51 ms     
  SAMPLE_MODE_32    Mean Value 32 samples        17,02 ms
  SAMPLE_MODE_64    Mean Value 64 samples        34,05 ms
  SAMPLE_MODE_128   Mean Value 128 samples       68,10 ms
  */
  //ina219.setADCMode(SAMPLE_MODE_128); // choose mode and uncomment for change of default
  
  /* Set measure mode
  POWER_DOWN - INA219 switched off
  TRIGGERED  - measurement on demand
  ADC_OFF    - Analog/Digital Converter switched off
  CONTINUOUS  - Continuous measurements (DEFAULT)
  */
  // ina219.setMeasureMode(CONTINUOUS); // choose mode and uncomment for change of default
  
  /* Set PGain
  * Gain *  * Shunt Voltage Range *   * Max Current *
   PG_40       40 mV                    0,4 A
   PG_80       80 mV                    0,8 A
   PG_160      160 mV                   1,6 A
   PG_320      320 mV                   3,2 A (DEFAULT)
  */
  // ina219.setPGain(PG_320); // choose gain and uncomment for change of default
  
  /* Set Bus Voltage Range
   BRNG_16   -> 16 V
   BRNG_32   -> 32 V (DEFAULT)
  */
  // ina219.setBusRange(BRNG_32); // choose range and uncomment for change of default

  Serial.println("INA219 Current Sensor Example Sketch - Continuous");

  /* If the current values delivered by the INA226 differ by a constant factor
     from values obtained with calibrated equipment you can define a correction factor.
     Correction factor = current delivered from calibrated equipment / current delivered by INA226
  */
  // ina219.setCorrectionFactor(0.98); // insert your correction factor if necessary
  
}

void loop() {
  float shuntVoltage_mV = 0.0;
  float loadVoltage_V = 0.0;
  float busVoltage_V = 0.0;
  float current_mA = 0.0;
  float power_mW = 0.0; 
  bool ina219_overflow = false;
  
  shuntVoltage_mV = ina219.getShuntVoltage_mV();
  busVoltage_V = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getBusPower();
  loadVoltage_V  = busVoltage_V + (shuntVoltage_mV/1000);
  ina219_overflow = ina219.getOverflow();
  
  Serial.print("Shunt Voltage [mV]: "); Serial.println(shuntVoltage_mV);
  Serial.print("Bus Voltage [V]: "); Serial.println(busVoltage_V);
  Serial.print("Load Voltage [V]: "); Serial.println(loadVoltage_V);
  Serial.print("Current[mA]: "); Serial.println(current_mA);
  Serial.print("Bus Power [mW]: "); Serial.println(power_mW);
  if(!ina219_overflow){
    Serial.println("Values OK - no overflow");
  }
  else{
    Serial.println("Overflow! Choose higher PGAIN");
  }
  Serial.println();
  
  delay(3000);
}

 

Parametereinstellung am Beispiel des Continuous.ino Sketch

An diesem Beispiel möchte ich nicht nur den kontinuierlichen Modus an sich, sondern auch die generellen Einstellparameter erklären.

Die Funktion init() sorgt dafür, dass der INA219 mit den Defaultwerten aktiviert wird. Um diese Grundeinstellungen zu ändern, könnt ihr im Setup an vier verschiedenen Schrauben drehen:

  1. ADC Modus für die Shunt- und Busspannungskonversion (setADCMode()):
    • BIT_MODE_X: Einzelmessungen mit X Bit Auflösung.
    • SAMPLE_MODE_X: Mittelwert aus X Messungen
    • Voreinstellung: BIT_MODE_12.
    • Die Zeiten für die A/D-Wandlung sind im Sketch angegeben. Beachtet dabei, dass pro Messzyklus zwei Wandlungen stattfinden, nämlich eine für die Shunt- und eine für die Busspannung.
  2. Messmodus (setMeasureMode())
    • CONTINUOUS – kontinuierlich: das ist die Voreinstellung, die hier verwendet wird.
    • TRIGGERED – „auf Anfrage“: wird im nächsten Beispiel erklärt.
    • ADC_OFF – Abschalten des A/D Wandlers
    • POWER_DOWN – schaltet den INA219 ab. Verwendet dazu aber besser die komfortablere powerDown() Funktion, welche weiter unten erläutert wird.
    • Der INA219 erlaubt es eigentlich auch, Shunt- oder Busspannungen zu ermitteln – das habe ich aber nicht implementiert.
  3. Verstärkungsfaktor (setPGain())
    • PG_X: Das „X“ gibt das Limit für die Shunt Spannung an. Z.B.: PG_40 –> 40 mV –> entspricht maximal 400 mA Strom
    • Je höher X, desto höher der maximale Strom, aber desto geringer die Auflösung für den Strom und die Leistung
  4. Busspannungsbereich (setBusRange())
    • 16 oder 32 Volt

Ihr könnt die Einstellungen aber auch jederzeit später, außerhalb der Setup Funktion ändern.

Mit setCorrectionFactor(factor) könnt ihr einen Korrekturfaktor einführen, falls die mit dem INA219 ermittelten Stromwerte von solchen abweichen sollten, die mit kalibrierten Messgeräten ermittelt worden sind. Der Faktor ist dabei der Quotient aus dem „richtigen“ und dem INA219 Wert. Bei mir stimmten alle INA219 Module gut mit meinem Multimeter überein.

Die Funktion getOverflow() prüft, ob eines der Datenregister einen Überlauf hat. Ist das der Fall, wählt bitte einen anderen Verstärkungsfaktor.

Die Funktionen zum Auslesen der Messergebnisse, wie z.B. getShuntVoltage_mV(), sind selbsterklärend.

Ausgabe

Ausgabe des Continuous Sketches für den INA219
Ausgabe des Continuous Sketches für den INA219

Aufmerksame Leser mögen fragen, warum „Current“ in dieser Ausgabe nicht exakt dem zehnfachen der Shuntspannung entspricht (RShunt war ja 0.1 Ohm). Das liegt daran, dass die Register jederzeit gelesen werden können. Die aktuell laufende Konversion wird nicht abgewartet. Der Inhalt des Shunt- und des Currentregisters können deshalb aus unterschiedlichen Messzyklen stammen. Eine weitere Folge ist, dass die Werte bis zu 68,1 ms „alt“ sein können (das wäre die Obergrenze im SAMPLE_MODE_128). Im kontinuierlichen Modus sollte das aber kein Problem darstellen. Im Triggered-Modus hingegen wird nach dem Starten der Messung mit der Ausgabe gewartet, bis die aktuelle Konversion abgeschlossen ist. 

Triggered („auf Anfrage“) Modus

Der Beispielsketch für den Triggered-Modus unterscheidet sich nur in zwei Zeilen vom Continous Sketch. In Zeile 35 wird der Modus aktiviert. In Zeile 63 startet die Funktion startSingleMeasurement() die Messung. Erst wenn die Messung abgeschlossen ist, erfolgt die Ausgabe.

#include <Wire.h>
#include <INA219_WE.h>
#define I2C_ADDRESS 0x40

INA219_WE ina219(I2C_ADDRESS);
// INA219_WE ina219 = INA219_WE(); // Alternative: sets default address 0x40

void setup() {
  Serial.begin(9600);
  Wire.begin();
  ina219.init();

  /* Set ADC Mode for Bus and ShuntVoltage
  * Mode *            * Res / Samples *       * Conversion Time *
  BIT_MODE_9        9 Bit Resolution             84 µs
  BIT_MODE_10       10 Bit Resolution            148 µs  
  BIT_MODE_11       11 Bit Resolution            276 µs
  BIT_MODE_12       12 Bit Resolution            532 µs  (DEFAULT)
  SAMPLE_MODE_2     Mean Value 2 samples         1,06 ms
  SAMPLE_MODE_4     Mean Value 4 samples         2,13 ms
  SAMPLE_MODE_8     Mean Value 8 samples         4,26 ms
  SAMPLE_MODE_16    Mean Value 16 samples        8,51 ms     
  SAMPLE_MODE_32    Mean Value 32 samples        17,02 ms
  SAMPLE_MODE_64    Mean Value 64 samples        34,05 ms
  SAMPLE_MODE_128   Mean Value 128 samples       68,10 ms
  */
  // ina219.setADCMode(BIT_MODE_12); // choose mode and uncomment for change of default
  
  /* Set measure mode
  POWER_DOWN - INA219 switched off
  TRIGGERED  - measurement on demand
  ADC_OFF    - Analog/Digital Converter switched off
  CONTINUOUS  - Continuous measurements (DEFAULT)
  */
  ina219.setMeasureMode(TRIGGERED); // Triggered measurements for this example
  
  /* Set PGain
  * Gain *  * Shunt Voltage Range *   * Max Current *
   PG_40       40 mV                    0,4 A
   PG_80       80 mV                    0,8 A
   PG_160      160 mV                   1,6 A
   PG_320      320 mV                   3,2 A (DEFAULT)
  */
  // ina219.setPGain(PG_320); // choose gain and uncomment for change of default
  
  /* Set Bus Voltage Range
   BRNG_16   -> 16 V
   BRNG_32   -> 32 V (DEFAULT)
  */
  // ina219.setBusRange(BRNG_32); // choose range and uncomment for change of default

  /* If the current values delivered by the INA226 differ by a constant factor
     from values obtained with calibrated equipment you can define a correction factor.
     Correction factor = current delivered from calibrated equipment / current delivered by INA226
  */
  // ina219.setCorrectionFactor(0.98); // insert your correction factor if necessary
  
  Serial.println("INA219 Current Sensor Example Sketch - Triggered Mode");
 
}

void loop() {
  float shuntVoltage_mV = 0.0;
  float loadVoltage_V = 0.0;
  float busVoltage_V = 0.0;
  float current_mA = 0.0;
  float power_mW = 0.0; 
  bool ina219_overflow = false;
  
  ina219.startSingleMeasurement(); // triggers single-shot measurement and waits until completed
  shuntVoltage_mV = ina219.getShuntVoltage_mV();
  busVoltage_V = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getBusPower();
  loadVoltage_V  = busVoltage_V + (shuntVoltage_mV/1000);
  ina219_overflow = ina219.getOverflow();
  
  Serial.print("Shunt Voltage [mV]: "); Serial.println(shuntVoltage_mV);
  Serial.print("Bus Voltage [V]: "); Serial.println(busVoltage_V);
  Serial.print("Load Voltage [V]: "); Serial.println(loadVoltage_V);
  Serial.print("Current[mA]: "); Serial.println(current_mA);
  Serial.print("Bus Power [mW]: "); Serial.println(power_mW);
  if(!ina219_overflow){
    Serial.println("Values OK - no overflow");
  }
  else{
    Serial.println("Overflow! Choose higher PGAIN");
  }
  Serial.println();
  
  delay(3000);
}

 

Im Triggered-Modus gehören alle Ausgabewerte zu einem Messzyklus:

Ausgabe des Triggered Sketches für den INA219
Ausgabe des Triggered Sketches für den INA219

Power-Down Modus

Mit dem Power-Down Modus könnt ihr den Strombedarf des INA219 von ca. 0.7 mA auf unter 10 µA herunterbringen (eigene Messungen). 0.7 mA ist ein so schon recht genügsamer Wert, aber im Jahr sind das auch immerhin über 6000 mAh. Für batteriebetriebene Projekte ist das schon sehr relevant.

Der folgende Beispielsketch zeigt den Power-Down Modus in Aktion. Der Sketch startet den INA219 mit den Standardparametern. Fünf Messwert-Pakete werden im Abstand von je drei Sekunden ausgegeben. Die Funktion powerDown() sichert dann den Inhalt des Konfigurationsregisters und schaltet den INA219 ab. Die Funktion powerUp() schreibt die Kopie des Konfigurationsregisters wieder zurück. Zum einen weckt dieser Schreibvorgang den INA219 auf, zum anderen stellt er sicher, dass der INA219 in den zuvor gewählten Modus (hier: kontinuierlich) zurückkehrt.

#include <Wire.h>
#include <INA219_WE.h>
#define I2C_ADDRESS 0x40

INA219_WE ina219(I2C_ADDRESS);
// INA219_WE ina219 = INA219_WE(); // Alternative: sets default address 0x40

void setup() {
  Serial.begin(9600);
  Wire.begin();
  // default parameters are set - for change check the other examples
  ina219.init();
  Serial.println("INA219 Current Sensor Example Sketch - PowerDown");
  Serial.println("Continuous Sampling starts");
  Serial.println();
}

void loop() {
  for(int i=0; i<5; i++){
    continuousSampling();
    delay(3000);
  }
  
  Serial.println("Power down for 10s");
  ina219.powerDown();
  for(int i=0; i<10; i++){
    Serial.print(".");
    delay(1000);
  }
  
  Serial.println("Power up!");
  Serial.println("");
  ina219.powerUp();
}

void continuousSampling(){
  float shuntVoltage_mV = 0.0;
  float loadVoltage_V = 0.0;
  float busVoltage_V = 0.0;
  float current_mA = 0.0;
  float power_mW = 0.0; 
  bool ina219_overflow = false;
  
  shuntVoltage_mV = ina219.getShuntVoltage_mV();
  busVoltage_V = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getBusPower();
  loadVoltage_V  = busVoltage_V + (shuntVoltage_mV/1000);
  ina219_overflow = ina219.getOverflow();
  
  Serial.print("Shunt Voltage [mV]: "); Serial.println(shuntVoltage_mV);
  Serial.print("Bus Voltage [V]: "); Serial.println(busVoltage_V);
  Serial.print("Load Voltage [V]: "); Serial.println(loadVoltage_V);
  Serial.print("Current[mA]: "); Serial.println(current_mA);
  Serial.print("Bus Power [mW]: "); Serial.println(power_mW);
  if(!ina219_overflow){
    Serial.println("Values OK - no overflow");
  }
  else{
    Serial.println("Overflow! Choose higher PGAIN");
  }
  Serial.println();
}

 

Überblick über alle Funktionen der Bibliothek

Und hier nochmal der Überblick über alle Funktionen. Er ist in Englisch, weil er zu meiner Dokumentation auf Github gehört. 

Liste der Funktionen der INA219_WE Bibliothek
Liste der Funktionen der INA219_WE Bibliothek

Details zur Bibliothek und den Registern

Dieser Teil ist nur noch für diejenigen, die die INA219_WE Bibliothek nachvollziehen oder die internen Vorgänge im INA219 besser verstehen wollen. 

Die Register des INA219

Der INA219 besitzt sechs 16-Bit Register. Beschreibbar sind lediglich das Konfigurations- (Configuration) und das Kalibrierungsregister (Calibration Register). Die anderen Register stellen die gemessenen bzw. berechneten Daten bereit und können entsprechend nur gelesen werden.

Register des INA219
Register des INA219

Im Konfigurationsregister werden die grundlegenden Einstellungen vorgenommen:

Das Konfigurationsregister

Konfigurationsregister des INA219
Konfigurationsregister des INA219
  • RST: Ein Setzen des RST Bits löst einen Reset aus. Die Registerinhalte werden auf Default zurückgesetzt.
  • BRNG: Bus Range legt den Bereich der Busspannung fest, also 16 oder 32 Volt.
  • PGX: Die beiden Bits bestimmen PGAIN
  • BADCX / SADCX: Diese Bits legen die Auflösung bzw. die Anzahl der Messungen pro Messzyklus für die Bus- und Shuntspannung fest (siehe Tabelle). In meiner Bibliothek können keine unterschiedlichen Werte in BADC und SADC geschrieben werden. Ich hatte mich dazu entschieden, um die Bedienung nicht zu komplex zu gestalten.
  • MODEX: Mit den drei Mode Bits wird der Betriebsmodus festgelegt (siehe Tabelle). Auch hier habe ich nicht alles implementiert, was möglich ist. Nur die grün hervorgehobenen Modi sind verfügbar. 
ADC Settings - gilt für die Shunt- und die Busspannungswandlung
ADC Settings – gilt für die Shunt- und die Busspannungswandlung
Einstellbare Modi des INA219 - nur die grün hinterlegten Modi sind implementiert
Einstellbare Modi des INA219 – nur die grün hinterlegten Modi sind implementiert

Die anderen Register

Das Shunt- und das Currentregister sind nicht besonders spannend. Es ist aber zu erwähnen, dass beide Vorzeichenbits haben, also Werte zwischen +32767 und -32767 annehmen können. Das Bus Voltage und das Power Register sind nicht vorzeichenbehaftet.

Zum Bus Voltage Register ist noch zu sagen, dass für die Busspannung nur 13 Bit zur Verfügung stehen (BD0 – BD12). Das Bit Nr. 2 ist ungenutzt, Bit Nr. 1 ist CNVR (Conversion Ready). Es wird gesetzt, wenn (frische) Daten in den Registern zur Verfügung stehen, d.h. alle Messungen und Berechnungen für einen Zyklus komplett sind. Lesen des Power Registers löscht das Bit. Bit 0 ist OVF (Overflow) und gibt an, ob eines der Datenregisters übergelaufen ist. Zur Ausgabe der Busspannung muss der Inhalt des Bus Voltage Registers um 3 Bits nach rechts verschoben werden.

Busspannungsregister des INA219

Das Calibration Register enthält den 15 Bit Kalibrierfaktor „Cal“. Das Register umfasst zwar 16 Bit, aber das Bit 0 ist reserviert. Wir kommen gleich dazu, was es mit dem Kalibrierfaktor auf sich hat. Aber, um Missverständnissen vorzubeugen, sollte ich schon mal darauf hinweisen, dass der Kalibrierfaktor zunächst nichts mit dem Korrekturfaktor (setCorrectionFactor()) zu tun hat.

INA219 – interne Berechnungen

Die Erklärungen zu den Berechnungen im Datenblatt empfand ich sehr verwirrend. Ich musste das mehrfach durchlesen, bevor ich mir einen Reim darauf machen konnte. Aber eigentlich ist es gar nicht so schlimm.

Zur Festlegung des Kalibrierfaktors überlegt ihr euch zunächst, wie groß der größte zu erwartende Strom (Max Expected Current) ist. Dieser muss in das Current Register passen. Da das Current Register einen Wertebereich von +/- 215 hat, ergibt sich damit für Current_LSB (Ampere pro Bit):

Current\_LSB = \frac{Max\ Expected\ Current}{2^{15}}

Aus der Gleichung resultiert normalerweise ein „krummer“ Wert. Diesen rundet ihr so auf, dass ihr im nächsten Schritt einen geraden Wert für den Kalibrierfaktor Cal erhaltet. Cal berechnet ihr nach der folgenden Formel:

Cal = trunc\left(\frac{0,\!04096}{Current\_LSB\cdot R_{Shunt}}\right)

Dabei ist 0.04096 ein intern festgelegter Wert, der für eine sinnvolle Skalierung sorgt, d.h. dass die Werte die Registerbreite gut nutzen.

Das Shunt Voltage Register enthält die Shuntspannung in 10µV / Bit. Da es ein vorzeichenbehaftetes Register ist, kann der Betrag maximal 215-1 sein. Daraus ergibt sich eine maximale Shuntspannung von 0,32767 Volt. Mehr passt nicht ins Register. Da der Shuntwiderstand 0,1 Ohm beträgt, ergibt sich theoretisch ein maximaler Strom von ca. 3,2 Ampere.

Das Current Register wird nach folgender Formel errechnet (darum müssen wir uns aber nicht kümmern):

Current\ Register=\frac{Shunt\ Voltage\ Register \cdot Cal}{4096}

Power_LSB, also die Leistung pro Bit (Watt/Bit), ist das 20fache des Current_LSB. Das ist intern so festgelegt.

Power\_LSB = 20 \cdot Current\_LSB

Der Inhalt des Power Registers lässt sich aus dem Inhalt des Current Registers und dem Bus Voltage Register berechnen. Aber auch darum müssen wir uns nicht kümmern, denn das berechnet der INA219 intern.

Power\ Register = \frac{Current\ Register \cdot Bus\ Voltage\ Register}{5000}

Das Bus Voltage Register hat ein festgelegtes LSB von 4 mV/Bit.

Berechnungen durch die Bibliothek

Im Grunde könntet ihr einfach nur das Shunt- und das Bus Voltage Register auslesen und den Rest so ausrechnen. Aber wir lassen den INA219 für uns arbeiten.

Dennoch müssen die aus den Registern gelesenen Werte noch umgerechnet werden:

Umrechnung der Registerinhalte
Umrechnung der Registerinhalte

Um handlichere Werte zu bekommen, habe ich noch einen Current Divider und einen Power Multiplier eingeführt:

Current\ \text{[mA]}=\frac{Current\ Register}{Current\ Divider}
\text{mit}\ \ \ Current\ Divider = \frac{1}{Current\_LSB \cdot 1000}

und

Power\ \text{[mW]} = Power\ Register\cdot Power\ M\!ultiplier
\text{mit}\ \ \ Power\ M\!ultiplier = Power\_LSB \cdot 1000

In der Bibliothek implementierte Messbereiche

Wie wir also gesehen haben, hängt die Auflösung für den Strom und die Leistung von der Größe des Wertes Current_LSB ab. Deswegen macht es Sinn, mehrere Bereiche mit unterschiedlichen Current_LSB Werten zu definieren. Mir erschien es die einfachste und naheliegendste Lösung, dafür die PGAIN Bereiche zu nehmen:

Messbereiche, Auflösung und Umrechnungsfaktoren für den INA219
Messbereiche, Auflösung und Umrechnungsfaktoren

Wenn ihr eine hohe Auflösung verwenden wollt, müsst ihr also ein kleines PGAIN wählen.

Danksagung

Das INA219 Fritzing Bauteil habe ich aus der Adafruit Fritzing Part Sammlung auf Github.

Das Beitragsbild stammt von Pixabay aus dem Free-Photos Fundus bei Pixabay und wurde von mir leicht modifiziert.

8 thoughts on “INA219 Strom- und Leistungssensormodul

  1. Hallo Wolle,

    sehr schön!
    Ich habe gute Erfahrungen mit dem INA226 gemacht (16Bit-Auflösung) und 0-36V U-Messung.

    Gruß
    Wölle

    1. Hi Wölle, der INA226 gefällt mir tendenziell auch noch besser. Aber ich will nicht zuviel vorwegnehmen. Ist mein nächstes Beitragsthema. Verwendest du ein Modul oder hast du den IC selbst „verdrahtet“?

  2. Hallo Wolfgang
    Danke für deinen Beitrag. Finde den INA219 sehr gut. Habe bereits einiges damit gemacht. Einiges scheint mir im Datenblatt nicht ganz klar gewesen (übersehen?). Dein Beitrag hat sehr zur „Erhellung“ beigetragen. Muss mir den INA226 noch mal ansehen.
    achim

  3. I have an INA219 that is working well with your INA219_WE example program, on a Teensy 3.6 on the SCL0, pin19 & SDA0, pin18. However, this is a larger project and I need the ADC channel that are also on these pins. I have tried to move it to another set of dedicated I2C pins on SCL2, pin3 & SDA2 pin4 and have used the following commands:
    uint8_t SCL = 3;
    uint8_t SDA = 4;

    Wire.setSCL(SCL);
    Wire.setSDA(SDA);

    This gives me the error of (conflicting declaration ‚int SCL‘)
    It seems to be in conflict with (const static uint8_t SCL = 19;)
    Can you please offer any remedial action to remedy this problem?

    1. Hi Frank,

      I don’t have much experience with the Teensy, but I think this issue is anyway not related with the use of this board. The problem is, I think, that you „SDA“ and „SCL“ have been declared before as constants. I think if you just use any other variable names which are not reserved, it will work, like:

      uint8_t Frank = 3;
      uint8_t Wolfgang = 4;

      Wire.setSCL(Frank);
      Wire.setSDA(Wolfgang);

      Regards, Wolfgang

    2. ….or, even better, try:

      Wire.setSCL(SCL2);
      Wire.setSDA(SDA2);

      You don’t need to declare SCL2 and SDA2, I am pretty sure they are also already defined somewhere as const static uint8_t.

  4. Hallo Wolle,
    ich würde gern den Shunt ändern, um größere Ströme messen zu können. An welcher Stelle der library kann ich dazu den Berechnungsfaktor ändern? Ich hab lediglich diese Zeile gefunden:
    float currentDivider_mA;
    Den eingestellten default Wert (100mOhm) hab ich nirgends gefunden.
    Danke und Gruß
    Christian

    1. Hallo Christian,

      beim INA226 habe ich die Möglichkeit den Widerstand zu ändern in der Bibliothek vorgesehen, für den INA219 noch nicht. Die 100 mOhm sind also (noch) unflexibel und fest in den Berechnungen verankert. Das zu ändern, steht auf meiner To Do Liste, nur die ist leider recht lang und deshalb gebe ich lieber keinen konkreten Zeitpunkt an.

      VG, Wolfgang

Schreibe einen Kommentar

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