Montag, 11. Juli 2016

#ChinaCluster impressions

Die neue Frontplatte im schlichten Aluminium-Lochblech, mit dem 2.2" TFT, drei Tastern und zwei USB- und einem HDMI-Anschluss. Das lila Leuchte ist eine Kombination der roten Power-LEDs und der ultra-hellen blauen LED des eingebauten USB-Hubs.


Hier nochmal deutlich heller aufgenommen.


In der Rückwand sind zwei Ethernet-Anschlüsse eingebettet. Einer führt auf den Cubietruck und der zweite direkt auf den internen Netzwerk-Switch.


In meinem vorherigen Post habe ich  über die Strommessung geschrieben. Der neu montierte OrangePi One (mit der rot leuchtenden LED) fungiert als Datenbank-Server.


Hier eine Übersicht über alle Messdaten die per Grafana dargestellt werden, damit entgeht einem keine Auffälligkeit.


Im dunkeln entfaltet sich dann ein ganz andere Atmosphäre.



Da Aaron mit ja ein schickes Gehäuse für den Cluster baut, benötige ich einige Adapterplatinen. Unter anderem habe ich einen um den HDMI-Anschluss des Cubietrucks nach außen an der Gehäuse zu führen. Leider ergaben sich dabei kleinere Störungen die ich aber mit ein klein wenig Aluminiumfolie beheben konnte.


Dienstag, 28. Juni 2016

ChinaCluster - Strom messen

Aus reinem Interesse habe ich von einer weile beschlossen den Stromverbrauch zu messen. Und da ich vor einigen Jahren, während meines Studiums, bereits solche Messungen an E-Bikes mittels eigens entwickelter Hardware durchgeführt habe, konnte ich mir die Suche nach einer brauchbaren Lösung ersparen.

Meine Umsetzung basiert dabei auf der Verwendung eines Messwiderstandes in Verbindung mit einem 'Current Shunt Monitor' und einem Mikrocontroller. 

Und da ich noch ein paar Arduino Nano hier herumliegen habe wird es einer von diesen werden. Das folgende Bild zeigt den aktuellen Aufbau.

Arduino Nano und Shunt Monitor

Das Prinzip hinter meiner umgesetzten Strommessung ist folgendes:
Ein Messwiderstand wird in die Zuleitung zwischen dem Netzteil des ChinaCluster und den restlichen Komponenten gebaut. In die 'plus'-Leitung. Wer im Physik-Unterricht aufgepasst hat weiß nun das an diesem eine Spannung anliegt, die in Abhängigkeit zum Widerstand und Strom steht. Also U=R*I, was dem Ohmschen Gesetzt entspricht. Mann kann also die Spannung einfach messen und über das Ohmsche Gesetz den aktuell fließenden Strom berechnen, sofern man den Widerstandswert weiß.


Skizze mit Shunt, Stromquelle und Verbraucher

Ein wichtiger Punkt, bei dieser Art der Messung, ist dabei jedoch folgender: Je höher der Wert des Messwiderstandes ist, desto höher ist auch die an diesem anliegende Spannung. Und genau die an diesem anliegende Spannung fehlt dann an den restlichen Komponenten des Clusters.

Vorstellen kann man sich das wie eine einfache Reihenschaltung, einen Spannungsteiler. Am Messwiderstand liegt die Spannung Us=Rs*I an. Der Strom I ist in der Reihenschaltung immer gleich. Und die Spannung an den Verbrauchern ist dann Uverb=5V-Us. Das Verhältnis der Aufteilung hängt letztlich vom Verhältnis des Messwiderstandes zum Widerstand der restlichen Verbraucher ab.
Und da die restlichen Verbraucher aber - beim ChinaCluster allesamt eine recht stabile und genaue 5V Spannung benötigen ist da eigentlich kein Spielraum für den Messwiderstand, oder?

Doch der ist da, jedoch nicht im Volt-Bereich, sondern eher im Millivolt- oder Mikrovolt-Bereich. Das bedeutet also das man sinnvollerweise einen Widerstand wählt der deutlich unter einem Ohm liegt.

Das Ohmsche Gesetzt kann einem helfen da einen Überblick zu bekommen wie Groß denn der Widerstand sein darf, damit die benötigten 5V an den Verbrauchern möglichst wenig verringert wird.

Beispiel:

Rs = 0.001185 Ohm
I = 2 Ampere
Us = 0.001185 Ohm *2 Ampere = 0,00237 Volt

Damit würden bei diesem Widerstand lediglich 0,00237 Volt von den benötigten 5V am den Verbrauchern fehlen, was etwa den Wert 4,99V ergibt. Also eine minimale Veränderung mit der man leben kann.

Leider besteht an dieser Stelle jedoch ein weiteres Problem. Der Mikrocontroller muss über seinen eingebauten ADC (Analog Digital Comparator) diese Spannung messen.

