Die perfekte USB-I2C-Bridge

TL;DR: Ich habe sie noch nicht gefunden und mich beschleicht das Gefühl, dass ich selbst eine (weitere, nicht perfekte) bauen muss.

Aber erst einmal auf Anfange: Mangels halbwegs flotter Alternative habe ich Libs in Python und C# (ein paar fixes stehen noch aus) um mit dem MCP2221 von Microchip zu sprechen.

Der Chip ist einfach und macht auch ungefähr, was er soll. Nur leider ist er – nicht nur aufgrund der natürlichen Beschränkung von USB HID – verdammt langsam. Speziell wenn es um Standardaufgaben wie Register lesen geht. Das ist ein richtig großer Zeit- und Performancefresser, denn: man muss es „kleinteilig“ durchführen: Register an den Controller schicken ist ein Befehl, auf den geantwortet wird, dann muss man den Lesebefehl senden (auf den auch wieder geantwortet wird) und anschließend muss man für jeden 60-Byte-Chunk der gelesenen Daten auch wieder lesen und auf die Antwort warten. Ich bin mir nicht ganz sicher, ob die Antwort im gleichen oder nächsten USB-Interrupt-Zeitschlitz kommt, aber im dümmsten Fall würde das bei einer ein Chunk großen Leseanforderung 2+2+2 ms bedeuten. Bei 20 Registern (manche Chips lassen das Lesen im Block nicht zu, durchaus aus guten Gründen) wären das 120 ms. Dann war’s das mit 10 Refreshes pro Sekunde – zugleich stottert das UI, wenn man die Kommunikation nicht in einen anderen Thread auslagert. Alles großer Mist. Im Datenblatt sind zudem Fehler u. a. in der Protokollbeschreibung und der einzige Kontakt bei Microchip (immerhin, sie haben geantwortet, was ich nicht erwartet hätte) hat sich hinter seiner NDA versteckt – obwohl die erfragten Infos teilweise schon im (von Microchip geschriebenen) Treiber für Linux stecken.

In der Hoffnung, dass es andere Hersteller besser machen, habe ich mir einen CP2112 von Silicon Labs geholt. Silabs hat einige Dinge deutlich besser gemacht – neben den deutlich höheren Bustakten (> 1 MHz) es gibt einen Befehl (und Konfiguration), der Leseanfragen deutlich verkürzt. Mit aktiviertem „Automatically send read response“ lässt sich ein Register mit n byte Länge am Chip mit Adresse a wählen und die Antwort der Länge l wird ohne weitere WriteReports an den Controller zurückgesendet. Im Schlimmsten Fall dauert der Lesen eines Chunks 2 ms. Beide Baumen Hoch!

Tja, wenn sie nicht in anderen Situationen ziemlich verkackt hätten. Hat man den auto read response an und möchte mit einer I2C-Adresse sprechen, die es auf dem Bus nicht gibt, läuft man ohne Threading in einen Deadlock, da es einfach keine Antwort vom Controller gibt und die ReadReport-Methode blocking ist (auch das Setzen des read timeout und retry count bringt nichts). Gerade beim I2C-Detect ist das ziemlich bescheiden. Richtig bescheiden ist an dieser Stelle auch, dass man keinen „Klingelstreich“ (Start, Adresse auswählen, Stop und einfach nur Auswerten, ob ein oder kein ACK kam) machen kann. Man muss immer mindestens ein Byte lesen. Das kann bei manchen Devices für Ärger sorgen. Gleichzeitig habe ich es nicht geschafft, bei Adresse 0 zu „klingeln“. Obwohl diese, gerade wenn man einen SMBus auf dem Tisch hat, wichtig ist.

Ja, das kann man alles umschiffen, aber wiederum zulasten der Performance. Dabei wäre alles super einfach in der Firmware zu implementieren. Anderes Manko des Chips: Man kann höchstens 512 Byte am Stück lesen und nur 61 (?) Byte am Stück schreiben. Warum nur?

