IO-WARRIOR40 mit Python!

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
EITA
Posts: 3
Joined: Sun Oct 21, 2012 1:16 pm

IO-WARRIOR40 mit Python!

Post by EITA »

Hallo,

ich versuche gerade IO-Warrior40 mit Python zu steuern. Dazu stellt Python das Modul ctypes zur Verfühgung, damit man auf dll-Funktionen zugreifen kann. Da ich aber leider keine Erfahrung mit C habe, wollte ich wissen, ob es Beispiele gibt, um IO-Warrior mit Python zu benutzen. Besonders habe ich Probleme mit Methoden wie "IowKitRead" oder "IowKitWrite."

Für Hilfe oder Tipps wäre ich sehr dankbar.
Gruß
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: IO-WARRIOR40 mit Python!

Post by Christoph Jung »

Bisher haben wir keine Beispiele für Python zur Hand.
Wo genau liegt denn das Problem?
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
EITA
Posts: 3
Joined: Sun Oct 21, 2012 1:16 pm

Re: IO-WARRIOR40 mit Python!

Post by EITA »

Das Problem mit Python habe ich jetzt gelöst. Ich konnte mindestens IO-Warrior steuern. Mein Code sieht jetzt so aus:

Code: Select all

import ctypes
from ctypes import *
import time

class IowReadResult40(Structure):
    _fields_ = [("ReportId", c_ubyte), ("IowReadResult", c_ubyte*63)]

try:
    
    IowKitHandle = windll.Iowkit.IowKitOpenDevice()
    windll.Iowkit.IowKitSetWriteTimeout(IowKitHandle, 5000)
    
    print "DevHandle: ", str(IowKitHandle)
    
    IowKit_ID = windll.Iowkit.IowKitGetProductId(c_ulong(IowKitHandle))
    
    print "ID: ", str(IowKit_ID)
    
    IowKit_NumbDevs = windll.Iowkit.IowKitGetNumDevs()
    
    print "NumbDevs: ", str(IowKit_NumbDevs)
    
    IowKit_Revision = windll.Iowkit.IowKitGetRevision(c_ulong(IowKitHandle))
    
    print "Revision: ", str(IowKit_Revision)
    
    SerNumb=create_unicode_buffer("xxxxxxxx")
    IowKit_SerNumb = windll.Iowkit.IowKitGetSerialNumber(c_ulong(IowKitHandle), SerNumb)
    
    print "SerNumb: ", str(SerNumb.value)
    
    
    datac = IowReadResult40()
    BytesWritten = windll.IowKit.IowKitWrite(IowKitHandle, 0, pointer(datac), sizeof(IowReadResult40))
    time.sleep(5)
    windll.Iowkit.IowKitCloseDevice(IowKitHandle)
except Exception, e:
    print str(e)
Bei mir geht es eigentlich darum, ein kleines Motor über IO-WARRIOR zu steuern. Das Motor wird verwendet, um auf einem Knopf zu drücken. Wenn ich diesen Code einmal ausführe, dann wird das Motor wirklich gesteuert und der Knopf wird gedrückt. Wenn ich aber den Code nochmal ausführe, um den Knopf nochmal zu drücken, dann wird das Motor nicht gesteuert. Erst wenn ich den USB-Kabel zwischen PC und IO-WARRIOR trenne und dann wieder einstecke, dann konnte ich den Code ausführen und IO-WARRIOR steuern.

Fehlt in meinem Code noch etwas, was ich machen muss?
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: IO-WARRIOR40 mit Python!

Post by Christoph Jung »

Ich habe nicht viel Erfahrung mit Python, aber habe mal was auf Basis des geposteten Codes zusammen gebastelt.

Code: Select all

import ctypes
from ctypes import *
import time

class Iow40_IoStruct(Structure):
    _fields_ = [("ReportId", c_ubyte), 
                ("Port_0", c_ubyte), #Like Byte[0]
                ("Port_1", c_ubyte), #Like Byte[1]
                ("Port_2", c_ubyte), #Like Byte[2]
                ("Port_3", c_ubyte)]  #Like Byte[3]
                
    
    
