Posts mit dem Label Schaltung werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Schaltung werden angezeigt. Alle Posts anzeigen

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

Donnerstag, 24. Dezember 2015

Neu Verkabeln


Eine Schaltung zu entwerfen ist schon eine tolle Sache und wenn das Ganze auch noch gut verlötet ist, dann macht das schon einen professionellen Eindruck. Obwohl ich für einen Freizeitelektroniker relativ viel Übung habe, erreiche ich nicht immer ein überzeugendes Ergebnis. Das liegt oft an den Kabeln selbst, die meistens sehr bunt sind. Klar dienen die Farben zur Orientierung und sagen etwas über ihre Zuständigkeit aus, aber wenn sie bereits verlegt sind, benötige ich diese Funktion nicht mehr.


Im Normalfall werden die zu langen Kabel zusammengerollt und mit Kabelbinder zusammengehalten. Das reicht grundsätzlich aus, besonders dann, wenn noch nicht klar ist, wie alles verlegt wird.


Meine letzte unzufriedene Verkabelung war an meinem Quadrocopter. Viele Kabel waren zu lang und aufgewickelt. Auch hier zeigen sich die Leitungen in verschiedenen Farben. Das ergab ein sehr unordentliches Bild. Deshalb entschied ich, alles auf eine brauchbare Länge zu kürzen. Leider fehlte mir dazu eine Kleinigkeit.
Zunächst suchte ich nach Kabeln, die wie eine Schnur aussehen, bis ich vor einigen Monaten die Gewebeschläuche gefunden habe. Auf Ebay finden sich die Artikel unter den Begriffen wie Gewebeschlauch.

Für die Verarbeitung des Gewebeschlauches gibt’s eine Sache zu tun. Damit der Gewebeschlauch sich nicht ausfranst, sollten mit einem Feuerzeug die Enden angesengt werden, bis sich die einzelnen Fäden miteinander verschmelzen.


Um das Ganze noch abzurunden, kann ich empfehlen, ein kleines Stück Schrumpfschlauch über die angesengten Enden zu ziehen.


Mit meinem Beispiel in der Zeitrafferaufnahme zeigen sich die einzelnen Schritte, wie die Verkabelung und die Verwendung des Schrumpfschlauches eingesetzt werden kann.


Dienstag, 12. Mai 2015

Beleuchtung mit dem ATtiny 45 (Ausbessern)

Quadrocopter_10

In meinem vorigen Post habe ich bereits geschrieben, dass die vorhandenen LEDs für meine Beleuchtung nicht alle vollständig durchgesteuert werden können. Der Grund liegt an dem verwendeten Spannungsregler, der für den Betrieb ca. 100mA zur Verfügung stellt und kurzzeitig auch bis zu 150mA. Die Lichtausbeute war somit nur eingeschränkt möglich.

Quadrocopter_12

Neu ist eine hintere LED Leiste mit fünf blauen und vier weißen LEDs. Dieser benötigt alleine bereits bis zu 200mA und da würde schon der einfache Spannungsregler nicht lange funktionieren. Nun mit dem etwas größer dimensionierten Spannungsregler sind solche Schwierigkeiten obsolet und am Programm muss nichts extra verändert werden, um Einsparungen für den Stromverbrauch vorzunehmen. Zudem können alle 16 LED RGBs (WS2812b) vollständig durchgeschaltet werden, ohne das die Spannung einbricht.

Quadrocopter_08

Kommen wir zu den Änderungen. Wie bereits erwähnt verwende ich einen anderen Spannungsregler von STMicroelectronics. Die Bezeichnung lautet L7805CV und fällt schon durch ein größeres Gehäuse auf, das der TO-220 Norm entspricht. Mit dem neuen kommen auch ungepolte Kondensatoren mit einer deutlichen kleineren Kapazität.

image

Die Schaltung ist dem Vorgänger sehr ähnlich und zeigt im Unterschied die neuen Anschlüsse für die hintere LED Leiste. Ebenfalls habe ich das Zusammenlöten der Komponenten so eingeplant, dass alles auf einer Platine Platz findet.

