USBLotIO

Aus Hobbyelektronik.org
Wechseln zu: Navigation, Suche
AVR
Typ ATtiny45
Takt 16,5 MHz
Fuses
High 0x75
Low 0xE1
Extended 0xFF
Engbedded com logo.png Details


Die parallele Schnittstelle am PC ist tot. Nachdem sie schon vor einigen Jahren bei Notebooks verschwunden ist, findet man sie heute auch kaum noch bei Desktop-PCs. Selbst bei teureren Mainboards sind oft nur noch Pinheader vorhanden. Ein Slotblech dafür wird generell nicht geliefert. Die ganzen Drucker sind jetzt schneller und mit dünneren Leitungen per USB angebunden. Soweit, so gut. Nur wird die Luft für Bastler langsam dünner, wenn man keine größeren Ambitionen zu RS232 hat (deren Anschlüsse am PC auch langsam aussterben).

Aus diesem Grund hatte ich die Idee, eine kleine Schaltung zu bauen, die zwar keinen Ersatz aber eine Alternative zum guten alten Parport darstellt.

Anforderungen

  • Anbindung, die auch noch in ein paar Jahren funktioniert
  • Einfacher Aufbau
  • Einfach vom PC ansprechbar
  • Erweiterbar

Hardware

Stromlaufplan der Platinen

Die Anbindung an den PC findet per USB statt. Hier soll (wieder einmal) V-USB zum Einsatz kommen. Davon gibt es zwar schon ein Referenzdesign (PowerSwitch), dieses hat meiner Meinung ein paar Schwachstellen:

  • keine Erweiterbarkeit
  • Treiber erforderlich (laufen die vorhandenen überhaupt unter Win7?)
  • relativ großer Aufbau

Diesen Schwächen möchte ich mit einem ATTiny45 entgegenwirken. Dieser ist schön klein und braucht dank PLL (und automatischer Taktkalibrierung per USB) keinen externen Quarz. Damit man keine Treiber braucht, soll er sich dem Computer gegenüber als HID (Human Interface Device) ausgeben. Bleibt nur noch eines: Mit der Anbindung am PC bleiben nur noch 4 Pins am Tiny über - einer davon ist der Reset-Eingang - wie soll man da großartig Ausgänge schalten können? Ganz zu schweigen von der angestrebten Erweiterbarkeit...

Die Lösung hierfür ist einfach: der Mikrocontroller steuert Schieberegister an, die beliebig kaskadiert werden können. So kann man quasi beliebig viele Ausgänge an den AVR dengeln. Als Ausgabeschieberegister dienen 74xx595, welche einen Latch haben und die Datenleitungen in einem Rutsch aktualisiert werden können.

Um Signale auch lesen zu können, kommen 74xx165 zum Einsatz. Zwar haben diese auch einen Latch, allerdings ist dieser (anders als beim 595) low-aktiv. Damit wird's mit 4 I/Os am AVR eng. Gut, die Strobe-Leitungen muss man trennen, Clock kann gemeinsam laufen, nur sind jetzt schon alle Pins belegt. Es ist zwar möglich, die Daten ins Register zu laden, aber was bringen die Daten, wenn man sie nicht lesen kann?

Mit einem kleinen Trick kann man das aber bewältigen: Die Datenleitungen beider Richtungen auf einen I/O. Zum Schutz des Ausganges des Registers gibt es aber einen Reihenwiderstand. Zwischen dem Lesen und Schreiben muss die Datenleitung einfach nur noch als Eingang bzw. Ausgang geschaltet werden.

Aber Vorsicht: dadurch, dass der Reset-Pin auch verwendet wird, kann der Mikrocontroller nur mit HVSP programmiert werden! (oder man lässt eine "Richtung" weg - noch ungetestet).

Ein Wort der Warnung sei noch angebracht: Bei vielen PCs ist die USB-Schnittstelle NICHT abgesichert, bei einem Kurzschluss geht dann die komplette Leistung des Netzteils durch! Das kann zu zerstörten Leiterbahnen (sowohl am USB-Gerät als auch auf dem Mainboard) oder sogar Bränden führen!

In der Firmware ist eine Stromaufnahme von 20mA angegeben, welche schon bei kleineren Aufbauten überschritten werden kann. Die Inbetriebnahme findet unter eigener Verantwortung statt! Rechnungen für neue Mainboards o.a. an mich werden mit Freude durch den Aktenvernichter gejagt.

Software

AVR

Wie bereits erwähnt läuft auf dem AVR objective developments V-USB als HID. Grundlage für meine Implementierung war das "Datastore"-Beispiel, das zusätzlich um die automatische Kalibrierung der CPU-Frequenz erweitert wurde.

Da die USB-Schnittstelle zwangsläufig auf einem Interrupt-Pin hängt, der gleichzeitig auch für SPI verantwortlich ist, müssen die Schieberegister mit einem wesentlich langsameren Soft-SPI angesprochen werden.

Der USB-Client reagiert bei dem Beginn einer Übertragung mit einem Aufruf der Methode usbFunctionSetup. In ihr wird dann entschieden, ob es sich um einen Schreib- oder Lesevorgang handelt. Hier wird zum einen die Speicheradresse auf 0 gesetzt und beim Leseaufruf die Zustände der Registereingänge in den RAM geschrieben.