Und ein zweites Problem haben wir uns damit auch noch auferlegt, ohne es bis jetzt zu merken. Woher bekommt man einen Widerstand von beispielsweise  0.001185 Ohm? Bei diversen Online-Händlern kann man verschiedene kaufen, um die 1Ohm und kleiner. Diese sind jedoch meist sehr teuer und nicht immer in vielen verschiedenen Größen verfügbar.

Das gute ist jedoch das man so einen Messwiderstand ganz einfach selbst machen kann. Je nachdem wie hoch die Spannung ist, welche das Netzteil liefert und wie hoch der maximale Strom ist der durch den Widerstand Fliesen soll ist, kann man auch einfach ein kurzes und dickes Stück Draht nehmen. In meinem Fall des ChinaCluster ist es ein Stück 1,5qmm isolierte Flexleitung, die für 230V Wechselspannung ausgelegt ist. Die Länge beträgt etwa 6,5cm, was über Umwege gemessen einen Widerstand von etwa 0.001185 Ohm ergibt.

Der Shunt - Das blaue Kabel
An diesem Punkt muss ich jedoch zugeben das meine Messung fehlerhaft sein kann. Gegebenenfalls werde ich an dieser Stelle den Widerstandswert noch korrigieren und beschreiben wie man den Wert genau ermitteln kann. Im Moment reicht mir persönlich diese Annäherung an den korrekten Widerstand jedoch aus.

Meine Bessung basiert darauf mit einem Multimeter und einem Oszilloskop den Wert indirekt zu ermitteln. Das Oszilloskop hat dabei die Spannung am den Messwiderstand gemessen und das Multimeter den aktuell fließenden Strom. Der Widerstandswert kann so relativ genau ermittelt werden indem man das Ohmsche Gesetzt anwendet.

Damit hätten wir nun das zweite Problem gelöst und stehen noch vor dem ersten, dass der Mikrocontroller per ADC die Spannung am Shunt - wie man den Messwiderstand auch oft nennt - messen soll.

Hierzu muss man jedoch zunächst grob verstehen was der ADC eigentlich tut. Er wandelt einen Spannungswert einer Quelle in einen Zahlenwert um. Der Zahlenwert ist dabei jedoch nicht identisch mit dem der anliegenden Spannung. Der ADC wird also nicht den Wert 4,5 liefern wenn die angelegte Spannung 4,5V entspricht.
Die Werte welche ausgegeben werden bewegen sich in einem definierten Wertebereich. Im Fall von meinem Mikrocontroller im Bereich von 0 bis 1023, man spricht hierbei auch von einer 10Bit Auflösung (2^10 -1).
Zudem gibt es oft die Möglichkeit eine Referenzspannung festzulegen. In meinem Fall habe ich eine externe Spannung von 3,3V gewählt. Hierbei gibt es einige Regeln wie hoch diese maximal sein kann, woher diese kommt usw. aber das soll hier nicht das Thema sein. Wichtig an dieser Stelle ist für uns nur das eine Spannung von 3,3 V dem Zahlenwert 1023 entspricht und 0V dem Zahlenwert 0.

Rechnen wir uns nun aus welche Spannung maximal an unserem 0.001185 Ohm Shunt anliegt:

U = Rs * Imax = 0.001185 Ohm * 12 A = 0,01422 V

Jetzt sind 0,01422 Volt drastisch viel kleiner als 3,3V. Und die 3,3V Referenzspannung dividiert durch die Auflösung des ADC, von 10 Bit, ergibt einen Spanungshub von 0,00322265625V pro Count. Man kann also sagen dass jedes Mal wenn die gemessene Spannung am Shunt um etwa 0,0032...V erhöht wird der ADC den Ausgabewert um den Zahlenwert (Count) von 1 erhöhen.
Im Fall von den oben berechneten 0,01422 V wird dieser also einen Count von maximal 4-5 ausgeben.
 Und das wenn der maximale Strom von 12 Ampere fließt. Wenn der ChinaCluster also im Leerlauf ist und gerade mal zwei Ampere benötigt wird der ADC eine Null ausgeben, da für diesen die Spannung einfach zu klein ist.

Oben habe ich bereits beschrieben das ich einen Current Shunt Monitor zur Messung verwende. Im Grunde kann man sich das als einen Verstärker oder Multiplikatoren vorstellen.
Dieser bekommt eine Eingangsspannung angelegt und liefert an dessen Ausgang eine um einen Faktor erhöhte Spannung. Der Faktor ist bei meinem Bauteil fest vorgegeben, es handelt sich dabei um den Faktor 50, da ich einen INA194 von Texas Instruments verwende.

