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 (mit 0.1 Ohm Shunt)
  • 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

/* There are several ways to create your INA219 object:
 * INA219_WE ina219 = INA219_WE()              -> uses Wire / I2C Address = 0x40
 * INA219_WE ina219 = INA219_WE(ICM20948_ADDR) -> uses Wire / I2C_ADDRESS
 * INA219_WE ina219 = INA219_WE(&wire2)        -> uses the TwoWire object wire2 / I2C_ADDRESS
 * INA219_WE ina219 = INA219_WE(&wire2, I2C_ADDRESS) -> all together
 * Successfully tested with two I2C busses on an ESP32
 */
INA219_WE ina219 = INA219_WE(I2C_ADDRESS);

void setup() {
  Serial.begin(9600);
  Wire.begin();
  if(!ina219.init()){
    Serial.println("INA219 not connected!");
  }

  /* 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 (if shunt is 0.1 ohms) *
   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 INA219 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 INA219
  */
  // ina219.setCorrectionFactor(0.98); // insert your correction factor if necessary
  
  /* If you experience a shunt voltage offset, that means you detect a shunt voltage which is not 
     zero, although the current should be zero, you can apply a correction. For this, uncomment the 
     following function and apply the offset you have detected.   
  */
  // ina219.setShuntVoltOffset_mV(0.5); // insert the shunt voltage (millivolts) you detect at zero current 
}

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.

INA219_WE ina219 = INA219_WE() erzeugt euer INA219 Objekt. Ich habe verschiedene Optionen implementiert. Ihr könnt ein Wire Objekt übergeben und so z.B. die beiden I2C Busse eines ESP32 nutzen. 

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.
    • PG_40: Gain = 1, PG_80: Gain = 1/2, PG_160: Gain = 1/4, PG_320: Gain = 1/8.
  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.

Anscheinend zeigen einige INA219 Module Shuntspannung-Offsets. Das heißt, obwohl kein Strom fließt (Verbraucher abgeschaltet) wird eine Shuntspannung angezeigt und ein daraus resultierender Strom. Mit setShuntVoltOffset() könnt ihr das ausgleichen. Tragt dort die Shuntspannung, die ihr ohne Strom messt, in Millivolt als Parameter ein.  

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 37 wird der Modus aktiviert. In Zeile 73 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

/* There are several ways to create your INA219 object:
 * INA219_WE ina219 = INA219_WE()              -> uses Wire / I2C Address = 0x40
 * INA219_WE ina219 = INA219_WE(ICM20948_ADDR) -> uses Wire / I2C_ADDRESS
 * INA219_WE ina219 = INA219_WE(&wire2)        -> uses the TwoWire object wire2 / I2C_ADDRESS
 * INA219_WE ina219 = INA219_WE(&wire2, I2C_ADDRESS) -> all together
 * Successfully tested with two I2C busses on an ESP32
 */
INA219_WE ina219 = INA219_WE(I2C_ADDRESS);

