| Raumschiff U.S.S.Adler |
| Radpanzer |
| Angler am Strand 3D |
| Ein zusammenschnitt der 3D Animationen mit Monzoom Pro in HD Auflösung. |
Wir haben nun das Zeitalter der KI erreicht, weshalb hier weniger Lösungen und mehr das Technik Tagebuch Posts kommen. Lösungen verlinke ich Kategorisch extra auf den weiteren Seiten des Blogs
| Raumschiff U.S.S.Adler |
| Radpanzer |
| Angler am Strand 3D |
| Ein zusammenschnitt der 3D Animationen mit Monzoom Pro in HD Auflösung. |
| Arduino Nano 3.0 und der Magnet Sensor HMC5883L. Gelb=SDA (Pin4), Orange=SCL (Pin5), Rot=+5V und Schwarz=GND |
Wenn ich keine Lösung für dem Netduino habe, dann finde ich eine für Arduino. Eines meiner ersten Programme war eines zum Lesen der Sensordaten. Zunächst verwendete ich den Arduino Monitor, der allerdings nichts anderes tat, als eine serielle Verbindung herzustellen. Mit ein “wenig” C# und .NET Framework Kenntnis kann auch ein eigenes Programm geschrieben werden, das die Daten ebenfalls lesen kann. Mein neues Bespiel zeigt die magnetischen Einflüsse auf 3 Achsen an, was ich mit Hilfe von Windows Forms visualisiere.
| Windows Forms mit analoger Anzeige |
Warum Windows Forms? Die GUI ist schon etwas in die Jahre gekommen und bietet kaum Neuerungen, dennoch kann man grafisch immer noch etwas an Ergebnissen erreichen. Also wäre es doch schön, eine analoge Anzeige auf digitalem Boden zu schaffen. Aber erstmal eins nach dem anderen.
Auf der Seite Gihub stellt der Entwickler Jeff Roberg seine Bibliotheken zur Verfügung für Zahlreiche Sensoren die mit dem Arduino angesprochen werden können. Für mein Beispiel wird der Ordner HMC5883L und die I2Cdev Inhalt benötigt, die dann in den Order “libraries” vom Arduino Compiler kopiert werden. Anschließend kann das mitgelieferte Beispiel “HMC5883L_Example” geöffnet und auf dem Arduino hochgeladen werden. Die Ausgabe erfolgt über die serielle Verbindung, die auf dem Arduino Monitor betrachtet werden kann.
| Ausgabe über den Monitor |
Nun zur PC Anwendung, die die Daten auswertet und sie in einer visuellen Form darstellt. Als erstes stellen wir die Verbindung sicher, und hier hilft uns das .NET Framework mit der Klasse “SerialPort”. Damit wir die Einstellungen auch später in der Anwendung anpassen können, benötigen wir eine kleine Setup Möglichkeit. Hier reichen die Auswahl des Ports und der Baudrate.
| Das kleine Setup mit einem Button zum “Aktualisieren” und einem für “Verbinden”. |
In “Form1.cs” Code Seite kommt zunächst die Event Methode, die durch einen Doppelklick auf dem Button im Designer erstellt wird. Dort schreiben wir etwas Code, um die Auswahl über die ComboBoxen auszufüllen.
| private void buttonUpdate_Click(object sender, EventArgs e) comboBoxChooseBaud.Items.Clear(); |
| Füllt die ComboBox mit den Einstellungen. |
Die SerielPort Klasse wird nun als Member in der “Form1.cs” angelegt. Einen weiteren Button, der den Text “Verbinden” erhält, erstellen wir ebenfalls durch Doppelklick auf die Event Methode. Hier initialisieren wir die Klasse mit den Einstellungen aus der ComboBox. Damit die Anwendung fehlerfrei läuft, sollte vorher geprüft werden, ob eine Auswahl besteht. Nach erfolgreicher Verbindung muss noch ein neuer Event erzeugt werden, der immer ausgeführt wird, sobald am seriellen Port neue Daten verfügbar sind.
| private void buttonConnect_Click(object sender, EventArgs e) _SerialPort.Open(); private void _SerialPort_DataReceived( |
| Mit den Einstellungen die Verbindung herstellen. |
Jetzt kommen wir zum visuellen Teil der Anwendung, wofür wir ein neues UserControl anlegen, indem wir in unserem Projekt mit Rechtsklick das Kontextmenü öffnen und dann über Hinzufügen > Neues Element.. das Benutzersteuerelement auswählen. Zuvor sollte ein entsprechender Name verwendet werden wie “AnalogView.cs” oder ähnliches. In meinem Bespiel hat das UserControl eine Größe von 200x100 Punkten, was über die Layout Eigenschaften festgelegt werden kann. Anschließend geht es auf der Code Seite weiter.
| public partial class UserControlAnalogView : UserControl public double Maxi_MinimumValue public UserControlAnalogView() public void RenderAnalogDisplay() Graphics g = CreateGraphics(); Pen p = new Pen(new SolidBrush(Color.Black), 2); g.FillPie(Brushes.WhiteSmoke, 5, 5, 190, 190, 0, -180); g.DrawPie(p, 5, 5, 190, 190, 0, -180); p.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid; ResumeLayout(false); public double DisplayValue double alpha = _DisplayRawValue / _MaximumValue; double w1 = Math.Cos(alpha) * 90; _PointerValue = new Point((100 + Convert.ToInt32(w2)), 100 - Convert.ToInt32(w1)); RenderAnalogDisplay(); |
| Der Codeabschnitt für das Erstellen der Analoganzeige. Die Methode “RenderAnalogDisplay()” zeichnet die Anzeige, und über “DisplayValue” wird die Zeigerposition neu ausgerichtet. |
Das Benutzersteuerelement ist fertig und nach dem Drücken der F6 Taste steht es auch schon in unser Toolbox, wo wir es in der Designeransicht auf die Form1 ziehen können. Für jede Achse wird eine analoge Anzeige verwendet; man stelle in den Eigenschaften das Maximum auf 4000 ein.
| Die Analoge Anzeige wird erst gerendert, wenn die Methode im UserControl “RenderAnalogDisplay()” ausgeführt wird. |
Als nächstes kommt das Auslesen der empfangen Werte. Der Inhalt sind Konstanten und können durch eine Methode einfach ausgewertet werden.
| Raw: 455 39 668 Scaled: 418.60 35.88 614.56 Heading: 0.13 Radians 7.52 Degrees |
| Die Zeichenkette, die uns der Arduino nach dem lesen des Sensor übermittelt. |
Im Beispiel beschränken wir uns auf die Raw Daten und programmieren entsprechend in die Event Methode vom SerialPort den Lesevorgang und schreiben das Ergebnis an die analogen Anzeigen.
| private void _SerialPort_DataReceived( int[] ia = new int[3]; userControlAnalogView1.DisplayValue = ia[0]; |
| Methode für das Einlesen der Raw Daten. |
An dieser Stelle sind wir mit dem Beispiel fertig und die Anwendung kann nun über F5 gestartet werden. Mit Aktualisieren erhalten wir die verfügbaren COM Verbindungen und wählen natürlich die vom Arduino.
| |
| Nähert man sich auf einige Zentimeter an den Sensor bewegen sich die Zeiger. |
Mit einem Magneten können wir das Magnetfeld um den Sensor manipulieren und sehen, wie die Zeiger ausschlagen. Mit ein paar weiteren Codezeilen lässt sich auch der Rest der Daten anzeigen, allerdings verbleibe ich dabei, mich möglichst kurz zu halten.
Zuletzt darf die bereits fertiggestellte und kommentierte Solution des kleinen Tools nicht fehlen:
| Verkabelungsbeschreibung ist am ende dieses Blogs. |
Bereits Anfang des Jahres habe ich eine Lösung in C# und .NET Micro Framework geschrieben. Ursprünglich habe ich die Lösung aus der in C++ geschriebenen Library portiert (Library für Arduino). Zuvor suchte ich nach einem kürzeren und funktionalem Beispiel, aber ohne Erfolg. Da ich nun selbst relativ gut mit dem Sensor vertraut bin, konnte ich ein kürzeres Beispiel für den Arduino schreiben.
| #include <Wire.h> #define sensor_address 0x68 void setup() delay(1000); void loop() // per Bit Shifting zusammengelegt werden. void SetConfiguration(byte reg, byte setting) |
| Kurzfassung für den Sensor Aufruf, ohne weitere Library. |
Mit dem Quellcode wird der Sensor mit den Standardwerten initialisiert, so dass die Empfindlichkeit des Gyroskop bei 250°/s und der Beschleunigungssensor bei 2g liegt. Steht der Sensor still auf dem Tisch sollten die Werte für das Gyroskop und den Beschleunigungssensor für X und Y Achse nahe bei 65536 oder 0 liegen. Beschleunigung auf der Z-Achse bei ca. 16000.
| Ausgabe über dem Arduino Monitor |
Ich hoffe, ich konnte somit dem einen oder anderen mit diesem kleinen Bespiel weiterhelfen. Bei Fragen kann gerne die Kommentarfunktion verwendet werden.
Anschluss Beschreibung:
Zuletzt geändert 20.11.2014
| Die LED 8x8 Matrix an meiner Schaltung. |
So einige wie ich haben seltsamerweise kein Dokument zu der LED Matrix im Internet gefunden. Letzten Endes habe ich dann selbst durch einiges Prüfen herausgefunden, welcher Pin nun für welche Funktion ist. Anschließend konnte ich dann einen Versuchsaufbau starten, der allerdings aufwendiger wurde. Auf den ersten Blick sieht meine Schaltung mit den vielen Kabeln ziemlich unüberschaubar aus. Dennoch habe ich den Aufbau mal wieder aus dem Kopf heraus zusammengesteckt, woran man sieht, dass diese Schaltung nicht sonderlich kompliziert sein kann.
| Die Verwendeten ICs. Shiftregister, 2x Demultiplexer und 2x Inverter |
Für die Schaltung habe ich Folgendes verwendet:
Der Netduino wird hier als Steuereinheit verwendet, auf dem später meine Library “Game of Life” läuft.
Der Shiftregister ist entscheidend für die Darstellung an der LED-Matrix, da diese Einheit den Zustand der Demultiplexer schaltet, wenn alle 8 Bits gesetzt wurden. Im meinem ersten Versuch habe ich die zwei Demultiplexer direkt am Netduino angeschlossen. Hierbei wurden mehrere LEDs als gesetzt geschaltet. Der Fehler ließ sich jedoch nachvollziehen. In einer Methode habe ich die 8 Ausgänge geschaltet, die sehr zeitnah nacheinander ausgeführt werden. Leider war dieser Vorgang nicht schnell genug, so dass sich während dieser Zeit auch andere Schaltzustände ergaben. Zwar leuchten die nicht gesetzten LEDs nicht hell, aber dennoch stört dieser Zustand.
| Schaltbild von der LED Matrix. |
An der LED Matrix sind insgesamt 24 Pins und deswegen sind es zum Anschließen an einen einzelnen Netduino oder Arduino zu viel. Abhilfe schafft hier der Demultiplexer, der mit seinen 4 Eingängen bis zu 16 Zustände annehmen kann. Da einer nicht reicht, kommt ein zweiter hinzu, und wenn man diese in eine Matrix einbindet, dann können bis zu 256 Zustände erreicht werden. Den ersten Demultiplexer verwende ich für die 8 Reihen Rot und 8 Reihen Grün. Der zweite ist für die 8 Zeilen, die vorher durch einen Inverter geschaltet werden. Grund hierfür sind die Signale an den Demultiplexerausgängen, die negiert sind. Die Widerstände teilen die Spannung auf und trimmen die Stromaufnahme bei 20mA. Jedoch hier der Hinweis, dass ich die Spannung der LEDs auf 2.0V schätze. Also ergibt sich aus meiner Rechnung, dass am Widerstand 3V anliegen sollten. Mit der Grundformel R=U/I erhält man den benötigten Widerstandswert von 150Ohm. Im folgenden habe ich mir aus meinem Beispiel ein Schaltbild in Eagle erstellt. Was hier allerdings nicht so schön ist,ist dass die Last von den LEDs direkt an den ICs liegt. Also ist diese Schaltung aus diesem Grunde nur experimentell und nicht für den Dauerbetrieb geeignet.
| Gesamtes Schaltbild, ohne Netduino. |
Nun ein bisschen Quellcode zum Ende, den ich jedoch von Netduino.com abgeschrieben und etwas abgeändert habe. Ich empfehle auf der Seite nachzuschauen, falls die Verbindungen mit Shiftregister und Netduino unklar sein sollten.
| private static OutputPort _Data = new OutputPort(Pins.GPIO_PIN_D0, false); /// Code von der Seite Netduino for (int i = 0; i < 8; i++) if (bit == 128) _Clock.Write(true); /// Dient als Ersatz zu Thread.Sleep |
| Members und die Methode für das ansteuern des Shiftregister. |
Wird nun an der Methode ein Wert zwischen 0 und 255 übergeben, wird die entsprechende Bit Einstellung am Shiftregister gesetzt. Dieser steuert die zwei Demultiplexer, die wiederum mit der LED Matrix verbunden sind und die entsprechende LED leuchtet.
Normalerweise würde man hier einen LED Matrix Treiber verwenden, um sich die umfangreiche Verkabelung zu sparen. Jedoch möchte ich zeigen, dass es auch andere Lösungen gibt und hoffe, dass dieses Bespiel dem einen oder anderen weiterhilft.
| |
| Mein Beispiel mit “Game of Life” und einem Gleiter. |
| Netduino Plus, Shield, WiFi Module und der Sensor |
Diesmal möchte ich ein Beispiel beschreiben, in dem nicht der Netduino der Empfänger ist, sondern der Sender, ohne dass auf die Serverfunktion verzichtet werden muss. Der Quellcode vom letzten Blog-Post wird an Server und Client seitig erweitert. Am Server (Netduino) Quellcode ist dies sogar recht simpel, da man an dieser Stelle nur vier weitere Zeilen Code hinzufügen muss:
| while (true) |
| Relativ simpel fällt der Code für das Senden aus. |
In der “While”-Schleife ist nun zu sehen, dass ich die aktuelle Zeit als String wiedergebe und anschließend in ein Byte Array umwandle, um es für den Schreibvorgang vorzubereiten. Die “Write”-Methode selbst erledigt den Rest und gibt den Inhalt an das WiFi Modul weiter.
Am Client jedoch ist ein wenig mehr Arbeit notwendig. Wenn die Daten ankommen, muss auch ein Event erfolgen, um die Daten zu verarbeiten und schließlich an die Anwendung auszugeben.
| Das Programm mit einem zusätzlichen TextBlock für den Empfang. |
Für den Empfang der PC Anwendung habe ich eine recht einfache Lösung verwendet, die auch leicht nachvollziehbar ist. Leider ist diese aber nicht ideal, da es eventuell zur Vollauslastung kommt, wenn hier die Schleife nicht etwas gebremst wird. Ein besseres Beispiel gibt es auf MSDN, wie hier mit Hilfe der Socket Klasse ein Event erstellt werden kann.
Nun zur Erweiterung in der Client Socket Klasse, wo eine weitere Methode später im Thread ausgeführt wird. Die Thread-Klasse selbst kommt in den Member Bereich mit dem Namen “_ThreadWaitReceive”. Der Grund hierfür ist, dass später beim Schließen der Klasse der Thread beendet werden muss. Sonst läuft der Thread weiter, obwohl die Anwendung selbst lange beendet wurde.
| private Thread _ThreadWaitReceive; private void WaitReceive(object obj) while (_Socket != null && buffer.Length > _Socket.Receive(buffer, SocketFlags.None)) |
| Die zusätzliche Methode für den Empfang. |
Mit der Encoding wird der String eingelesen und über die Methoden Replace() und Trim() werden die leeren Inhalte gefiltert. Mit der folgenden Zeile wird dann der Inhalt an die Event Methode übergeben.
| public delegate void NetworkReceiveEventHandler(object sender, NetworkStatusEventArgs e); |
| Die Methode, mit Handler und Event. |
Mit dem Event geht es weiter an die Oberfläche, um den Inhalt des Empfang in einem TextBlock lesen zu können.
| public MainWindow() private void _Client_NetworkReceiveEvent(object sender, NetworkStatusEventArgs e) private delegate void WriteReceiveHandler(string message); private void WriteReceive(string message) |
| Event zugewiesen, Handler für die Oberfläche und Methode, um in die Textbox zu schreiben. |
Mit ein paar Code Zeilen Ergänzungen ist nun die PC Anwendung und der Netduino imstande, in beide Richtungen zu kommunizieren. Sicherlich gibt es hier etwas besseres, als sich nur das DateTime anzuzeigen.
Wie bereits zuvor gibt es wieder das Ganze in zwei fertigen Solutions, mit den Quelltexten und natürlich auch den Kommentaren.
Die Solutions für den Download:
| Netduino Plus, Shield, WiFi Module und der Sensor MPU6050 |
Bereits letztes Jahr habe ich einen Post darüber geschrieben, wie dieses Modul eingerichtet wird und mit einem Arduino verwendet werden kann. Schon lange ist es daher überfällig, dass ich auch ein Bespiel mit dem Netduino schreibe. Aber bevor ich darüber schreiben konnte, musste ich so einige Versuche anstellen.
Zuvor war das Ergebnis, dass über dem Webbrowser ein “Hello World!” auf dem Browser erschien. Diesmal kommt ein Beispiel auf dem Netduino, das den Text im Debugger anzeigt. Leider ist es beim dem WiFi Modul nicht möglich mit der Socket Klasse zu arbeiten, so dass uns nur die serielle Verbindung bleibt. Und zugegeben, wie ich später herausfand, funktioniert dies besser und einfacher, als ich erwartet hatte.
| Mein neuer Netduino Shield für WiFi Modul und Sensor |
Zunächst die Verkabelung, wofür ich meinen Netduino Plus und einen neuen (eigens erstellten) Shield verwende, mit dem ich nun den Sensor und das WiFi Modul aufstecken kann. Es ist noch nicht fertig, reicht aber für dieses Beispiel aus. Kommen wir zu ein wenig Quellcode.
| using System.Threading; namespace SerialPortExample public static void Main() _SerialPort = new SerialPort(SerialPorts.COM2, 115200); while (true) string reading = string.Empty; Debug.Print(reading); |
| Inhalt aus der Program.cs klasse. Das “public Class” herum und using |
Dieser Code Ausschnitt reicht bereits aus, um Daten vom WiFi Modul zu lesen, die empfangen wurden. Zwei Sachen sind hier nur wichtig: An welchen COM Port habe ich mein Modul angeschlossen? Und mit welcher Baud Rate wird kommuniziert?
Kommen wir zum nächsten Punkt. Damit die Daten beim WiFi Modul ankommen, brauche ich einen Client zum Senden. Grundsätzlich reicht ein Browser aus, um Daten per Http zu versenden. Einfach in der Adresszeile die IP Adresse und Port Nummer des WiFi Moduls eingeben und dahinter den gewünschten Inhalt. Falls dies nicht klappen sollte, dann noch ein “Http://” davor schreiben, da es vorkommen kann, dass die Integrierte Suchmaschine startet.
| Eingabe in die Adresszeile des Browsers. |
Sieht man sich die Ausgabe im Debugger an, so sieht das doch nach relativ viel aus. Neben dem Text “Test”, sind noch viele anderen Informationen übermittelt worden. Ob die Daten gebraucht werden, ist vom Projekt abhängig und ich denke, für den Anfang möchte man einfach nur den Text haben.
| “Debug.Print” Ausgabe |
Daher ist es sinnvoll hier gleich einen eigenen Windows Client zu schreiben, der einfach nur den Text übermittelt und das geht mit Hilfe der der Socket Klasse. Mein neues Beispiel ist ähnlich wie aus meinem Blog Post zu “(Teil 1) Netzwerkverbindung zwischen Windows Phone 7 und Netduino Plus”, nur dass dieses mal eine Anwendung auf dem PC geschrieben wird.
| using System; namespace NetworkClient private int _Timeout = 5000; public string Connect(string hostAddress, int port) _Socket.ConnectAsync( _ClientDone.WaitOne(_Timeout); return _OperationResult; public void Send(byte[] data) private void Send_InThread(object obj) private SocketAsyncEventArgs CreateOperationEvent(EndPoint remoteEndPoint) socketEvent.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) _ClientDone.Reset(); return socketEvent; public void Close() public bool IsSending return false; public bool IsConnected public delegate void NetwokrStatusHandler(object sender, NetworkStatusEventArgs e); public event NetwokrStatusHandler NetworkStatus; public virtual void StatusEvent(string message) |
| Klasse für eine Client Verbindung (Achtung, Eventklasse ist hier nicht gepostet, siehe Download) |
Die Client Klasse unterscheidet sich kaum von der Client Klasse, die ich für das Windows Phone 7 bereits verwendet habe. Daher waren nur wenige Änderungen notwendig, um den Programmcode für den PC tauglich zu machen. Natürlich werde ich wieder hier den Quellcode mit Kommentaren als Download zur Verfügung stellen.
| Beispiel Anwendung das über Socket Klasse den Text übermittelt. |
| Ergebnis des Empfangenen Text. |
Leider ist das Beispiel nur für das Debuggen geeignet, es sei denn, am Netduino wird ein Display angeschlossen, das den Text ebenfalls wiedergeben kann. Aber mit etwas Kreativität findet sich sicherlich ein passendes Projekt zum umsetzen.
Ein kleiner Hinweis. Je nach dem, wie der Puffer eingestellt ist, kann ein Text abschneiden, der gesendet wurde. Das bedeutet, dass ggf. der Netduino am Serial Port, die Event Methode für den Empfang mehrmals aufgerufen wird.
Die Dateien für den Download:
| Netduino mit Shield - Aufsatz, für Sensor und Reglern |
| MPU6050 (Die Platine selbst, scheint für verschieden Sensor Typen gedacht zu sein, wegen der Aufschrift MPU-x050) |
| Der Sensor verbunden mit dem Arduino Nano 3.0 |
| Unregelmäßige Werte vom Sensor. (Ausgabe Wert wird hier verkürzt dargestellt zwischen 0 bis 100) |
| Stabile Werte, die sich erst verändern, wenn ich den Sensor bewege. |
Nachtrag (07.07.2013):
RGB LEDs und LIPO Akkus sind bestellt. Weil ich bereits die Abmessungen habe, kann ich schon mal mit dem Gehäuseentwurf in Blender anfangen....