I2C Ansteuerung in VBA

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Post Reply
mipu
Posts: 3
Joined: Fri Mar 26, 2010 4:31 pm

I2C Ansteuerung in VBA

Post by mipu »

Hallo,

mittels VBA möchte ich auf einen I2C-Sensor sowohl schreiben als auch lesen können.
Die Anbindung des Sensors erfolgt dabei über den USB-I2C Dongle mit dem IO-Warrior24.
Über das Programm Simple-I2C funktioniert dies bestens.

Ich bin absoluter Anfänger in Sachen Ansteuerung mittels Visual Basic.
Die Schreibadresse des Sensors ist hex 90 und die Leseadresse hex 91.
Weiterhin besitzt der Sensor noch eine Subadresse/eigenes Register mit hex 9, auf welches sowohl geschrieben als auch gelesen werden kann.

Mit folgenden vollständigen Quellcode habe ich versucht auf den Sensor zu schreiben (bzw. zu lesen, auskommentiert).
Leider war dies bislang nicht erfolgreich.
Ich würde mich freuen wenn mir jemand Tipps geben könnte was ich falsch gemacht habe bzw. ob noch was fehlt.
Vielen Dank schon einmal im Voraus!

Code: Select all

Public Declare Function IowKitOpenDevice Lib "iowkit" () As Long  'Warrior öffnen

Public Declare Sub IowKitCloseDevice Lib "iowkit" (ByVal iowHandle As Long)   'Warrior schließen

Public Declare Function IowKitWrite Lib "iowkit" (ByVal iowHandle As Long, ByVal numPipe As Long, _
     ByRef buffer As Byte, ByVal length As Long) As Long                'Schreibfunktion Warrior

Public Declare Function IowKitRead Lib "iowkit" (ByVal iowHandle As Long, _
     ByVal numPipe As Long, ByRef buffer As Byte, ByVal length As Long) As Long     'Lesefuntkion Warrior


Dim aus As Byte
Dim counter As Integer
Dim buffer(7)


' IO-Warrior low-level library API functions
Public Sub IowKitEnableIIC()
 Dim iicPacket(7)    'entspricht buffer?
 Dim nWritten As Long
  ' Set up IIC enable packet
  ' 1st report ID is for IIC control
  iicPacket(0) = 1
  ' Enable/disable IIC
  iicPacket(1) = enable
  ' Write Report
  nWritten = IowKitWrite(iowHandle, numPipe, iicPacket(0), 8)
'  IowKitEnableIIC = nWritten
End Sub

Public Sub Schreiben()
 buffer(0) = 2     'ReportID=2, Schreibzugriff special functions
 buffer(1) = C3    'Start-/Stoppbit setzen, 3 folgende Bytes
 buffer(2) = 90    'Schreibadresse des Sensors
 buffer(3) = 9     'Subadresse/Register 
 buffer(4) = 1     'Schreiben des Wertes HEX 1 in Register
 For counter = 0 To 4
  nWritten = IowKitWrite(iowHandle, numPipe, buffer(counter), 8)   'Übertragung an IO Warrior
 Next counter
End Sub

Public Sub Lesen()
 buffer(0) = 3      'ReportID=3, Lesezugriff special functions
 buffer(1) = 1      '1 Byte soll gelesen werden
 buffer(2) = 91    'Leseadresse des Sensors
 buffer(3) = 9      'Subadresse/Register
 For counter = 0 To 3
  nWritten = IowKitWrite(iowHandle, numPipe, buffer(counter), 8)
 Next counter
 aus = IowKitRead(iowHandle, numPipe, buffer(3), length) '1 Byte von IO Warrior lesen
 Cells(1, 1) = aus      'Übergabe an Zelle1:1 der Tabelle
End Sub

Sub main()
 IowKitOpenDevice
 IowKitEnableIIC
' Lesen
 Schreiben
 IowKitCloseDevice (iowHandle)
End Sub
Guido Körber
Site Admin
Posts: 2879
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Re: I2C Ansteuerung in VBA