void setup() {
  Serial.begin(9600);
  Wire.begin();
  if(!ina219.init()){
    Serial.println("INA219 not connected!");
}

  /* 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 INA219 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 INA219
  */
  // ina219.setCorrectionFactor(0.98); // insert your correction factor if necessary

  /* If you experience a shunt voltage offset, that means you detect a shunt voltage which is not 
     zero, although the current should be zero, you can apply a correction. For this, uncomment the 
     following function and apply the offset you have detected.   
  */
  // ina219.setShuntVoltOffset_mV(0.0); // insert the shunt voltage (millivolts) you detect at zero current
  
  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

/* There are several ways to create your INA219 object:
 * INA219_WE ina219 = INA219_WE()              -> uses Wire / I2C Address = 0x40
 * INA219_WE ina219 = INA219_WE(ICM20948_ADDR) -> uses Wire / I2C_ADDRESS
 * INA219_WE ina219 = INA219_WE(&wire2)        -> uses the TwoWire object wire2 / I2C_ADDRESS
 * INA219_WE ina219 = INA219_WE(&wire2, I2C_ADDRESS) -> all together
 * Successfully tested with two I2C busses on an ESP32
 */
INA219_WE ina219 = INA219_WE(I2C_ADDRESS);

void setup() {
  Serial.begin(9600);
  Wire.begin();
  // default parameters are set - for change check the other examples
  if(!ina219.init()){
    Serial.println("INA219 not connected!");
  }
  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();
}

 

Andere Shuntgröße wählen

Trotz intensiver Suche habe ich nur Module mit einem 0.1 Ohm Shunt gefunden. Damit seid ihr auf eine Stromstärke von 3.2 Ampere begrenzt. Wenn Ihr größere Ströme messen wollt, dann habt Ihr drei Möglichkeiten:

  1. Verwendet kein Modul, sondern den blanken INA219 Chip.
  2. Ihr lötet den R100 Shunt aus und ersetzt ihn. Mit nur einem Lötkolben ist das aber nicht trivial. 
  3. Pragmatische Lösung: ihr lötet einfach einen zweiten Shunt im Sandwichverfahren auf den ersten Shunt.

Ich habe Weg 3 ausprobiert (siehe rechts). Zwei parallele Shunts von 0.1 und 0.05 Ohm ergeben einen Gesamtshunt von 0.0333 Ohm. Hat wunderbar funktioniert. 

Mit setShuntSizeInOhms() legt ihr den Shunt fest. Auch setPGain() funktioniert noch in Verbindung mit dem geänderten Shunt. Bei Verwendung von PG_Value und einem Shunt mit dem Widerstand R ist die maximale Stromstärke I: 

I_{\text{max}}\;\text{[A]}= \frac{Value}{R\cdot 1000}

Einen Beispielsketch dazu gibt es als Teil der Bibliothek. 

Überblick über alle Funktionen der Bibliothek

Und hier noch einmal 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

Die maximale Auflösung für den Strom ergibt sich aus dem LSB des Shunt Voltage Registers (10 µV) und der Shuntgröße (0.1 Ω). Imin = Umin/R = 100 µA  = 0.1 mA. In der folgenden Tabelle habe ich die in der Bibliothek implementierten Messbereiche und die sich daraus ergebenden LSBs für Strom und Leistung berechnet.

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

Die berechneten Current LSBs sind, außer für PG_320, kleiner als die tatsächlich mögliche Auflösung. Lasst euch also von den Werten nicht irreführen. Erst mit größeren Shunts würde man Vorteile bei der Auflösung erzielen.

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.

90 thoughts on “INA219 Strom- und Leistungssensormodul

  1. Hallo zum 2. (ist ne weile her),
    neues problem, ich habe 2 INA`s die auch einen effizienz wert anzeigen sollen.
    kalibrieren im lib default modus war kein problem. also zb *0.98x und anzeige passt
    aber ich fange am niedrigsten gain an und schalte hoch , also PG40-320. (quasi automodus)
    feststellung , unter PG320 wirkt der correctionfactor nicht mehr , kann auch unsinnige werte angeben = keine wirkung
    auch bei leistung gibt ein problem, manuelle rechnung u*i vs power_mW = weicht sehr ab
    und jeder ina zeigt andere werte an (3 geschrottet) würde mir eine spannungs kalibrierung wünschen
    hinweis 1.ina =3x .1ohm (=0.033) 2.ina 1x .1ohm shunt

    1. Hallo,
      in der Tat wird der Korrekturfaktor in der aktuellen Version nicht berücksichtigt, wenn PGain während des laufenden Programmes geändert wird. Ich habe es jetzt in einer neuen Version der Bibliothek (1.3.7) veröffentlicht. Mit dem Programm unten funktioniert das. Es dauert ein paar Stunden bis wenige Tage, bis das in der Arduino IDE ankommt. Solange kann man sich behelfen, indem man den Korrekturfaktor nach Wechsel des PGains neu setzt.

      Wie den Kommentaren in meinen Beispielen zu entnehmen ist, deckt PG_320 den größten Strombereich ab. Die 320 steht für den maximalen Spannungsbereich des Shunts in Millivolt. PG320 ist die niedrigste Verstärkung. Bei einem Automodus für PGAIN sollte man also mit PG_320 beginnen und dann prüfen, ob die nächsthöhere Verstärkung den von mir angegebenen maximalen Strom überschreiten würde. Ob es den INA219 zerstören kann, wenn man eine zu hohe Verstärkung wählt, das weiß ich nicht. Ich vermute aber, dass man höchstens auf VCC verstärken kann.

      Allerdings hat der Korrekturfaktor seine Grenzen für die Shuntgrößenkorrektur. Der Korrekturfaktor korrigiert das Calibration Register des INA219. Bei PG_320 ist der Wert des Calibration Registers 4096. Bei einem Korrekturfaktor von 16 läuft das Register über (16 * 4096 = 65536), da es ein 16 Bit Register ist. Bei PG_40 ist der Standardwert des Calibration Registers 20480. Hier ist der maximale Korrekturfaktor 3,2. Da die Bibliothek keine Änderung des Gains nach dem Setup vorgesehen hatte, war auch nicht vorgesehen, dass der Shunt verkleinert und gleichzeitig die Verstärkung erhöht wird, oder zumindest nicht in diesem Ausmaß.

      #include <Wire.h>
      #include <INA219_WE.h>
      #define I2C_ADDRESS 0x40
      
      INA219_WE ina219 = INA219_WE(I2C_ADDRESS);
      
      void setup() {
        Serial.begin(9600);
        Wire.begin();
        if(!ina219.init()){
          Serial.println("INA219 not connected!");
        }
      
        ina219.setPGain(PG_320); 
        ina219.setCorrectionFactor(2.0); 
      }
      
      void loop() {
        static int counter = 0;
        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; 
        
        if (counter > 4){
          ina219.setPGain(PG_160);
        }
        if (counter > 8){
          ina219.setPGain(PG_80);
        }
        if (counter > 12){
          ina219.setPGain(PG_40);
        }
        
        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);
        
        Serial.println(counter);
        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);
       
        delay(3000);
        counter++;
      }
      
  2. Hallo,

    mal eine Frage: Die Einstellungen im setup kann man doch auch noch im laufenden Programm ändern?
    Hintergrund ist daß ich den INA219 mit einem Seeeduino xiao an einen CAN-Controller MCP2515
    koppeln will zwecks Fernabfrage. Da wäre es hilfreich wenn man die Parameter im Betrieb anpassen kann.

    mfg

    f91w

      1. Danke!
        Habe jetzt den Triggered-Sketch mit dem INA219 und dem Seeeduino XIAO am Laufen.
        Dabei ist mir aufgefallen dass im Sketch Serial mit 9600 Baud eingestellt ist und mein Serieller
        Monitor in der IDE auf 115200 Baud stand. Trotzdem problemlose Anzeige der Daten.
        Das dürfte doch eigentlich nicht funktionieren?

        mfg

        f91w

  3. If load is disconnected and inputs are floating or if inputs are shorted the INA219 will report a random bus voltage up to 1V.
    This is a known characteristic of the INA219.

  4. Hallo,
    Ich wollte die Samplezeit der verschiedenen Modi messen und musste feststellen die ist immer gleich bei ca560us.
    egal ob Bit Mode oder Sample Mode.
    verwende die demo triggert mit dieser Anpassung um die Zeit zu messen. Wo ist das problem, was mache ich falsch. bitte Hilfe.

    ———-
    Anmerkung Wolfgang: den Programmcode habe ich entfernt. Siehe meine Antwort.

    1. Hi Jürgen,
      die eigentliche Messung wird mit der Funktion ina219.startSingleMeasurement(); durchgeführt. Die Funktion wartet, bis die Messung abgeschlossen ist. Danach stehen die Messwerte in den verschiedenen Registern bereit und können durch die get… Funktionen „abgeholt“ werden. D.h., wenn du z.B. diese Funktionen ausführst:
      time_start = micros();
      busVoltage_V = ina219.getBusVoltage_V();
      time_end = micros();
      dann ist time_end – time_start lediglich die Zeit, die du brauchst um das Ergebnis auszulesen. Und die bleibt konstant.

      Um die Zeit der Messung zu bestimmen, müsstest du folgendes anwenden:
      time_start = micros();
      ina219.startSingleMeasurement();
      time_end = micros();

      Ich erlaube mir, deinen Programmcode aus dem Kommentar herauszunehmen.

      VG, Wolfgang

  5. Hallo Wolfgang,
    danke für diese tolle Inspiration. Ich habe mir darauf aufbauend eine „elektronische Sicherung“ gebastelt. Das Modul INA219 misst den Strom – bei einem bestimmten Schwellenwert schaltet es ein Relais ab. Anzeige erfolgt über ein LCD-Display und nicht mehr am SerialMonitor. Wenn man alles Überflüssige auskommentiert funktioniert das innerhalb von 5-20 msec (an meinem Oszilloskop gemessen). Das ist so schnell wie eine flinke bis superflinke Schmelzsicherung. Mit allen Kommentaren und Anzeigen auf dem LCD-Display wird es aber deutlich langsamer und leider auch variabler.
    Gerne kann ich auch mal ein Foto davon schicken.
    Bei mir funktioniert es bestens, das ist meine erste Programmierarbeit (d. h. es dürfte noch Verbesserungspotential haben).
    Zur Hardware: ein I2C-fähiges LCD-Display mit 2×16 Feldern, ein Taster für Reset (an PIN 8), Taster geht auf Masse, PIN 8 über einen 10 kOhm Widerstand auf Vcc, ein Relais mit Elektronik an PIN 13 (damit der Ausgang nicht durchbrennt, das Relais braucht bei mir mehr als die erlaubten 40 mA) – und natürlich den Uno und die INA…
    Hier der Programmtext:
    – entfernt von Wolle –

    1. Hallo Christian,

      vielen lieben Dank für deinen Kommentar. Ich habe den Programmtext herausgenommen, da die Darstellung im Kommentarfeld sehr schlecht ist und Teile nicht dargestellt werden. Das liegt daran, dass der Text im Kommentarfeld als HTML interpretiert wird und das ist unverträglich mit Einrückungen. Gerne kannst du mir ein Foto vom Aufbau schicken (wolfgang.ewald@wolles-elektronikkiste.de) und auch das Programm. Ich bin immer interessiert was meine Leser oder Nutzer meiner Bibliotheken so basteln.

      VG, Wolfgang (Wolle)

  6. Hallo Wolfgang,

    Ich versuche einen INA219 mit einem Heltec LoRa ESP32 V3 zu betreiben. Dazu brauche ich eine Library, welche es mir gestattet, einen Constructor für Wire einzusetzen, da bei dem Heltec Board externe I2C Geräte nur mit Wire1 ansprechbar sind.
    So bin ich auf deine Bibliothek für den INA gestoßen. Ich teste das Ganze gerade an einem Wemos D1 Mini (ESP8266). Seltsamerweise bekomme ich keine vernünftigen Werte mit den meisten Bibliotheken. Bei deinem Continuous-Script erhalte ich folgendes:

    Shunt Voltage: 0.00
    Bus Voltage: 0.00
    Load Voltage: 0.00
    Current: nan
    Bus Power: nan
    Values OK – no overflow (dazu musste ich vorher diesen Wert setzen: ina219.setPGain(PG_160), sonst gab es einen Overflow)

    Der Sensor scheint aber ok zu sein. Mit der INA219 Bibliothek von DFRobot erhalte ich die folgenden Werte:

    Bus Voltage: 3.32 V
    ShuntVoltage: 0.630 mV
    Current: 6.0 mA (ich betreibe nur eine LED)
    Power: 40.0 mW

    Wenn ich anstelle der 3.3 V die 5 V vom USB Port nehme, bekomme ich entsprechend:

    Bus Voltage 5.15 V

    Current: 15.0 mA

    Was mache ich falsch, bzw. wie muss ich dein Script anpassen, damit ich vernünftige Werte bekomme?

    Vielen Dank und herzliche Grüße
    Martin

    1. Hmm, seltsam ..
      mit einem ESP32 funktioniert dein Script. Warum nicht mit dem ESP8266?

      1. Hi, bin mir nicht sicher, ob ich die Bibliothek auf einem ESP8266 schon mal getestet habe. Ich hoffe, ich komme heute abend dazu, das zu probieren. Zumindest ist es schon mal hilfreich zu wissen, dass die Hardware i.O. ist. Fehlermeldungen oder Warnungen des Compilers gibt es nicht? Du könntest mal probieren, in den Voreinstellungen der Arduino IDE alle Warnmeldungen zu aktivieren. Dann könntest du mir senden, was er beim Compilieren ausgibt (wolfgang.ewald@wolles-elektronikkiste.de).
        VG, Wolfgang

        1. Ok, prima. Heute schaffe ich das nicht mehr. Du kannst aber schon mal schauen, was die Bibliothek von DFRobot anders macht, denn diese war bei mir die einzige von allen verfügbaren INA libraries, die dem Sensor vernünftige Werte entlockt hat.

          1. Hallo Martin,

            bei mir funktioniert es. Folgende Bedingungen:

            Wemos D1 mini Board (AZ-Delivery)
            Boardauswahl: ESP8266 Boards (3.1.2) – LOLIN(WEMOS) D1 R2&mini
            Arduino IDE 1.8.19 / 2.1.0 beide probiert
            Sketche: Continuous / Triggered unverändert und mit Wire-Übergabe
            Stromversorgung: 5V / 3.3V beides probiert
            Gemessene Ströme (5V): 0 mA, 1x LED mit ca. 9 mA und 1x Leistungs-LED mit ca. 40 mA

            Stellt sich die Frage, was bei dir anders ist. Wie schon gesagt, schicke mir mal, was der Compiler mitteilt, vielleicht kann ich da etwas herauslesen, z.B. Bibliotheksunverträglichkeiten. Und probiere auch mal Triggered.ino. Ich denke nicht, dass du irgendetwas falsch machst – da kommen irgendwelche Dinge zusammen, die dazu führen, dass es nicht geht. Die Herausforderung ist das herauszufinden. Schwierig, weil ich den Fehler nicht nachvollziehen kann.

            Einmal hatte ich auch einen Aussetzer, war aber ein Wackelkontakt.

            Wenn jemand anderes das hier liest und ähnliche Probleme hat, bitte melden!

            Mehr fällt mir erst mal nicht ein.

            VG, Wolfgang

            1. Hallo Wolfgang,

              also nachdem ich alles neu aufgebaut habe (das gleiche Board wie bei dir, IDE 2.1.0, ESP8266 Library 2.7.4), funktioniert es seltsamerweise 🙂 – sowohl continuous als auch triggered.
              Auch mein eigentliches Projekt: Heltec Board (s.o.) und BME280 und INA219 über TwoWire am gleichen I2C Bus läuft dank deiner Bibliothek super.

              Danke für den Support!
              Martin

              1. Hallo Martin,

                das freut mich. Manchmal passieren halt komische Dinge!

                VG, Wolfgang

  7. Vielen Dank für die ausführliche Darstellung! Prinzipiell klappt bei mir die Verwendung des INA219 (original Adafruit, kein Nachbau) mit einem ESP32. Jedoch schwanken die Messwerte (toggeln bspw. zwischen 16.6 und 17.2 mA recht schnell). Ich messe an einer Pumpensteuerung, die den Pegelstand über einen Drucksensor misst und im Bereich 4mA bis 20mA auch extern zur Verfügung stellt (Klemmen V+, V-) – man kann das auf https://www.lesa.de/pdfs/Betriebsanleitung-PS2LCD.pdf im Abschnitt 7.8 sehen (Klemmen 46, 47). Dadurch habe ich natürlich keinen Einfluss darauf, ob die Last highside oder lowside gemessen wird, weil ich nicht „hinter“ die Klemmen komme und dort auch nicht an deren Stromversorgung komme).

    Die Software:

    setup():
    ina = new Adafruit_INA219(iicAddr);
    ina->begin();

    loop():
    float shuntvoltage = ina->getShuntVoltage_mV();
    float busvoltage = ina->getBusVoltage_V();
    current_mA = ina->getCurrent_mA();
    float loadvoltage = busvoltage + (shuntvoltage/1000);

    und der verwendete Wert ist dann current_mA.

    Ich frage mich, ob ich V- zusätzlich mit GND des INA219/des ESP verbinden sollte, um ggf. die Messung zu stabilisieren? Ich scheue mich davor, das einfach so auszuprobieren und wäre für einen Rat denkbar.

    1. Hallo, ob man V- der Pumpensteuerung mit GND verbinden darf oder nicht, da halte ich mich lieber zurück. Aus meiner Sicht sollten aber ESP, INA219 und Pumpensteuerung dasselbe GND haben. Eine stabile Stromversorgung für den INA219 sollte gewährleistet sein. Ein Kondensator könnte helfen. Wie gut das Ausgangssignal der Pumpensteuerung ist, weiß ich natürlich nicht, aber die Schwankung ist schon Recht hoch. Was vielleicht noch etwas bringt, ist den Messbereich des Ina219 auf 400 mA einzustellen (siehe Adafrit Beispielsketch). Dann kann der INA219 auch bis zu 128 Messwerte mitteln. Leider scheint die Adafruit Bibliothek das nicht implementiert zu haben. Das ist einer der Gründe weswegen ich eine eigene Bibliothek geschrieben habe. Mehr fällt mir dazu im Moment nicht ein.

      1. Hallo Wolfgang,

        vielen Dank für die tolle Lib für den INA219.

        Ich habe für die ersten Tests Dein Beispielprogramm 1:1 übernommen und in meinen UNO geladen.
        Verdrahtet habe ich nach Deinem Schaltplan.
        Soweit ist alles OK, nur die „Bus Voltage“ bekomme ich nicht korrekt. Es wird je nach eingestellter Busrange (BRNG)
        entweder 16,00V oder 32,00V im seriellen Monitor angezeigt.

        Shunt Voltage [mV]: 102.55
        Bus Voltage [V]: 32.00
        Load Voltage [V]: 32.10
        Current[mA]: 1025.50
        Bus Power [mW]: 32816.00
        Values OK – no overflow

        Wenn ich
        busVoltage_V = ina219.getBusVoltage_V();
        schreibe, bleibt der Ausdruck getBusVoltage_V() schwarz. Wird aber fehlerfrei kompiliert.
        Wenn ich
        busVoltage_V = ina219.getBusVoltage();
        schreibe, dann wird der Ausdruck getBusVoltage() rot, genauso wie die anderen get-Anweisungen. Hier bringt
        mir der Compiler eine Fehlermeldung:
        ‚class INA219_WE‘ has no member named ‚getBusVoltage‘; did you mean ‚getBusVoltage_V‘?

        Ist da ein Fehler in der Lib oder mache ich etwas falsch?

        Viele Grüße
        Thomas

        1. Hallo Thomas,

          beim Syntax -Highlighting (also dem „rot werden“) ist mir tatsächlich ein Fehler unterlaufen. Das Syntax Highlighting aktiviert man, indem man der Bibliothek eine Datei namens „keyword.txt“ beifügt, in der man die zu hervorzuhebenden Schlüsselwörter anmeldet. Dort habe ich tatsächlich getBusVoltage anstelle getBusVoltage_V angemeldet. Das fiel mir aber bisher nicht auf, da ich eine weitere Bibliothek (für den INA226) installiert habe, die das Schlüsselwort getBusVoltage_V auch verwendet. Leider liest die Arduino IDE alle keyword.txt Dateien ein die installiert sind, egal ob man sie einbindet oder nicht.

          OK, Fehler ist beseitigt, die Arduino IDE sollte das Update spätestens morgen verfügbar haben (da sind immer ein paar Stunden Verzögerung). Und danke für den Hinweis!

          ABER: Das Syntax-Highlighting hat nichts mit der Funktionalität zu tun. Und ein Fehler in der Bibliothek wäre mir sicherlich schon von mehreren Usern gemeldet worden. Stellt sich die Frage, was falsch sein könnte. Die einzige Erklärung, die ich für dieses Verhalten habe, ist dass der Verbraucher nicht dasselbe GND hat wie der INA219. Dann würdest du immer noch die richtige Shuntspannung messen (weil es die Differenz zwischen V+ und V- ist), aber das Niveau von V+ ggü dem GND des INA219 wäre nicht definiert. Kannst du das mal prüfen?

          1. Servus Wolfgang,

            vielen Dank für Deine schnelle Rückmeldung! Leider konnte ich nicht früher antworten, da mir für weitere Tests mit dem Modul die Zeit fehlte.

            Das Update habe ich kurz nach Deiner Antwort geladen. Das Highlighting funktioniert perfekt. 🙂
            Mein INA219-Modul war aus irgendeinen Grund defekt, somit wurden die Messwerte nicht richtig angezeigt. Mittlerweile habe ich mir ein neues Modul besorgt und siehe da, es funktioniert alles wie es sein soll.

            Nochmals vielen Dank für Deine Hilfe.

            Viele Grüße aus Marktredwitz im Fichtelgebirge
            Thomas

  8. Hi Wolfgang,
    ich lese gerade hier und an anderen Stellen zur Strommessung, aber vorerst nur informativ.
    Zu INA am Wechselstrom: wäre eine Graez-Schaltung in Reihe zum Verbraucher, mit dem INA in der +/- Leitung, nicht eine Möglichkeit? Oder würden die Dioden das Ergebnis verfälschen?
    Hans

    1. Hallo Hans,
      der INA219 misst sklavisch die Spannung, die am Shunt abfällt. Viel Erfahrung mit Wechselstrom habe ich nicht, aber eine Gleichrichterschaltung alleine gibt eine pulsierende Spannung. Wenn man die nicht glättet, dürfte man auch keine stabilen Werte bekommen. Vielleicht geht es wenn man einstellt, dass der Mittelwert aus 128 Messungen genommen wird. Aber ich fange an, zu spekulieren. Habe ich denn dein Frage überhaupt richtig verstanden? Ansonsten kannst du auch nochmal die Diskussion mit Horst anschauen, etwas weiter unten. Besonders der Link am Ende hilft vielleicht weiter.
      VG, Wolfgang

      1. Hm, ich bin inzwischen etwas abgekommen vom INA219 zugunsten der Stromspulentechnik. Aber die Wechselstrommessung über eine Graetzschaltung werde ich irgendwann mal testen. Das muß dann ja auch linear sein!
        Sicher sollte man das Signal glätten, da wäre ein Kompromiß zwischen Reaktionszeit und Kondensatorgröße zu bedenken (nF-Bereich?). Eine zyklische Messung würde für „normale“ Bedürfnisse wohl nicht nötig sein.
        Hans

  9. Hallo Wolfgang,
    ich bin gerade dabei ein Oszilloskop mit einem Microcontroller zu bauen, dabei bin ich auf diesen interessanten Beitrag gestoßen. Ich möchte mit meiner Schaltung das Laden eines Kondensators messen und mir auf dem Seriellen Plotter möglichst eine E-Funktion ausgeben lassen.
    Der Spitzenstrom liegt bei ca. 100mA (24V) und nach 0,1 Sekunde ist der Kondensator geladen bzw. die Messung ist beendet.
    Mir ist nicht ganz klar, ob das überhaupt mit dem INA219 möglich ist, oder empfiehlst du ein anderes Sensormodul.
    Ich würde mich sehr über eine Antwort freuen!
    Grüße Tim

    1. Hallo Tim,

      die schnellste Messung in voller Auflösung benötigt 532 µs, d.h. theoretisch bekommst du in 0.1 Sekunden 188 Messwerte. Dann musst du 400kHz für die I2C Übertragungsrate mit Wire.setClock(400000) einstellen, um auch alle abfragen zu können. Bei 100 mA solltest du eine ausreichende Auflösung bekommen.
      Also: ich bin optimistisch, dass das geht.
      VG, Wolfgang

  10. Guten Tag her Ewald

    ich hoffe sie können mir helfen, ich hab das Problem das wenn ich mehrere INA219 an den Arduino anschließe.
    ich kein Strom Mehr messen kann ich bekomm dann von beiden entweder „inf“ oder „nan“ als Ergebnis.
    Versuchs Aufbau:
    das messen von 2 und 3 Leiter Systemen mit 2leiter = 4-20mA 3leiter = 0-20mA und 3Leiter = 0-10V
    mit 2 lcd Displays.
    1 Arduino Nano 33 IoT
    4 INA219
    2 LCD Displays 16×2
    shunt Widerstand auf 13 Ohm Geändert weil ich Strom im Bereich von 0-24mA messe und eine Genauigkeit von min 1/8% brauche
    ich habe 2 Schalter um zwischen 2 Leiter und 3 Leiter System zu wechseln.

    der Quelltext ist was länger kann ich einfach hier rein kommentieren oder lieber per email ?

    1. Hallo Herr Driesers,

      zunächst würde ich mal prüfen, ob alle INA219 unterschiedliche I2C Adressen haben. Sie können das mit einem I2C Scannersketch prüfen, den gibt es z.B. hier:
      https://wolles-elektronikkiste.de/i2c-scanner

      Wenn das der Fall ist , dann schau ich mir den Sketch gerne an (wolfgang.ewald@wolles-elektronikkiste.de). Vielleicht liegt das Problem bei dem Erzeugen der INA219 – Objekte.

      Im Kommentarbereich gehen die Einrückungen verloren und größer als und kleiner als Zeichen werden teilweise als HTML interpretiert.

      VG, Wolfgang Ewald

  11. Hi!

    Man kann sogar einen ESP-01 verwenden, wenn man in setup Wire.begin(2,0); angibt, für die GPIO Leitungen 2 (SDA) und 0 (SCK), was echt super ist.

    Ich wüsste so gern, wie (*) das mit negativen Spannungen auf V- über GND ist. Du schreibst, man bekommt dann negative Werte angezeigt, wenn man V+ und V- vertauscht, das ist ja auch logisch. Nach dem Blockschaltbild wird ja nur V+ über V- oder V- über GND gemessen, daher könnte (*) ja auch irgendwie funktionieren. Allerdings steht im manual, dass dies nicht erlaubt sei, daher habe ich natürlich Angst, das auszuprobieren. Es wird allerdings auch nicht gesagt, was dann passiert. Erscheint nur overflow oder doch magischer Rauch? Und könntest du raten, warum eine negative Spannung über GND zum Problem wird, wo doch die prinzipielle Messung sowieso differentiell ist?

    Und könntest Du mir ein Modul für Wechselspannungen empfehlen? Ich brauche das jetzt noch nicht, aber später evtl. mal.

    Besten Gruß und danke!

    1. Hi Horst,

      der AC712 ist auch für Wechselstrom geeignet:
      https://wolles-elektronikkiste.de/acs712-stromsensor
      Er ist nur nicht so gut für kleine Ströme von wenigen Milliampere geeignet.

      Du kannst beim INA219 zwar VIN- und VIN+ vertauschen, aber trotzdem müssen die Spannungen an den Pins positiv gegenüber GND sein (oder ganz gering negativ). Steht auch im Datenblatt(7.1 Absolute Maximum Ratings):
      „VIN+ and VIN– may have a differential voltage of –26 to 26 V; however, the voltage at these pins must not exceed the range –0.3 to +26 V“.

      Also besser nicht probieren!
      VG, Wolfgang

      1. Hi Wolfgang!

        Hm, na gut. Leider passt der ac712 nicht zum ESP8266, da dessen adc ungenau und langsam ist. Auch hat der ESP-01 keinen adc pin. Ich hatte aber gelesen, dass der ina219 auch mit negativen Strömen arbeiten kann, ich glaube deshalb hatte ich ihn mir auch besorgt.

        Denkst du, man könnte einfach nur V+/V- nutzen und GND galvanisch vom Meßkreis trennen und dann den 101 Mode verwenden? Dann wäre jedenfalls ich fein raus. Oder müssen beide Kreise unbedingt gemeinsame Masse haben?

        1. Wenn du dir das Blockschaltbild des INA219 anschaust (Figure 13), dann siehst du, dass nicht direkt die Spannungsdifferenz zwischen VIN- und VIN+ gemessen wird, sondern abwechselnd die Spannung zwischen VIN+ und GND und zwischen VIN- und GND. Du brauchst also ein definiertes GND. Und das GND wiederum muss dem GND des MCU entsprechen, da sonst die I2C Leitung nicht funktioniert. Tut mir leid!

          1. Ich hab das so gelesen, dass der PGA 2 Eingänge hat und einen Umschalter (shunt/bus). In der einen Position wird demnach V+/V- gemessen, in der andern V-/GND. Im Mode 101 würde gar nicht mehr umgeschaltet, sondern nur noch Shunt gemessen werden. Jedenfalls habe ich das so verstanden. Und Fig.13 scheint mir das auch so darzustellen. Aber ich werde deine Warnung beachten!

            LG!

            1. Du hast Recht, da hab ich falsch hingeguckt, brauche wohl doch mal eine Nahsichtbrille! Sonst probiere es einfach aus- schlimmstenfalls opferst du einen INA219.

  12. Hallo Wolfgang,

    vielen Dank für den super ausführlichen Beitrag. Ich benutze den Sensor um Perowskit Solarzellen zu charakterisieren. Als ich anfangs alles angeschlossen hatte, hat alles super funktioniert und ich konnte den Strom messen. Ich habe jedoch weiter rumprobiert und seither ein komisches Problem.
    Ich bekommen keine Werte mehr angezeigt, weder Strom noch Spannung. Das komische ist jetzt, wenn ich die beiden Kabel des I2C Anschlusses berühre und festhalte funktioniert es und ich sehe wieder Werte…
    Was kann ich dagegen tun und wieso tritt der Fehler aus heiterem Himmel auf?

    Viele Grüße
    Denis

    1. Hallo Denis, Sachen gibt’s!? Als erstes würde ich einen Wackelkontakt vermuten. Vielleicht ist ein Kabel gebrochen, eine Lötstelle nicht richtig verbunden o.ä.? Eine bessere Erklärung habe ich nicht. Einfach mal neue verbinden? Viel Glück.
      VG, Wolfgang

  13. Hallo Wolle,

    ganz große Klasse! Wirklich gut gemacht. Hat mir richtig Spaß gemacht deine Seite zu lesen und auch selber was zu bauen. Die Beschreibung und Erklärungen sind einfach nur Top, hat mich alles genau da abgeholt wo ich mit meinem wissen stand. Kann nur sagen: vielen Dank und weiter so 🙂

    viele Grüße
    Tim

  14. Hi Wolle!

    Danke für die Bibliothek, funktioniert wirklich perfekt.
    Ich habe damit den INA219 in ein kleines Projekt integriert, das Einlöten des Breakout-Boards dauerte alles in allem um die 15min – die Integration der Lib gerade mal 5… 😉

    Eine Frage hab ich zur maximalen Busspannung von 26V:
    Das Projekt soll später mit einer Busspannung von 24V DC laufen, das ist nach meinem Geschmack schon ziemlich knapp „auf Kante“ genäht. Eine kleine Spitze und der INA219 ist hin?
    Hast Du eine Idee wie man die Spannung effektiv begrenzen könnte damit der INA eine Überlebenschance hat?

    Beste Grüße!

    1. Hallo Christian, brauchst du unbedingt die Leistung oder reicht Dir vielleicht auch einfach der Strom? Denn dann könntest du das INA219 Modul auf der Low-Side einbauen. Für die Strommessung ist nur der Spannungsabfall über dem Shunt relevant und dafür wäre es egal wo man das Modul einbaut. VG, Wolfgang

      1. Hallo Wolfgang und danke für die Antwort.

        Auf der Lowside kann ich das Modul leider nicht einsetzen da die Komponente deren Strom ich messen möchte leider mit einigen anderen Dingen einen gemeinsamen GND-Anschluss hat. Daran kann ich nix ändern und ich kann den INA219 auch nicht dort integrieren.

        Ich werde es einfach erstmal drauf ankommen lassen. Da das verwendete Netzteil ziemlich „amtlich“ daher kommt und auch nirgends induktive Lasten geschaltet werden klappt es vllt. auch so. Ansonsten muss ich eben auf den INA226 ausweichen.

        Ich hätte aber noch eine andere Frage: Derzeit sind zwei INA219 verbaut. Wenn kein „Prüfling“ an meine Schaltung angeschlossen ist fließt logischerweise auch kein Strom, über dem Shunt ist also auch keinerlei Spannung messbar. Trotzdem geben die beiden INAs 0.2mA bzw. 1.5mA aus. Das sind imo schon ziemliche Abweichungen, oder? Kann man dafür auch irgendwo einen Korrekturwert angeben? Muss ich dafür über das Calibration Register gehen?

        Beste Grüße!

        1. Hallo Christian,

          zumindest die 1.5 mA finde ich schon recht viel. Das Problem ist, dass ich nicht weiß wo der Fehler herkommt. Und da ich das nicht weiß, ist es auch schwer zu sagen ob es sich um einen festen Offset handelt, den man ganz schlicht vom Messergebnis abziehen kann oder sich der Fehler mit der Stromstärke ändert. Ich würde mal mit dem Multimeter deines Vertrauens bei verschiedenen Stromstärken messen und schauen ob die Abweichung konstant ist. Wenn sie das ist, dann würde ich die Werte wie gesagt einfach abziehen.

          VG, Wolfgang

  15. Hallo Wolfgang,
    eigentlich bin ich kein Elektroniker (eher Mechaniker) und habe mir nur leichte Grundkenntnisse beigebracht. Jetzt muss ich aber (wegen Kündigung des eigentlichen Elektroniker) ein Einstellgerät bauen mit der man eine Pegelsonde (4-20mA) einstellen kann. Um den mA-Wert zu ermitteln wollte ich den INA219 verwenden. Jetzt habe ich aber folgende zwei Probleme:
    1. der Wert den ich vom INA bekomme ist ca. 1 mA höher als der von meinem Handamperemeter.
    2.der Wert(INA) schwankt um +/- 0,5mA zwischen den Messungen
    Ich habe alles auf einem Arduino aufgebaut und lasse den Wert (nur mA) auf einem LCD-Display ausgeben. Weil das Endgerät als „standalone“, ohne PC laufen muss.

    Gibt es eine Möglichkeit die Schwankungen und die Differenz zu korregieren?

    1. Hallo Thomas,

      um Rauschen zu reduzieren, ist die offensichtlichste Methode die Mittelung mehrerer Messwerte. Mit setADCMode kannst du verschiedene Werte zwischen 2 und 128 einstellen.
      Eine stabile Stromquelle ist auch von Vorteil. Du könntest einen 10 mikroF Kondensator in die Spannungsversorgung setzen.
      Wenn die Abweichung ein fester Offset ist (was ich nicht glaube), also du misst 1 statt 0 mA, 11 statt 10 mA usw., kannst du den Offset ja einfach abziehen. Wenn die Abweichung linear ist, du also z.B. 9.5 mA statt 10 und 95 mA statt 100 misst, dann kannst du mit setCorrectionFactor einen Korrekturfaktor setzen. Solche lineare Abweichung könnte dadurch bedingt sein, dass der Shunt nicht exakt 0.1 Ohm hat.
      Hoffe das hilft!
      VG, Wolfgang

      1. Hallo Wolfgang,
        Danke für die schnelle Antwort. Ja, es hat sehr geholfen! Ich konnte über: setADCMode & setCorrectionFactor die Werte so einstellen das es fürs erste passt. Ich hoffe das die Sonden die mit meinem Einsteller kalibriert werden, die QM-Kontrolle bestehen!

        Vielen Dank
        Thomas

      2. Also bei meinem INA ist es wohl ein Offset. Das könntest du ja noch in deine Lib integrieren 😉 . Das Problem ist nur, Wenn man da Power Register ließt, passt das nicht mehr zu Strom und Spannung. Dann müsste die Leistung aus Strom und Spannung (incl. Offset) errechnet werden. Z.B ist Offset = 0 dann Register lesen und Offest != 0 dann errechnen.
        Laut TI und Datenblatt ist ein kleiner Offset auch normal.

        1. Danke für den Hinweis. Muss ich mal schauen wie ich das am besten integriere und vor allem: wann! Ist auf jeden Fall zumindest auf der To-Do-Liste.

        2. Hallo Martin, hallo Thomas, ist einer von euch marsman7 auf Github? Ich habe gerade heute am offset gearbeitet, die Bibliotheksdateien einschl. Beispielen und keyword.txt angepasst als ich gesehen habe, dass ein Pull Request für den Offset vorliegt. Schlechtes Timing….
          Der Patch passt natürlich auch nicht mehr zum neuen Release. Ich muss mir mal anschauen, ob der Ansatz evtl. besser ist. Tut mir leid. Da hätte sich einer von uns Arbeit sparen können.

  16. Guten Abend! Ein sehr interessanter Beitrag! Ich konnte über das Datenblatt leider nicht herausfinden, was der kleinste messbare Strom ist? Ich möchte die Salinität einer Flüssigkeit über einen Messstrom von ca. 0,3 bis 0,6 mA messen und diesen Strom dann mittels dieses ICs messen und im Arduino auslesen/speichern.

    Würde dies möglich sein?

    Viele Grüße

    1. Hallo,

      das Shuntregister hat eine Auflösung von 10 Mikrovolt, also 0.00001 Volt. Der Shunt hat einen Widerstand von 0.1 Ohm. Damit ist die Auflösung 0.0001 Ampere, also 0.1 Milliampere. Das ist natürlich nicht so doll. Es gäbe die Möglichkeit, den Shunt auszulöten und durch einen größeren zu ersetzen. Z.B. 10 Ohm, dann wäre die Auflösung 100al größer. Eine andere Möglichkeit wäre, einen Stromsensor selbst zu bauen. Das ist nicht besonders kompliziert

      https://wolles-elektronikkiste.de/stromsensor-selber-bauen

      Vielleicht gibt es auch noch Module für kleinere Ströme, da müsste ich aber auch selbst erst einmal recherchieren.
      VG, Wolfgang

      1. Moin moin,

        danke für die schnelle Antwort! Ich werde mir den andern Post gleich mal einverleiben!

        VG

  17. hallo Wolfgang,
    kann ich mit dem sensor den ladestrom eines 12V solarpanels messen? Das solarpanel soll einen 12V akku laden und ich möchte den ladestrom messen. Wie ist es dann im sinne Deiner beschreibung mit der reihenfolge des moduls und des „verbrauchers“? Ich würde rein gefühlmässig den sensor in die plus leitung des panels legen, panel an Vin- und Vin + an den akku anschliessen. Masse würde direkt durchgehen. Richtig?
    Damit es nicht zu einfach wird, kann ich den sensor auch mit einem raspberry zero verwenden, also auch mit hilfe eines python „sketches“ nutzen?

    vielen dank…

    1. Hallo Georg,
      12 Volt sind kein Problem. Nur mehr als 3.2 Ampere gehen nicht, das ist die Begrenzung. Ich würde auch in die Ausgangsleitung des Panels gehen. VIN+ in Richtung des Panels VIN- in die Richtung des zu ladenden Gerätes. Ich weiß nicht ob ich verstanden, habe was du mit „die Masse würde durchgehen“ meinst. Wichtig ist das alles eine gemeinsame Masse hat, sprich GND vom INA219 an die Masse vom Rest der Schaltung. Sonst fehlt der Bezugspunkt.
      Und ja, mit einem Raspberry Zero geht es auch. Der kann auch I2C. Nur brauchst dann eine Python Bibliothek, wenn du dich nicht mit den Innereien des INA219 herumschlagen möchtest. Ich hab mal kurz gegoogelt und das gefunden:
      https://www.rototron.info/raspberry-pi-ina219-tutorial/
      Das müsste sich auf einen Pi Zero übertragen lassen.
      Viel Erfolg! Schöne Grüße, Wolfgang

      1. Wegen der 3,2A max. Strom …
        Das gilt nur für einen 0,1 Ohm Widerstand. Wenn man einen 0,01 Ohm Widerstand nimmt, kann man auch 32A messen, man muss nur den Wert, den man aus dem INA219 ließt mit 10 multiplizieren. Der INA misst ja nur den Spannungsabfall über den Shunt.

        1. Das ist richtig, 3.2 A bezieht sich auf das Modul, das es normalerweise nur mit einem 0.1 Ohm Shunt gibt. Siehe Kapitel: „Andere Shuntgröße wählen“. Zum Zeitpunkt des Kommentars gab es die Funktion setShuntSizeInOhms() noch nicht.

  18. Hallo Wolfgang,
    vielen Dank für die Mühe, einen so ausführlichen Beitrag zu veröffentlichen und dann auch noch auf spezielle Fragen einzugehen!
    Ich habe mich spontan dazu entschlossen, das Modul und Deine Bibliothek für meine mini-Solaranlage einzusetzen, bei der ich die Messdaten mit einem Arduino nano oder ESP32 drahtlos übertragen möchte.
    Eines ist mir jedoch aufgefallen:
    In der Funktionsübersicht steht: „float getCurrent_mV() – delivers current in mV“. Im Scetch findet sich jedoch „current_mA = ina219.getCurrent_mA();“. Müsste nicht Letzteres korrekt sein?

    1. Hello, ja stimmt. Milliampere ist richtig. Das muss ich ändern. Vielen Dank und viel Spaß mit dem Projekt!

  19. Hallo Wolfgang,
    vielen Dank für deine Mühe. Ich habe mit größeren Strömen und verschiedenen Verstärkungen experimentiert.
    Es stimmt, dass am AD-Wandler maximal 40mV verarbeitet werden und der Faktor die Spannung entsprechend dividiert.
    Hier ein Beispiel mit 12v und einer Last von etwa 1,12A. In meinem Fall mehrere LED’s.

    Verschiedene Faktoren mit immer gleicher Last von 1,12A an 0,1 Ohm Shunt
    1. PG_320
    Shunt Voltage [mV]: 112.90
    Bus Voltage [V]: 11.25
    Load Voltage [V]: 11.36
    Current[mA]: 1128.70
    Bus Power [mW]: 12694.00
    Values OK – no overflow
    ConfigReg: 000 11 0011 0011 111

    2. PG_80
    Shunt Voltage [mV]: 80.0000
    Bus Voltage [V]: 11.2760
    Load Voltage [V]: 11.3560
    Current[mA]: 800.00
    Bus Power [mW]: 9020.80
    Values OK – no overflow
    ConfigReg: 000 01 0011 0011 111

    3. PG_40
    Shunt Voltage [mV]: 40.0000
    Bus Voltage [V]: 11.2440
    Load Voltage [V]: 11.2840
    Current[mA]: 400.00
    Bus Power [mW]: 4498.00
    Values OK – no overflow
    ConfigReg: 000 00 0011 0011 111

    Eigentlich erwarte ich bei 80 und 40 overflow.
    Gibt es eine Erklärung???

    1. Ja, die gibt es. Das Datenblatt sagt:

      „The Math Overflow Flag (OVF) is set when the Power or Current calculations are out of range. It indicates that current and power data may be meaningless.“

      Es bezieht sich also nicht auf einen Overflow des A/D Wandlers. Der merkt nicht wenn er das Maximum überschritten hat, sondern gibt schlicht das Maximum an.

      Ich habe das jetzt aber geändert. Wenn das Shunt Voltage Register sein Maximum erreicht, wird nund auch ein Overflow angezeigt.

  20. Hallo Ewald,
    danke für deinen Beitrag zu INA219. https://wolles-elektronikkiste.de/ina219
    Der Code läuft und zeigt den richtigen Strom an, nachdem ich den Widerstand im Code auf 0,1 Ohm geändert habe.
    Die ShuntVoltage ist falsch Ist=8,14mA Anzeige=3,52mV.
    Bei Änderung des Verstärkungsfaktors veräbdert sich nichts.
    Ich versthe nicht welchen Einfluss die
    Verstärkung oder
    V_SHUNT_MAX oder
    I_MAX_EXPECTED oder
    16 oder 32V (evtl Auflösung ohne direkte Erkennung) haben.

    Ausdruck:
    Shunt Voltage [mV]: 3.52 (ist=8,14mV)
    Bus Voltage [V]: 12.15
    Load Voltage [V]: 12.16
    Current[mA]: 35.32
    Bus Power [mW]: 428.80
    Values OK – no overflow

    Ich habe das Config register ausgelesen das stimmt:

    ConfREg=010000110011111 40 + 32V
    ConfREg=011100110011111 320 + 32V
    ConfREg=001000110011111 160 + 16V
    ConfREg=001100110011111 320 +16V

    1. Hallo Herr Krauß,

      Sie schreiben, dass die ShuntVoltage falsch ist, aber der Strom sei korrekt. Und Sie schreiben, dass Sie einen Shunt von 0.1 Ohm verwenden. Im Ausdruck unten ist die ShuntVoltage 3,52 mV und der Strom ist 35,32 mA. Das passt gut zum 0,1 Ohm Shunt. 8,14 mV ShuntVoltage passt hingegen überhaupt nicht rein, denn bei einem 0,1 Ohm Shunt müsste der Strom 81,4 mA betragen. Und das ist keine Frage meiner Bibliothek, sondern einfach Ohmsches Gesetz.

      Die ShuntVoltage ist unabhängig vom PGain. Das ist nicht so leicht zu verstehen und ich musste selbst auch noch einmal nachschauen, wie das funktioniert. Eigentlich „passen“ nur +/-40mV in das Shunt Register (PG_40). Die Auflösung des A/D-Wandlers beträgt +/- 12 Bit = 4096. Ein Bit (LSB) entspricht einer Spannung von 10 µV. Damit ist die Kapazität auf +/- 4096 * 10 µV = ~ +/- 40 mV beschränkt. Das Shunt Register hat 16 Bit. 12 Bit werden für das Ergebnis der A/D-Wandlung benutzt, ein Bit für das Vorzeichen. Drei Bits bleiben ungenutzt. Wenn man nun auf PG_80 wechselt, wird die Spannung auf die Hälfte heruntergeregelt, bevor sie in den A/D-Wandler geht. Um nun aber zu erreichen, dass das LSB weiterhin 10 µV beträgt, wird das Ergebnis der A/D-Wandlung um ein Bit nach links verschoben, sprich verdoppelt. Das Datenblatt sagt:

      „Shunt Voltage register bits are shifted according to the PGA setting selected in the Configuration register (00h).“

      Bei PG_160 wird die Spannung geviertelt, bei PG_320 geachtelt und das Ergebnis der Wandlung um 2 bzw 3 Bit verschoben. Bei PG_320 sind 15 Bit des Shuntregisters durch den Betrag des Ergebnisses belegt und das 16te Bit ist das Vorzeichenbit. Damit ist das Register voll ausgenutzt. Aus diesem Grund wäre mit der Architektur auch kein „PG_640“ möglich.

      Also kurz gesagt: Der PGAIN Faktor – oder besser PGAIN-Teiler – teilt die Spannung und im Shunt Register wird sie entsprechend wieder multipliziert.

      Sie schreiben, dass Sie den Widerstand auf 0,1 Ohm geändert haben. D.h. Sie haben den Sketch SetShuntSize.ino genommen, richtig? Den Sketch sollten Sie nur verwenden, wenn Sie nicht den Standardshunt auf dem Modul oder einen anderen 0,1 Ohm Shunt verwenden. Wenn Sie einen 0,1 Ohm Shunt verwenden, dann bietet sich der Sketch Continuous.ino oder der Triggered.ino an.

      Trotzdem sollte natürlich auch der SetShuntSize.ino Sketch mit 0,1 Ohm funktionieren. Aber damit ich dazu etwas sagen kann, senden Sie mir bitte den Sketch, so wie sie ihn verwendet haben an Wolfgang.Ewald@wolles-elektronikkiste.de. Nur dann kann ich der Sache auf den Grund gehen.

      VG, Wolfgang Ewald

  21. Hallo Wolfgang,

    so wie immer sehr gute Beschreibung und Erklärung.

    Na ja nicht jeder hat englisch gelernt und versteht die Datenblätter trotz guter Übersetzung.
    Meine Frage, ist es möglich mit externen Shunt (100A 75mV) ströme zB. ab 0,25A bis 100A messen ohne das der INA Rauchzeichen sendet ?

    Mein Gedanken ist den PGAIN mit Software vom PG_40 bis PG_320 stufenweise erhöhen bei Wertüberschreitung.
    Auf die Frage warum möchte das – habe im Schrebergarten PV Anlage (240 W + 12V Akku 100Ah). Normal wird der Akku mit 3W belastet aber ab und zu mit 600 bis 1200W.
    Schreibe extra in Watt wegen Akkuspannung in Ampere ist das von 0,25 A bis 100A

    Grüße
    Bernhard

    1. Hallo Bernhard,

      der INA 219 vergleicht nur die Spannung zwischen Eingang und Ausgang des Shunts. Du musst also nur schauen, dass du den Shunt so dimensionierst, dass beim maximalem Strom (also maximaler Shuntspannung) das Shuntregister nicht überläuft. Das Shuntregister misst bis zu ca. 0.32 V. Da sollte mit dem 100A/75mV Shunt also nichts passieren.

      Generell wäre ich aber bei diesen Stromstärken sehr vorsichtig. Wenn irgendwo eine Leitung oder ein Kontakt nicht ausreichend dimensioniert ist, kann das gefährlich werden. Wenn du nicht ganz genau weißt, was du tust, dann lass lieber einen Elektriker drüber schauen.

      Ich übernehme für meine Angaben keine Haftung!

      VG, Wolfgang

  22. Gute Lib! Scheinbar ist der Chip aber nicht ganz zuverlässig. Selbst wenn der Shunt kurzgeschlossen ist oder kein Strom drüberläuft, springt manchmal die Anzeige auf vom 0 auf ca. 100mA. Ist so etwas bekannt? Grüße R.

    Shunt[mV]:-0.01 Bus[V]:0.57 Load[V]:0.57 Curr[mA]:102.50 Bus[W]:59.00
    Shunt[mV]:0.01 Bus[V]:0.58 Load[V]:0.58 Curr[mA]:102.50 Bus[W]:59.00
    Shunt[mV]:0.00 Bus[V]:0.57 Load[V]:0.57 Curr[mA]:102.50 Bus[W]:59.00
    Shunt[mV]:0.00 Bus[V]:0.57 Load[V]:0.57 Curr[mA]:-0.10 Bus[W]:0.00
    Shunt[mV]:-0.01 Bus[V]:0.58 Load[V]:0.58 Curr[mA]:102.50 Bus[W]:59.00
    Shunt[mV]:0.00 Bus[V]:0.57 Load[V]:0.57 Curr[mA]:-0.10 Bus[W]:0.00
    Shunt[mV]:0.00 Bus[V]:0.58 Load[V]:0.58 Curr[mA]:-0.10 Bus[W]:0.00
    Shunt[mV]:-0.02 Bus[V]:0.57 Load[V]:0.57 Curr[mA]:102.50 Bus[W]:59.00

    1. Das ist eigenartig weil der Strom aus der Shuntspannung berechnet wird und die Shuntspannung sehr konstant um Null herum schwankt. Verwendest du den Standardshunt des Moduls? Auffällig ist auch, dass wenn es hoch geht, der Wert immer genau 102.5 mA ist. Kannst du mir deinen ganzen Code mal schicken? An Wolfgang.Ewald@wolles-elektronikkiste.de, dann schaue ich mal, wie mein Modul damit läuft.

  23. Ich muss den Thread noch mal anwärmen…
    Ich nutze alle wie oben beschriebne und und es funktioniert für mich auch wunderbar.
    Nur bin ich auf ein kleines Problem gestoßen.
    Ich nutze an meinem Arduino der den INA abfragt und die werte auf einem Display ausgibt auch ein paar Kontroll LEDs. Diese sind so angesteuert das die im Idle Modus Flackern sollen.
    Der INA219 wird alle 2 Sek. abgefragt und genau dann stoppen die LEDs das Flackern für ca. eine halbe Sek.
    Ich hab in der LIB leider nichts finden können was dies auslöst.
    Oder hat das einfach mit der Übertragung zu tun? Das er sozusagen wartet bis er die werte alle hat?

    Gruß Richi

    1. Hi Richi, die Abfrage der Register selbst geht sehr schnell. Wenige Millisekunden, wenn überhaupt. Die Zeit, die die Konversion braucht, hängt davon ab, wie viele Werte du mittelst. Aber selbst bei dem Maximum bist du bei 68 ms. Und wenn du im Continuous Modus arbeitest, dann spielt auch das keine Rolle, weil er die Werte nimmt die gerade in den Ergebnisregistern vorhanden sind. Also für eine halbe Sekunde habe ich keine Erklärung.

      Vielleicht kannst du Zeit für die Abfrage mal messen? Ein millis direkt vor der Abfrage und ein millis dahinter. Sonst kannst du mir deinen Sketch mal schicken (wolfgang.ewald@wolles-elektronikkiste.de), vielleicht fällt mir ja etwas auf. VG, Wolfgang

  24. Hallo Wolfgang,
    die „ina219.init()“ ist ein boolean !
    Das finde ich prima.
    Für mich ist es immer wichtig bei der Initalisierung eine Rückmeldung der Hardware zu bekommen.
    Das kann viel Zeit ersparen.
    Super Arbeit , da bleibt kein Auge Trocken.

    Andreas

    1. Stimmt! Vielen Dank, das muss ich mal in der Funktionsliste ändern.

      Update: erledigt.

  25. Hallo,
    erst einmal vielen Dank für die ausführliche Beschreibung!
    Ich habe den zur Verfügung gestellten Code auf meinem ESP8266 geladen, den INA219 entsprechend verkabelt, aber ich bekomme immer keine Werte:

    21:40:06.782 -> Shunt Voltage [mV]: 0.00
    21:40:06.782 -> Bus Voltage [V]: 0.00
    21:40:06.828 -> Load Voltage [V]: 0.00
    21:40:06.828 -> Current[mA]: nan
    21:40:06.828 -> Bus Power [mW]: 0.00
    21:40:06.874 -> Values OK – no overflow

    Ich habe schon ESP8266 und INA219 getauscht, trotzdem komme ich nicht weiter.

    Die Verkabelung sieht wie folgt aus:
    ESP8266 INA219
    D1 –> SLC
    D2 –> SDA
    VIN –> VCC
    G –> GND

    Der Verbraucher (ein 12V USB Ladegerät) ist wie folgt mit dem INA219 verkabelt:
    +12V (vom Netzteil) –> Vin+
    Vin- –> Plus vom besagten USB Ladegerät

    Masse vom Netzteil geht an Masse vom USB Ladegerät.

    Der INA hängt also in der Plus-Leitung vor dem Verbraucher.

    Hat noch jemand eine Idee, wo der Fehler liegt?
    Das ist nach der Spannungsmessung ueber den analogen Eingang mein erstes Projekt, also kann es sehr gut sein, dass ich etwas grundlegendes vergessen habe

    Ich habe einfach nur einen Weg gesucht, die Spannung einer 12V Batterie zuverlaessig zu messen, da mir die Schwankungen bei der analogen Messung zu gross waren, fiel die Wahl auf den INA219. Leistungsmessung brauche ich eigentlich nicht, bin also fuer Alternativen offen

    1. Hallo, du wirfst ein bisschen Strom und Spannung durcheinander in deiner Anfrage. Nur nochmal zur Klarstellung: der INA219 ist ein Strom- und kein Spannungssensor. Er misst den Strom durch einen Spannungsabfall über den Shunt. Hast du denn auch was zum Laden am Ladegerät während der Messung? Sonst fließt natürlich kein Strom. Allerdings solltest du trotzdem eine Busspannung messen. Und auch sonst klingt alles erstmal richtig. Du schreibst, dass Ladegerät und Netzteil eine gemeinsame Masse haben. Ist auch GND des INA219 an der Masse? Das ist wichtig, sonst funktioniert es nicht. Das wäre mein Favorit bei den möglichen Fehlern. Wenn das auch nicht der Fehler ist, dann vielleicht noch eine Stufe tiefer: hast du überhaupt ein funktionierende I2C Verbindung zum INA219? Mit dem I2C Scanner Sketch könntest du das prüfen:
      https://wolles-elektronikkiste.de/i2c-scanner
      Melde dich nochmal, wenn du nicht weiterkommst. Dann muss ich mir noch mehr Gedanken machen.

      1. Hallo Wolfgang,
        danke fuer deine schnelle Antwort!

        GND des INA219 auf Masse zu legen hat leider nichts gebracht, das Problem liegt auch scheinbar woanders!
        der I2C Scanner gibt mir folgendes zurueck:
        17:41:47.527 -> Scanne im standard mode (100 kHz):
        17:41:47.575 -> Keine Adresse erkannt
        17:41:47.575 ->
        17:41:47.575 -> Scanne im fast mode (400 kHz):
        17:41:47.575 -> Keine Adresse erkannt
        17:41:47.622 ->
        17:41:47.622 -> ****************************
        17:41:47.670 ->
        17:41:50.530 -> Scanne im standard mode (100 kHz):
        17:41:50.576 -> Keine Adresse erkannt
        17:41:50.576 ->
        17:41:50.576 -> Scanne im fast mode (400 kHz):
        17:41:50.624 -> Keine Adresse erkannt
        17:41:50.624 ->
        17:41:50.624 -> ****************************

        was kann ich noch tun?

        Vielen Dank!

        1. Die gute Nachricht ist, dass das das Problem eingrenzt. Hast du Pull-up Widerstände für die I2C Leitungen verwendet? Wenn nicht, dann probiere das mal.

          1. Habe jetzt einen ESP32 anstatt des ESP8266 verbaut. Jetzt funktioniert alles einwandfrei! Vielen Dank für die Hilfe!

  26. 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

      1. Hallo,
        Gibt es schon Neuigkeiten, wann der Shunt Widerstand in der Bibliothek geändert werden kann?

        Liebe Grüße

        Felix

  27. 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.

  28. 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

  29. 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“?

Schreibe einen Kommentar

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