INA 219 - Strommessung

Dieses Thema im Forum "Hardware" wurde erstellt von achim S., 9. April 2018.

  1. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Hallo Gemeinde
    Bin gerade dabei eine Strommesung mit dem INA219 aufzubauen. Das Modul für mein System ist fertig und möchte in Betrieb gehen. Das Datenblatt aheb ich schon "studiert". Leider gibt es zahlreche Probleme damit. So z.B. das einstellen der Register, welches Register für was, auslesen der 16 Bit Werte, Kalibrierung usw.
    Kennt jemand ein gutes Tut dazu oder Anleitung. Vielleicht auch ein kleines Beispiel in C (nicht Arduino) zum testen und lernen. Bin für jede Hilfe dankbar.

    achim
     
  2. Dirk

    Dirk Administrator
    Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.198
    Zustimmungen:
    119
    Punkte für Erfolge:
    63
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Für alle, die mal schnell in das Datenblatt reinschauen möchten ...
    INA219 Datasheet
     
  3. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Sorry, hatte ich ganz vergessen.
    Danke Dirk
     
  4. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Hmm...
    bisher hat Dir keiner helfen können - ich selbst kenne den IC nicht.
    Was hat Dich denn bewogen, Dich mit genau diesem zu beschäftigen?

    Von null(!) anfangend wären meine(!) ersten Schritte:
    • Kommunikation via I²C - antwortet der IC mit einem ACK auf seine Adresse?
    • Auslesen des Configuration Registers (Adresse 0x00). Sollte nach dem PowerUp 0x0399 sein
    • Mode auf Bus Voltage Continous setzen
    • Bus Voltage Register (wiederholt) lesen (Ergebnis ausgeben lassen)
    Welche Erfolge konntest Du denn bereits erzielen?
    Anmerkungen:
    • der IC besitzt 6 (16bit-)Register (Configuration, Ushunt, Ubus, Pshunt, Ishunt, Calibration)
    • der Schreib-/Lesepointer inkrementiert nicht - einmal gesetzt sollte(!!) sich auf dasselbe Register also wiederholt zugreifen lassen.
    • (welchen Wert dieser Pointer nach dem PowerUp besitzt, ist mir(!) nicht klar (habs nicht gefunden) - im Zweifelsfall also immer erstmal schreiben.
    • Beschreiben kannst Du eines (der beiden beschreibbaren) Register in einem Rutsch (also SLA+W, Register-Adresse, DataMSB, DataLSB) - beim Lesen kann nur das, durch den Pointer referenzierte Register gelesen werden (mit SLA+R, DataMSB, DataLSB)
    • nach dem Schreiben eines Registers benötigt der IC 4µs, um die Werte zu übernehmen.
    Wenn bis hier die generelle Kommunikation klar ist, kann man sich mit den Einstellungen im Configurations- und Calibrationsregister auseinandersetzen...
     
    #4 LotadaC, 10. April 2018
    Zuletzt bearbeitet: 10. Mai 2018
  5. addi

    addi Mitglied

    Registriert seit:
    2. September 2013
    Beiträge:
    107
    Zustimmungen:
    4
    Punkte für Erfolge:
    18
    Sprachen:
    BascomAVR, C, Assembler
  6. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Hallo
    Danke für eure Antworten.
    In Arduino Kreisen soll dieser IC sehr weit verbreitet sein. Vom Hersteller gibt es auch ein Demo dazu. Im gesamten Netz beziehen sich alle darauf. Es gibt aber so gut wie keine Erklärung oder so was dazu. Du hast das Datenblatt gut zitiert. Am meisten gefällt mir an diesem IC das er einen so weiten Bereich (relativ) hat. Vom Aufbau und Anwendung passt er sehr gut in mein System. Damit kann ich dann endlich messen warum manche Module an der Grenze arbeiten. Ist mir schon klar das 256 LEDs einiges an Strom brauchen. Aber wieviel zieht ein 3,2 Zoll TFT Farb Display? Das weiteren sind die Register. Möchte lernen damit zu arbeiten und die 16 Bit Wörter zu lesen und zu verarbeiten. Ist allerdings ein recht grosser Umfang.
    Der eigentliche Aufbau des ICs ist für Baster schwer zu händeln, da kam mir der Aufbau des Hersteller ganz recht.
    - Die Hardware ist komplett aufgebaut und läuft korrekt
    - Der IC kann mit einem Bus Scanner die Adresse ausgelesen werden
    - der I2C läuft also ohne Probleme. Benutze die Dateien von Peter die sich seht bewährt haben
    Leider funktioniert das setzen der Register nicht und es kommen keine Werte zurück.
    Habe einen Artikel aus dem englischen gefunden, der die komplette Berechnung erläutert. Ist sehr gut beschrieben. Kenne keinen anderen IC (in dieser Art) der eine Kalibrierung zulässt.
    Habe mir die Dateien von Henry runter geladen und werde sie auseinander nehmen. das Problem liegt auch in diesen Dateien. Sind in C++ geschrieben und der Rückbau auf nur C fällt mir halt schwer.
    Wieder bin ich bei der Kalibrierung. Habe nichts in den Dateien dazu gefunden (übersehen?)
    Daher bin ich sehr dankbar für jede Hilfe dazu

    achim
     
  7. addi

    addi Mitglied

    Registriert seit:
    2. September 2013
    Beiträge:
    107
    Zustimmungen:
    4
    Punkte für Erfolge:
    18
    Sprachen:
    BascomAVR, C, Assembler
    hmmm...glaube nicht, das es schwierig werden könnte.
    schau dir einfach die werte an, die diese lib in die Register reinschiebt.
    integer etc bleiben gleich, da solltest du drauf abheben.
    wo werden die variabeln mit welchen werten versehen und wo werden diese hingeschoben?
    73 de addi
     
  8. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Damit bist Du Dir bezüglich der Hardware und der Adresse sicher. Wäre also zu klären, warum Du mit der Bibliothek nicht hinkommst.
    Wie gesagt - mein(!) nächster Schritt wäre, erstmal das Konfigurationsregister lesen zu lassen, und zwar mit der final zu verwendenden Leseroutine. Wenn möglich unter Verwendung eines Logicanalyzers.
    Zum auslesen mußtest Du übertragen lassen:
    Startcondition
    SLA+W
    0x00
    Stopcondition

    Um den Pointer auf das Konfigurationsregister zu setzen, dann mindestens 4µs warten, und dann übertragen lassen:
    Start
    SLA+R
    8 Clock-Strobes
    8 Clock-Strobes
    Stop

    Also die Strobes als ein Byte lesen.

    Für Euch C-ler mag es natürlich sinniger sein, 'ne vorhandene, funktionierende(!) Bibliothek "auseinanderzunehmen" - ich könnte mich nur bemühen(!), das mithilfe des Datenblattes komplett selbst zu erarbeiten...
    In C oder Arduinesisch arbeite ich mich nicht ein...;)
     
  9. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Seite 16, Figure 15 & 16. Es muß immer zuerst geschrieben werden.
    (Welchen Bezug das jetzt zu Figure 19 hat ist mit nicht klar)

    Die Register 1 bis 4 können nur gelesen werden, also muß man wohl nach schreiben der Adresse und des Registerpointers einen Repeated-Start ausführen um dann das jeweilige Register zu lesen.
    Das ist wohl nur bei höheren Übertragungsraten relevant, bei 100 kHz dauert ein Bit ja schon 10µs.
    (Edit: Steht ja auch im Datenblatt: when using SCL frequencies in excess of 1 MHz)

    Es empfiehlt sich, nach der Initialisierung zuerst das Bus Voltage Register (02) zu lesen, weil es das Conversion Ready Bit enthält.
     
  10. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Und nochmal genauer:
    Beim Schreiben (SLA+W) ist das erste gesendete Byte (nach SLA+W) immer der (neue) Pointer; ein eventuell folgendes Word wird in das damit referenzierte Register geschrieben.
    Beim Lesen hingegen wird sofort nach dem SLA+R gelesen, und zwar das Register, wo der Pointer grad hinzeigt. Soll ein anderes Register gelesen werden, muß vorher der Pointer umgeschrieben werden, sonst kannst Du aber das Register beliebig oft lesen (ohne den jedesmal Pointer neu zu schreiben).
    Der Pointer besitzt wie gesagt kein Autoinkrement/-dekrement.
    Streng nach dem Datenblatt muß also der Pointer vor dem ersten Lesen beschrieben werden - aber irgendwohin sollte der Pointer ja nach dem Powerup zeigen. Möglicherweise auf irgendwas zufälliges, möglicherweise 0x00. Mich würde übrigens nicht wundern, wenn da sogar nur die minderwertigsten drei Bit relevant sind.
    Ich denke, daß damit
    gemeint ist...
    Jedes Register kannst Du lesen, indem Du erst den Pointer auf die Adresse setzt (Start, SLA+W, Adresse, Stop) und danach das Register liest (Start, SLA+R, Readbyte, Readbyte, Stop).
    Zum repeatet Start gibt es keine Figure, aber auf Seite 14/15 findet sich:
    Den Start nach dem Pointer schreiben könnte man auch als repeated start verstehen - Stops werden ja leider nicht weiter erwähnt. Möglicherweise muß aber vor dem Start wirklich'n Stop kommen, also zwei Telegramme...
    Zu den 4µs: achim hat nicht geschrieben wie schnell er unterwegs ist. Die Länge der Pause soll mindestens 4µs betragen. Wenn die bereits durch das Protokoll gesichert sind, klar. Aber grundsätzlich stört 'ne längere Pause nicht, und achim will erstmal überhaupt was lesen...
    (wobei das eh nur die Übernahme der gesendeten Werte in die beschreibbaren Register betrifft.)
    Wenn das Konfigurationsregister erfolgreich ausgelesen werden konnte, würde ich als nächstes das Kalibrationsregister lesen (0x00 wäre zu erwarten), anschließend mit irgend'nem anderen Wert beschreiben, und diesen dann zurücklesen lassen...
     
  11. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    274
    Zustimmungen:
    21
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Spielt im Prinzip keine Rolle. Um irgendwas sinnvolles mit dem Teil anzufangen (es interessieren üblicherweise wenigstens der Strom und oft auch noch die Leistung), müssen eh zuerst das Calibrationregister und meistens auch noch das Configurationregister beschrieben werden.

    Das mit Figure 19 ist wohl ein Druckfehler. Auf Seite 14 steht schon:
    In Figure 18 wird nach dem Registerpointer ein Stop gesendet. Wird wohl beides gehen. Wenn kein Stop gesendet wird, wird Start als Repeated Start angesehen und anschließend wird sowieso die Adresse mit R-Bit (R/W = high) gesendet und dann werden die beiden zu lesenden Bytes empfangen.
    Nein, aber vermutlich nicht mit mehr als 1MHz. Denn dazu müßte er erstmal in den High-Speed-Mode umgeschaltet haben. ;)
     
  12. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Haloo an alle
    Erst mal die gute Nachricht, das Teil mit INA219 läuft ohne Probleme. Kann bereits den Strom (über Shunt) und die Spannung auslesen. Eine vergleichende Messung aber ergeben das es Abweichungen von bis zu 20% gibt. Die Messung der Leistung ist nicht möglich bzw. bringt immer eine 0. Im Teil 8.6 in der Tabelöle ich unter 2 angebeben das erst die Grösse des Shunts eingegeben werden muss. Es ist auch eine Formel angegeben (8.5.1). Das rechnen ist kein Problem. Doch wo muss das Ergebnis eingegeben werden. Das mit dem Auslesen der 16 Bit und das Berechnen klappt soweit. Mache es so:


    CodeBox C und C++
    // Spannungsmessung
           i2c_start(adr_ina219);                   // Angabe Adresse
           i2c_write(0x02);                       // Register Spannung
           i2c_stop();
           i2c_start(adr_ina219 +1);               // Auslesen Adresse + 1
           msb_spannung = i2c_readAck();           //...speichere oberes Bit
           lsb_spannung = i2c_readNak();           //...speichere unteres Bit
           i2c_stop();
           spannung_wrd = (msb_spannung << 8 | lsb_spannung);  // Zusammensetzung von o. & u. Byte
           spannung_anz = spannung_wrd / 2;       // Wert Spannung / 2
    

    ist zwar ein bisschen umständlich und geht auch einfacher. Kommt alles noch.
    Doch wie und wo gebe ich das Ergebnis der Rechnung ein und wie mache ich das Kalibrieren? (Schreiben einer 16 Bit Zahl und Position im Register)

    LG Achim
     
  13. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Wie genau meinst du das?
    Du kannst dir doch eine Funktion schreiben, der übergibst du den "AD - Wert" und lässt entweder diese Funktion in einen "globalen Puffer" schreiben oder lässt dir dieses Ergebniss zurück liefern.

    Meinst du den "kalibrations Ablauf" oder das errechnen der Offset Werte?
     
  14. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Eigentlich mußt Du doch bis hier gar nicht rechnen. Der Sensor liefert die Shunt-Spannung als binäre 16bit-Zahl. Negative Zahlen zusätzlich im Zweierkomplement. Das ist nichts anderes als ein vorzeichenbehafteter 16bit-Integer. (wobei das letzte Bit 10µV entspricht)

    Die AVR arbeiten grundsätzlich mit 8 Bit. Ob ein Byte als vorzeichenloses Byte, vorzeichenbehaftetes Byte, ASCII, Teil eines Words, Integers, Strings, single,... ist, ist Sache der Verwendung. In einer Hochsprache weist Du der Variable deswegen einen Variablentypen zu, damit der Compiler(!) weiß, welche Instruktionen er verwenden soll.
    Alles was keinem Byte entspricht, setzt der Compiler also aus (ggf mehreren) Byte(s) um/zusammen. Einen vorzeichenbehafteten 16bit-Integer (Int16 ? ) also aus zwei Bytes.

    Du müßtest also nur einen 16bit-Integer allokieren, und dem oberem Byte das erste empfangene Byte zuweisen, dem Unteren das Zweite.

    Du hast in etwa folgendes:
    Du willst eine zweistellige Dezimalzahl von mir empfangen, und die in ein Heft schreiben (linke Seite Zehner, rechte Seite Einer). Ich kann Dir die Ziffern aber nur nacheinander schicken. Ich sende also 'ne "4" als Zehner. Du legst die Temporär ab. Ich sende 'ne "2". Du legst die temporär ab.
    Jetzt rechnest Du 10*4+2=42 (meinetwegen schiebst Du die 4 auch eine Dezimalstelle nach links und addierst 2 -> 42). Dann läßt Du das in Dein Heft schreiben - dabei wird das wieder in Zehner und einer zerpflückt, der Zehner ("4") landet auf der linken, der Einer ("2") auf der rechten Seite...

    Du könntest nach dem Empfang der "4" (Zehner) diese aber auch gleich auf die linke Seite (=high) schreiben, die "2" (Einer) auf die rechte (=low). Ohne zu rechnen.
     
  15. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Das Problem liegt in der Leistungsmessung. Strom und Spannung wird angezeigt. Später möchte ich auch die Register dazu einsttellen und den Messbereich einzuängen.
    Nach dem Datenblatt wird das Register für die Leistungsmessung mit 0 vorbelegt. Dadurch kommt nur eine 0 bei der Abfrage raus. Im Datenblatt steht auch, das ich erst den R Shunt angeben muus und dazu steht eine Formel drin. Das Ergebnis muss in das Konfigurationsregister eingetragen werden. Unterschiedliche Bereich habe ich nach den Angaben gemacht. Beispiel

    0000 00x1 1101 1111
    16V, 40mV, 12 Bit, 8 Samples, Mode

    0011 10x0 0110 1111
    32V, 320mV, 9 Bit, 32 Samples, Mode

    Dies Angaben muss ich ins Konfi Register schreiben. Wen ich mich nicht verlesen habe muss die Berechnung bzw. Angabe der Werte darauf berechnet werden. Wie übertrage ich diese Zahl ins Register 00?
    Dann kommt noch die Berechnung des Cali.. Register

    LG achim
     
  16. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    @achim S.
    Du musst also 2 Bytes ins Konfigurationsregister schreiben, richtig?

    Du schreibst dir jetzt einfach eine Funktion die entweder jeweils 2 Bytes ( uint8_t ) oder ein Word ( uint16_t ).
    Dann baust du dir entweder mit einem Makro oder co. ein Kommandowort.

    Oder du benutzt eine Struktur.

    Bsp.:



    CodeBox C und C++
    typedef struct
    {
    uint8_t samples :1;
    uint8_t mode :4;
    usw.
    }ina219_t;
    
    typedef union
    {
     ina219_t cnfg;
    uint8_t all;
    }ina219_u;
    
    ina219_u ina219;
    
    // Konfiguriere Mode
    ina219.cnfg.mode = WAS_AUCH_IMMER
    
    uint8_t writeCnfgReg( ina219_u *cmd )
    {
    // schreibe die Daten in das Register, I2C oder co.
    i2c_write( cmd.all );
    }
    
     
  17. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Dein Code ist leider in C++. Das klappt nicht bei mir. Hatte s jetzt so gemacht. Zeigt zwar keine Fehler, geht aber auch nicht.


    CodeBox C und C++
    #define con_var 0x386F
    
    i2c_start(adr_ina219);                   // Angabe Adresse
       i2c_write(0x00);                       // Register Spannung
       i2c_write(con_var >> 8);                       // Register Spannung
       i2c_write(con_var & 0xFF);                       // Register Spannung
       i2c_stop();
    

    Da scheint was nicht zu stimmen

    achim
     
  18. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Das ist C und kein C++.

    Probiere lieber mal..



    CodeBox C und C++
       i2c_write( (con_var & 0xFF00) >> 8);                       // Register Spannung
       i2c_write( con_var & 0x00FF )
    


    Habe es gerade getestet. So funktioniert es.


    CodeBox C und C++
    typedef struct
    {
       uint8_t samples :1;
       uint8_t mode :4;
    }ina219_t;
    typedef union
    {
         ina219_t cnfg;
       uint8_t all;
    }ina219_u;
    ina219_u ina219;
    
    uint8_t writeCnfgReg( ina219_u *cmd )
    {
       printf("%d", cmd.all );
    }
    
     
  19. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    401
    Zustimmungen:
    6
    Punkte für Erfolge:
    18
    Sprachen:
    C
    Bei diesem Code bekomme ich keine Fehlermedung



    CodeBox C und C++
    i2c_write( (con_var & 0xFF00) >> 8);                       // Register Spannung
    i2c_write( con_var & 0x00FF )
    

    das andere Stück ist mir von der Funktion nicht klar. Du vrwendest hier union. Da muss ich es^rst mal das Buch befragen.
    Habe das andere eingegeben. Hatte vorher nach DB studiert und die Zahle rausgesucht. Leider hat das in der Anzeige keinerlei änderung zur Folge. vollkommen unklar
    Es soll ein 16 Bit wort übertragen werden auf das Register Null. Das 16 Bit Wort wird zerlegt in 2 x 8 Bit und nacheinadner übetragen.

    achim
     
  20. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.282
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C, C#
    Kannst du denn nach einem POR folgenden Wert ermitteln "0x399F" ?
     
  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)
  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren und die Seite optimal für dich anzupassen. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden