Häufig gestellte Fragen zum USB2LPT

Es gibt Meldungen über Fehler von USB2LPT!
Folgende Bugs sind bekannt und bestätigt:


Funktioniert USB2LPT unter Windows Vista oder Windows 7?


Funktioniert USB2LPT unter Windows XP oder Windows Server?
Ja; allerdings wird stets LPT3 im Geräte-Manager angezeigt. Kann man getrost ignorieren.


Funktioniert USB2LPT mit Kopierschutzsteckern (Dongles)?
Im Allgemeinen nein!
Es besteht eine gewisse Chance für ältere Programme (etwa vor 1995; das bezieht sich auf das letzte Update!).

Im Vorfeld kann unter Windows 3.1, 3.11, 95, 98, Me und 2000 mit dem Dongle-Emulator geprüft werden, ob Zugriffe mitgeschnitten werden können. Jenes Programm läuft nicht unter XP und neuer. (Es funktioniert anscheinend, aber es wird nichts mitgeschnitten: Debugregister-Klau.)

Unabhängig vom Alter der Software besteht eine gewisse Chance, wenn man das Dongle erwartende Programm in einer Virtuellen Maschine (also im Gastsystem) startet. Wo USB2LPT laufen muss (im Host- oder im Gastsystem) muss man ausprobieren.


Warum funktionieren kommerzielle Konverter auf Seriell (RS232, COMx) gut? Und Konverter nach Parallel (Drucker) überraschenderweise nicht?
Die meiste anzuschließende Hardware verhält sich nicht wie ein Drucker, sondern wird über ein eigenes hausgemachtes Protokoll angesprochen, bspw. um einen extra angeschlossenen Drucker nicht zu stören oder direkt mit einem bestimmten Chip zu kommunizieren. Es gibt jedoch keine Windows-Funktion, um einzelne Portpins der parallelen Schnittstelle zu setzen oder abzufragen. Allenfalls Drucker oder drucker-ähnliche Geräte können angesprochen werden. Die Folge ist, dass jeder Programmierer sein eigenes Süppchen kochen muss und einen Direktzugriff programmiert. Häufig werden dazu bestimmte DLLs verwendet, etwa inpout32.dll oder porttalk.dll.

Serielle Schnittstellen sind in ihrer Funktionalität durch die Win32-API so gut abgedeckt, dass ein Direktzugriff so gut wie nie erforderlich ist (und auch recht viel Arbeit macht). Die Steuerleitungen RTS und DTR sind neben TxD mittels EscapeCommFunction() digital steuerbar. Die Statusleitungen CTS, DSR, DCD, RI und RxD können mittels GetCommModemStatus() abgefragt werden. Dies gilt übrigens auch für 16-bit-Windows-Programme.

Manche Programme sind mit Umsetzern auf Seriell extrem langsam. Solche Programme benutzen die beiden Steuerleitungen RTS und DTR; die Umsetzung von EscapeCommFunction() auf USB ist bisweilen schlecht gelungen. In diese Kategorie fallen einfache Programmiergeräte für PICs.


Ich programmiere selbst und möchte mit einigen Ausgabeleitungen ein externes Gerät steuern (bspw. Kamera-Verschluss, Fernrohr-Rotor, Flüssigkristall-Anzeigen). Da erscheint USB2LPT die richtige Lösung zu sein, oder?
Nein, USB2LPT ist hierfür nicht perfekt, wenngleich geeignet. Die Nachteile sind:

Für bis zu 3 Ausgabeleitungen (und bis zu 5 Eingabeleitungen) nimmt man besser das serielle Port (siehe oben). Dann funktionieren USB→Seriell-Umsetzer wie dieser problemlos. Nur um die Pegelumsetzung nach TTL muss man sich kümmern, wenn erforderlich; am einfachsten mit Zener-Dioden 3,9 V. Die maximale Datenübertragungsrate über USB liegt bei 1000 Pegelwechseln pro Sekunde. Bei echten seriellen Schnittstellen bei 10000 Pegelwechseln pro Sekunde.
Die Steuerung der Ausgabeleitungen erfolgt mittels (Win32:) EscapeCommFunction(), das Abfragen von 4 Eingabeleitungen mittels GetCommModemStatus(), RxD mittels WaitCommEvent() (man muss auf EV_BREAK warten).
Obendrein kann man via TxD Einzelpulse definierter Länge im µs-Bereich ausgeben, indem man bei gewählter Baudrate ein geschicktes Byte aussendet. Und mittels RxD kann man die Pulslänge von eingehenden Einzelimpulsen in 8 Stufen „messen“, indem man das Empfangsbyte entsprechend auswertet.
Vorteil: Funktioniert gleichermaßen mit eingebauten sowie USB-seriellen Schnittstellen. Einfache Zeitsteuerung möglich
Nachteil: Bei USB-Seriell-Konvertern ist eine herstellerspezifische Treiberinstallation erforderlich. Pegelkonvertierung

Für bis zu 8 Ausgabeleitungen und 3 Eingabeleitungen ist die Verwendung von handelsüblichen USB→Drucker-Adaptern (oder dieser) eine günstige Lösung, sofern man auf die „harte“ 5-V-USB-Speisespannung verzichten kann. Die Ankopplung erfolgt mit dieser oder jener Hilfsschaltung — oder komfortabel und universell mit Eingangsbitparallelisierung. Die maximale Ausgabe-Datenübertragungsrate liegt bei 100000 Pegelwechseln pro Sekunde (auch mehrere Leitungen gleichzeitig, das ist schon recht schnell). Günstig für LEDs und Flüssigkristall-Anzeigen mit Controller (Text oder vollgrafisch), Hauptsache, man kommt mit 8 Ausgabeleitungen hin. Auch typisch serielle Gerätschaften wie Schrittmotoren, serielle D/A-Wandler sowie im Amateurfunkbereich gern verwendete DDS-Generatoren lassen sich damit gut ansteuern.
Die Statusleitungen ERR ⑮, ONL ⑬ und PE ⑫ können mittels DeviceIoControl(…,IOCTL_USBPRINT_GET_LPT_STATUS,…) mit maximal 1 kByte/s gelesen werden. Zur Not lässt sich INIT (16) als Reset-Ausgabeleitung benutzen, mittels DeviceIoControl(…,IOCTL_USBPRINT_SOFT_RESET,…) kann man einen LOW-Impuls von einigen µs Dauer ausgeben. Die übrigen Steuer- und Statusleitungen STB ①, AF ⑭, SEL (17), ACK ⑩ und BUSY ⑪ können definitiv nicht verwendet werden!
Für den Einsatz solcher Konverter spricht, dass diese oftmals als Fehlinvestitionen in Schubläden des Bastlers herumgammeln und auf ihren Sankt Nimmerleinstag warten (denn Drucker mit Parallelport verschwinden ebenfalls). Die Nachbausicherheit ist durch den massenhaften Import aus China gegeben.
Vorteil: Viele Ausgabeleitungen, hohe Geschwindigkeit, keine sichtbare Treiberinstallation (außer Win98), TTL-Pegel
Nachteil: Alternative echte Parallelports erfordern Verzweigung in Software mit dem Problem des Direkt-Portzugriffs, AUSSER bei Verwendung meiner InpOut32.dll (enthält automatischen Redirektor). Geringere Verbreitung
Ein Handle zum USB→Drucker-Adapter bekommt man unter Windows mit diesem unübersichtlichen SetupAPI-Kode. Bei Linux ist es hingegen so einfach: Bloß /dev/usb/lpn öffnen …

Beliebig viele Ausgabeleitungen kann man mittels Portexpandern (74HCT595) aus jeder der vorhergehenden Lösungen erreichen.

Für Aus- und Eingabeleitungen und USB-Strom (und eingebaute Intelligenz) nehme man (am besten HID-basierte) Lösungen, etwa diese oder jene oder — noch besser — dieses Universalkonzept (wollte ich eigentlich erfinden).
Damit hat man keinerlei Sorgen mit Kernel-Mode-Treiber, Debugregister-Klau oder x64. USB2LPT bietet zusätzlich ein HID-kompatibles Interface.

Wer 8..16 Ports via serielle Schnittstelle (COM-Port) steuern will, kommt am preiswertesten und bastelfreundlichsten mit einem PIC16F145x weg. Einen Urlader mit zusätzlicher Ein-/Ausgabe-Funktion habe ich mit Assembler in 512 14-Bit-Worte gequetscht. Und hier ist die Firmware. Damit kann man sogar Analogwerte einlesen und PWM generieren. Mit dem Datenblatt in der Hand muss man sich da Portadresse für Portadresse durcharbeiten.

Für bis zu 2 (manchmal auch 6) Ausgabeleitungen mit exakter Zeitsteuerung im µs-Bereich nimmt man die … Soundkarte!! Um das Problem der fehlenden Gleichspannungskopplung und der unbekannten (kleinen) Spannungspegel muss man sich selber kümmern (OPV, Komparator); der Ausgang ist ohnehin nur für kurze Impulse geeignet. Statt analoger Werte gibt man nun eben digitale Werte mittels (Win32:) waveOutWrite() aus.


Einsatz zur Schrittmotorsteuerung von CNC-Maschinen: Schafft USB2LPT die notwendigen hohen Schrittfrequenzen?
Da muss ich erst mal ganz weit ausholen: Jetzt müsste nur noch das Funktionsprinzip der NC-Steuerung abgeändert werden; das bekannteste MACH3 hat dafür ein geeignetes, brauchbar dokumentiertes Plugin-Interface.

Als Mikrocontroller zur Stromsteuerung kommen am ehesten ARM7-basierte Controller wie NXP (ehem. Philips) LPC214x oder Atmel AT91SAM7S oder etwa AT32UC3B64 zum Einsatz. Die modernen MSP430F55xx von Texas Instruments sind wegen fehlender isochroner USB-Pipes leider nicht geeignet.
Ich werde mich umgehend diesem Problem annehmen da mir eine NC-Maschine vor die Füße gefallen ist; hat aber nichts mehr mit USB2LPT zu tun. (110401)

Die theoretische maximale Schrittfrequenz bei USB2LPT (High-Speed) ist 4 kHz. Praktisch ist das Limit eher bei 1 kHz. Sonderlich äquidistant ist die Ausgabe dann trotzdem nicht. Deshalb: Für verminderte Verfahrgeschwindigkeiten ist USB2LPT 1.7 geeignet. Wegen seines RAM-Hauptspeichers ließe sich eine maßgeschneiderte Firmware on-the-fly herunterladen, die deutlich mehr kann als ein klassisches Parallelport und dem Steuerrechner die Forderung nach Echtzeit nimmt.
Mit etwas lausigerer Performance (aber immer noch viel besser als jedes native USB2LPT, womöglich sogar besser noch als ein echtes Parallelport) ließe sich USB2LPT 1.6 (1.5) zu einer derartigen Steuerung umfunktionieren: Gleiches Gehäuse, gleiche Leiterplatte, gleiche Bestückung, gleicher Bootloader, andere Firmware, und somit anderes Gerät. Genug Platinen habe ich ja noch. Problem bei V-USB-basierten Lösungen bleibt, dass USB-Transfers Interrupts sperren und damit ein gewisser Jitter unvermeidlich ist. Dieser liegt – bei INTERRUPT-Transfers mit 8 Byte Nutzdaten – bei 120 µs. Wie sehr das stört muss das Experiment zeigen! Problem ist und bleibt die Anbindung an bereits vorhandene CAM-Programme.
Für MACH3 gibt es spezielle USB-Ausgabekarten — bspw. SmoothStepper — für hohe Verfahrgeschwindigkeiten. Diese sind nicht umsonst entwickelt worden und auch nicht umsonst teurer. Wie oben bemerkt sind derlei Karten ein rechentechnischer Umweg, weil die nachgeschaltete Mikroschrittsteuerung die Schritte wieder in Strangstromwerte umwandeln muss.