Mit diesem kleinen Trick bringen wir den Spannungsbereich von 0,01422 V maximal auf das fünfzigfache davon, also etwa 0,7 V. Das ist zwar immer noch nicht hoch, aber besser als zuvor. Damit würden die 12 Ampere die das Netzteil maximal liefern kann als Zahlenwert vom ADC etwa der Zahl 217 entsprechen. Im Vergleich zu dem Wert 4-5 ist das eine deutliche Verbesserung.

An dieser Stelle möchte ich nochmals darauf hinweisen das sich hierbei an einigen Stellen der Berechnungen und Messungen Fehler in der Genauigkeit einschleichen. Für mich sind diese akzeptabel, da ich lediglich einen Groben Wert in eine Datenbank logge und mir daraus nur einen Grafen anzeigen lasse. In diesem Grafen ist nicht genau ersichtlich wie der exakte Wert ist, wichtig ist mir dabei nur das sich die Auslastung meines Netzteils in definierten Bereich bewegt.

Grafana Strom-Kurve

Um mehr Detailschärfe bei der Strommessung zu erhalten kann man zum einen eine kleinere Referenzspannung verwenden, die deutlich näher an der maximal zu messenden liegt. Sofern der Mikrocontroller dies zulässt. Oder man verwendet einen anderen Current Shunt Monitor mit einem höheren Multiplikator. Alternativ kann man sich auch mit einem OPAMP einen Spannungsfolger basteln und diesen auf einen exakt berechneten Faktor einstellen. Dies hat dann einige Vor- und Nachteile auf die ich jedoch hier nicht eingehen möchte.

Schlussendlich bleibt zuletzt, nachdem nun alle Probleme gelöst sind, nur noch die Werte des ADC wieder in den fließenden Strom umzurechnen.

I = Ushunt / Rshunt wobei Ushunt = Uadc / 50

Dieses Bild zeigt eine Liste von Messwerten des Mikrocontrolles, als Hex und Dezimalzahl, deren Umrechnung in die anliegende Spannung und der Umrechnung in den fließenden Strom.
Das Python-Script welches über eine Serielle-Verbindung (USB zu Seriell) die Daten von einem Arduino empfängt ist hier verfügbar. Die Firmware für den Arduino kann hier heruntergeladen werden.


Mittwoch, 22. Juni 2016

Cubietruck GPIO with python und SWIG

Um für meinen ChinaCluster diverse externe Hardware steuern und auslösen zu können benötigte ich vor einiger Zeit eine Möglichkeit auf das GPIO-Subsystem des Cubitrucks zugreifen zu können. Dieser ist das Master-System im Cluster.

Für die Implementierung von Software in C/C++ sind die beiden folgenden Quellen die grundlegenden Informationen zum Ziel. Das allgemeine Cubietruck Tutorial und das Cubieboard GPIO tutorial. Ich jedoch würde gerne per Python - und das ohne möglichst alles neu implementieren zu müssen - auf das GPIO-System zugreifen.

Theoretisch gibt es bereits ein WiringCB-Projekt, welches theoretisch ein GPIO-Interface für Cubieboards bereitstellen sollte, in meinem Fall funktionierte dies jedenfalls in keinem meiner Tests.

Was tun also wenn es keine adäquate Lösung gibt? Selbst umsetzen. Daher habe ich hier bereits ein Repository eingerichtet mit dem per Python auf das GPIO-Subsystem - zumindeste meines Cubitrucks - zugegriffen werden kann.

Letztendlich basiert diese Lösung darauf das ich um die C-Implementierung von Stefan Mavrodiev einen Python-Wrapper gelegt habe. Der gängige Weg ist dabei wohl diesen mittels SWIG, unter Zuhilfename eines .i-Files in dem alle zu exportieren Elemente aus der ursprünglichen Library aufgelistet bzw. definiert werden, den Wrapper automatisch generieren und kompilieren zu lassen. Wichtig ist hierbei ein Setup-File manuell erzeugt zu haben in dem die Eigenschaften der neuen GPIO-Library definiert sind. Das Repository beinhaltet eine sehr übersichtliche Umsetzung und kann so ggfls. theoretisch als Beispiel dienen.

Spezielle Software-Pakete habe ich auf dem Armbian des Cubitrucks nicht installiert. Lediglich Python, pypy swig und make und der gcc sollten installiert sein.

Meine Software kann simpel mittels make durchgeführt werden. Achtung, es wird jeweils die Python und pypy-Version der Library kompiliert. Benötigt man beispielsweise die Python-Version kann man diese Zeile einfach im Makefile auskommentieren. Hat man make als normaler User ausgeführt und bereits ausreichend Rechte auf das GPIO-Subsystem wird zudem der automatisch ausgeführte Library-Test ohne Fehlermeldungen ausgeführt. Ansonsten bleibt einem nur der Weg über den User root.