ATtiny45QuadrocopterLicht

Zusammengelötet und fast fertig auf der Platine.

Quadrocopter_09

Am Quellcode kann nun das Ansteuern des Pin 1 ergänzt werden. Damit wird später die hintere Lichtleiste ein- und ausgeschaltet.

// NeoPixel Bibliothek hinzufügen für die Ansteuerung der WS2812B LED Streifen
#include <Adafruit_NeoPixel.h>

// Instanz initialisieren
// Parameter Angaben:
// 1. Anzahl für verwendeter RGB LEDs
// 2. Auf welchen Pin soll verwendet werden.
// 3. Auswahl zwischen RGB, GRB oder BRG und verwendeter Takt 400KHz oder 800KHz

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(4, 2, NEO_GRB + NEO_KHZ800);

// Helligkeit einstellen. Kann von 0 bis Maximal 255 festgelegt werden.
// Bei Maximaler Ausleuchtung ist zu prüfen, ob die Maximale Stromabnahme erreicht wird.

int brightness = 100;

// Helligkeit bei verwendung der WS2812b, wenn sie weis auf blitzen sollen.
// Bei 210 wird die Maximale Stromabnahme überschritten.
// Darf nur kurz verwendet werden, ansonsten brennt der Spannungsregler durch.

int brightnessWhite = 210;

// Wird zum festlegen des Licht Einstellung verwendet.
// Damit die Einstellung funktioniert,
// muss an der Fernsteuerung einmal hin und her Geschaltet oder gedreht werden,
// um die längste Pulslänge zu ermitteln.

unsigned long maxPwmIn = 2;

void setup() {
  // Signal von der Fernsteuerung aufnehmen.
  pinMode(3, INPUT);
  // Positionslichter schalten
  pinMode(0, OUTPUT);
  // Neu. Um die LED Leiste ein- und auszuschalten.
 
pinMode(1, OUTPUT);
  // RGB LEDs Stribes starten
  pixels.begin();
  pixels.show();
}

void loop() {
  // Signal von der Fernsteuerung einlesen.
  // Für die Verwendung sollte ein Schalter genutzt werden.

  unsigned long pwmIn =  pulseIn(3, HIGH);
  // Wird zum Anlernen verwendet. Durch festlegen der maximalen Pulslänge
  // können zwei Zustände verwendet werden.

  if(pwmIn > maxPwmIn) { maxPwmIn = pwmIn; }
 
  // Wenn das Signal kürzer ist als der Maximalen Pulslänge.
  if(pwmIn < maxPwmIn - 100){
    // Positionslichter einschalten
    // (Bei verwendung von NPN Transisitor, kann die '255 -' weg)

    analogWrite(0, 255 - brightness); delay(100);
    // Ausschalten (Bei NPN, den Wert auf 0 setzen.)
    analogWrite(0, 255); delay(100);
    // Die LED Leiste einschalten
   
analogWrite(1, 255);
    // RGB LED Streifen ansteuern.
    // Rot und Grün

    allRGB_LED_Off();
    pixels.setPixelColor(0, pixels.Color(brightness, 0, 0));
    pixels.setPixelColor(1, pixels.Color(0, brightness, 0));
    pixels.show();
    delay(100);
    allRGB_LED_Off();
    pixels.setPixelColor(2, pixels.Color(brightness, 0, 0));
    pixels.setPixelColor(3, pixels.Color(0, brightness, 0));
    pixels.show();
   delay(100);
  }
  else
  {
    // Positionslichter ausschalten
    // (Bei verwendung von NPN Transisitor, ist zum Ausschalten der Wert 0)

    analogWrite(0, 255);
    // Die LED Leiste ausschalten.
   
analogWrite(1, 255);
   // RGB LED Streifen ansteuern.
    for(int i = 0; i < 4; i++)
    {
      // Alle aus.
      allRGB_LED_Off();
     // Mit der Aktuellen Iteration als Index verwenden,
      // um den entsprechende RGB LED zu überschreiben.

      pixels.setPixelColor(i, pixels.Color(brightnessWhite, brightnessWhite, brightnessWhite));
      pixels.show();
      delay(100);
    }
  }
}
// Stellt alle Werte zurück.
void allRGB_LED_Off()
{
  for(int i = 0; i < 4; i++)
  {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
  }
}

