Anykey x6

Aus Hobbyelektronik.org

There's also an English translation of this article.

Fertig aufgebaute Hardware (Farben leicht retuschiert)

Meine Schwester ist Lehrerin.

Ein Job, um den ich sie nicht beneide - gerade in 2020. Hier in Bayern fängt (Stand Anfang Mai) das Leben an der Schule langsam wieder an, parallel zum Unterricht in den Schulen müssen jedoch die daheim bleibenden Kinder noch unterrichtet werden. Wenn man die eigene Arbeit ernst nimmt, ist das kein Spaß. Klar, man könnte für das Eigenstudium einfach Arbeitsblätter über den Zaun werfen und auf Seiten in den Büchern verweisen, aber wenn ich da an meine eigene Schulzeit und die eher extrinsische Motivation denke...

Obwohl meine Schwester schon sehr viel digital hat, braucht Unterricht (gerade bei Sprachen) auch jemanden, der/die vor der Klasse spricht und natürlich ist eigenständiges Lernen für viele nicht ganz einfach. Aus diesem Grund hat meine Schwester angefangen, Videos zu machen. Vorerst nur mit ausgedruckten Blättern und dem Handy auf dem Stativ. Um Ihre digitalen Materialien besser nutzen zu können, fragte sie dann doch mal nach einem screen recorder. OBS war schnell installiert und eingerichtet. Blöd nur, dass sie keinen zweiten Monitor (bzw. Displayport-Adapter) für ihr MS Surface hat.

Damit ihre Schüler sie auch mal sehen können (oder auch mal "Tafelunterricht" zu machen), habe ich ihr mehrere Szenen in OBS eingerichtet:

  • Bildschirmaufnahme
  • Bildschirmaufnahme + Kamera in der Ecke
  • Kamera

Blöd ist nur, dass sie ohne besagten zweiten Bildschirm für jede Aktion OBS in den Vordergrund holen muss. Zwar kann man dort auch globale Hotkeys anlegen, aber ohne vollständige Tastatur läuft man sehr schnell Gefahr, Doppelbelegungen zu bekommen und dadurch sehr merkwürdiges Verhalten am PC zu haben. Gleichzeitig sieht man nicht, was OBS nun tatsächlich macht.

Ja, man kann eine Fernbedienung für OBS auf dem Tablet oder Smartphone installieren, aber das schafft eigentlich nur mehr Probleme als es löst, zumal man die (freien) Clients, die ich auf Anhieb gefunden hab für jede Session neu konfigurieren muss. Zudem muss das Gerät am Laufen halten und kann die Tasten nicht erfühlen. Das lenkt unnötig ab und erhöht auch die Akzeptanz nicht wirklich.

Auch fertige Lösungen wie das Elgato Stream Deck ist für die (hoffentlich) kurze Nutzungsdauer unverhältnismäßig teuer.

Gleichzeitig sitzt hier ein Ingenieur herum, der aufgrund der aktuellen Situation erst einmal Gleitzeit abbaut.

Die Idee

Da kann man doch was basteln. Ein paar Taster, ein paar LEDs, ein bisschen Firmware und noch ein paar Zeilen Code auf dem PC. Was soll daran so aufwändig sein?

Um eines vorweg zu nehmen: Übers Ziel hinausschießen, das kann daran aufwändig werden.

Ziel ist, 6-8 bunt beleuchtete Taster zu haben, die in OBS eingebunden werden können.

Der Mikrocontroller ist schnell gefunden. Um nicht zu weit von den Codebeispielen von V-USB zu sein, soll ein oller ATmega8 zum Einsatz kommen.

Weil ich schon länger was mit intelligenten LEDs machen wollte, liegt schon viel zu lange ein Streifen mit WS2812B herum. Der Plan war, diese – womöglich sogar noch auf dem Streifen – auf Taster zu kleben.

Natürlich muss der WAF auch halbwegs passen, deshalb ist ein nicht zu schäbiges Gehäuse angesagt.

3D-Drucker sei dank bin ich auch dazu (zumindest seitens der Ausstattung) in der Lage.

Elektronik

Die Ernüchterung kam schneller als erwartet.

Dass die Ansteuerung der LEDs zeitkritisch ist, wusste ich. Dass das auch für V-USB gilt, ebenfalls. Dass man beides nicht so einfach kombinieren kann, würde dann sehr schnell klar. Der USB-Stack braucht zwingend einen Pin-Interrupt, für die Ansteuerung der LEDs muss dieser aber abgeschaltet werden – sonst blinkt alles wie ein Weihnachtsbaum auf LSD. Tim (aka cpldcpu) hat sich die Mühe gemacht, V-USB mit Polling zu ermöglichen - gleichzeitig sogar mit entsprechender LED. Den Weg wollte ich nicht gehen, weil das potenziell an anderen Stellen schmerzhaft werden könnte.

Ok, was nun? Ein Coprozessor, der UART/I²C auf das LED-Protokoll umwandelt? Eigentlich wollte ich kein Mehrprozessor-System bauen – und auch hier bleibt das Problem mit Interrupts vs. keine Interrupts, auch durch die Einschränkungen durch USI dürfte das noch etwas unentspannter sein.

Da ist guter Rat teuer.

Auf einfarbige LEDs wollte ich aber auch nicht zurückgehen.

LED-Treiber

6 RGB-LEDs mit PWM anzusteuern, braucht es 18 PWM-Kanäle. Das hat glaube ich kein AVR8. ich habe zwar noch einen PCA9685 herumliegen, der aber auch nur 16 Kanäle bereitstellt. Zudem nimmt das Teil mit seinem Breakout-Board relativ viel Platz ein. Zu viel für das, was ich vor dem inneren Auge habe.

Habe ich 18 Kanäle geschrieben? Jein. Betreibt man Multiplexing, reichen zwischen 3 und 6. Schlussendlich habe ich mich dafür entschieden, die Farben in den Multiplex zu nehmen und den PWM pro Taste laufen zu lassen - mit entsprechenden Einbußen der Helligkeit (ein Drittel). Aber wo bekommt man an einem ATmega8 6 synchrone PWM-Kanäle her? Ganz einfach: gar nicht. Zumindest in Hardware - anders schaut es in Software aus, wo es auch keine richtige PWM ist, sondern eher eine Pulsleistungsmodulation (kurz PDM - einen passenden Begriff konnte ich finden, daher die Neukreation), wie sie 2011 auf der Schatenseite schon beschrieben wurde.

Um es kurz zu beschreiben: bei gewöhnlicher PWM gibt es für jeden Kanal zwei Schaltzeitpunkte, von denen einer pro Kanal individuell ist (da er den Helligkeitswert vorgibt). Hat man n Kanäle, gibt es n Zeitpunkte, die man möglichst zielgenau treffen muss. Gerade wenn diese nah beieinander liegen, kann das zu Timingproblemen führen.

Der hier verwendete Dimmer funktioniert anders. Man muss dabei bedenken, dass es beim Dimmen von LEDs relativ egal ist, ob sie über einen Zyklus am Stück an sind, oder ob sie zwischendurch ausgeschaltet werden - wichtig ist unterm Strich nur, wie viel sie im im Laufe eines Zyklus aktiv sind.

Bei einer Auflösung von b bit gibt es bei dieser Methode b Zeitpunkte - ganz egal wie viele Kanäle man verwendet und: deren Timing ist fest. Zudem sind diese sind zeitlich immer mit Faktor 2 voneinander getrennt. Nun schaltet man den Kanal immer dann an, wenn im Helligkeitswert das "Bit" des zugehörigen Zeitschlitzes aktiv ist.

Da es visuell deutlich besser als mit Text funktioniert, hier mal zwei Beispiele mit einer Modulation mit 3 Bit. Die Wertigkeit steht links, die An-Zeiten entsprechen den grünen Blöcken (deren X-Achse der Zeit entspricht) und die nötigen Interrupts sind mit roten Pfeilen markiert:

