Dienstag, 3. Oktober 2017

Arduino Control (Teil 6) - LED über LAN einschalten


Das Internet der Dinge geht die meisten Wege über eine Netzwerk Verbindung. Mit dem passenden Shield für Arduino kann die Netzwerkverbindung hergestellt werden. Mit relative wenig Programm Code kann eine simple Datenübertragen vom PC an den Arduino versendet werden.


Ethernet Shield und LED
Für das Beispiel wird das Ziel sein, die LED auf dem Arduino ein und Auszuschalten. Auf dem PC kommt wiederum eine Consolen Anwendung der die Befehle über die LAN Verbindung versenden kann. Der Arduino benötigt für den Empfang den Ethernet Shield, dass wiederum die selbe Verbindung zum Netzwerk hat wie der PC.


Grüne Low Current LED mit einem 2,2kOhm Widerstand


Consolen Anwendung
Fangen wir zunächst mit der Consolen Anwendung an und legen zunächst eine neue Klasse an mit dem Namen 'NetworkHost.cs'. Für die Verbindung wird die Socket Klasse verwendet und ermöglicht die Kommunikation über das Netzwerk. Initial wird die Klasse im Konstruktor mit den wesentlichen Einstellungen als Server festgelegt. In der Methode 'SendCommand' wird das einzelne Zeichen in das zu Übertragenden UTF8 Format gebracht und als Byte Wert versendet. Die 'Stop' Methode ist zwar für das Beispiel nicht erforderlich, jedoch sollte man auch bei kleinen Dingen aufräumen.


 public class NetworkHost  
 {  
   private Socket _connection;  
   public NetworkHost(int port)  
   {  
     Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
     socket.Bind(new IPEndPoint(IPAddress.Any, port));  
     socket.Listen(1);  
     this._connection = socket.Accept();  
   }  
   public void SendCommand(char command)  
   {  
     if (!char.Equals(command, ' '))  
     {  
       this._connection.Send(Encoding.UTF8.GetBytes(new char[] { command }));  
     }  
   }  
   public void Stop()  
   {  
     if (this._connection != null)  
     {  
       this._connection.Dispose();  
       this._connection = null;  
     }  
   }  
 }  

In der Klasse 'Program.cs' wird die Klasse instanziiert. Ggf. kann hier auch eine andere Port Nummer verwendet werden. In der Schleife wird die Eingabe eines Zeichen eingelesen und versendet. Allerdings auf 'A' und 'B' beschränkt und mit 'C' lässt sich die Anwendung zusammen mit der Verbindung beenden.

 class Program  
 {  
   static void Main(string[] args)  
   {  
     NetworkHost host = new NetworkHost(1200);  
     bool run = true;  
     while (run)  
     {  
       Console.WriteLine("a = ON");  
       Console.WriteLine("b = OFF");  
       Console.WriteLine("c = Close application");  
       string enter = Console.ReadLine();  
       if(enter.Contains("a") || enter.Contains("b"))  
       {  
         host.SendCommand(enter.ToCharArray()[0]);  
       }  
       else if(enter == "c")  
       {  
         run = false;  
       }  
     }  
     host.Stop();  
   }  
 }  

Arduino Client
Der Programmcode ist kaum länger als das von der Consolen Anwendung. Allerdings habe ich die 'Serial.println' Ausführungen gelassen womit man nicht zwingend eine LED braucht und sich das Ergebnis auch im 'Arduino -> Serielle Monitor' beobachten kann.

Gegebenenfalls anpassen
In der Regel muss die MAC Adresse nicht geändert werden, es sei denn ein anderes Gerät verwendet am Netzwerk genau dieselbe wie im Beispiel.
Für die Funktionsvariable 'ip' wird die IP Adresse für den Arduino mit dem Ethernet Shield festgelegt. Ggf. muss hier die dritte Oktett geändert werden und das vierte, wenn ebenfalls ein System die Adresse verwendet.
Mit der Funktionsvariable 'serverip' wird die Adresse vom PC eingetragen, auf der die Consolen Anwendung ausgeführt wird.
HINWEIS: zu den beiden 'includes' fehlen die spitzen Klammern. Der Code Formatierer kann das nicht erkennen.

#include SPI.h  
#include Ethernet.h 

 byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x91, 0x8C };  
 byte ip[] = {192,168,20,99};  
 byte serverip[] = {192,168,20,69};  
 EthernetClient client;  
 int ledPin = 2;  

 void setup() {  
  pinMode(ledPin, OUTPUT);  
  Ethernet.begin(mac, ip);  
  Serial.begin(115200);  
  tryConnectToServer();  
 }  
 void loop() {  
  if(client.available()) {  
   char c = client.read();  
   if(c == 'a') {  
    Serial.println("ON");  
    digitalWrite(ledPin, true);  
   }  
   else if(c == 'b') {  
    Serial.println("OFF");  
    digitalWrite(ledPin, false);  
   }  
   Serial.println(c);  
  }  
  checkForReconnect();  
 }   
 void checkForReconnect() {  
  if(!client.connected()) {  
   Serial.println("disconnecting");  
   client.stop();  
   delay(1000);  
   tryConnectToServer();  
  }  
 }  
 void tryConnectToServer() {  
  Serial.println("connecting...");  
  bool runTryToConnect = true;  
  while(runTryToConnect) {  
   if(client.connect(serverip, 1200)) {  
    Serial.println("Connected");
    runTryToConnect = false;  
   }  
   else {  
    Serial.println("wait...");  
    delay(1000);  
    Serial.println("try to connect again...");  
   }  
  }  
 }  

Nachdem der Arduino Sketch geschrieben wurde und das Ethernet Shield eine Verbindung zum Netzwerk hat, kann die Consolen Anwendung gestartet werden. Die Verbindung kann ein paar Sekunden andauern, bevor man ein Befehl senden kann. Anschließend kann dann mit 'a' die LED eingeschaltet und mit 'b' wiederum ausgeschaltet werden.


Hmm.. Vielleicht hätte ich doch eine hellere LED verwenden sollen :D

Sonntag, 17. September 2017

Eigene Sprites erstellen (Arduino Esplora, Part 3.1)


Im Internet habe ich nach einer Einfachen Lösung gesucht, wie mein ein Sprite bzw. Bild  auf seine eigenen Anforderungen erstellen kann. Damit ist gemeint, dass eine durchgehende Farbpallette für das Eigene Ziel abbilde und Numerisch bezeichnen kann. Zudem sollte dies in einer Byte Folge ausgegeben werden, so dass ich diese im Programmcode ablegen kann.
Natürlich gibt es so ein Programm nicht. Im Grunde ist die Ausgabe eines Bildes durch ein Skript zu übersetzen relative einfach oder auch mal schnell ein eigenes kleines Programm schreiben. Denn das habe ich zunächst gemacht, um schnell eigene Sprites anzulegen. Also zwei Abende dran ran gesetzt und fertig war der Bildeditor. Die Benutzbarkeit beschränkte sich auf die mehr auf die Verwendung der Funktionen.
Mit der Zeit wurden dann noch ein paar Farben hinzugefügt und neu Sortiert, ansonsten hat sich nichts weiter geändert.


  
Übung ist trainieren
Irgendwann bekam es mich doch. Ich schrieb zu Übungszwecken weiter und räumte einiges an Programmcode auf, fügte ein paar weitere Funktionen hinzu und verpasste noch ein paar Optische Verbesserungen. Da ich nicht immer Zeit hatte, verstrichen Monate und ich stellte mal wieder fest, wenn man etwas ordentlich macht, dann kann dabei schon eine Menge Zeit vergehen. Oberflächlich wird man die Mühe nicht sehen, nur die Dinge die nicht funktionieren. Schließlich sind wir in Deutschland und gemeckert wird immer.

Wie verwende ich das Programm
Man schreibt ein Programm, kopiert sich die fertigen Code aus dem Beispiel, malt ein Bild und klickt auf Exportieren. Na gut, etwas mehr Detaillierter darf die Beschreibung dann doch sein.

Am besten verwendet ihr den folgenden Beispiel Programmcode. Je nach Größe des Bildes, müssen die Breite und Höhe angepasst werden. Das sind die Member Variablen 'pictureWidth' und 'pictureHeight', sowie auch die Array Größe und dessen eingetragenen Byte Werte. Im Beispiel ist ein Bild das 10 Pixel Breit und 16 Pixel hoch ist. Multipliziert man die beiden Werte, dann bekommen wir den Wert 160, dass hier die Byte Array Größe festlegt.

 #include <SPI.h>  
 #include <TFT.h>  
 #include <Esplora.h>  
 // zu renderndes Bild  
 int pictureWidth = 10;  
 int pictureHeight = 16;  
 byte picture[160] = {  
  0,0,1,1,1,1,1,1,0,0,0,1,3,3,3,3,3,3,1,0,1,3,3,3,3,3,3,3,3,1,1,3,3,4,4,2,4,3,3,1,1,3,5,5,2,2,5,5,3,1,1,3,4,1,2,2,1,4,3,1,0,1,2,1,2,2,1,2,1,0,0,0,1,2,2,2,2,1,1,0,0,1,8,8,3,3,8,8,6,1,1,8,8,8,8,8,8,6,2,1,1,2,1,8,8,8,8,1,1,0,0,1,1,10,10,7,7,1,0,0,0,1,9,10,1,7,6,1,0,0,0,0,1,1,1,7,6,1,0,0,0,0,0,0,1,9,11,1,0,0,0,0,0,0,0,1,1,0,0,0  
  };  
 void setup() {  
  // init display  
  EsploraTFT.begin();  
  EsploraTFT.initR(INITR_BLACKTAB);  
  EsploraTFT.setRotation(1);  
  EsploraTFT.background(0, 0, 0);  
 }  
 void loop() {  
   drawPictureArray(40, 40, picture);  
 }  
 uint16_t mapNumberToColor(byte c) {  
  uint16_t result = ST7735_RED;  
  switch(c) {  
   case(1): { result = ST7735_BLACK; break; }  
   case(2): { result = 0xF590; break; } // haut  
   case(3): { result = 0x81E1; break; } // braun  
   case(4): { result = 0xC2C2; break; } // hell braun  
   case(5): { result = 0x8300; break; } // braun gelb  
   case(6): { result = 0x5406; break; } // gruen  
   case(7): { result = 0x32A4; break; } // dunkel gruen  
   case(8): { result = 0xAE91; break; } // hell gruen  
   case(9): { result = 0x2146; break; } // dunkel grau blau  
   case(10):{ result = 0x31E9; break; } // grau blau  
   case(11):{ result = 0x84B6; break; } // hell blau  
   case(12):{ result = 0xFFE0; break; } // gelb  
   case(13):{ result = 0xFC08; break; } // orange  
   case(14):{ result = 0xFA8A; break; } // hell rot  
   case(15):{ result = 0xD759; break; } // hell gruen 2  
   case(16):{ result = 0xF800; break; } // rot  
   case(17):{ result = 0x8208; break; } // dunkel braun  
   case(18):{ result = 0xC618; break; } // grau  
   case(19):{ result = 0xF7BE; break; } // sehr hell grau  
   case(20):{ result = 0xFE97; break; } // hell haut  
   default: {  
    result = 0;  
    break;  
   }  
  }  
  return result;  
 }  
 void drawPictureArray(int relationX, int relationY, byte pictureArray[]) {  
  int index = 0;  
  for(int y = 0; y < pictureHeight; y++) {  
   for(int x = 0; x < pictureWidth; x++) {  
     EsploraTFT.drawPixel(relationX+x, relationY+y, mapNumberToColor(pictureArray[index]));  
     index++;  
    }  
   }  
 }  

Wenn ihr den Bild Editor Startet, dann wird gleich ein neues Bild von 10 mal 16 Pixel angelegt.


Über ‚Edit' kann die Größe des Pixelfeldes geändert werden. ACHTUNG: Nach Umstellung der Größe, gehen bereits eingetragene Pixel verloren.


Ist das Bild fertig, dann kann über File -> Export die Byte Kette selektiert und per STRG+C kopiert werden.


Über STRG+V wird zwischen den geschweifte Klammern der Member Variable 'picture' hinzugefügt. Ggf. Breite, Höhe und byte Array Größe anpassen und schon kann der Programmcode auf den Arduino Esplora geschrieben werden.


Sobald das Programm auf dem Arduino Esplora ausgeführt wird, sollte nun das Bild zu sehen sein, dass als Byte Kette hinein kopiert wurde.


Hinweise:
  • Im Programm sind bereits mehr Farben hinterlegt, da ich zu diesen Zeitpunkt mit dem Eigentlichen Projekt weiter gearbeitet und weitere Farben ergänzt habe.
  • Touch Fähigkeit wird noch bearbeitet.
  • Ein Bild mit Programmcode darf nicht mehr Bytes verbrauchen als der Maximale Arbeitsspeicher des Arduinos.

Der Bildeditor ist an für sich fertig. Fehler sind nicht ausgeschlossen und können über die Kommentar Funktion des Blogs eingetragen werden.

Nächster Post: Karte anlegen (Arduino Esplora, Part 4)

Low Pixel Maker Download
Anmerkung: Ich räume noch das kleine Programm auf. Sobald ich damit fertig bin, lade ich die Solution auf Github hoch.

Sonntag, 3. September 2017

Bildanimation (Arduino Esplora, Part Teil 3)


Die Adafruit GFX Bibliothek gibt uns die Möglichkeiten Pixel für Pixel auf das TFT zu schreiben, womit sich dann auch ein Bild zusammen setzen lässt. Bei größeren Bilder sollte klar sein, dass der Bildaufbau mit 16MHz nur langsam abläuft. Als Ziel ist jedoch eine Darstellung zur Laufzeit zu verändert, wie z.B. eine Runde Analoge Anzeige.


Relativ schnell stellte sich heraus, dass die Umsetzung einer solchen Anzeige zwar einfach ist, aber ab einer bestimmten Größe zu langsam gerendert wird. Alternative und einfacher ist die das Verwenden von bereits fertigen Bildern in 16 mal 16 Format. Zugegeben ist eine Analoge Anzeige mit dieser Auflösung sehr grob und auf Dauer nicht zu friedend stellend. Eine Low Pixel Figur wiederum würde passen und das kombiniert mit den Tasten, könnte die Figur auch über den Bildschirm gesteuert werden. An dieser Stelle erinnerte ich mich wieder an den Anfang von Octoawesome von Tom Wendel, der in seinen ersten folgen ähnliche Schritte unternahm ein Spiel zu entwickeln mit C# und Windows Forms (später wurde die Windows form Oberfläche abgelöst  durch MonoGame).

Technische Umgebung und Anforderung
Kommen wir zu den Bildern die zunächst auf ein Format gebracht werden müssen, die möglichst wenig Ressourcen verbrauchen. Mit dem Format 16x16 muss jeder Pixel eine Farbe zugewiesen werden. Der Bildschirm unterstützt 16Bit, womit zwei Byte pro Pixel anfallen würden. Das wären dann 512 Bytes für ein Bild, womit dann eine Sinnvolle Animation mit 2,5 Kilobyte SRAM nicht sinnvoll wäre.
An der Stelle sollten man sich vor Augen halten, wie viele Farbabstufungen 16Bit haben. Und dann schaut man nochmal auf die Anforderung. Daraus stellen sich die Fragen:
Wie viele Farben werden benötigt?
Wie viele Pixel braucht meine Figur?


Auf die Hälfte und weniger reduzieren
Anstatt zwei Byte als Pixelfarbinformation zu hinterlegen, wird dies auf ein Byte reduziert. Der Byte Wert trägt später nur die Nummer aus einer Farbpallette. Mit einer entsprechenden Mapping Funktion, wird dann später die Farbe für den Pixel abgerufen. Durch diesen Vorgang reduziert sich das Bild von 16x16 von 512 auf 256 Bytes. Die Figur selbst benötigt in der Breite nur zehn Pixel, womit der Speicher verbrauch sich auf 160 Bytes weiter reduziert.

 uint16_t mapNumberToColor(byte c) {  
  uint16_t result = ST7735_RED;  
  switch(c) {  
   case(1):{ result = ST7735_BLACK; break; }  
   case(2):{ result = 0xF590; break; } // haut  
   case(3):{ result = 0x81E1; break; } // braun  
   case(4):{ result = 0xC2C2; break; } // hell braun  
   case(5):{ result = 0x8300; break; } // braun gelb  
   case(6):{ result = 0x5406; break; } // gruen  
   case(7):{ result = 0x32A4; break; } // dunkel gruen  
   case(8):{ result = 0xAE91; break; } // hell gruen  
   case(9):{ result = 0x2146; break; } // dunkel grau blau  
   case(10):{ result = 0x31E9; break; } // grau blau  
   case(11):{ result = 0x84B6; break; } // hell blau  
   default: {  
    result = 0;  
    break;  
   }  
  }  
    
  return result;  
 }  

Bild Editor in Arbeit
Kommen wir zum Erstellen eines Bildes. Ein Bild Byte für Byte zu schreiben ist so spaßig wie einen Film auf Indisch mit Kantonesischen Untertitel zu schauen. Hier für stelle ich demnächst ein kleines Tool zur Verfügung, mit denen ihr Farbpixel für Farbpixel euer Bild Zeichnen und nach Fertigstellung die byte Kette in den Sketch kopieren könnt.




Keine Metadaten
Die Byte Kette selbst enthält keine Metadaten. Das bedeutet, dass das Bild nicht weist wie Breit und wie hoch sie ist. Diese Informationen müssen vom Programmcode festgelegt werden.

 void drawFigurArray(int relationX, int relationY, byte figureArray[], boolean mirror, boolean clearColor) {  
  int index = 0;  
  for(int y = 0; y < 16; y++) {  
   for(int x = 0; x < 10; x++) {  
    if(clearColor) {  
      EsploraTFT.drawPixel(relationX+x, relationY+y, mapNumberToColor(figureArray[1]));  
    }  
    else {  
     int indexTarget = index;  
     if(mirror) {  
      indexTarget = index - x + (10 - x) - 1;  
     }  
   
     EsploraTFT.drawPixel(relationX+x, relationY+y, mapNumberToColor(figureArray[indexTarget]));  
     index++;  
    }  
   }  
  }  
 }  

Sprite Animation
Den Sketch den ich zur Verfügung stelle, kann die Farbnummern übersetzen aus dem Byte Array und so mit ein Bild auf den TFT schreiben. Hier fehlt nur die Sequenz abfolge der verwendeten Sprites als Animation. Würde man die paar Bilder direkt hintereinander abspielen, würden diese zu schnell ablaufen. Mit 'delay' lässt sich dieses Problem provisorisch lösen, führt jedoch zu Problemen mit dem späteren Abfragen der Taster. Deshalb werden zwei Variable vom Typ long und int im Funktionsvariable angelegt. Der mit dem Typ long (hier gametime benannt), wird pro Methoden Loop durchlauf, um einen hochgezählt. Der zweite Wert von Type int Mit einer Modulo Abfrage wird dann immer der vierte Durchlauf verwendet, um den Sequenz Bildindex der Animation um einen fortzusetzen oder von vorne abzuspielen.
Die Figur kann sich in vier Richtungen bewegen, womit dann auch vier verschiedene Animationsabläufe sich abbilden. Für Links und Rechts können die selben Bilder verwendet werden, da für die gegenteilige Richtung gespiegelt werden kann.
UPDATE: Zuvor war an der Methode der Parameter 'walk' übergeben worden, der jetzt entfällt. Und 'default' führt jeweils nochmal das zweite Sprite aus, womit dann die Figur weniger flimmern sollte.

 void drawFigure(int directionX, int directionY, int relationX, int relationY) {  
   
  if(gameTime % 4 > 0) {  
   if(animStep > 2) {animStep = 0;}  
   else {animStep++;}  
  }  
   
   if(directionX == 0 && directionY == 1) {  
    switch(animStep){  
     case(0): { drawFigurArray(relationX, relationY, spriteFigureFrontLeft, false, false); break; }  
     case(1): { drawFigurArray(relationX, relationY, spriteFigureFrontMiddle, false, false); break; }  
     case(2): { drawFigurArray(relationX, relationY, spriteFigureFrontLeft, true, false); break; }  
     default: { drawFigurArray(relationX, relationY, spriteFigureFrontMiddle, false, false); break; }  
    }  
   }  
   else if(directionX == -1 && directionY == 0) {  
    switch(animStep){  
     case(0): { drawFigurArray(relationX, relationY, spriteFigureSideLeft, false, false); break; }  
     case(1): { drawFigurArray(relationX, relationY, spriteFigureSideMiddle, false, false); break; }  
     case(2): { drawFigurArray(relationX, relationY, spriteFigureSideRight, false, false); break; }  
     default: { drawFigurArray(relationX, relationY, spriteFigureSideMiddle, false, false); break; }  
    }  
   }  
   else if(directionX == 0 && directionY == -1) {  
    switch(animStep){  
     case(0): { drawFigurArray(relationX, relationY, spriteFigureBackLeft, false, false); break; }  
     case(1): { drawFigurArray(relationX, relationY, spriteFigureBackMiddle, false, false); break; }  
     case(2): { drawFigurArray(relationX, relationY, spriteFigureBackLeft, true, false); break; }  
     default: { drawFigurArray(relationX, relationY, spriteFigureBackMiddle, false, false); break; }  
    }  
   }  
   else if(directionX == 1 && directionY == 0) {  
    switch(animStep){  
     case(0): { drawFigurArray(relationX, relationY, spriteFigureSideLeft, true, false); break; }  
     case(1): { drawFigurArray(relationX, relationY, spriteFigureSideMiddle, true, false); break; }  
     case(2): { drawFigurArray(relationX, relationY, spriteFigureSideRight, true, false); break; }  
     default: { drawFigurArray(relationX, relationY, spriteFigureSideMiddle, true, false); break; }  
    }  
   }  
 }  