Zuletzt dürfen zur Demo die Videos nicht fehlen.

Sonntag, 19. April 2015

Beleuchtung mit dem ATtiny 45

image

Zuerst habe ich darüber nachgedacht, was ich alles an Beleuchtung am Quadrocopter anschließen möchte und kam zu dem Entschluss Positionslichter anzubringen. Das macht dann besonders Sinn, wenn der Quadrocopter bereits 40 Meter entfernt ist. Für diesen Zweck eignen sich ultrahelle LEDs ab einer Lichtstärke von über 5000mcd. Für das Bunte sah ich die WS2812B auf Streifen für die Unterbodenbeleuchtung. Diese RGB LEDs sind nicht nur leuchtstark, sondern können über eine Leitung angesteuert werden.

image

Normalweise würde ich einen ATMega328 oder 168 verwenden, doch die bessere Wahl ist ein ATtiny. Der ATTiny45/85 z.B. hat insgesamt acht Pins. Zwei für die Stromversorgung, einen für Reset und der Rest kann frei programmiert werden.

image

Für das Vorhaben werden folgende Teile benötigt:

  • 1x ATTiny45
  • 2x Ultrahelle LEDs Grün (3mm, 6000mcd)
  • 2x Ultrahelle LEDs Rot (3mm, 5000mcd)
  • RGB LEDs WS2812B
  • 2x PNP Transistoren (es gehen auch 2x NPN, muss nur im Code umgedreht werden)
  • 2x 22µF Kondensatoren (63V, darf auch niedriger sein)
  • 1x 5V Spannungsregler (UTC LP2950G 5.0 QC4, 160mA)
  • 2x 75 Ohm Widerstand (100Ohm kamen in meiner Schaltung)
  • 2x 2,2kOhm Wiederstände
  • 1x Rasterplatine
  • ausreichend Schrumpfschläuche
  • und natürlich dürfen die Kabel nicht fehlen

[Bild von den Teilen]

Bevor das Ganze zusammengelötet wird, empfiehlt sich ein Test der Schaltung auf dem Breadboard. In meinem Fall war dies auch notwendig, da die Anzahl der angeschlossen LEDs mehr Strom benötigt hat. Der vorgegebene Spannungsregler kann bis zu 160mA durchlassen und reicht für die grünen und roten LEDs auch aus. Kommen nun die RGB LEDs hinzu, dann wird es knapp. Selbst wenn jetzt die vier LEDs ca. 120mA verbrauchen, bleiben nur 40mA übrig. Das reicht gerade mal für zwei weitere LEDs, in einer RGB LED sind aber drei. Abgesehen davon, dass der ATtiny für die Ansteuerung der WS2812B verwendet wird, kann dieser auch die Ansteuerung der Helligkeit regulieren und somit den Stromverbrauch reduzieren. Hierbei werden die einzelnen LEDs mit einem PWM Signal angesteuert. Kommen wir zur Grundschaltung.

image
Schaltbild vom Versuchs- und Testaufbau.

Kommen wir nun zu dem ATtiny. Um diesen zu beschreiben verwende ich einfach einen Arduino und einen eigenen, selbst gelöteten Shield. Alternativ kann dies auch auf einem Breadboard zusammengesteckt werden.

image

Ich empfehle, die Arduino Entwicklungsumgebung zu verwenden; dies erspart weitere Kosten für ein neues Board. Das setzt natürlich voraus, dass man bereits einen Arduino besitzt.

Nachteil ist, dass für die Verwendung eine weitere Komponente installiert werden muss.

Die Seite high-low tech erklärt, wie der Arduino als ISP Programmer für den ATtiny verwendet werden kann. Daher fasse ich kurz zusammen, was für die Installation wichtig ist.

