Messen mit MCP3426 (16-Bit AD-Wandler mit I2C-Bus)

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Messen mit MCP3426 (16-Bit AD-Wandler mit I2C-Bus)

      Hallo

      Ich versuche hier einen in einem Gerät fix verbauten MCP3426 per I2C-Bus anzusprechen -
      besser gesagt zum Spannung und Strom messen zu bewegen.

      Hierfür habe ich mir eine Include-Datei gebastelt:

      BASCOM-Quellcode

      1. ' Modul: MCP3426inc
      2. ' Status: Bearbeitung
      3. ' Beschreibung:
      4. ' Messung von Strom und Spannung am Prüfling über ADC-Baustein MCP3126.
      5. ' - 2-Kanal AD-Wandler mit 16 Bit auflösung
      6. ' - Gain 1x, 2x, 4x und 8x
      7. ' - interne Referenz = 2,048V
      8. '
      9. ' Kanal 0 = Spannung
      10. ' Kanal 1 = Strom
      11. ' --------------------------------------------------------
      12. ' Konstanten
      13. ' --------------------------------------------------------
      14. Const AD_DEVICE_WRITE = &b1101_0000 ' Device-Adresse Schreiben
      15. Const AD_DEVICE_READ = AD_DEVICE_WRITE + 1 ' Device-Adresse lesen
      16. ' Channel-Bits
      17. Const AD_CH0 = &b0000_0000 ' Channel 0
      18. Const AD_CH1 = &b0010_0000 ' Channel 1
      19. ' Gain-Bits
      20. Const AD_GAIN_1 = &b0000_0000 ' Gain x1
      21. Const AD_GAIN_2 = &b0000_0001 ' Gain x2
      22. Const AD_GAIN_4 = &b0000_0010 ' Gain x4
      23. Const AD_GAIN_8 = &b0000_0011 ' Gain x8
      24. ' --------------------------------------------------------
      25. ' Interne Variablen
      26. ' --------------------------------------------------------
      27. Dim AD_Buffer(3) as Byte
      28. Dim AD_Value as Integer at AD_Buffer(_base) Overlay
      29. ' --------------------------------------------------------
      30. ' Deklarationen
      31. ' --------------------------------------------------------
      32. Declare Function AD_Check() as Byte
      33. Declare Sub AD_StartConversation(Byval Channel as Byte , Byval Gain as Byte)
      34. Declare Function AD_ReadValue() as Integer
      35. ' --------------------------------------------------------------------------------------
      36. Goto Modul_MCP3426_Exit
      37. ' --------------------------------------------------------------------------------------
      38. ' Sub MCP_Init()
      39. ' End Sub
      40. Function AD_ReadValue() as Integer
      41. Local ErrCount as Byte
      42. ErrCount = 100 ' Anzahl Leseversuche, bis RDY=0
      43. I2CStart
      44. I2CWByte AD_DEVICE_READ ' Adressieren zum Lesen
      45. I2CRByte AD_Buffer(_base + 1) , Ack
      46. I2CRByte AD_Buffer(_base + 0) , Ack
      47. Do
      48. I2CRByte AD_Buffer(_base + 2) , Ack
      49. If AD_Buffer(_base + 2).7 = 0 then Exit Do
      50. Decr ErrCount
      51. Waitms 5
      52. Loop Until ErrCount = 0
      53. I2CRByte AD_Buffer(_base + 2) , NAck
      54. I2CStop
      55. If ErrCount = 0 then ' Fehler, keine Versuche mehr
      56. AD_ReadValue = -100
      57. Exit Function
      58. End If
      59. ' Messwert auslesen
      60. I2CStart
      61. I2CWByte AD_DEVICE_READ ' Adressieren zum Lesen
      62. I2CRByte AD_Buffer(_base + 1) , Ack
      63. I2CRByte AD_Buffer(_base + 0) , Nack
      64. I2CStop
      65. AD_ReadValue = AD_Value ' Messwert an Aufrufer
      66. End Function
      67. ' --------------------------------------------------------
      68. ' Startet eine Einzelmessung mit 16Bit Auflösung
      69. ' --------------------------------------------------------
      70. Sub AD_StartConversation(Byval Channel as Byte , Byval Gain as Byte)
      71. Local cfgByte as Byte
      72. ' Configurations-Byte zusammensetzen
      73. cfgByte = &b10001000 ' Start-Conversation Single, 16 Bit
      74. cfgByte = cfgByte or Channel ' Kanal hinzufügen
      75. cfgByte = cfgByte or Gain ' Gain hinzufügen
      76. Locate 1 , 11 : Lcd bin(cfgByte)
      77. I2CStart
      78. I2CWByte AD_DEVICE_WRITE ' Adressieren
      79. I2CWByte cfgByte ' Conversation starten
      80. I2CStop
      81. End Sub
      82. ' --------------------------------------------------------
      83. ' Prüft, ob der Baustein MCP3426 am Bus antwortet.
      84. ' Rückgabe: True bei Antwort, sonst False
      85. ' --------------------------------------------------------
      86. Function AD_Check() as Byte
      87. I2CStart
      88. I2CWByte AD_DEVICE_WRITE ' Adressieren zum Schreiben
      89. I2CStop
      90. If Err = 0 then
      91. AD_Check = True
      92. Else
      93. AD_Check = False
      94. End If
      95. End Function
      96. ' --------------------------------------------------------------------------------------
      97. Modul_MCP3426_Exit:
      98. ' --------------------------------------------------------------------------------------
      Alles anzeigen

      Im Hauptprogramm wird die Hardware-TWI initialisiert.

      Dann versuche ich mit folgendem Code eine Spannung (Kanal 0) zu messen.

      BASCOM-Quellcode

      1. Call AD_StartConversation(AD_CH0 , AD_GAIN_1)
      2. tmpInteger = AD_ReadValue()
      3. Locate 2 , 2 : LCD "U: " ; tmpInteger
      In Variable tmpInteger sollte nun der ADC-Wert des MCP3426 enthalten sein.

      Als Ergebnis bekomme ich stets den Wert -1.

      Per Function AD_Check() reagiert der Baustein am I2C-Bus. Also ist Bus und IC soweit OK.

      Kann mir jemand sagen, was ich falsch mache?
    • Hallo Oskar

      Am Timing kann es eher nicht mehr liehen. Ich habe schon 2 Varianten versucht.

      Variante 1:
      Zum Einen die Conversation anzustoßen und dann 200ms warten, bevor ich auslese. Das hat nicht funktioniert, Ergebnis -1 ($FFFF).

      Variante 2:
      Zum Anderen strikt nach Anleitung. Da wird die Conversation auch angestoßen und danach gleich die Daten samt dem Config-Register ausgelesen.
      Man bekommt nach den Daten bei weiterem Lesen dann immer nur noch das Config-Register. Man soll lt. Datenblatt also immer weiter lesen, bis das Bit RDY gelöscht ist. Dann ist die Conversation abgeschlossen. Nun soll man den MCP2426 erneut adressieren und die Daten auslesen. Genau so habe ich es gemacht.
      So ist es auch in dem Code drin, den ich hier eingestellt habe. Das ist die Function AD_ReadValue().

      Ich habe hier noch einen Zähler in die Function eingebaut, der bis zu 100x versucht das Config-Register zu lesen. Wenn das RDY-Bit nicht gelöscht wird, wird -100 zurückgegeben. Nach jedem Leseversuch wird noch 10ms gewartet. So kommen auf alle Fälle 100ms zusammen.

      Aber es kommt -1 ($FFFF). D.h. Es wird offensichtlich gewandelt, aber wie komme ich an den Wert ran?
    • Hallo Mitch64,
      ==>When the Master sends a read command (R/W = 1), the device outputs both the conversion data and configuration bytes.
      Stimmen denn die mit zurückgegebenen Konfigurationsdaten mit deiner programmierten Konfiguration überein? Sonst besteht ein generelles Kommunikationsproblem mit dem Chip. Da ERR=0 liegt das jedenfalls nicht am I2C-Bus...der funktioniert.
    • Noch was: Woher hast du denn die Adressbits A0...A2 ? Gescannt?
      Ich finde in dem Microchip-pamphlet nur:
      MCP3426: Programmed at the factory during production.
      Ja, und wie? Ich habe noch nichts genaueres gefunden. Das ist typische Microchip-Schei..., man muss sich die benötigten Informationen mühsam zusammensuchen, wo eine einfache Tabelle genügen würde.
      Hast du mal den Bus gescannt auf welche Adressen er reagiert?
    • Ich habe mal schnell in das Datenblatt geschaut:
      5.3.1 I2C DEVICE ADDRESSINGThe first byte after the START bit is always the addressbyte of the device, which includes the device code (4bits), address bits (3 bits), and R/W bit. The devicecode for the devices is 1101, which is programmed atthe factory. The I2C address bits (A2, A1, A0 bits) areas follows:
      usw.

      Es gibt verschiedene Gehäusetypen.
      entweder gar keine Adresspins, oder zwei oder drei für A0, A1, A2

      Je nachdem, was vorliegt, mal Kapitel 5.3 ff lesen!
      Code first, think later - Natural programmer :D
    • Pluto25 schrieb:

      Mit bit4 =1 Konvertiert er kontinuierlich mit 0 nur einmal. Dennoch sollte das Ergebniss stimmen. Die Eingänge liegen auf richtigen Pegel? Die TWi Speed ist nicht zu schnell? Es gibt auch kein plausibles Ergebnis mit einmal lesen? (ohne ihn vorher mit Abfragen zu bombadieren)
      Bit 4 = 0, weil ich nur einmalig messen will. Eingänge sind auf richtigem Pegel, und Signale sind steil-flankig, so wie es sein soll. Speed ist auch OK, ist Hardware-TWI mit 400kHz. Das kann der MCP3426 locker. Habs auch mit Pause zwischen Conversation starten und nach 100ms /200ms abgefragt. Immer -1.

      oscar schrieb:

      Noch was: Woher hast du denn die Adressbits A0...A2 ? Gescannt?
      Ich habe das kleine IC, welches keine Adressleitungen nach außen geführt hat. Im Datenblatt steht nicht bezüglich dieser 3 Adressbits. Also habe ich zunächst 0 für die 3 Bits angenommen. Habe es später aber noch mit einem Adress-Scanner überprüft. Device-Code ist 1101b hinzu kommen dann 3 Adressbits je 0 + write-Bit=0 ergibt 11010000b oder D0h. Zum Lesen D1h.

      Den Hinweis, ob das geschriebene Configurationsbyte auch zurückgelesen wird, werde ich überprüfen! Guter Tip!

      Und du hast recht. Datenblätter können die keine schreiben. Atmel-Datenblätter sichd dagegen vorbildlich!


      six1 schrieb:

      Ich habe mal schnell in das Datenblatt geschaut:
      Das hab ich auch, aber länger. Und immer wieder. Aber bezüglich Adresse ist außer dem Device-Code dem Datenblatt kein Adresswert für MCP3426 zu entlocken.
      Die Adressbits sind alle auf 0 gesetzt. Leider haben die das im Datenblatt nicht angegeben.

      Also Adresse ist soweit auch korrekt.

      Ich werde mal den Tip von Oscar verfolgen.
      Zum Glück hat das Gerät eine serielle Schnittstelle. Kann mir also während der Kommunikation mal die Werte anzeigen lassen.

      Soweit erst mal die Info von mit.
    • Hallo Mitch64,
      teste das Ganze doch erst mal mit einem Minimalprogramm (nur I2C mit Direktwerten ohne Rechnerei und dem pi pa po drumrum) und schau was du da dem Chip entlocken kannst und wenn das funktioniert kannst du ja daraus eine include-Datei schmieden. Ich hatte mal ein Microchip-Teil (weiß nicht mehr welches) das funktionierte erst stabil nachdem ich vor dem I2CRepstart ein paar µs Pause einlegte( natürlich kein Hinweis im pdf dazu).
    • Hallo Leute

      Vielen Dank für eure Hilfe.
      Ich habe den Fehler gefunden.

      Vorweg, mein Code funktioniert. Falls also mal wieder jemand so ein Sch.. Ding anlabern muss hier nochmal der Code:

      BASCOM-Quellcode

      1. Function AD_ReadValue() as Integer
      2. Local ErrCount as Byte
      3. ErrCount = 100 ' Anzahl Leseversuche, bis RDY=0
      4. I2CStart
      5. I2CWByte AD_DEVICE_READ ' Adressieren zum Lesen
      6. I2CRByte AD_Buffer(_base + 1) , Ack ' High-Byte Data
      7. I2CRByte AD_Buffer(_base + 0) , Ack ' Low-Byte Data
      8. Do
      9. I2CRByte AD_Buffer(_base + 2) , Ack ' Config-Register
      10. If AD_Buffer(_base + 2).7 = 0 then Exit Do ' RDY-Bit = 0 ?
      11. Decr ErrCount
      12. Waitms 5
      13. Loop Until ErrCount = 0
      14. I2CRByte AD_Buffer(_base + 2) , NAck ' Config-Register, NACK senden
      15. I2CStop
      16. ' If ErrCount = 0 then ' Fehler, keine Versuche mehr
      17. ' 'AD_ReadValue = -100 ' Fehler melden
      18. ' Exit Function
      19. ' End If
      20. ' Messwert auslesen
      21. I2CStart
      22. I2CWByte AD_DEVICE_READ ' Adressieren zum Lesen
      23. I2CRByte AD_Buffer(_base + 1) , Ack ' High-Byte Data
      24. I2CRByte AD_Buffer(_base + 0) , Nack ' Low-Byte Data
      25. I2CStop
      26. AD_ReadValue = AD_Value ' Messwert an Aufrufer
      27. End Function
      28. ' --------------------------------------------------------
      29. ' Startet eine Einzelmessung mit 16Bit Auflösung
      30. ' --------------------------------------------------------
      31. Sub AD_StartConversation(Byval Channel as Byte , Byval Gain as Byte)
      32. Local cfgByte as Byte
      33. ' Configurations-Byte zusammensetzen
      34. cfgByte = &b10001000 ' Start-Conversation, Einzel-Messung, 16 Bit
      35. cfgByte = cfgByte or Channel ' Kanal hinzufügen
      36. cfgByte = cfgByte or Gain ' Gain hinzufügen
      37. 'Locate 1 , 11 : Lcd bin(cfgByte) ' (Debug)
      38. I2CStart
      39. I2CWByte AD_DEVICE_WRITE ' Adressieren
      40. I2CWByte cfgByte ' Conversation starten
      41. I2CStop
      42. End Sub
      Alles anzeigen
      Den Rest aus dem Post 1 entnehmen.

      Mein Fehler war, dass ich nach Schaltbild immer den Kanal 0 (Spannung) gelesen habe. Kanal 1 soll Strom sein.
      Der Erbauer des Gerätes (nicht ich) hat aber die Kanäle vertauscht samt Beschaltung. Oder am IC einfach die Beschriftung verkehrt gemacht.

      Ich habe also immer den Strom ausgelesen.
      Wenn ich den Kanal 1 lese (der ja Strom messen sollte) habe ich meinen korrekten Spannungswert.

      Also alles gut.

      Vielen Dank nochmal an alle für die Tips, die mich dann auf die richtige Spur gebracht haben.