Betrachtet man die aktive Fläche der einzelnen Helligkeitswerte, kommt man auf das gleiche - nur dass die PDM deutlich ressourcenschonender ist. Dazu kommt der Effekt, dass durch das "Zerhacken" der PWM die LEDs mit einer höheren Frequenz flackern (auch wenn sie variiert). Dadurch wird der Stroboskop-Effekt verringert - des einen Freud ist des anderen Leid: achtet man auf EMV, wird es and er Stelle unangenehmer.

Aber genug dazu.

Aufgrund des Multiplexing gibt es, wie oben beschrieben, nur ein Drittel an Helligkeit. Die meisten LEDs halten bei pulsförmiger Ansteuerung deutlich mehr Strom als im Dauerbetrieb aus weil der limitierende Faktor die Erwärmung ist. Da die LEDs (im 5050-Gehäuse) für den Aufbau von einem LED-Streifen "geerntet" wurden, habe ich kein Datenblatt zur Komponente, aber Wissen: z. B. kommt für den roten Strang ein 330 Ohm-Widerstand zum Einsatz, bei 12 V und 3 roten LEDs in Reihe mit ca. 1,85 V Vorwärtsspannung sind das etwa 20 mA. Ohne weitere Infos zu maximalen Strömen und weil die Helligkeit eigentlich reichen sollte, bin ich bei diesem Strom geblieben.

Taster

Die Taster kommen direkt an IOs und sind gegen Masse verschaltet. Eine rudimentäre Entprellung wird in Software gemacht.

USB

Die USB-Beschaltung entspricht weitestgehend der aus den Beispielen von Objective Development. Aus reiner Faulheit habe ich die Schutzbeschaltung vom USB-Fußtaster übernommen. Sprichwörtlich: Die nötigen Bauteile bestückt und die Leiterkarte auf die passende Größe gestutzt.

Schaltplan

Die gesamte Schaltung ist also relativ einfach. Als FETs für die LEDs kommen BSS84 (p-Kanal, aufseiten der Anoden) und BSS138 (n-Kanal, aufseiten der Kathoden) zum Einsatz. Aufgrund der Komplexität reicht es als Handskizze:

Firmware

Die Firmware ist erstaunlich einfach, zumal ich mich nicht sonderlich bemüht habe.

Die LEDs werden mit der oben beschriebenen Methode (in leddrv.c) angesteuert, wobei zusätzlich noch eine Fading-Funktion zum Einsatz kommt. Das entlastet den USB-Stack und verringert das Flackern (siehe weiter unten)

Die Tasten werden (sofern die PWM nicht höhere Priorität hat) jede Millisekunde abgefragt (buttons_tick()) und wenn der Pegel low (Taste gedrückt) ist, ein Zähler inkrementiert. Bei High-Pegel wird der Zähler auf 0 zurückgesetzt.

Ist der Zähler größer als 10, gilt die entsprechende Taste gedrückt. Alle Buttons in einem Byte können über die Methode buttons_values() abgefragt werden.

In Sachen USB wird ein Out-Report (PC -> Device) mit Netto 16 Byte und ein In-Report mit Netto 8 Byte (Device -> PC) verwendet.

Der Out-Report dient zum Setzen der LEDs und sieht wie folgt aus:

> I0 R0 G0 B0 T0 I1 R1 G1 B1 T1 I2 R2 G2 B2 T2 xx

  • Ix: Index der LED (1-6)
  • Rx: Rot-Wert der LED (0 ... 255)
  • Gx: Grün-Wert der LED (0 ... 255)
  • Bx: Blau-Wert der LED (0 ... 255)
  • Tx: Dauer für den Übergang (0 ... 255, in 5 ms-Schritten)

Es können somit 3 Farben gleichzeitig geschrieben werden, Index 0 wird nicht verwendet, da es üblicherweise der Init-Wert für Arrays ist und somit nicht versehentlich die Farbe einer Taste gesetzt wird.

Der In-Report ist denkbar einfach, im ersten Byte steht das Bit-Muster der aktuell gedrückten Taster:

< K1 xx xx xx xx xx xx xx

Der Report wird bei jeder Änderung des Zustands der Taster gesendet. Das ist in mehrerlei Hinsicht nicht ganz ideal, da zum einen der Initiale Zustand (nach Öffnen des Devices) nicht ermittelt werden kann und falls doch mal ein USB-Paket verloren geht, verpasst man Tastendrücke.