Post by Guido Körber »

Beim Lesezugriff kann kein weiteres Byte gesendet werden. Wenn eine Adresse im IIC Gerät gesetzt werden muss, dann muss das mit einem Schreibzugriff vorher geschehen.
friend-of-rq
Posts: 389
Joined: Sun Feb 13, 2005 1:22 pm
Location: Gerblingerode / Duderstadt
Contact:

Re: I2C Ansteuerung in VBA

Post by friend-of-rq »

@mipu

Hast Du deine Schaltung schon mal mit dem Test-Programm All-In-One getestet ?
Wird der Sensor damit erkannt ?
mipu
Posts: 3
Joined: Fri Mar 26, 2010 4:31 pm

Re: I2C Ansteuerung in VBA

Post by mipu »

@friend-of-rq:
Ja, der Sensor wird sowohl mit All-in-One als auch Simple I2C erkannt

@Gudio Körber:
Um auf den Sensor lesen zu können muss folgende Sequenz erfolgen:
Startbit -> Leseadresse (91) -> Acknowledge(Sensor) -> Register (hier: 9) -> Acknowlege (Sensor) -> Startbit -> Leseadresse (91) -> Acknowlege (Sensor) -> Daten -> no Acknowlege (Master) -> Stoppbit
Dann müsste das Programm wie folgt aussehen oder?

Code: Select all

Public Declare Function IowKitOpenDevice Lib "iowkit" () As Long  'Warrior öffnen

Public Declare Sub IowKitCloseDevice Lib "iowkit" (ByVal iowHandle As Long)   'Warrior schließen

Public Declare Function IowKitWrite Lib "iowkit" (ByVal iowHandle As Long, ByVal numPipe As Long, _
     ByRef buffer As Byte, ByVal length As Long) As Long                'Schreibfunktion Warrior

Public Declare Function IowKitRead Lib "iowkit" (ByVal iowHandle As Long, _
     ByVal numPipe As Long, ByRef buffer As Byte, ByVal length As Long) As Long     'Lesefuntkion Warrior


Dim aus As Byte
Dim counter As Integer
Dim nWritten As Long
Dim buffer(7)


Public Sub IowKitEnableIIC()
Dim iicPacket(7)    'entspricht buffer?
  iicPacket(0) = 1   ' Enable/disable IIC
  iicPacket(1) = enable
  nWritten = IowKitWrite(iowHandle, numPipe, iicPacket(0), 8)   'Schreiben auf IO Warrior
End Sub


Public Sub Schreiben()
buffer(0) = 2     'ReportID=2, Schreibzugriff special functions
buffer(1) = C3    'Start-/Stoppbit setzen, 3 folgende Bytes
buffer(2) = 90    'Schreibadresse des Sensors
buffer(3) = 9     'Subadresse/Register
buffer(4) = 1     'Schreiben des Wertes HEX 1 in Register
For counter = 0 To 4
  nWritten = IowKitWrite(iowHandle, numPipe, buffer(counter), 8)   'Übertragung an IO Warrior
Next counter
End Sub


Public Sub Lesen()
buffer(0) = 2      'ReportID=2, Schreibzugriff special functions
buffer(1) = 82     'Startbit setzen, 2 folgende Bytes
buffer(2) = 91     'Leseadresse des Sensors
buffer(3) = 9      'Subadresse/Register
For counter = 0 To 3
  nWritten = IowKitWrite(iowHandle, numPipe, buffer(counter), 8)
Next counter
buffer(0) = 3      'ReportID=3, Lesezugriff special functions
buffer(1) = 1      '1 Byte soll gelesen werden
buffer(2) = 91     'Leseadresse des Sensors
For counter = 0 To 2
 aus = IowKitRead(iowHandle, numPipe, buffer(counter), length) 'Wert des Registers von IO Warrior lesen
Next counter
Cells(1, 1) = aus      'Übergabe an Zelle1:1 der Tabelle
End Sub