Nun fehlt noch eine Sache. Für die Verwendung der WS2812B RGB LEDs wäre eine wenig mehr Code notwendig. Ich greife deshalb auf eine fertige Library zurück. Diese wird von Adafruit bereit gestellt auf GitHub.com/adafruit/Adafruit_NeoPixel. Die fertige Bibliothek kommt diesmal in den Ordner ../Arduino/libraries/Adafruit_Neopixel.

Jetzt kann der eigentliche Spaß losgehen. Der folgende Beispiel Code ist extra kurz gehalten und geht mehr auf die verwendete Inhalte ein.

// NeoPixel Bibliothek hinzufügen für die Ansteuerung der WS2812B LED Streifen
#include <Adafruit_NeoPixel.h>

// Instanz initialisieren
// Parameter Angaben:
// 1. Anzahl für verwendeter RGB LEDs
// 2. Auf welchen Pin soll verwendet werden.
// 3. Auswahl zwischen RGB, GRB oder BRG und verwendeter Takt 400KHz oder 800KHz

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(4, 2, NEO_GRB + NEO_KHZ800);

// Helligkeit einstellen. Kann von 0 bis Maximal 255 festgelegt werden.
// Bei Maximaler Ausleuchtung ist zu prüfen, ob die Maximale Stromabnahme erreicht wird.

int brightness = 100;

// Helligkeit bei verwendung der WS2812b, wenn sie weis auf blitzen sollen.
// Bei 210 wird die Maximale Stromabnahme überschritten.
// Darf nur kurz verwendet werden, ansonsten brennt der Spannungsregler durch.

int brightnessWhite = 210;

// Wird zum festlegen des Licht Einstellung verwendet.
// Damit die Einstellung funktioniert,
// muss an der Fernsteuerung einmal hin und her Geschaltet oder gedreht werden,
// um die längste Pulslänge zu ermitteln.

unsigned long maxPwmIn = 2;

void setup() {
  // Signal von der Fernsteuerung aufnehmen.
  pinMode(3, INPUT);
  // Positionslichter schalten
  pinMode(0, OUTPUT);
 
  // RGB LEDs Stribes starten
  pixels.begin();
  pixels.show();
}

void loop() {
 
  // Signal von der Fernsteuerung einlesen.
  // Für die Verwendung sollte ein Schalter genutzt werden.

  unsigned long pwmIn =  pulseIn(3, HIGH);
  // Wird zum Anlernen verwendet. Durch festlegen der maximalen Pulslänge
  // können zwei Zustände verwendet werden.

  if(pwmIn > maxPwmIn) { maxPwmIn = pwmIn; }
 
  // Wenn das Signal kürzer ist als der Maximalen Pulslänge.
  if(pwmIn < maxPwmIn - 100){
    // Positionslichter einschalten
    // (Bei verwendung von NPN Transisitor, kann die '255 -' weg)

    analogWrite(0, 255 - brightness); delay(100);
   // Ausschalten (Bei NPN, den Wert auf 0 setzen.)
   analogWrite(0, 255); delay(100);
   
    // RGB LED Streifen ansteuern.
    // Rot und Grün

    allRGB_LED_Off();
    pixels.setPixelColor(0, pixels.Color(brightness, 0, 0));
    pixels.setPixelColor(1, pixels.Color(0, brightness, 0));
    pixels.show();
    delay(100);
    allRGB_LED_Off();
    pixels.setPixelColor(2, pixels.Color(brightness, 0, 0));
    pixels.setPixelColor(3, pixels.Color(0, brightness, 0));
    pixels.show();
   delay(100);
  }
  else
  {
    // Positionslichter ausschalten
    // (Bei verwendung von NPN Transisitor, ist zum Ausschalten der Wert 0)

    analogWrite(0, 255);
   
   // RGB LED Streifen ansteuern.
    for(int i = 0; i < 4; i++)
    {
      // Alle aus.
      allRGB_LED_Off();
     
     // Mit der Aktuellen Iteration als Index verwenden,
      // um den entsprechende RGB LED zu überschreiben.

      pixels.setPixelColor(i, pixels.Color(brightnessWhite, brightnessWhite, brightnessWhite));
      pixels.show();
      delay(100);
    }
  }
}