IowKitHandle = windll.Iowkit.IowKitOpenDevice()
    
if IowKitHandle != 0:
        
    windll.Iowkit.IowKitSetWriteTimeout(IowKitHandle, 1000)
    windll.Iowkit.IowKitSetTimeout(IowKitHandle, 1000)
   
    print "DevHandle: ", str(IowKitHandle)
   
    IowKit_ID = windll.Iowkit.IowKitGetProductId(c_ulong(IowKitHandle))
   
    print "ID: ", str(IowKit_ID)
   
    IowKit_NumbDevs = windll.Iowkit.IowKitGetNumDevs()
   
    print "NumbDevs: ", str(IowKit_NumbDevs)
   
    IowKit_Revision = windll.Iowkit.IowKitGetRevision(c_ulong(IowKitHandle))
   
    print "Revision: ", str(IowKit_Revision)
   
    SerNumb = create_unicode_buffer("xxxxxxxx")
    IowKit_SerNumb = windll.Iowkit.IowKitGetSerialNumber(c_ulong(IowKitHandle), SerNumb)
   
    print "SerNumb: ", str(SerNumb.value)
   
    #datac = IowReadResult40()   
    datac = Iow40_IoStruct(0x00, 0x00, 0x00, 0x00, 0xfe)
    
    #print "Size: ", sizeof(Iow40_IoStruct)
    BytesWritten = windll.IowKit.IowKitWrite(IowKitHandle, 0, pointer(datac), sizeof(Iow40_IoStruct))
    time.sleep(5)
    
    windll.Iowkit.IowKitCloseDevice(IowKitHandle)
else:
    print "Error: IOW-Handle not free or no device found"
    windll.Iowkit.IowKitCloseDevice(IowKitHandle)
Das Problem, was ich bzw. Python hat ist, dass wenn IowKitClose aufgerufen wird die DLL entladen wird aber die Python.exe braucht ein wenig länger zum beenden. Solange noch dieser Prozess offen ist kann die DLL, bzw. IowKitOpenDevice() nicht erfolgreich neu aufgerufen werden.
Daher hab ich den Code mal etwas angepasst und prüfe, ob OpenDevice() etwas gültiges zurückliefert und wenn nicht, dann schließen und beenden.
Desweiteren war das Struct falsch (oder ich hab das nicht richtig mitgeschnitten). Ich hab das Struct mal so abgeändert, wie es sein sollte. Auch beim Schreiben habe ich die Anzahl der zu schreibenen Bytes geändert. 63 Byte sind es bei IO-Warrior 56 und auch nur bei der der Special-Mode Pipe.

Beim Io-Warrior 40 sind des bei der IO-Pipe 5 ( 1x ReportID und 4 Bytes Daten) und bei der Special-Mode Pipe 8 (1x ReportID und 7 Daten).

Also einfach zwischen den Skriptausführungen ein wenig Warten und schaun ob es was bringt.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
EITA
Posts: 3
Joined: Sun Oct 21, 2012 1:16 pm

Re: IO-WARRIOR40 mit Python!

Post by EITA »

Hallo Christoph,

danke für die Anpassung des Codes, denn das hat jetzt super funktioniert. Danke vielmals!

Falls ich das richtig verstanden habe, entspricht ein Port 8 Pins. Heißt das, wenn ich ein Port auf 1 setze, dann werden alle Pins dieses Ports auf 1 gesetzt? Wenn ja, dann möchte ich wissen, ob es möglich ist die Pins einzeln auf 1 bzw. 0 zu setzen?

P.S: so sieht mein Code jetzt aus:

Code: Select all

import ctypes
from ctypes import *
import time