FTDI FT232H (und andere). Kein HID, also muss man sich entweder mit einer DLL von FTDI herumschlagen oder mit LibUSB/WinUSB herumbasteln (Tolle Projekte aber da man Zadig verwenden muss, ist es kein wirkliches Plug & Play mehr. Was mir an der Sache überhaupt nicht gefällt: Obwohl man für das beste Benutzererlebnis die DLL von FTDI benutzten muss, ist es nötig, die MPSSE-Pakete selbst zusammenbasteln. Gleichzeitig gibt es beim Initialisieren anscheinend Glitches auf den Busleitungen und zwischen Start condition, Adressierung und Stop condition habe ich bei ersten Tests wahnsinnig große Zeitlücken gesehen. Ich habe mich nicht wirklich intensiv damit auseinandergesetzt, aber bis jetzt hat mich das elendige Treibergeschwurbel aktiv davon abgehalten, Code dafür zu schreiben.

WCH CH341A: Ein Kit liegt hier und ich habe aus Anwendersicht erste Tests (mit einem EEProm) durchgeführt. Sieht nicht ganz schlecht aus. Wie der FT232H ist es kein USB-HID und man darf wieder mit der bereitgestellten DLL oder anderen Libs basteln. Ein Bastelkollege hat sich der Sache schon angenommen. Großes Problem: Alles aus erster Hand ist nur auf chinesisch. Da ich auf der Website nix lesen kann, ist sie auch nicht verlinkt. Englische Dokus kommen m. W. nur aus der Community. Muss nicht schlecht sein, aber es riecht halt alles ein bisschen arg bastelig.

Von Cypress habe ich mal ein PSoc4-Devkit (so ein Stick) mit Kitprog USB bekommen, der auch sehr schnell I2C sprechen kann. Das Teil hat sich aber durch mehrere Dinge sehr schnell disqualifiziert: Den Treiber gab’s nicht einzeln, eine Doku zum Protokoll glaube ich auch nicht und das Teil hat sich extrem schnell so stark verschluckt, dass man die Hardware neu starten musste.
Es gibt noch z. B. den CY7C65211, allerdings ist mir in freier Wildbahn noch kein Devkit über den Weg gelaufen und ich hatte mit einem anderen USB-Chipsatz schon ein bisschen Probleme, was Treiberstabilität (irgendein USB-UART-Wandler, man konnte den Port öffnen, aber es gingen keine Daten durch). Ein paar haben sich auch ziemlich empfindlich gegenüber Störungen von außen gezeigt. Ob es der Chip oder die externe Beschaltung war, ließ sich nicht mehr richtig rekonstruieren, aber da haben doch ein paar Bauteile dicke Backen gemacht.

Alternativen? Da gäbe es noch den Buspirate von Dangerous Prototypes. Für den Entwickler-Tisch ok, aber für den ganzen Rest einfach zu groß. Zudem bis jetzt keine Single-Chip-Lösung eher ein USB <> UART <> irgendwas-Wandler

Ok, wenn wir schon beim Entwicklertisch sind – Aardvark von TotalPhase. Macht man da einmal den Deckel auf (zumindest den, den ich mal auf dem Tisch hatte), sieht man nix anderes als einen USB <> UART + AVR. Zugleich konnte man ihn nicht standalone verwenden, sondern braucht(e) eigentlich immer den ziemlich klobigen Levelshifter. Die Software ist fummelig und instabil, wobei ich nicht herausgefunden hab, ob es nicht vielleicht auch die Hardware war. Hab das Teil auf jeden Fall sehr schnell wieder zur Seite gelegt. Für meine Begriffe ist das Teil nicht seinen Kosten gerecht.

Was wäre da sonst noch? TI? Die hatten IIRC mal etwas im Programm aber das war entweder ziemlich lausig oder zumindest für Normalsterbliche faktisch nicht verfügbar.

Sonst fällt mir nicht mehr viel ein. Außer, dass ich schon vor längerer Zeit die Idee hatte, selbst einen USB<>irgendwas-Wandler zu bauen. Leider ist es bis jetzt in der Planungs-Featuritis hängen geblieben. Mal grob, was ich mir vorgestellt habe, was es können muss^Wsoll:

  • GPIOs + IRQs, PWM, …
  • ADCs
  • SPI
  • I2C
  • OneWire
  • SMI/MDIO (clause 22/45)
  • UART + RS485

APDS-9960 decap

Der APDS-9960 von Avago/Broadcom ist das, was man sich unter einem vernünftigen Lichtsensor vorstellt: ALS, Proximity, RGB.

Weil ich eine Konkrete Idee für eine Anwendung hatte, landete einer für billig Geld auf dem Basteltisch. Nur leider wollte er nicht so richtig. Ich konnte ihn nicht dazu überreden, RGB-Werte auszuspucken und die ID passte auch nicht wirklich.

Im Internet gab es nichts zu finden, auch die IDs der anderen APDS-Sensoren passten nicht.

Da das Teil zu meinem Erstaunen einen Metalldeckel hat: warum nicht kurz drunterschauen? An der ersten Seite hat das leichte Hochbiegen noch ganz gut funktioniert, bei der zweiten nicht mehr:

Man erkennt es leider nicht ganz so gut, aber die IR-LED und ein paar Bonddrähte blieben im oberen Teil. Well, fuck.

Naja, jetzt brauch ich schon nicht mehr das passende Datenblatt suchen.

廉价 oder 有利

Günstig oder billig?

Ein Kollege brachte heute ein Stück Technik vorbei, das zwar funktionierte, aber nicht so richtig wertig wirkte:

Links ist das gute Stück, rechts ein zum Verwechseln ähnlicher USB-Charger von Samsung. Abgesehen von der Größe und und dem fehlenden Samsung-Logo (ok, das CE-Logo sieht auch eher nach „China Export“ aus) merkt man den Unterschied, wenn die Steckernetzteile in der Hand hält: Das Gewicht ist doch ziemlich unterschiedlich: Der Samsung-Charger wiegt mit 40 g ein bisschen mehr als doppelt so viel wie das Teil aus dem Reich der Mitte (18 g).

Mit ein bisschen Gewalt am oberen Ende offenbarte das Ladegerät seine inneren Werte, die man vorher schon an der USB-Buchse riechen konnte (heißes Hartpapier). Entsprechend meinen Erwartungen wurde ich nicht enttäuscht:

Hmmm, Crusty!

Zum Vergleich die Innereien eines anderen Samsung-Ladegerätes, das ich mal auseinandergenommen habe (IIRC ohne „adaptive fast charging“):

Auffälligster Unterschied: Eine richtige Sicherung, eine Common-Mode-Choke zur Funkentstörung, bisschen höherwertige Kondensatoren (wobei mir „Chang“ nicht als besonders hochwertig in Erinnerung ist), ein im Vergleich richtig fetter Transformator und ein halbwegs seriöser X-Kondensator zwischen Primär- und Sekundärseite. Der größte und auffälligste Unterschied: Eine Isolationsplatte, die durch den Slot zwischen Netzspannung und Schutzkleinspannung greift. In den Bildern sieht man es leider nicht so richtig: sie ragt 3,5 mm über die andere Seite der Leiterkarte heraus.

Aber auch auf der Unterseite sieht man deutliche Unterschiede. Zunächst, als Positivbeispiel Samsung:


Muss man noch etwas dazu sagen?

…und nun das, was man für 3,50 1,86 Euro mit USB-Kabel und Versand bekommt:

Der Isolationsabstand zwischen Primär- und Sekundärseite beträgt ca. 1,5 mm. Die Kriechstrecke sollte IIRC eher die vierfache Breite haben

Völlig unklar ist auch, wie gut die Wicklungen im Trafo voneinander isoliert sind. Wenn man genauer hinsieht, kann man zwar noch eine rote Folie unter der äußeren Wicklung erkennen, aber die Zweifel bleiben

Kurzgesagt: Das Teil würde ich definitiv nicht an mein Telefon oder etwas anderes anschließen.

Noch ein weiteres Leckerchen: Die Interpretation einer Sicherung (der Eingangswiderstand) oder besser sein Beinchen (unten mitte-links im Bild) ist so ungeschickt abgeschnitten, dass der Pin sehr nah in Richtung Ausgangsseite des Gleichrichters reicht.

Den Ausfall dürfte man dann ziemlich schnell merken 😉

Fail: USB-Switch

Man spricht und schreibt eher ungern über eigene Fehler und/oder das eigene Unvermögen.

Aber Fehler gehören dazu. Man kann zwar ohne sie auch lernen, aber am besten und meisten lernt man meiner Meinung immer noch aus Fehlern.

Folgende Bastelei liegt schon ewig auf dem Tisch, genau genommen seit 2016:

An den Fädeldrähten sieht man – da passte etwas am Layout nicht. Der Schaltplan dazu sieht wie folgt aus:

Keine Ahnung woran es lag, der Knoten im Kopf mit negiertem Output Enable, high side switch und Inverter war wahrscheinlich zu groß. Eigentlich total Pillepalle aber es wollte einfach nicht.

Mit Fädeldraht hat es dann auch funktioniert aber das ganze Teil ist so unbefriedigend, dass ich mich entschieden habe keinen Artikel zu schreiben. Der USB-Switch ist schlecht beschaffbar und noch bescheidener zu Löten, die Einschaltfolge (erst Strom dann Daten beim Einschalten, beim Ausschalten umgekehrt) wird nicht eingehalten, die Höhe von Stecker und Buchse passen nicht zueinander, von richtigem Differential-Pair-Routing fange ich noch nicht einmal an zu sprechen.

Trotzdem hat das Teil seinen Zweck zumindest einmal erfüllt. Ob es mal eine out-of-box funktionierende Variante geben wird – keine Ahnung. Am liebsten wäre – zumindest mir – etwas, das deutlich mehr kann, sprich: USB Switch, Strommessung, Stromlimit, Schalten per PC (ohne zusätzliche Hardware), usw.

Vielleicht. Irgendwann.