Die Animation sollte nur dann abgespielt werden, wenn eines der Tasten gedrückt wurde. Im zweiten Teil der Blogpost Reihe wurde nur ein Kreis bewegt und wurde von der Methode in der folgenden If Abfrage ausgeführt.

 // Wenn sich X oder Y Position unterscheiden, dann den zu bewegenden Punkt neu zeichnen.  
  if(lastPosX != lastPosXtemp || lastPosY != lastPosYtemp) {  
   drawPoint(lastPosXtemp, lastPosYtemp, false);  
   drawPoint(lastPosX, lastPosY, true);  
  }  

Der Inhalt der If Abfrage Zeichnete einen Kreis, der durch die Sprite Animation ersetzt wird. Hier werden nun die Joystick eingaben auf ihre Ausrichtung geprüft bevor die Figur mit den richtigen Sprite Bilder gezeichnet werden.

 // Wenn sich X oder Y Position unterscheiden, dann den zu bewegenden Punkt neu zeichnen.  
  if(lastPosX != lastPosXtemp || lastPosY != lastPosYtemp) {  
   
   int directX = 0;  
   int directY = 0;  
   
   if(lastPosXtemp > lastPosX) { directX = -1; }  
   if(lastPosXtemp < lastPosX) { directX = 1; }  
   if(lastPosYtemp > lastPosY) { directY = -1; }  
   if(lastPosYtemp < lastPosY) { directY = 1; }  
   
   drawFigure(directX, directY, lastPosX, lastPosY);  
  }  

So das sollte erstmal alles sein für diesen Post. Im nächsten Post kommt eine Beschreibung zum Bild Editor, dass für das Erstellen der Sprites erleichtert.

Nächster Post: Eigene Sprites erstellen (Arduino Esplora, Part 3.1)

Dienstag, 13. Juni 2017

Netduino Netzwerk Adresse ändern


Seit langer Zeit hatte ich wieder einen Grund gefunden meinen Netduino aus zupacken und ein altes Projekt zu prüfen. Eigentlich suche ich eine Lösung, wie man eine Verbindung zum Netduino und einem SignalR Service herstellen kann. Zuvor hatte ich vor Jahren ein Beispiel mit WCF geschrieben, dass am Ende sogar relativ einfach war. Aber jetzt zum eigentlichen.