// Stellt alle Werte zurück.
void allRGB_LED_Off()
{
  for(int i = 0; i < 4; i++)
  {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0));
  }
}

Im folgendem Video wird gezeigt, wie dieses Code Beispiel aussieht. Daneben ist noch ein Netduino der ein PWM Signal abgibt und alle drei Sekunden wechselt zwischen 900 und 1100 Mikrosekunden Pulslänge, um das Umschalten zu simulieren.

Bei dem ATtiny45 wird man schnell feststellen, dass der Speicher sehr knapp ist. Wer mehr Lichtanimationen einsetzen möchte, sollte auf einen ATtiny85 wechseln. Und wer mehr Licht einsetzen und nicht unbedingt an Strom sparen will, wird einen größeren Spannungsregler benötigen.

 Referenzen

Freitag, 16. Januar 2015

Arduino Control (Teil 4) – Potentiometer Wert am PC ausgeben

image

Der Arduino kann auch analoge Signale einlesen. Dieser Wert kann zwischen 0 und 1023 liegen. Für dieses Beispiel wird ein Potentiometer verwendet, der möglichst hochohmig sein sollte. In meinem Fall habe ich einen 470 Ohm Stellwiederstand verwendet. Empfohlen ist 1k Ohm.

image

Der Quellcode ähnelt dem Beispiel für den Button. Nur müssen hier für den Empfang zwei Bytes zu einem Wert zusammengesetzt werden. Das Stichwort ist hier Byte Shifting. Das erste Byte wird um acht Bits nach links verschoben, um die Bits von 9 bis 16 abzubilden. Das zweite Byte bleibt für die ersten acht Bits.

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}", (int)buffer[0] << 8 | buffer[1]);
    }
}

Der Input verwendet diesmal analogRead(), statt des digitalRead(). Unterscheidet sich der Wert zu dem zuletzt versendeten, dann soll der neue gemessene Wert gesendet werden. Der Wert kann bis zu 1023 betragen und passt nicht in ein Byte. Daher wird dieser in zwei Bytes aufgeteilt und anschließend versendet. Am Ende wird eine Verzögerung von 100 Millisekunden festgelegt, um zwischen den Sendungen eine Lücke zu erzeugen. Ansonsten kann nicht erkannt werden, welches das erste und das zweite Byte ist.

// Pin Nummer A0 vom Arduino
int pinPegel = A0;

// Enthält den letzten Button Zustand.
int lastValue = 0;

void setup()
{
  // Baudrate wie bei dem C# Programm
  Serial.begin(115200);
  pinMode(pinPegel, INPUT);
}

void loop()
{
  // Status am Pin abfragen
  int readValue = analogRead(pinPegel);
 
  // Nur Inhalt im If ausführen,
  // wenn der Status sich geändert hat.
  if(readValue != lastValue)
  {
   // Member Field überschreiben.
    lastValue = readValue;
  
   // Buffer vorbereiten und
   // den Wert in zwei bytes aufteilen.
    byte ba[2];
    ba[0] = (byte)((readValue >> 8) & 0xff);
    ba[1] = (byte)(readValue & 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);
  }
}

Damit ist auch schon alles getan.

 

Quellcode zum Download

Sonntag, 17. August 2014

Feuchtigkeitssensor HTU21D mit dem Netduino (Teil 1)

image

Zuvor habe ich für meinem Weather Shield einen Feuchtigkeitssensor DHT11 verwendet. Wer diesen kennt, weiss sicherlich wie ungenau die Messwerte sind. Ich möchte den Sensor nicht schlecht reden, denn immerhin ist er sehr günstig. Möchte man allerdings für eine Anwendung mehr Genauigkeit und eine schnelle Abtastung der aktuellen Feuchtigkeit und Temperatur, bieten andere Sensoren deutlich bessere Ergebnisse.