Aber: es musste schnell gehen.

Mechanik

Die Mechanik ist (zumindest für mich als Neuling in Sachen Design und 3D-Druck) ein Stück aufwändiger.

Einfach nur die Leiterkarte auf den Tisch zu knallen geht hier nicht, es muss nicht wie aus dem Ei gepellt aussehen, aber nicht nur aus der Kategorie "form follows function" sein.

Um schnell voran zu kommen, kam das MS Paint im 3D-Design zum Einsatz: SketchUp. Mit allen Einschränkungen und fehlender Parametrisierung bin ich darin leider noch immer am schnellsten, etwas für den Druck vorzubereiten.

Tasten

Mit ein bisschen Zeichnen in 2D-Software stellte sich heraus, dass rechteckige Tasten mit 15 mm Breite und Höhe, einer Abrundung mit Radius 2,5 mm und einem Abstand von 5 mm zueinander eine angenehme Haptik aufweisen.

Ein erstes Muster mit Kragen (damit die Taste nicht durchs Gehäuse fällt) aus transparentem PLA, (wenn ich mich richtig erinnere) 50 % Infill und konzentrischem Top/Bottom-Pattern (in Cura gesliced) ist schnell gedruckt und sieht, nachdem es mit Farbe beschmiert wurde um zu sehen wie dicht der Druck ist, auch nach dem Reinigen versaut aus.

Licht geht durch, sieht aber eher bescheiden aus:

Als nächstes kommt die Frage: wie die LEDs und Taster montieren? um das mechanische Design zu vereinfachen, habe ich die Idee verfolgt, möglichst Gleichteile zu verwenden. In meinen letzten Leiterkarten-Bestellungen habe ich im Waste immer 1x1 mm Kupferflächen im 1,27 mm-Raster platziert, ein Streifen damit ist etwa 9,6 mm breit (bei 1,6 mm Materialdicke) - eine gute Größe für diese Anwendung.

LED auf die eine Seite, Taster auf die andere und eine Idee, für die mich die Mechaniker in der Arbeit (völlig zu Recht) vermutlich nicht mehr anschauen würden: Constraining auf zwei Bezugsebenen. Normalerweise strebt man an, dass sich die Toleranzen von einer Seite aus ausbreiten, damit man die Toleranzketten in Griff halten kann. Würde hier heißen: Die Tasten sind auf die Gehäusefront referenziert und dementsprechend müssen die Taster auch an einer Ebene montiert werden, deren Toleranz sich auf die Front bezieht.

Bei mir sollen die Taster aber gegen die Bodenplatte drücken. Mit vielen Nachteilen. Da es sich aktuell allerdings um ein Einzelstück handelt: Egal.

Das Platinchen mit LED vorne und Taster hinten wird einfach in eine Nut im Taster eingeschoben. Bis auf einen kleinen (reproduzierbaren) Druckfehler funktioniert das prächtig. Hier die verschiedenen Designiterationen:

Mit Infill auf 100 % und der Tasterfront auf dem Druckbett entsteht eine relativ schöne Oberfläche. Da Concentric Top/Bottom-Pattern ein Kreuz in der Diagonale erzeugt hat, bin ich auf "Lines" umgestiegen, das die Taster, gemeinsam mit dem konzentrischen Rahmen fast schon "wie gekauft" aussehen lässt.

Um eine bessere Farbmischung zu erzeugen (und die Taster eine eigenwillige Streuwirkung haben), habe ich etwas Band aus meinem Beschriftungsgerät (Wenn es wichtig ist: Brother P-touch) hinter den Taster geklebt. Dadurch wird die Ausleuchtung der drei LED-Kristalle zumindest ein bisschen homogener:

Insgesamt hat das Sandwich eine Höhe von 12,4 mm - 0,25 mm weniger, wenn der Taster gedrückt ist. Der Kragen ist 2,5 mm nach innen versetzt. Das, plus die Dicke der Gehäuseteile, wird die Gesamtdicke des Geräts.