Übrigens: Warum Schrittmotor-Endstufen mit dem bipolaren Heizstein L298 immer noch zu astronomischen Summen verkauft werden, ist mir ein Rätsel. Schon längst gibt es ausgereifte Lösungen in MOSFET-Technologie, entweder mit externen Transistoren (für große Leistungen) oder vollintegriert wie beim A4983 (immerhin 2 A). Da wird's bestenfalls handwarm.


Für die Steuerung von LCD wurde mir USB2LPT empfohlen. Ist das korrekt?
USB2LPT eignet sich recht gut für LCD. Meistens geht es ja um die Ansteuerung des HD44780-kompatiblen Displaycontrollers. Für controllerlose Displays ist USB2LPT nicht geeignet!

Aber genau genommen muss ich auch hier ausholen:
Ernsthafte Bastler, die das Programmieren von Mikrocontrollern scheuen, sollten es mit USB→Drucker-Adaptern (siehe oben) versuchen. Vorteile: Nachteil: Zurzeit ist dafür noch Windows-Treibersoftware zu programmieren, solange bis sich ein Bastler-Quasi-Standard dafür herausgebildet hat.


Kann man, anstatt extra eine Schaltung mit dem EZUSB aufbauen zu müssen, den in vielen Konvertern verbauten Prolific PL-2305 nicht dazu verwenden?
Foto eines USB-zu-Parallel-Konverters
Ein gewöhnlicher Parallelport-Adapter von innen (NICHT die von mir gefertigte Leiterplatte!)
Diese Konverter emulieren USB-Drucker ensprechend der USB-Geräteklasse Nr. 7. Das Protokoll sieht nicht den Zugriff auf einzelne Portpins vor. Gerade mal »Paper End«, »Select« und »Error« können abgefragt werden. Siehe oben. Die 8 Datenleitungen können nur dann per Bulk-Out-Transfer gesetzt werden, wenn sich eine Logik an den Steuerleitungen wie ein Drucker verhält: Das erfordert Brücken zwischen Und selbst dann erscheinen die Daten nur kurzzeitig und müssen mit einem 8-bit-Latch aufgefangen werden — etwas aufwändig, nur 8 Bit Ausgabe. Ein funktionierendes Beispiel ist dieses Discolitez-Plugin zur Steuerung von 8 Lampen aus WinAMP.


Ließe sich ein solcher Chip (PL-2305) nicht umprogrammieren?
Der Chip ist sicherlich maskenprogrammiert. Oder OTP (one-time programmable). Ex und hopp. Nichts zu machen.
Vielleicht hat er ja eine Hintertür (zusätzliche Control-Transfers zum direkten Zugriff auf Portpins), aber das ist erstens unwahrscheinlich und zweitens unheimlich schwer herauszufinden.

Der PL-2305 hat eine Hintertür. Sein Beschreiber-Aufbau ist nämlich folgender:
  • Gerät (String-Deskriptoren über EEPROM einstellbar), Klasse »Multifunktion«
    • Konfiguration Nr. 1
      • Interface Nr. 0
        • Alternative Einstellung Nr. 0
          Klasse: 07/01 = Drucker, Protokoll: 01 = eine Richtung
          • Ende Nr. 2, Bulk, Ausgabe, 64 Bytes
        • Alternative Einstellung Nr. 1
          Klasse: 07/01 = Drucker, Protokoll: 02 = zwei Richtungen
          • Ende Nr. 1, Bulk, Ausgabe, 64 Bytes
          • Ende Nr. 2, Bulk, Eingabe, 64 Bytes
        • Alternative Einstellung Nr. 2
          Klasse: FF/00 = gusto, Protokoll: FF = gusto
          • Ende Nr. 1, Bulk, Ausgabe, 64 Bytes
          • Ende Nr. 2, Bulk, Eingabe, 64 Bytes
          • Ende Nr. 3, Interrupt, 4 Bytes, Abfrageintervall: 1 ms