Ein paar interessante Daten zum Sensor:

  • Schnittstelle I²C
  • Betriebsspannung: 3,3V (max. 3,6V)
  • Stromaufnahme: ca. 10mA
  • Temperaturmessung ca. 50ms bei 14Bit (7ms bei 11Bit) (-40°C bis 125°C)
  • Feuchtigkeitmessung ca. 16ms bei 12bit (3ms bei 8Bit)
  • Kostet ab 6,50€ bei Ebay über einem chinesischen Händler

Weitere Daten findet ihr im Datenblatt.

Ansprechen lässt sich der Sensor über den I²C Bus und kann mit dem .NET Micro Framework mit geringen Aufwand programmiert werden. Das Einstiegsverhalten lässt sich mit dem Luftdruck Sensors BMP085 vergleichen, über den ich bereits geschrieben habe.

Erstellen wir eine neue Klasse mit dem Namen des Sensors, um zunächst die Verbindung herzustellen und die Rohdaten zu erhalten.

public class HTU21D : I2CDevice
{
    // Konstruktor mit vererbten Konstruktor aus der I2CDevice Klasse
    // 0x40 = Adresse des Sensors
    //  100 = Takt in kHz

    public HTU21D()
        : base(new Configuration(0x40, 100))
    {
    }

    // Luftfeuchtigkeit Messen und Rohwert zurückgeben
    public int Read()
    {
        // Befehl senden.
        if (this.Write(new byte[] { 0xf5 }) == 0)
        {
            throw new SystemException("Fehler beim Senden!");
        }

        // Warten bis der Sensor mit dem Lesevorgang fertig ist.
        Thread.Sleep(50);

        byte[] data = new byte[3];

       // Messergebnis abrufen
        if (this.Read(data) == data.Length)
        {
           // Es werden für dieses Beispiel zwei Bytes verwendet
            int raw = (data[0] << 8) | data[1];
            raw &= 0xFFFC;
            return raw;
        }

        Debug.Print("Sensor konnte nicht gelesen werden!");
        return 0;
    }

    // Sendet den Inhalt des Byte Arrays
    private int Write(byte[] buffer)
    {
        I2CTransaction[] trans = new I2CTransaction[]
        {
            CreateWriteTransaction(buffer)
        };

        return Execute(trans, 1000);
    }

    // Liest den zu empfangene Byte Array
    private int Read(byte[] buffer)
    {
       I2CTransaction[] trans = new I2CTransaction[]
        {
            CreateReadTransaction(buffer)
        };

        return Execute(trans, 1000);
    }
}

Die Rohdaten können nun über die Program.cs Klasse aufgerufen und über die Ausgabe in Visual Studio ausgegeben werden.

public class Program
{
    public static void Main()
    {
        HTU21D sensor = new HTU21D();

        while (true)
        {
            Debug.Print("Humidity RAW Value: " + sensor.Read().ToString());
            Thread.Sleep(1000);
        }
    }

}

Im nächsten Schritt wird das Modul mit dem Feuchtigkeitsensor mit dem Netduino verbunden. Je nach Ausführung des Sensor, werden eventuell zwei Widerstände mit 2,2kOhm benötigt. In der Variante die ich erhalten habe, sind diese aufgelötet, aber mit der 3,3V Zuleitung nicht verbunden. Das Modul habe ich zunächst so belassen und habe für den Testlauf zwei Pull Up Widerstände hinzu gesteckt.

HTU21D_Pullups_bearbeitet-1

Ansonsten hält sich die Schaltung mit den Netduino und dem Feuchtigkeitssensor sehr Übersichtlich.

image

Wie bereits aus den Technischen Grunddaten hervorgeht, gibt es auch einen Temperatursensor zum Messen. Dafür muss nur in der Methode “Read()”, das zu sendende Byte von 0xf5 auf 0xf3 umgeschrieben werden. Damit erhält man den Rohwert der gemessenen Temperatur.

Dienstag, 27. Mai 2014

TCS3200 Farbsensor einlesen (Netduino)

TCS3200_01