Gehäuse

Mit den Maßen der Tasten geht es los, wobei die Ausschnitte für diese um 0,25 mm in alle Richtungen erweitert wurden. Das bringt zwar etwas Spiel, aber bevor der Cutter angesetzt oder nochmals gedruckt werden muss, dürfen die Tasten eher ein bisschen wackeln - zumal es bei den ersten Tastern ordentlich Elefantenfüße gab. Mit einem Überstand von 7,5 mm von der Kante der Taster zu den Gehäusewänden in drei Richtungen und etwas mehr (17,5 mm) in die vierte Richtung - irgendwo muss ja die Elektronik hin - ist das Gehäuse relativ kompakt. Im inneren befinden sich zwischen den Tastern 4 mm hohe Wände - nicht zum Ausrichten, sondern vielmehr um Streulicht zwischen den Tastern zu vermeiden. Damit sich das Gehäuse nicht durchbiegt und dadurch versehentlich mehrere Taster auf einmal betätigt werden, befinden sich in den Kreuzungspunkten der Taster Erhöhungen, die die Stabilität in Z-Richtung erhöhen.

Um Material und vor allem Druckzeit zu sparen, gab es zwei abgeschnittene Druckmuster, die man dank transparentem Filament auf weißem Grund fast nicht sieht:

Als Zugentlastung des fest installierten USB-Kabels befindet sich hinter dem U-förmigen Ausschnitt eine kleine Rampe und ein Loch, durch den ein Kabelbinder passt. Die Rampe dient lediglich dazu, dass der Kabelbinder die untere Gehäusehälfte nicht nach unten drückt. Man könnte mutmaßen, dass durch die Druckschichten bedingte Treppenstruktur die Leitung sogar ein bisschen verhakt wird.

3 Löcher, durch die M2,5-Schrauben passen, dienen zur Befestigung der Bodenplatte.

Insgesamt gab es 4 Iterationen, wobei nur zwei den Weg auf den Drucker gefunden haben - und das auch nur, weil sich das erste Druckteil vom Druckbett abgelöst und dadurch unschön verzogen hat.

Anscheinend sind die STL-Daten nicht ganz sauber, wodurch das Modell wohl etwas in der Luft hängt. Durch einen Microstep von -0,001 in Z-Richtung wurde das Druckergebnis besser, aber die erste Lage ist trotzdem noch etwas lückig...

Das untere Gehäuseteil sind eigentlich 7 Teile und brauchte keine Revision (aber einen kleinen Eingriff mit dem Skalpell). Die Komplexität ist auch deutlich geringer. Auffallend sind zunächst die 4 "Kamine" - die Idee dahinter ist, Muttern einzulegen und diese mit dem oberen Gehäuseteil zu verschrauben. Das ganze ist (eher unbeabsichtigt) auf Pressung designed, sowohl für die Mutter, als auch in Richtung anderes Gehäuseteil. Immerhin rutscht nichts.

An den Positionen der Taster befinden sich Sacklöcher/Kerben - aus einem sehr einfachen Grund: Material und Druckzeit sparen. Die Bodenplatte soll in weiten Teilen dick genug sein, dass sie stabil ist aber auf keinen Fall ein zweites Mal gedruckt werden muss.

Um die Taster in der Höhe einzupassen, werden kleine Distanznippel eingesetzt, die klein sind und dadurch sehr schnell angepasst und gedruckt werden können. Weil ich keinen Sekundenkleber mehr da hatte, sind sie lediglich einseitig auf der Bodenplatte mit doppelseitigem Klebeband befestigt.

Insgesamt war der Drucker etwa 4 Stunden beschäftigt, wobei er auch nicht mit maximaler Geschwindigkeit lief. Die Materialkosten liegen (ohne Probestücke und Fehldrucke) bei etwa 50 cent wenn ich mich nicht täusche, also nicht wirklich der Rede wert.

Zusammenbau