Anschließend wird von V-USB usbFunctionWrite bzw. usbFunctionRead je nach Reportgröße mehrmals aufgerufen. Im Read wird einfach nur der Inhalt des RAMs an den PC übertragen, beim Schreiben wird zuerst die Variable (die gleiche wie beim Lesen) gefüllt und nach dem letzten Wert vom PC die Methode processCommand aufgerufen.

Die übertragenen Werte werden in Anschlussreihenfolge aus Sicht der Hauptplatine angegeben. Gibt man z.B. 0x01 0x02 aus, wird am Ausgabemodul, das am nächsten zur Hauptplatine angeschlossen ist 0x01 ausgegeben, am "zweitnächsten" 0x02. Bei den Eingabemodulen verhält es sich genauso.


Dort findet das eigentliche Schreiben auf die Register statt. Zusätzlich zum simplen Schreiben kann man den Controller mit ein paar Logikfunktionen beauftragen. Diese werden immer mit der letzten Ausgabe verarbeitet. Folgende Operationen sind möglich:

  • Überschreiben
  • OR
  • AND
  • XOR

Zusätzlich kann man ein Flag zum Invertieren übergeben, dadurch werden die Funktionen NOR, NAND und XNOR sowie invertiertes Überschreiben ermöglicht. Mit einem weiteren Flag kann man die errechneten Werte ins EEProm des Controllers schreiben. Dadurch kann man direkt beim Einschalten der Hardware einen definierten Zustand ausgeben.

Das einzige, das man in der Software noch anpassen muss, ist die Anzahl der jeweiligen Schieberegister. Oder einfach unverändert lassen - dann werden jeweils 8 Register angenommen. Diese Werte muss man nur anpassen, wenn man mehr als 8 Schieberegister verwendet oder mehr Performance (Auswirkung noch nicht geprüft) wünscht.

Ferner kann man eine ID in den EEProm schreiben, um mehrere (256) Devices zu unterscheiden. Diese ID wird bei jedem Lese-Vorgang im untersten Byte des Reports zurückgegeben.

Im AVR programmierte Fuses

Damit man die Hardware vollständig genutzt werden kann, müssen die Fuses wie folgt programmiert werden (siehe auch Screenshot oder in der Infobox oben):

  • Extended: 0xFF
  • High: 0x75
  • Low: 0xE1

SPIEN kann nur deaktiviert werden, wenn man per HVSP programmiert, RSTDISBL sollte eigentlich reichen, habe ich allerdings nicht ausprobiert ;-)

PC

Auf dem PC kann eigentlich alles werkeln, was auf die entsprechenden USB-APIs zugreifen kann. Ich beschränke mich auf Windows, die Portierung auf *nix/Mac/etc. sollte aber nicht allzu schwierig sein.

Im Grunde muss man nicht viel machen, das Schwierigste dürfte wahrscheinlich das Finden des Devices sein. Ich habe im C#-Programm Teile aus der WiimoteLib von Brian Peek genommen. Ist das HID gefunden und ein Handler gesetzt, können mit HidD_SetFeature und -GetFeature Reports an den AVR gesendet oder von ihm angefordert werden.

Wichtig ist hier eigentlich nur die Größe des übergebenen Arrays, bei falscher Länge kommt oft einfach nichts beim Device an! Man kann relativ viel Zeit damit verbringen, dort nach einem Fehler zu suchen, zumal sich ein vollbelegter Mikrocontroller (dessen UART man nicht verwenden kann) schlecht debuggen lässt.

Zur Demonstration habe ich eine kleine Konsolen-Anwendung rund um die USBLotIO-Klasse geschrieben. Kann sein, dass ich die Klasse noch ein wenig umstrukturiere - die nullable Byte-Arrays gefallen mir nicht sonderlich.

Im Ordner \csharp\USBlotIO\bin\Release\ befindet sich ein kleines Konsolenprogramm (USBlotIO.exe), mit dem man alle Features der Hardware testen/nutzen kann.

Einfach einmal ohne Parameter starten, dann werden alle möglichen Aufrufe angezeigt (wem es beim Start per Doppelklick zu schnell geht: cmd starten und damit die Anwendung aufrufen).

Test

Die Hardwareinstallation ist im Baukastenprinzip. Module anstecken und per USB-Kabel mit dem PC verbinden. Nach wenigen Sekunden ist das Gerät bereit für die Verwendung.

Leider konnte ich das Board für Eingabemodule nicht testen, da Reichelt keine 74xx165 in SMD hat. Auf dem Breadboard hat es funktioniert, dennoch gebe ich momentan keine 100%ige Garantie auf korrekte Funktion!

Erfolgreich getestet wurde die C#-Anwendung bisher unter WinXP Pro SP3 sowie Windows 7. Für Vista brauche ich erst noch einen Probanden, Windows 2000 lasse ich außen vor (freue mich aber über Erfolgsmeldungen).

Download

Datei:Usblotio.zip Firmware, EAGLE-Dateien und C#-Testprogramm (VS2008, .NET 2.0)