Die »Alternative Einstellung Nr. 2« ließ sich nicht zu einer geeigneten Funktion bewegen. Vermutlich handelt es sich hierbei um eine ansatzweise Implementierung des IEEE-1284.4-Protokolls.


Kann man nicht irgendwie doch noch die Trägheit der IN-Zugriffe verringern? (Auch ohne Änderung der Software?)
Könnte man! Wenn es gelingt, den Weg des gelesenen IN-Bytes zu verfolgen und dieses dann nachträglich zu modifizieren. Bei einem bedingten Sprung erscheint mir der Schluss mit einer solchen Prädiktion. Weil viele IN-Befehle Status-Abfragen sind (denen ein bedingter Sprung folgt), erscheint es mir wenig sinnvoll.
Lohnenswerter erscheint die Emulation von REP INS-Befehlen. Diese kommen aber beim Druckerport so gut wie nie vor, höchstens bei ECP/EPP.


Kann man durch Änderung der Software eine Geschwindigkeitssteigerung erreichen?
Auf jeden Fall, wenn sich IN-Zugriffe zusammenfassen lassen. Dann sendet man entsprechende Datenblöcke (Dokumentation siehe Quelltext und API-Dokumentation) an den Konverter, die er umgehend ausführt und die Antwort-Bytes zurückgibt.
Der Mikrocontroller führt die IN- und OUT-Befehle etwa in 1 µs aus. Eine langsamere zeitliche Abfolge lässt sich per se nur in 1-ms-Stückelung erreichen. Für Wartezeiten im µs-Bereich ist ein Warte-Befehl im zu sendenden Datenblock vorgesehen.

Der High-Speed-Konverter hat folgenden Beschreiber-Aufbau:
  • Gerät "USB2LPT-Konverter", Klasse »Multifunktion«
    • Konfiguration Nr. 1
      • Interface Nr. 0
        • Alternative Einstellung Nr. 0
          Klasse: FF/FF = gusto, Protokoll: FF = gusto
          • Ende Nr. 2, Bulk, Ausgabe, 64 Bytes
          • Ende Nr. 2, Bulk, Eingabe, 64 Bytes
      • Interface Nr. 1
        • Alternative Einstellung Nr. 0
          Klasse: 07/01 = Drucker, Protokoll: 01 = eine Richtung
          • Ende Nr. 4, Bulk, Ausgabe, 64 Bytes
        • Alternative Einstellung Nr. 1
          Klasse: 07/01 = Drucker, Protokoll: 02 = zwei Richtungen
          • Ende Nr. 4, Bulk, Ausgabe, 64 Bytes
          • Ende Nr. 4, Bulk, Eingabe, 64 Bytes
Mit zwei Interfaces bildet das Gerät ein echtes »Multifunktionsgerät«, für das Windows auch zwei Treiber lädt.

Für genauere Zeitsteuerung empfiehlt es sich, eine selbstgeschriebene 8051-Firmware in den Mikrocontroller zu laden und ausführen zu lassen. Dann »verkommt« dieser Konverter zum gut verpackten Demo-Board für den EZUSB.


Gibt es auch USB2LPT mit männlichen SubD-Steckern?
Man kann nicht einfach statt der Buchse einen Stecker bestücken! Das würde zum Pintausch 1↔13, 2↔12 usw. führen.
Eine neue Leiterplatte wäre erforderlich: Lohnt nicht; dafür gibt es preiswerte „Mini Gender Changer“ zu kaufen.


Gibt es auch USB2LPT mit 36-poligen Centronics-Steckern?
Eine neue Leiterplatte wäre erforderlich. Außerdem gibts keine ordentlichen (Plast-)Gehäuse zu kaufen (Hauptproblem). Ein Druckerkabel als Adapter tut's doch auch!