Ursprünglich habe ich einen Atmega8 im DIP-Gehäuse vorgesehen. Da es aber doch ein bisschen eng geworden wäre, kam dann doch einer im TQFP-Gehäuse zum Einsatz. Neben dem Mikrocontroller finden auch die 9 Transistoren für die LED-Ansteuerung Platz auf der Selfmade-Punktrasterplatine:

Die LED-Tasten bekommen gehörig lange Anschlussleitungen aus Kupferlackdraht, die durchgepiepst und auf passend beschriftete Klebebandstreifen landen. Miteinander verdrillt und verlötet kommen sie dann an die FETs. Gleiches Spiel für die Massen der Taster.

Damit die Tasten beim Zusammenfügen nicht immer wieder aus ihren Löchern entwischen, kommt Klebeband von außen auf das Gehäuse. Zur Sicherheit mit Nummern beschriftet, damit mit Drehen und Spiegeln nix schief geht. Tasten eingelegt, Leitungen im Gehäuse verlegt und den Kupfer-Knäuel zusammengedrückt. Papa sagte schon immer: Salat ist gesund.

Das USB-Kabel liegt fest verzurrt und sehr engem Biegeradius im Gehäuse - hält (hoffentlich).

In die untere Gehäusehälfte sind die Nippel schon eingeklebt und es wird spannend: passt es?

Leider sind keine Senkkopfschrauben im Haus, also bleibt es mit den verzinkten Zylinderkopf-Schrauben etwas hässlich. Oder pragmatisch. Naja, es hält - und die Tasten liegen so im Gehäuse, dass sie weder (allzu sehr) klappern noch permanent gedrückt werden. Erfolg! :)

Um bei den Tasten nicht im kompletten Blindflug zu sein, ziert noch ein Label und ein paar Symbole der FontAwesome die obere Reihe. Damit sollte nun nichts mehr schief geben.

Software

Erster Test

Die erste Testsoftware ist in Python geschrieben und lässt einen Regenbogen durchlaufen. Der Einfachheit halber fasst sie nur eine LED gleichzeitig an:

import hid
import time
import colorsys

devices = hid.enumerate(0x16C0, 0x05DF)
if len(devices) == 0:
    print("no devices found")
    exit()

dev = hid.device()
dev.open_path(devices[0]['path'])