Das Licht leuchtet hier in verschiedenen Farben. Mit Hilfe des TCS3200 Sensor, können die verschiedenen Farben gemessen werden. Anders als bei einem lichtempfindlichen Sensor, an dem sich der Leitwert verändert, liegt ein Pulssignal an. Für die Schaltung werden insgesamt fünf Digitale Ports und zwei Pins für die Spannungsversorgung benötigt.

image

Wenn mal kein Breadboard zur verfügung steht, geht das auch so wie im folgendem Bild. Die Pins von S0 bis S3 und OUT auf die digitalen Ausgängen von Pin 2 bis Pin 6 steckt.

TCS3200_Netduino_03

Wie die Schaltung bereits verrät, ist das einlesen deutlich anders. Anstatt über OneWire , I²C oder eines Spannungspegel, kommt ein PWM (oder auch PPM) Signal. Je nach Farbe müssen die Anschlüsse von S0 bis S3 entsprechend geschaltet sein. Das bedeutet wiederum, dass die Farben nacheinander gemessen werden. Im .NET Micro Framework gibt es zum Einlesen die Klasse "InteruptPort", mit der auf das PWM Signal reagiert werden kann. Das erfordert etwas zusätzlichen Programmcode.

// Optionen für Ausgangsfrequenz
public enum
OutputFrequencyScaling
{
    PowerDown,
    TwoPercent,
    TwentyPercent,
    HundredPercent
}

// Filter Auswahl
public enum SelectColor
{
    Red,
    Blue,
    Green,
    Clear
}

public class Program
{
    // Die Klasse wird für das Einlesen des PWM Signals verwendet.
   private static InterruptPort _IntPort = new InterruptPort(
        Pins.GPIO_PIN_D6,
        true,
        Port.ResistorMode.Disabled,
        Port.InterruptMode.InterruptEdgeBoth);

    // Ruft die gemessene Zeit ab,
    // wann die HIGH Pegele begonnen hat oder legt diese fest.
    private static long _HighTicks = 0;

    // S0 und S1 Schaltet die Ausgangs frequenz entsprechend ein (Siehe dazu Datasheet)
    private static OutputPort _S0 = new OutputPort(Pins.GPIO_PIN_D2, false);
   private static OutputPort _S1 = new OutputPort(Pins.GPIO_PIN_D3, false);

   // S2 und S3 Schaltet die verschiedenen Filter Möglichkeiten ein
    private static OutputPort _S2 = new OutputPort(Pins.GPIO_PIN_D4, false);
    private static OutputPort _S3 = new OutputPort(Pins.GPIO_PIN_D5, false);

    // Die Onboard LED als Status Aktivität
    private static OutputPort _StatusLED = new OutputPort(Pins.ONBOARD_LED, false);

    private static string _readColorName = string.Empty;

    private static bool _valueIsSet = false;
    private static long _resultTemp = 0;
    private static int _resultRed = 0;
    private static int _resultBlue = 0;
    private static int _resultGreen = 0;
    private static int _resultClear = 0;

    public static void Main()
    {
        OutputFrequencyScaling scale = OutputFrequencyScaling.TwoPercent;

       while (true)
        {
          
// Status Lesen
            _StatusLED.Write(true);

            // Farben nach einander einlesen.
            ReadPwmSignal(ref _resultRed, SelectColor.Red, scale);
            ReadPwmSignal(ref _resultBlue, SelectColor.Blue, scale);
            ReadPwmSignal(ref _resultGreen, SelectColor.Green, scale);
            ReadPwmSignal(ref _resultClear, SelectColor.Clear, scale);

            // Ausgabe über die Messergebnisse.
            Debug.Print("Red:" + _resultRed.ToString() +
               "\t Blue:" + _resultBlue.ToString() +
               "\t Green:" + _resultGreen.ToString() +
               "\t Clear:" + _resultClear.ToString());

           // Status warten
            _StatusLED.Write(false);
           Thread.Sleep(500);
        }
           
    }