In meinem Windows-XP-Computer habe ich schon 3 PCI-Parallelports eingebaut, und ich möchte USB2LPT als LPT4 verwenden. Ist das möglich? Kann ich etwas in der Registrierungsdatenbank ändern, um Windows beizubringen, dass 4 Parallelports existieren?
Zu letzterem ist mir nichts bekannt; Windows sollte von selbst beliebig viele Parallelports per PnP finden und verwalten können.

USB2LPT.SYS enumeriert sich auf das nächstfreie LPT-Port bis zu LPT9999. Damit ist USB2LPT als viertes Parallelport automatisch bspw. mittels CreateFile("\\\\.\\LPT4", …) ansprechbar.

USB2LPT.SYS hingegen enumeriert sich nicht mit Funktionen wie SetupDiEnumDeviceInterfaces(), im Gegensatz zu echten Parallelports. Ich weiß nämlich nicht, wie man das programmiert.

Auch kann man das USB2LPT-Parallelport nicht über die Registrierung erfassen – hier gab und gibt es unterschiedliche Wege.

Die meisten Anwendungsprogramme interessieren sich überhaupt nicht für die „Nummer“ des Parallelports (daher spielt deren Anzahl überhaupt keine Rolle), sondern nur für seine Basisadresse. Diese müssen Sie im Geräte-Manager unter USB2LPT→Eigenschaften wahlfrei einstellen, und dabei eine freie, noch nicht anderweitig verwendete Adresse angeben.
Ohne nachzusehen ist man ziemlich sicher mit Adressen von 100h bis 1D8h.

Nicht „austricksen“ lassen sich DOS-Programme, die die Basisadresse von den Adressen [40h:08h], [40h:0Ah] oder [40h:0Ch] lesen, es sei denn, Sie schreiben ein kleines DOS-Hilfsprogramm, welches die o.g. Speicherzelle modifiziert und anschließend das gewünschte DOS-Programm (Int21/AH=4Bh) startet.


Wie sieht's mit Linux-Treibern aus?
Ich hätte nicht gedacht, dass man für Linux einen Treiber braucht, ist da nicht i.d.R alles quelloffen? So kann man den Quelltext anpassen und die notwendigen USB-Transfers anschubsen.

Bevor ein Linux-Treiber geschrieben wird, sollte erkundet werden, auf welches device die in Frage kommenden Programme zugreifen, und welche Steuerkodes benutzt werden. Oder greifen die Programme per modifizierter IOPM-Tabelle aus dem User-Mode direkt auf Portadressen zu? Dann wären ebenfalls Klimmzüge wie Debugregister-Trap notwendig...

Aber ich verwende kein Linux und habe keine Ahnung von Linux-Kernel-Programmierung, noch dazu die fällige PnP-Unterstützung für die verschiedenen Distributionen.

Anmerkung von JGrosJean at ieee.org: “My low speed USB2LPT works in WinXP running on a virtual machine using Oracle VirtualBox in Linux.”


Kann man das USB-Gerät mit einem anderen Mikrocontroller als Cypress CY7C68013A oder Atmel ATmega8 bauen?
Ja.

Um den gleichen Treiber verwenden zu können, muss man nur das Interface 1:1 nachbilden. In diesem Fall ist auch die Wiederverwendung „meiner“ VID und PID zulässig und vernünftig.

Das Interface ist offen gelegt und durch zwei verschiedene Quelltexte (einer in 8051-Assembler und einer in avrgcc-C) nachvollziehbar. Siehe API.


Es wird permanent „Neue Hardware“ gefunden, alles geht gut (das Gerät funktioniert sogar!) und am Ende kommt so eine sinnlose Fehlermeldung wie „Genannte Datei wurde nicht gefunden“. Sobald man auf „Abbrechen“ klickt, geht's wieder von vorn los. Neuinstallation von Windows (hier 2000)?
Der Registrierungsschlüssel HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce wird benötigt, sonst kommt es zu diesem Fehler bei jedem neuen USB-Gerät.

Tipp gefunden bei Dokumentation von u-eye, Danke! Application Note AN_AB.1.0019