def setled(dev, index, color):
    r = int(color[0] * 255)
    g = int(color[1] * 255)
    b = int(color[2] * 255)
    dev.write([0, index + 1, r, g, b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

d = 60

while True:
    for h in range(0, 360):
        for i in range(0, 6):
            setled(dev, i, colorsys.hsv_to_rgb(((h + d * i) % 360) / 360, 1, 1))
        time.sleep(0.02)

Sieht dann als Momentaufnahme in etwa wie folgt aus:

Der OBS-Client

Ein "echtes" Plugin für OSB Studio zu schreiben spare ich mir mangels Tiefe in C++. Stattdessen nutze ich obs-websocket, das eine API für C# anbietet, die extrem einfach zu bedienen ist.

Für die Buttons ist eine extrem rudimentäre Klasse sehr schnell zusammengehackt. Gänzlich ohne Fehlerbehandlung. Das Auslesen der Buttons erfolgt in einem Background-Worker, der Events feuert (und beim Loslassen zusätzlich die Dauer des Drückens ermittelt), das Setzen der LED-Farben erfolgt für alle 6.

Hier merkt man auch wie heiß die Nadel ist mit der gestrickt wird: Zwischen dem Schreiben der beiden "Sets" legt sich die Software für eine Millisekunde schlafen. Der Grund einst einfach die dämlich - schreibt man zu schnell, geht evtl. das erste der beiden Datenpakete in der Firmware verloren, weil die Übergabe nicht (wenn man es so nennen will) threadsafe ist.

Die GUI hat lediglich einen "Connect"-Button, der nur gedrückt werden sollte, wenn OBS läuft und die Hardware verbunden ist. Die Konfiguration ist ebenfalls eher grundlegend und in AnykeyOBS.exe.config zu finden.

Hier kann für jede Taste die Aktiv/Inaktiv-Farbe als Hex-Code (oder named color, ungetestet) abgelegt werden, die Funktion definiert und ein Argument für diese Funktion angegeben werden.

Zum Zuordnen einer Szene packt man in die Funktion "Scene" und schreibt den zugehörigen Szenen-Namen ins Argument.

Für die Aufnahme heißt die Funktion "Record" und als Argument kann "Toggle", "Start" und "Stop" definiert werden. Streaming wird noch nicht unterstützt.

Aus mir nicht ganz verständlichen Gründen kann der Zustand des Streamings/Recordings nur über Events ermittelt werden, dadurch bleibt die Taste mit entsprechender Zuordnung beim Start des Programms orange. Dies ist auch die (fest hinterlegte) Farbe für Übergänge zwischen Aufnahme und keine Aufnahme.

Ein weiteres Feature ist das Abbrechen einer Funktion - Grundsätzlich werden die Aktionen erst beim Loslassen des Tasters getriggert - außer man drückt diesen länger als eine Sekunde. In diesem Fall wird die Aktion abgebrochen.

Insgesamt kann man die Software allerhöchstens als Proof of Concept bezeichnen. Es funktioniert, irgendwie.

Feuerprobe

Mittlerweile durfte ich meine Schwester sogar besuchen, um ihr die Hardware zu geben. yay! Das Einrichten fand aber trotzdem online statt. obs-websockt installiert, AnykeyOBS aufs Tablet und: Exception.

************** Ausnahmetext **************
System.ComponentModel.Win32Exception (0x80004005): Element nicht gefunden
   bei SimplerHid.HidDevice.GetName(IntPtr handle)
   bei SimplerHid.HidDevice.GetInfoSets()
   bei AnykeyOBS.Anykey6.Connect(Int16 vid, Int16 pid, String SerialNumber)
   bei AnykeyOBS.Form1.btnConnect_Click(Object sender, EventArgs e)
   bei System.Windows.Forms.Control.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
   bei System.Windows.Forms.Button.WndProc(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Mist.

Die vermutliche Ursache ist schnell gefunden: Bei manchen USB-Geräten kann der Name nicht gelesen werden. Eine Packung try-catch auf das Problem geworfen und eine Prise Console.WriteLines und das Programm bleib nach dem Klick auf "Connect" geöffnet.

"Leuchten die Knöppe?" - "Oh mann, wie geil" - "Also ja?".

Danach hörte ich nur noch wildes Klicken. Ich glaube, das Teil gefällt.

Und so sieht es aus:

Fazit

Wo fange ich an? Beim Guten, beim Schlechten oder bei den Sachen, für die ich mich schäme?

Unterm Strich: für eine sehr hemdsärmelig zusammengestrickte Hardware sieht es (ohne dass ich mich selbst loben möchte) ganz ordentlich aus. Schlimm wird es erst, wenn man unter die Haube schaut. Das dafür aber auch konsequent.

Das Gute:

  • Meine Schwester hat etwas, das ihr hoffentlich die Arbeit etwas erleichtert
  • Ich habe wieder einiges in Sachen 3D-Druck gelernt
  • Es hat ziemlich viel Spaß gemacht
  • Alles ist bunt

Das Schlechte:

  • Decoupling, welches Decoupling?
  • LEDs
    • Nicht sonderlich hell
    • Flackern bei USB-Traffic (durch INT0)
    • In dunkler Umgebung zu hell und bei Tageslicht schlecht sichtbar
  • Das Setzen von LEDs und Tastendrücke können verschluckt werden
  • Taster
    • Können auch von der Gehäuseunterseite betätigt werden
    • Relativ laut (im Video hörbar)
    • Wackeln, sind schief und haben keine Führung
  • Software
    • An allen Ecken und Enden rudimentär, wenn etwas ausfällt, funktioniert erst einmal nichts
    • Kein automatisches Verbinden mit OBS und der Hardware
    • Keine GUI für die Konfiguration
    • So gut wie keine Funktionen in OBS unterstützt
    • Außer OBS-Steuerung keine weiteren Funktionen
  • Keine Standby-States

Downloads

  • Datei:Anykeyx6.zip SketchUp-Dateien, zugehörige STLs, Firmware und C#-Software um mit OBS zu sprechen.