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.

Sonntag, 17. Januar 2016

Arduino Control (Teil 5) - PWM Signal einlesen


Das Einlesen und Ausgeben des PWM Signals ist mit dem Beispiel für "Analoges Signal einlesen" vergleichbar. Daher gehe ich nochmal auf das Signal selbst ein.

Im Modellbau werden oft Analog Servos verwendet und nutzen zur Ansteuerung das PWM Signal. Die eingesetzte Frequenz liegt bei 50Hz. Bei Digital Servos wird ebenfalls ein PWM Signal verwendet, allerdings können diese mit einer deutlichen höheren Frequenz umgehen. Das bedeutet natürlich am Ende, dass in jeder Sekunde die Position des Servoarms mehrmals eingestellt wird. Also je höher die Frequenz, desto öfter pro Sekunde wird die Position festgelegt. Der Vorteil liegt auf der Hand: mit dem Digital Servo kann man wesentlich genauer arbeiten, hat aber entsprechend mehr Verbrauch. Hier muss man abwägen, ob sich für den geplanten Einsatz ein Digital Servo lohnt.

Zunächst zu dem PWM selbst sollte klar sein, wie  eigentlich das Signal aussieht. Im folgenden Bild ist zu sehen, dass eine Periodendauer aus einem HIGH und einem LOW Pegel besteht.
Mit der Pulslänge von 1ms bis 2ms wird das Steuersignal für den Ziel Steuereinheit bestimmt. Zum Beispiel bei einem Servo wäre dann bei 1ms Pulslänge der Winkel bei 0 Grad, bei 1,5ms bei 60 Grad und bei 2ms wäre die Ausrichtung  dann 120 Grad.
Im Modellbau ist der HIGH Level für gewöhnlich zwischen 4,8V und 6V. Wer einen Mikrocontroller mit einer Betriebsspannung von 3,3V verwendet, benötigt einen Pegelwandler. Hier reicht ein Wandler von 3,3V auf 5V aus. Natürlich können einige Servos wiederum mit der niedrigen Signalspannung umgehen. Dazu gehören z.B. Micro Servos.
Das HIGH Signal beinhaltet den Steuerwert und kann generell im RC Modellbau eine Pulslänge von 1 bis 2 Millisekunden betragen. Der LOW Zustand stellt die restliche Zeit der gesamten Periode. Zeitlich gesehen wird nichts mehr weiteres unternommen bis die nächste Periode beginnt. Bei 50Hz liegt die Periodendauer bei 20 Millisekunden, was bedeutet, dass 18 bis 19 Millisekunden kein neuer Steuerwert zugewiesen wird. Bei Digital Servos kann der LOW-Level-Zeitraum verkürzt werden. Als Beispiel könnte dann eine Periodendauer von 5 Millisekunden geschaltet werden, so das der LOW Zustand nun zwischen drei bis vier Millisekunden andauert.
Kommen wir zum Arduino Code. Anstatt der Methode analogRead, wird pulseIn(pinNumber, HIGH) verwendet. Der Ausgabewert kommt als ganze Zahl und stellt die Microsekunden dar. Wenn ein Signal von einem einfachen Empfänger gelesen wird, dann sollte ein Wert zwischen 900 bis 2000 als Ergebnis kommen.

// Digitaler Pin Nummer 3
int pin = 3;

void setup() {
 
  Serial.begin(9600);
 
  // Pin Eingang festlegen
  pinMode(pin, INPUT);
}

void loop() {
 
  // Pin Eingang einelsen
  int result = pulseIn(pin, HIGH);
 
  // Nur Inhalt im If ausführen,
  // wenn der Status sich geändert hat.
  if(result != lastValue)
  {
   // Member Field überschreiben.
    lastValue = result;
  
   // Buffer vorbereiten und
   // den Wert in zwei bytes aufteilen.
    byte ba[2];
    ba[0] = (byte)((result >> 8) & 0xff);
    ba[1] = (byte)(result & 0xff);
   
    // Buffer Inhalt von zwei Bytes senden.
    Serial.write(ba, 2);
       
    // Ermöglicht das Erkennen vom 1. und 2. Byte
    // in dem zwischen den Sendungen eine Pause gesetzt wird.
    delay(100);
  }  

  delay(20);
}

Für das Programm auf dem Desktop kann der selbe Code Schnipsel verwendet werden, wie aus meinem Blog Post "Arduino Control (Teil 4) - Potentiometer Wert am PC ausgeben". Zur Vollständigkeit steht dieser im folgenden Abschnitt.

static void Main(string[] args)
{
    
// Die Verwendete COM Verbindung
    // sollte der aus dem Arduino Programm entsprechen.
    
    SerialPort sp = new SerialPort("COM16", 115200);
    // Event zuweisen für den Empfang.    
    sp.DataReceived += sp_DataReceived;
    // Verbindung öffnen.
   
// Wenn das Programm gestartet ist, 
    // sollte der Arduino bereits mit dem PC verbunden sein.
    
    sp.Open();
    while (true)
    {
       
// Nur warten.        
       Thread.Sleep(1000);
    }
}

// Wird ausgeführt, wenn Daten im Empfangspuffer vorhanden sind.
static void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    
// SerialPort aus 'sender' casten.    
    SerialPort sp = (SerialPort)sender;
    // Bytes einlesen vom Empfang und auf die Console wiedergeben.    
    byte[] buffer = new byte[2];
    
if (sp.Read(buffer, 0, 2) != 0)
    {
        
Console.Clear();
        
// Die zwei empfangenen Byte müssen wieder zusammengelegt werden, 
        // um den Eigentlichen Wert wiederzugeben.
        
        Console.WriteLine("Received: {0} micro secounds", (int)buffer[0] << 8 | buffer[1]);
    }
}

Sinnvollerweise kann dieses Beispiel mit einer Fernsteuerung und einem Empfänger verwendet werden.

Quellcode zum Download
·         Für den Arduino reicht der Code aus dem Post aus.


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...