Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteuern

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
King555

Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteuern

Post by King555 »

Ich habe eine USB-Relaiskarte ("RK10-USB" der Firma "GWR-Elektronik"). Darin ist der Controller "IO-Warrior24" verbaut.

Mit der Relaiskarte steuere ich einen Motor an. Das 1. Relais startet/stoppt den Motor und das 2. Relais dient zur Bestimmung der Laufrichtung (links- oder rechtsrum).

Im SDK von Code Mercenaries gibt es u. a. ein Beispiel für Visual Basic 6 (so wie ich's benötige). Leider konnte ich damit nicht herausfinden, wie ich die beiden Relais schalte.

Ich habe nun aber entdeckt, dass bei den vielen Beispielprogrammen im SDK auch ein funktionierendes mit Code dabei ist, geschrieben in Delphi ("\Windows\samples\Simple IO\Delphi\LEDs DLL"). Zwar kenne ich eigentlich Delphi, da ich damit von 2001 bis 2006 täglich programmiert habe, aber trotzdem habe ich eine Umsetzung in VB6 bisher nicht hinbekommen.

Die einzige wirklich relevante Stelle im Delphi-Quellcode ist das hier:

Code: Select all

procedure TMainForm.LEDClick(Sender: TObject);
var
  LEDByte: Integer;
  I: Integer;
  Report: IOWKIT56_IO_REPORT;
begin
  if not Assigned(IOWarrior) then
    Exit;

  // initialize report to not interfere with input
  FillChar(Report, IOWKIT56_IO_REPORT_SIZE, $FF);
  Report.ReportID := 0;
  // the LEDs are connected to different ports
  case Pid of
    IOWKIT_PID_IOW40:
      LEDByte := 3;
    IOWKIT_PID_IOW24:
      LEDByte := 0;
    IOWKIT_PID_IOW56:
      LEDByte := 6;
  else
    LEDByte := 0;
  end;

  for I := Low(LEDs) to High(LEDs) do
    // translate SpeedButton state into correct bit in the byte
    // IO-Warrior uses negative logic
    if LEDs[I].Down then
      // set the bit to 0 to switch the LED on
      Report.Bytes[LEDByte] := Report.Bytes[LEDByte] and not (1 shl I)
    else
      // set the bit to 1 to switch the LED off
      Report.Bytes[LEDByte] := Report.Bytes[LEDByte] or (1 shl I);

  // write the bits to the IO-Warrior
  case Pid of
    IOWKIT_PID_IOW40:
      IowKitWrite(IOWarrior, IOW_PIPE_IO_PINS, PChar(@Report), IOWKIT40_IO_REPORT_SIZE);
    IOWKIT_PID_IOW24:
      IowKitWrite(IOWarrior, IOW_PIPE_IO_PINS, PChar(@Report), IOWKIT24_IO_REPORT_SIZE);
    IOWKIT_PID_IOW56:
      IowKitWrite(IOWarrior, IOW_PIPE_IO_PINS, PChar(@Report), IOWKIT56_IO_REPORT_SIZE);
  end;
end;
Ganz konkret die Zeilen >>Report.Bytes[LEDByte] := Report.Bytes[LEDByte] and not (1 shl I)<< fürs Einschalten der Relais und >>Report.Bytes[LEDByte] := Report.Bytes[LEDByte] or (1 shl I);<< zum Ausschalten. Mein VB6-Pendant dazu sieht wie folgt aus:

Code: Select all

Private Sub iowWrite(ByVal motor As Byte, ByVal richtung As Byte)
  ' Write value
  Dim Res As Long
  Dim N As Long
  Dim Pid As Long

  Pid = IowKitGetProductId(iowHandles(0))
  If Pid = IOWKIT_PID_IOW24 Then
    N = 3
  Else
    If Pid = IOWKIT_PID_IOW40 Then
      N = 5
    Else
      If Pid = IOWKIT_PID_IOW56 Then
        N = 8
      End If
    End If
  End If

  ' Report ID 0
  data(0) = 0
  If motor = 0 Then
    data(1) = data(1) Or (ShiftLeft(1, 0))
  Else
    data(1) = data(1) And Not (ShiftLeft(1, 0))
  End If
  
  If richtung = 0 Then
    data(2) = data(2) Or (ShiftLeft(1, 1))
  Else
    data(2) = data(2) And Not (ShiftLeft(1, 1))
  End If
  
  ' Write to IOW
  Res = IowKitWrite(iowHandles(0), IOW_PIPE_IO_PINS, data(0), N)
  ' Handle error
  If Res <> N Then
    ' You can get error code from GetLastError()
    MsgBox "ioWarrior: Write to IOW failed!", 0, "Error"
  End If
End Sub
Konkret die Zeilen unter data(0) = 0. Den Motor ein- und ausschalten kann ich nun, aber das 2. Relais, zur Steuerung der Drehrichtung, lässt sich partout nicht umschalten. Das ShiftLeft ist übrigens von hier: http://www.vb-tec.de/bitshift.htm#left
Die Werte data(1..7) wurden mit &HFF initialisiert.

Ich muss zugeben, dass ich mich mit Bit"schubsereien" nicht wirklich auskenne.

Hat jemand eine Idee? Ich kann gerne weitere Quellcodes nachreichen, falls diese zu einer Lösung führen können.
Thoene
Posts: 33
Joined: Sat Aug 29, 2009 8:13 pm

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by Thoene »

Hallo.
Zum Initialisieren:
Data(0) = 0 ; Hierbei Immer 0 damit wird Normalmodus angewählt.
Data(1) = 0 ; Alle Bit Port 0 sind Aus
Wert = 0 Variable vom Typ Byte

Motor 1 Schalten:
Data(0) = 0
Wert = Wert OR 1 ; Ausgang Port 0 Bit 0 Ein Jeweiligen Befehl verwenden
Wert = Wert AND 254 ; Ausgang Port 0 Bit 0 Aus "
Data(1) = Wert.

Motor 2 Schalten.
Data(0) = 0
Wert = Wert OR 2; Ausgang Port 0 Bit 1 Ein
Wert = Wert And 253 ; Ausgang Port 0 Bit 1 Aus
Data(1) = Wert

Data(2) für Port 1 und Data(3) für Port 2

Bit 7 6 5 4 3 2 1 0
Alter Wert 1 1 1 0 0 0 1 1
And 253 1 1 1 1 1 1 0 1 ;Bit 2 löschen
Neuer Wert 1 1 1 0 0 0 0 1

Bit 7 6 5 4 3 2 1 0
Alter Wert 1 1 1 0 0 0 0 1
Or 2 0 0 0 0 0 0 1 0 ; Bit 2 Setzen
Neuer Wert 1 1 1 0 0 0 1 1
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by Christoph Jung »

Es ist zwar ein IO-Warrior24 in der Relaiskarte verbaut, aber das Produkt selber ist nicht von uns.
Und ohne Schaltplat, welcher Pin was macht kann ich schlecht helfen. Und die Doku zur Relaiskarte in dem Shop ist leider nicht sehr
Aussagekräftig.

Aber der Beitrag von Thoene könnte das Problem lösen.
Da es 10 Relais sind nehme ich mal an, dass es dann auch 10 Bit sind um diese zu steuern, Also müsste Relais 1-8 im ersten Byte sein und 9+10 im 2 Byte des IO-Warriors (byte[1] und byte[2]). Ist aber nur eine Vermutung.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
King555

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by King555 »

Erstmal danke für die Antworten. Es sind übrigens nur 2 Relais, nicht 10. Leider haben wir zu der Karte auch nur die Dokumente, die man online findet.

Das Delphi-Beispiel funktioniert ja, dort kann ich die beiden Relais unabhängig voneinander jeweils ein- und ausschalten. Und genau das wollte ich einfach so nach VB übernehmen.

Das Beispiel von Thoene hat mich schon einen großen Schritt weiter gebracht. Aber eine Frage dazu: Was ist denn mit "Motor 2 Schalten" gemeint?

Über data(2) konnte ich nun erfolgreich mit "255" Relais 2 aus- und mit "0" einschalten. Bei data(1) habe ich nun "0 or 1" zum Aus- und "0 and 254" zum Einschalten gemacht. Scheint generell zu gehen, nur trotzdem frage ich mich, was mit Motor 1 und 2 gemeint ist.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by Christoph Jung »

Ich schätze das ist aus einem Quellcode von ihm und daher der Kommentar.

Eine Möglichkeit zum Rausfinden des richtigen Bits wäre die "logischen" Bits einen nach dem anderen durchzugehen: $80, $40, $01, $02.
Da aber auch nichts weiter dran hängt und man nicht auf die 10-Relais version umsteigt geht auch $FF und $00 zum ein und ausschalten. Wäre aber sauberer die richtigen Bits zu kennen.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
King555

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by King555 »

So ganz scheint es doch noch nicht zu gehen. Ich kann das 2. Relais nur anschalten, nicht ausschalten.

Egal ob ich 0 oder 255 hinschicke, es geht immer an.

Im VB6-Beispiel im SDK gab es die Routine "iowWriteLEDs". Die verwende ich, um alles zu resetten, d. h. beide Relais auszuschalten. Damit geht das Ausschalten also.

Aufgerufen wird das mit "Call iowWriteLEDs(&HFF)". Nur damit kann ich nichts einschalten und separat ansteuern sowieso nicht.

Streng genommen bin ich so schlau wie vorher: das 1. Relais lässt sich schalten, das 2. nicht.

Hier meine aktuelle Routine (nicht die "iowWriteLEDs"):

Code: Select all

Private Sub iowWrite(ByVal motor As Byte, ByVal richtung As Byte)
  ' Write value
  Dim Res As Long
  Dim N As Long
  Dim Pid As Long

  Pid = IowKitGetProductId(iowHandles(0))
  If Pid = IOWKIT_PID_IOW24 Then
    N = 3
  Else
    If Pid = IOWKIT_PID_IOW40 Then
      N = 5
    Else
      If Pid = IOWKIT_PID_IOW56 Then
        N = 8
      End If
    End If
  End If

  ' Report ID 0
  data(0) = 0
  
  If motor = 0 Then
    data(1) = 0 Or 1
  Else
    data(1) = 0 And 254
  End If
  
  If richtung = 0 Then
    data(2) = 255
  Else
    data(2) = 0
  End If
  
  ' Write to IOW
  Res = IowKitWrite(iowHandles(0), IOW_PIPE_IO_PINS, data(0), N)
  ' Handle error
  If Res <> N Then
    ' You can get error code from GetLastError()
    MsgBox "ioWarrior: Write to IOW failed!", 0, "Error"
  End If
End Sub
Es stellt sich mir immer noch die Frage, warum das Delphi-Sample so perfekt funktioniert.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by Christoph Jung »

Werden auch immer data(1) und data(2) gesendet? Der IO-Warrior bekommt im IO-Modus immer alle Bytes, auch wenn diese nicht gesetzt werden.
Wenn also eines der beiden Bytes nicht gesetzt wird ist es (in der Regel) 0.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
King555

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by King555 »

Im VB6-Beispiel im SDK steht nur

Code: Select all

Res = IowKitWrite(iowHandles(0), IOW_PIPE_IO_PINS, data(0), N)
Also nur data(0). In allen anderen Beispielen ebenfalls.

Ich ging aber davon aus, dass die Methode "IowKitWrite" durch die Übergabe des letzten Parameters (N, welcher hier 3 ist), automatisch data(1) und data(2) bekommt.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by Christoph Jung »

Ja das stimmt und data(0) ist auch korrekt. Aber werden data(1) und data(2) auch immer mit Daten gefüttert. Ich meine wird auch immer wieder Relais 1 gesetzt wenn nur nelais 2 gesetzt werden soll?
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by Christoph Jung »

Ich kann das hier schlecht testen, da ich so eine Relaiskarte nicht habe. Aber hier mal ein extrem gekürzter Code um die 2 Byte zu senden.
Was in data(1) und data(2) steht muss einfach mal durchgetestet werden.

Wichtig ist, dass data halt Bytes sind und diese jeweils 8 Bit haben. Für jedes Bit könnte ein Relais stehen. Also einfach folgende Werte für die beiden Bytes durchgehen:
1,2,4,8,16,32,64,128

Am besten erste data(1) und dann nach den 8 Werten data(2). Dann müsste eigentlich irgendwann das 2. Relais regaieren.

Code: Select all

Pid = IowKitGetProductId(iowHandles(0))
  If Pid = IOWKIT_PID_IOW24 Then
    N = 3

'Fill data struct
data(0) = 0 'report ID
data(1) = 1 'report Byte[0]
data(2) = 1 'report Byte[1]
  
' Write to IOW
Res = IowKitWrite(iowHandles(0), IOW_PIPE_IO_PINS, data(0), N)
 
' Handle error
 If Res <> N Then
    ' You can get error code from GetLastError()
     MsgBox "ioWarrior: Write to IOW failed!", 0, "Error"
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
King555

Re: Relaiskarte mit IO-Warrior24 via Visual Basic 6.0 ansteu

Post by King555 »

Ich habe mir nun nochmal genau den Post von "Thoene" durchgelesen. Dabei kam mir eine Idee, was er mit "Motor 1" und "Motor 2" gemeint haben könnte. Ich habe es einfach mal gestestet und es klappt!

Hier mein funktionierender VB6-Quellcode:

Code: Select all

Private Sub iowWrite(ByVal motor As Byte, ByVal richtung As Byte)
  ' Write value
  Dim Res As Long
  Dim N As Long
  Dim Pid As Long

  Pid = IowKitGetProductId(iowHandles(0))
  If Pid = IOWKIT_PID_IOW24 Then
    N = 3
  Else
    If Pid = IOWKIT_PID_IOW40 Then
      N = 5
    Else
      If Pid = IOWKIT_PID_IOW56 Then
        N = 8
      End If
    End If
  End If

  Dim i As Integer
  Dim wert As Byte
  wert = 0

  ' Report ID 0
  For i = 0 To 1
    data(i) = 0
  Next i
  For i = 2 To 8
    data(i) = 255
  Next i

  If motor = 0 Then
    wert = wert Or 1
  Else
    wert = wert And 254
  End If

  If richtung = 0 Then
    wert = wert Or 2
  Else
    wert = wert And 253
  End If

  data(1) = wert

  ' Write to IOW
  Res = IowKitWrite(iowHandles(0), IOW_PIPE_IO_PINS, data(0), N)
  ' Handle error
  If Res <> N Then
    ' You can get error code from GetLastError()
    MsgBox "ioWarrior: Write to IOW failed!", 0, "Error"
  End If
End Sub
Die Lösung: Man muss bei meiner Relaiskarte ausschließlich data(1) setzen! data(2) (und alle darüber hinaus) sind irrelevant. Ich setze nun also data(0) auf 0, data(1) anhand des Beispiels von Thoene (darin stecken dann Motor an/aus und die Drehrichtung) und alle anderen data()-Werte auf 255.

Vielen Dank für die Hilfe!
Post Reply