class Iow40_IoStruct(Structure):
    _fields_ = [("ReportId", c_ubyte), 
                ("Port_0", c_ubyte), #Like Byte[0]
                ("Port_1", c_ubyte), #Like Byte[1]
                ("Port_2", c_ubyte), #Like Byte[2]
                ("Port_3", c_ubyte)]  #Like Byte[3]

IowKitHandle = windll.Iowkit.IowKitOpenDevice()
try:   
    windll.Iowkit.IowKitSetWriteTimeout(IowKitHandle, 1000)
    windll.Iowkit.IowKitSetTimeout(IowKitHandle, 1000)
    print "DevHandle: ", str(IowKitHandle)
    
    IowKit_ID = windll.Iowkit.IowKitGetProductId(c_ulong(IowKitHandle)) 
    print "ID: ", str(IowKit_ID)
    
    IowKit_NumbDevs = windll.Iowkit.IowKitGetNumDevs()  
    print "NumbDevs: ", str(IowKit_NumbDevs)
    
    IowKit_Revision = windll.Iowkit.IowKitGetRevision(c_ulong(IowKitHandle))
    print "Revision: ", str(IowKit_Revision)
    
    SerNumb=create_unicode_buffer("xxxxxxxx")
    IowKit_SerNumb = windll.Iowkit.IowKitGetSerialNumber(c_ulong(IowKitHandle), SerNumb)
    print "SerNumb: ", str(SerNumb.value)

    # Motor Arm rausziehen bzw. Taste drücken.
    datac = Iow40_IoStruct()
    BytesWritten = windll.IowKit.IowKitWrite(IowKitHandle, 0, pointer(datac), sizeof(Iow40_IoStruct))
    time.sleep(0.2)

    # Motor Arm reinziehen bzw. Taste los lassen.
    datac = Iow40_IoStruct(0x00, 0x00, 0x00, 0x00, 0xfe)
    BytesWritten = windll.IowKit.IowKitWrite(IowKitHandle, 0, pointer(datac), sizeof(Iow40_IoStruct))

    windll.Iowkit.IowKitCloseDevice(IowKitHandle)
except Exception, e:
    print str(e)
Danke nochmal für die Hilfe.
User avatar
Christoph Jung
Posts: 670
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: IO-WARRIOR40 mit Python!

Post by Christoph Jung »

Naja das gehört zwar zu den Grundkenntnissen der Programmierung, aber ich bin mal nicht so.

Ein IO-Port hat 8 Pins, das ist richtig und das Entspricht einem Byte welches wiederrum 8 Bit hat.
Ein Byte hat einen Bereich von 0 .. 255 (Dezimal) oder von 0x00 bis 0xFF (Hexadezimal).

Wenn man also einen Port schreiben will, dass der erste und der letzte Pin an einem Port gesetzt sind schreibt man 0x81 rein oder 129 (Dezimal).
Dabei ist der Taschenrechner von Windows 7 ganz praktisch, der hat in der Programmierungsansicht die nette angewohnheit die Zahl auch in einzelnen Bits anzuzeigen (also 1000 0001 in diesem Fall).

Wenn man neue Daten reinschreiben möchte, also z.B. 0x44 und die alten Pins gesetzt(!) bleiben sollen muss man den alten und den neuen Wert zusammennehmen und dann gemeinsam reinschreiben. Sprich 0x81 + 0x44 ergibt 0xC5.
Man überschreibt mit jedem schreibbefehl die alten Daten nämlich.

Hoffe das war einigermaßen verständlich.
Abteilung: Softwareentwicklung
Folge uns auf Twitter
Follow us on twitter
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Re: IO-WARRIOR40 mit Python!

Post by Guido Körber »

Also ich kann zwar kein Python, aber mir sieht das doch sehr danach aus, dass die Daten für die Ports vor dem ersten Schreiben an den IO-Warrior nicht gesetzt werden?

Dann ist es eine Frage der Variablenverwaltung von Python was in dem Struct drin steht und das wird dann an den IO-Warrior geschrieben.
Post Reply