Sub main()
IowKitOpenDevice
IowKitEnableIIC
' Lesen
Schreiben
IowKitCloseDevice (iowHandle)
End Sub


Ich werde das Gefühl nicht los, dass irgendwo noch was fehlt!?
Guido Körber
Site Admin
Posts: 2879
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Re: I2C Ansteuerung in VBA

Post by Guido Körber »

Der Fehler ist, dass beim Setzen der Registeradresse (zweiter Schreibzugriff, der ohne Stop) das Read Bit gesetzt wird. IIC Adressen haben 7 Bit, das unterste Bit ist das R/W Bit. Also muss bei einem ReportID $02 beim IO-Warrior immer eine gerade IIC Adresse geschickt werden, also ohne Read Bit, sonst denkt der IIC Slave er soll Daten senden und macht das dann auch.
friend-of-rq
Posts: 389
Joined: Sun Feb 13, 2005 1:22 pm
Location: Gerblingerode / Duderstadt
Contact:

Re: I2C Ansteuerung in VBA

Post by friend-of-rq »

Code: Select all

buffer(0) = 2     'ReportID=2, Schreibzugriff special functions
buffer(1) = C3    'Start-/Stoppbit setzen, 3 folgende Bytes
buffer(2) = 90    'Schreibadresse des Sensors
buffer(3) = 9     'Subadresse/Register
buffer(4) = 1     'Schreiben des Wertes HEX 1 in Register
For counter = 0 To 4
  nWritten = IowKitWrite(iowHandle, numPipe, buffer(counter), 8)   'Übertragung an IO Warrior
Next counter
Da hast Du einen Gedanken Fehler drin ... Du musst nicht jedes Buffer() Byte einzeln an den IOW über eine Schleife übertragen !

?? Wie ist denn das in VB ... in RQ ist ein Wert z.B. 90 = Dezimal und &H90 = HEX
Man übergibt der DLL die Feld-Variabel das langt ...

Code: Select all

buffer(0) = 2     'ReportID=2, Schreibzugriff special functions
buffer(1) = C3    'Start-/Stoppbit setzen, 3 folgende Bytes
buffer(2) = 90    'Schreibadresse des Sensors
buffer(3) = 9     'Subadresse/Register
buffer(4) = 1     'Schreiben des Wertes HEX 1 in Register
nWritten = IowKitWrite(iowHandle, 1, buffer(0), 8)   'Übertragung an IO Warrior


buffer(0) = 3      'ReportID=3, Lesezugriff special functions
buffer(1) = 1      '1 Byte soll gelesen werden
buffer(2) = 91     'Leseadresse des Sensors
nWritten = IowKitWrite(iowHandle, 1, buffer(0), 8)     'IOW zum I2C lesen auffordern



aus = IowKitRead(iowHandle, 1, buffer(0), 8) 'Wert des Registers von IO Warrior holen

"aus" muss den Wert 8 haben sonst IOW-ERROR 

buffer(0) = 3  ' muss Report ID (3) haben ... sonst IowKitRead wiederholen
buffer(1) = x   ' x = Anzahl der eingelesen Bytes (max 6 in einem Report  BIT(7) muss 0 sein, wenn 1 dann I2C-Error
buffer(2) = Data
...
buffer(7) = Data
mipu
Posts: 3
Joined: Fri Mar 26, 2010 4:31 pm

Re: I2C Ansteuerung in VBA

Post by mipu »

Folgende Fehler konnte ich noch ausfindig machen und beseitigen:
- für numPipe sollte entsprechend des special mode 1 gesetzt werden
- alle Werte müssen in VB als hexadezimal (&H) gekennzeichnet werden, sonst werden sie dezimal übergeben
- buffer(8) anstatt buffer buffer(7)
- das Startbyte beim Lesevorgang muss die Schreibadresse (&H90) sein, nicht die Leseadresse

Entsprechend dem mitgelieferten Beispielcode für den MAX127 sollte der Code also folgendermaßen aussehen:

Code: Select all

Public Declare Function IowKitOpenDevice Lib "iowkit" () As Long  'Warrior öffnen

Public Declare Sub IowKitCloseDevice Lib "iowkit" (ByVal iowHandle As Long)   'Warrior schließen

Public Declare Function IowKitWrite Lib "iowkit" (ByVal iowHandle As Long, ByVal numPipe As Long, _
     ByRef buffer As Byte, ByVal length As Long) As Long                'Schreibfunktion Warrior

Public Declare Function IowKitRead Lib "iowkit" (ByVal iowHandle As Long, _
     ByVal numPipe As Long, ByRef buffer As Byte, ByVal length As Long) As Long     'Lesefuntkion Warrior

Public Declare Function IowKitGetProductId Lib "iowkit" (ByVal iowHandle As Long) As Long

Dim aus As Integer
Dim eingabe As Integer
Dim ID As Integer
Dim IOWarrior As Integer
Dim buffer(8) As Byte


Public Sub Initialisierung()
  'Öffnen des IO Warriors und Benutzung des erstgefundenen Gerätes
  IOWarrior = IowKitOpenDevice
  ID = IowKitGetProductId(IOWarrior)
  
  'Überprüfung, ob IO Warrior erkannt wurde (mittels ProductID)
  If IOWarrior <> 0 Then
    MsgBox "Verbindung zu IO Warrior erfolgreich!"
  Else
    MsgBox "Verbindung zu IO Warrior fehlgeschlagen!"
  End If
  
  'Aktivierung der I2C Funktionen
  buffer(0) = &H1
  buffer(1) = &H1
   eingabe = IowKitWrite(IOWarrior, 1, buffer(0), 8)
End Sub


Public Sub Schliessen()
  'Deaktivieren der I2C Funktionen
  buffer(0) = &H1
  buffer(1) = &H0
   eingabe = IowKitWrite(IOWarrior, 1, buffer(0), 8)
  IowKitCloseDevice (IOWarrior)
End Sub


Public Sub Schreiben()
  buffer(0) = &H2     'ReportID=2, Schreibzugriff special functions
  buffer(1) = &HC3    'Start-/Stoppbit setzen, 3 folgende Bytes
  buffer(2) = &H90    'Schreibadresse des Sensors
  buffer(3) = &H9     'Subadresse/Register
  buffer(4) = &H1     'Schreiben des Wertes HEX 1 in Register
   eingabe = IowKitWrite(IOWarrior, 1, buffer(0), 8)   'Übertragung an IO Warrior
End Sub


Public Sub Lesen()
  buffer(0) = &H2      'ReportID=2, Schreibzugriff special functions
  buffer(1) = &HC2     'Start-/Stoppbit setzen, 2 folgende Bytes
  buffer(2) = &H90     'Schreibadresse des Sensors
  buffer(3) = &H9      'Subadresse/Register
   eingabe = IowKitWrite(IOWarrior, 1, buffer(0), 8)  'Übertragung an IO Warrior
   eingabe = IowKitRead(IOWarrior, 1, buffer(0), 8) 'Acknowledge lesen

  buffer(0) = &H3      'ReportID=3, Lesezugriff special functions
  buffer(1) = &H2      '2 Bytes sollen gelesen werden, ohne Start-/Stoppbit
  buffer(2) = &H91     'Leseadresse des Sensors
  buffer(3) = &H9      'Subadresse/Register
   eingabe = IowKitWrite(IOWarrior, 1, buffer(0), 8)
   
  aus = IowKitRead(IOWarrior, 1, buffer(0), 8) 'Wert des Registers von IO Warrior lesen

  Cells(1, 1) = buffer(2)      'Übergabe an Zelle1:1 der Tabelle
End Sub

Sub main()
  Initialisierung
  Schreiben
' Lesen
  Schliessen
End Sub
Testen konnte ich das Ganze bis jetzt leider noch nicht wieder..
Post Reply