    // Methode mit Filter- und Ausgangsfrequenzschalten und gibt das Ergebnis über "result" zurück.
   private static void ReadPwmSignal(ref int result, SelectColor color, OutputFrequencyScaling scaling)
    {
       // Ausgangsfrequenz schalten
        switch (scaling)
        {
            case (OutputFrequencyScaling.TwoPercent): { _S0.Write(false); _S1.Write(true); break; }
            case (OutputFrequencyScaling.TwentyPercent): { _S0.Write(true); _S1.Write(false); break; }
           case (OutputFrequencyScaling.HundredPercent): { _S0.Write(true); _S1.Write(true); break; }
            default: { _S0.Write(false); _S1.Write(false); break; }
        }

        // Filter einstellen
        switch (color)
        {
            case (SelectColor.Red): { _S2.Write(false); _S3.Write(false); break; }
            case (SelectColor.Blue): { _S2.Write(false); _S3.Write(true); break; }
            case (SelectColor.Green): { _S2.Write(true); _S3.Write(true); break; }
            default: { _S2.Write(true); _S3.Write(false); break; }
        }

       // Member für das erfassen des Messergebnisses.
        _HighTicks = 0;
        _resultTemp = 0;
        _valueIsSet = false;

        // Event zuweisen
        _IntPort.OnInterrupt += _IntPort_OnInterrupt;

        // Warten
        for (int i = 0; i < 5; i++) { Thread.Sleep(2); }

        // Event wieder abziehen
        _IntPort.OnInterrupt -= _IntPort_OnInterrupt;
           
        // Ergebniss kopieren
        result = (int)_resultTemp;
    }

    // Wird ausgeführt, wenn sich der Pegel am Digitalen Port geändert hat.
    private static void _IntPort_OnInterrupt(uint data1, uint data2, DateTime time)
    {
        // Lock verhindert, das ein zweiter unmittelbarer Event nicht erfolgen kann.
        lock (_IntPort)
        {
           // Wenn noch kein Wert erfasst wurde.
            if (!_valueIsSet)
            {
               // Wenn HIGH Pegel anlieg und die Aktuelle
                // Zeit in Ticks noch nicht erfast wurde.
                if (data2 == 1 & _HighTicks == 0)
                {
                    // Aktuelle Zeit in Ticks zwischen speichern
                    _HighTicks = time.Ticks;
                }
                else if (_HighTicks != 0 & !_valueIsSet)
                {
                    // Wenn der Pegel von HIGH nach LOW gewechselt hat
                    _resultTemp = time.Ticks - _HighTicks;
                   // True zuweisen, dass der Messwert erfasst wurde
                    _valueIsSet = true;
                    // Event abziehen
                    _IntPort.OnInterrupt -= _IntPort_OnInterrupt;
                }
            }
        }
    }
}

Als Ausgangsergebnis werden vier Werte wiedergegeben. Wenn nun vor dem Sensor eine Farbige Fläche mit einer der Grundfarben gehalten wird, dann verändern sich die Werte dementsprechend. Stammt die Farbe von einem Bildschirm (wie im folgenden Bild von einem Smart Phone), dann kann der Blaue Jumper herausgezogen werden, um die LED Beleuchtung abzustellen.

TCS3200_Netduino_01

  Bei grob angemalten Flächen wie dieser Karteikarte funktioniert es weniger gut..

TCS3200_Netduino_02

Anhand der Farbe stellen sich die Werte neu ein. Je ein deutiger die Farbe ist, um so deutlicher zeigt sich das Ergebnis.

Also bei durch gehenhenden Blau, Grün oder Rot zeigt sich ein hoher Wert. Wenn die Farbfläche jedoch wie bei meinem Beispiel mit der Karteikarte durchgeführt wird, stehen an jeden Ausgang relativ hohe Werte.

image

Noch ein Hinweis. Die Pulslänge wird kürzer, wenn der Weg des reflecktierten Licht kürzer wird, oder salobt gesagt, wenn die Farbfläche zu nah am Sensor ist, dann ist das Pulssignal sehr kurz. Dies führt dann dazu, dass die letzte Methode sehr häufig ausgeführt wird. Im schlimmsten Fall kommt es zu einem Speicherüberlauf und das Programm bleibt stehen.

Beispiel Programm zum Herunterladen für Netduino mit .NET Micro Framework 4.2

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