Netzwerk, Socket und Netduino
Mein Beispiel Projekt verwendete den SimpleSocket aus der Bibliothek Toolbox (https://netmftoolbox.codeplex.com/). Damit lässt sich in wenigen Codezeilen eine Verbindung zu einem anderen System über Netzwerk herstellen. Der Folgende Code Beispiel zeigt den Grundsätzlichen Aufbau einer Verbindung.

SimpleSocket socket = new IntegratedSocket(this._IpAddress, 80);
socket.Connect();
socket.Send("Hallo Welt");
socket.Close();


Das Problem
Die Verbindung blieb immer bei der Methode "socket.Connect()" stehen. Das kann dadurch festgestellt werden, wenn nach einer Weile nicht das gewünschte Ergebnis kommt und man dann die Pause Taste für das Debuggen klickt.



Ursache Prüfen
Meine Vermutung war, dass ich anscheinend nicht die richtige Adresse im Netduino Plus eingestellt hatte. Also startete ich aus dem Ordner "C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.3\Tools" das Programm MFDeploy.exe. Über den Menü Punkt "Network" (Target > Configuration > Network) kann die Adresse eingerichtet werden.




Falsche Adresse
Wie ich bereits vermutet, hatte ich noch eine andere IP Adresse sowie auch eine andere Adresse für Gateway eingestellt. Nach dem ich die gewünschte Netzwerk Adresse eingetragen hatte, sollten die Einstellungen nach dem Click auf den "Update" Button auf den Netduino geschrieben werden. Doch dies wurde verhindert und ich erhielt einen Hinweis.




Lösung
Kommt diese Hinweismeldung "Unable to erase configuration sector memory", dann muss einmal der Befehl "Reboot and Stop" (Plug-in > Debug > Reboot and Stop) gesendet werden.



Bevor die Konfiguration für das Netzwerk wieder aufgerufen werden kann, musste ich auf die Nachricht "Reboot and Stop Complete" abwarten, die wiederum im unteren Rahmen angezeigt wurde.



Nun kann die Adresse geändert und erfolgreich auf dem Netduino geschrieben werden. Nach dem klicken "Update" sollte sich das Konfigurationsfenster schließen und im unteren Rahmen "Signature PASS" oder zumindest "Chk signatu" stehen.



Jetzt kann das Netduino Projekt mit dem SimpleSocket neu gestartet werden und die Verbindung mit der Ziel Adresse sollte hergestellt werden.

Mittwoch, 5. April 2017

Umzug auf passende Plattform (Arduino Esplora, Part 2)


Nachdem ich viel probiert habe und dabei fast ein Spiel zusammen hatte (Nicht Pong, das ist zu einfach), entschied ich den Arduino Esplora zu bestellen. Normalerweise würde ich vom Breadboard umziehen und dann etwas selbst auf eine Platine mit den entsprechenden Komponenten zusammenlöten. Aber warum nicht eine fertige Plattform nutzen.

Etwas enttäuschend, fand ich die Suche im Internet, weil ich keine aufwendigen Spiele für den Arduino Esplora entdeckt habe. Damit will ich das nicht schlecht reden, aber etwas mehr hatte ich schon erwartet.

Der Umzug vom Breadboad auf den Arduino Esplora ist in wenigen Schritten erledigt. Als erstes werden die Adafruit Bibliotheken gegen die 'Esplora.h' und 'TFT.h' ausgetauscht. Die Beschreibung an welchen Pin vom TFT zum Arduino Uno (oder Nano) verbunden werden soll, sowie auch die Pin Variablen entfallen. Das Initialisieren der Pins sowie auch das TFT Display, wird durch ein 'EsploraTFT.begin()' ersetzt. Die Steuerrichtung wird durch den Joystick abgenommen, allerdings bleibt das Verhalten der Bewegungsgeschwindigkeit. Hinzu kommt noch, dass ein Offset benötigt wird. Bei analogen Eingängen kann es zu Abweichungen kommen die durch das Offset korrigiert werden können. Für diesen Zweck ist eine neue Methode hinzugekommen, mit der die Werte auf dem Display angezeigt werden können.


 #include <SPI.h>   
 #include <TFT.h>   
 #include <Esplora.h>   
   
 // ruft die letzte Postion X ab. (Pixel Position)   
 int lastPosX = 5;   
 // ruft die letzte Postion Y ab. (Pixel Position)   
 int lastPosY = 5;   
   
 // mittelstellung des Joystick   
 int offsetX = -3;   
 int offsetY = 4;   
   
 void setup() {  
   EsploraTFT.begin();   
   EsploraTFT.background(0, 0, 0);   
 }   
   
 void loop() {   
   
   // Eingänge einlesen   
   int stickX = Esplora.readJoystickX() + (offsetX * -1);   
   int stickY = Esplora.readJoystickY() + (offsetY * -1);   
   
   boolean buttonLeft = false;   
   boolean buttonRight = false;   
   boolean buttonUp = false;   
   boolean buttonDown = false;   
   
   if(stickX > 3 || stickX < -3) {   
     buttonLeft = stickX > 3;   
     buttonRight = stickX < -3;   
   }   
   
   if(stickY > 3 || stickY < -3) {   
     buttonUp = stickY < -3;   
     buttonDown = stickY > 3;   
   }   
   
   // Werte ausgeben auf dem Bildschirm   
   writeValue(10, 10, stickX, false);   
   writeValue(10, 20, stickY, false);   
   
   // Temporaer letzte Position merken   
   int lastPosXtemp = lastPosX;   
   int lastPosYtemp = lastPosY;   
   
   // Abfragen zu den gesetzten joystick   
   // Es kann nur in eine Richtung die Bedingung erfüllt werden.   
   
   // Wenn nach links oder rechts gedrückt wird.   
   if(buttonLeft && !buttonRight && lastPosX > 0) {   
     // nach links und letzte Position Y ist groesser als '0'.   
     lastPosX--;   
   }   
   else if(!buttonLeft && buttonRight && lastPosX < EsploraTFT.width()) {   
     // nach rechts und letzte Position X ist kleiner als die TFT Pixel Breite.   
     lastPosX++;   
   }   
   
   // wenn nach oben oder unten gedrückt wird.   
   if(buttonUp && !buttonDown && lastPosY > 0) {   
     // nach oben und letzte Position Y ist groesser als '0'.   
     lastPosY--;   
   }   
   else if(!buttonUp && buttonDown && lastPosY < EsploraTFT.height()) {   
     // nach unten und letzte Position X ist kleiner als die TFT Pixel hoehe.   
     lastPosY++;   
   }   
   
   // Wenn sich X oder Y Position unterscheiden, dann den zu bewegenden Punkt neu zeichnen.   
   if(lastPosX != lastPosXtemp || lastPosY != lastPosYtemp) {   
   
     // vorigen punkt entfernen mit den temporären Positionen.   
     drawPoint(lastPosXtemp, lastPosYtemp, false);   
   
     // neuen punkt zeichnen mit der neuen Position.   
     drawPoint(lastPosX, lastPosY, true);   
   }   
   
   writeValue(10, 10, stickX, true);   
   writeValue(10, 20, stickY, true);   
 }   
   
 void writeValue(int x, int y, int val, boolean clr) {   
   if(clr) {   
     EsploraTFT.stroke(0, 0, 0);   
   }   
   else {   
     EsploraTFT.stroke(30, 200, 50);   
   }   
   String accResult = String(val);   
   char valuePrint[5];   
   accResult.toCharArray(valuePrint, 5);   
   EsploraTFT.text(valuePrint, x, y);   
 }   
   
 // Einachen Punkt Zeichnen, der nicht ausgefuellt ist.   
 void drawPoint(int x, int y, boolean setColor) {   
   
   // Schwarz Zeichnen.   
   EsploraTFT.stroke(0, 0, 0);   
   
   // Farbe festlegen   
   if(setColor) {   
     EsploraTFT.stroke(120, 100, 200);   
   }   
   
   EsploraTFT.circle(x, y, 2);   
 }   

Sobald das Programm auf dem Esplora ist, sollte mit dem Lauf des Programms die Werte für X und Y des Joysticks zu sehen sein. Die angezeigten Wert zeigen die Abweichungen, die im Anschluss im Offset einzutragen sind.

Der Arduino Esplora ist eine schöne Plattform und kann wie jeder andere Arduino Programmiert und angesteuert werden. Das Potenzial an Möglichkeiten ist da. Abgesehen vom Joystick, Buttons und dem passenden TFT, sind noch weitere Sensoren und Aktoren auf der Plattform vorhanden. Falls diese nicht reichen sollten, dann können oben an die Stecker weitere Komponenten angeschlossen werden und Betrieben werden.

Einen wesentlichen Unterschied gibt es zwischen den Arduino Nano (den ich zuvor verwendet habe) und dem Arduino Esplora. Der SRAM vom ATMega32u4 ist um 512 Bytes größer 😃

Technische Daten
Microcontroller:   ATmega32u4
Flash Speicher:    32kb (4kb werden vom bootloader verwendet)
SRAM:                2,5 kb
EEPROM:           1 kb
Takt:                    16 MHz

Sensoren / Eingabemöglichkeiten: Analog X Y Joystick
                                                        4 Taster
                                                        Linear Potentiometer
                                                        Mikrofone
                                                        Lichtsensor
                                                        Drei Achsen Beschleunigungssensor

Aktor, Widergabe, Ausgabe:          Buzzer
                                                        RGB LED
                                                        TFT Display (gibt's wahlweise mit als Bundle)




Github - BlogPost_02_MoveLibrary

Sonntag, 19. März 2017

Bewegter Punkt (Arduino und TFT, Part 1)


Eigentlich sollte das Display für die Wiedergabe der Messwerte meiner Wetterstation wieder geben. Aber zu diesen Zeitpunkt war nicht klar, welche Möglichkeiten eigentlich mit dem TFT und vor allem mit dem ATMega328 mit den 16MHz machbar sind. Nur blanke Werte sind für meine Anforderung zu wenig und daher galt zunächst herauszufinden, wie schnell sich die Inhalte auf dem Display aktualisiert werden können.

Punkt bewegen
Das einfachste ist, man lässt einen Punkt von A nach B bewegen. Aber besser ist, wenn man die Bewegungsrichtung des Punktes selbst zur Laufzeit bestimmen kann. Daher wurden auf dem Breadboard, noch vier Taster an den Arduino Angeschlossen.












Das sieht etwas wirr aus und was vielleicht nicht gleich zu erkennen ist, dass an den Button jeweils ein 4,7 Kilo Ohm Pull-Down Widerstand gesetzt sind. Das ist erforderlich, damit die Kontakte an dem Arduino keinen Zufälligen Zustand einnehmen. Denn selbst hohe Luftfeuchtigkeit, kann zu unerwünschten Effekten führen.













Neben dem Initialisieren des Bildschirms, müssen auch die Eingänge definiert werden, die später die Steuerknöpfe abbilden. Pro Loop durchlauf, wird der Zustand eingelesen und die Bedingungen für die Bewegung abgefragt.


#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

// Verkabelung / Pins
// SCLK => D13
// MOSI/DIN => D11
// CS => D10
// DC => D9
// RST => D8

// instanz anlegen zu dem verwendeten Bildschirm.
Adafruit_ST7735 tft = Adafruit_ST7735(10, 9, 8);

// Pins festlegen
// ruft die Pin Nummer ab, um die Helligkeit des Displays anzusteuern.
const int pinBrightness = 5;
// ruft die Pin Nummer ab, um den Status des linken Buttons abzufragen
const int pinButtonLeft = 6;
// ruft die Pin Nummer ab, um den Status des rechten Buttons abzufragen
const int pinButtonRight = 3;
// ruft die Pin Nummer ab, um den Status des oberen Buttons abzufragen
const int pinButtonUp = 2;
// ruft die Pin Nummer ab, um den Status des unteren Buttons abzufragen
const int pinButtonDown = 7;

// ruft die letzte Position X ab. (Pixel Position)
int lastPosX = 5;
// ruft die letzte Position Y ab. (Pixel Position)
int lastPosY = 5;

void setup() {

  // initialisiere Display
  tft.initR(INITR_BLACKTAB);

  // pin Eingänge festlegen
  pinMode(pinButtonLeft, INPUT);
  pinMode(pinButtonRight, INPUT);
  pinMode(pinButtonUp, INPUT);
  pinMode(pinButtonDown, INPUT);

  // pin für tft Helligkeit festlegen
  pinMode(pinBrightness, OUTPUT);
  // helligkeit auf maximal einstellen
  analogWrite(pinBrightness, 255);

  // Bildschirm Schwarzausfüllen und um 90 Grad drehen.
  tft.fillScreen(ST7735_BLACK);
  tft.setRotation(1);
}

void loop() {

  // Eingaenge einlesen
  boolean buttonLeft = digitalRead(pinButtonLeft);
  boolean buttonRight = digitalRead(pinButtonRight);
  boolean buttonUp = digitalRead(pinButtonUp);
  boolean buttonDown = digitalRead(pinButtonDown);

  // Temporaer letzte Position merken
  int lastPosXtemp = lastPosX;
  int lastPosYtemp = lastPosY;

  // Abfragen zu den gedrückten Buttons
  // Es kann nur in eine Richtung die Bedingung erfüllt werden.

  // Wenn nach links oder rechts gedrückt wird.
  if(buttonLeft && !buttonRight && lastPosX > 0) {
    // nach links und letzte Position Y ist groesser als '0'.
    lastPosX--;
  }
  else if(!buttonLeft && buttonRight && lastPosX < tft.width()) {
    // nach rechts und letzte Position X ist kleiner als die TFT Pixel Breite.
    lastPosX++;
  }

  // wenn nach oben oder unten gedrückt wird.
  if(buttonUp && !buttonDown && lastPosY > 0) {
    // nach oben und letzte Position Y ist groesser als '0'.
    lastPosY--;
  }
  else if(!buttonUp && buttonDown && lastPosY < tft.height()) {
    // nach unten und letzte Position X ist kleiner als die TFT Pixel Hoehe.
    lastPosY++;
  }

  // Wenn sich X oder Y Position unterscheiden, dann den zu bewegenden Punkt neu zeichnen.
  if(lastPosX != lastPosXtemp || lastPosY != lastPosYtemp) {
    // vorigen punkt entfernen mit den Temporaeren Positionen.
    drawPoint(lastPosXtemp, lastPosYtemp, false);
    // neuen punkt zeichnen mit der neuen Position.
    drawPoint(lastPosX, lastPosY, true);
  }
}

// Einfachen Punkt Zeichnen, der nicht ausgefuellt ist.
void drawPoint(int x, int y, boolean setColor) {

  int setupColor = ST7735_BLACK;
  // farbe festlegen
  if(setColor) {
    setupColor = ST7735_CYAN;
  }
  tft.drawCircle(x, y, 2, setupColor);
  delay(2);
}

Damit wäre der erste Schritt getan und ihr könnt nun auf dem Bildschirm einen Punkte bewegen. Das ist zwar nicht sonderlich spektakulär, aber dafür gibt es ein wenig nostalgisches Gefühl mit der grafischen Darstellung.

Wie bereits oben der Titel verrät, kommen mehre Zusammenhängende Posts. Hierbei werden die Anliegen und Anforderungen Möglichst einfach gelöst und sind nicht nach einer Ziel Architektur ausgelegt.

Nächster Post: Umzug auf passende Plattform (Arduino Esplora, Part 2)

Github - BlogPost_01_MovingPoint

Sonntag, 6. November 2016

TFT Module und die richtige Bibliothek

Die Tage werden wieder kälter und ich sitze wieder länger Zuhause. Was gibt es besseres zu tun um einige Dinge heraus zu finden.

Bei meinen Versuchen mit dem TFT Modul traten Schwierigkeiten auf, wo ich oft nur wenig im Internet an „Lösungen“ (nicht) fand und zudem die Einträge schon relativ alt waren.

Was brauche wir für das Beispiel:
  • 1 x Arduino UNO
  • 6 x Kabel
  • 1 x Experimentierboard
  • 1 x 1.8“ TFT Modul, SPI 128x160


Bevor der erste Code geschrieben werden kann und auf den Arduino geladen wird, muss zunächst die Bibliothek eingebunden werden. In der Entwicklungsumgebung von Arduino sind bereits viele Bibliotheken vorhanden, sowie auch für das Display.



Wenn ihr beim kompilieren mehrere Fehler erhält, dann ist vielleicht die vorhandene Bibliothek die alte Version. Zumindest in meinem Fall und das führte dazu dass, sich der Quellcode nicht Kompilierern lies. Dieser Fehler trat mit der Arduino Version 1.6.8 auf, allerdings sei angemerkt, hat dieser Fehler nichts mit der Versionsnummer zu tun.

Falls neben der Bibliothek “Adafruit ST7735 Library” eine “Adafruit ST7735” vorhanden ist, dann sollte diese deinstalliert werden. Das gleiche gilt auch mit „Adafruit GFX Library“ und „Adafruit GFX“. Nur die, die am Ende des Namen „Library“ haben, müssen bestehen bleiben.

Das kann dann über dem Verzeichnis „../Dokumente/Arduino/libraries/ gelöscht werden. Sobald die aktuellere Bibliothek installiert ist, sollte der folgende „Hello World!“ Quellcode kompilierbar sein.

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

// Verkabelung / Pins
// SCLK     => D13
// MOSI/DIN => D11
// CS       => D10
// DC       => D9
// RST      => D8

// Instanz anlegen zu dem verwendeten Bildschirm.
Adafruit_ST7735 tft = Adafruit_ST7735(10, 9, 8);

void setup() {

  // Initialisiert den Bildschirm
  // und legt die Spalten Adressierung fest.
  tft.initR(INITR_BLACKTAB);

  // Zusätzlichen Pin Ausgang festlegen
  // für die Beleuchtung
  pinMode(5, OUTPUT);

  // Bildschirm Beleuchtung einschalten.
  analogWrite(5, 255);
}

void loop() {

  // bildschirm zurück setzen,
  // bzw. es werden alle Pixel auf Schwarz umgestellt.
  tft.fillScreen(ST7735_BLACK);

  // Textgröße einstellen
  // Text ist mit einem Wert 2 doppelt so groß.
  tft.setTextSize(1);
  // Start Postion festlegen, von wo aus
  // der Text begonnen wird zu schreiben
  // x von links nach rechts
  // y von oben nach unten
  tft.setCursor(5,5); //x, y

  // farbe des Textes
  tft.setTextColor(ST7735_WHITE);
  // Ausgabe Text.
  tft.println("Hello World!");

  // fünf Sekunden warten
  delay(5000);
}

Für gewöhnlich kann die Verkabelung vorgenommen werden, wie bereits im Quellcode beschrieben ist. Dennoch zur Vollständigkeit darf das Bild dazu nicht fehlen.


Wenn das kompilieren klappt, dann sollte auf eurem Display „Hello World!“ leuchten.


Im Grunde ist der erste Schritt zur Verwendung des Display sehr leicht, dennoch können nicht gleich erkennbare Fehler auftreten. Zum Beispiel traten mit sehr günstigen Arduino Nano Klone ein Fehler mit der der Beleuchtung des Displays auf. So funktionierte das Display nicht an 3,3V sondern an 5V.
Wenn ihr andere Fehler und vielleicht auch Lösungen habt, schreibt mir einen Kommentar zu diesem Thema.

Ameisen Simulation und andere Dinge

Wer lange sich schon mit C# beschäftig, hat sicherlich schon mal was von AntMe gelesen oder gehört. Diese Idee hatte ich aufgegriffen und mi...