Posts mit dem Label Remote Control werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Remote Control werden angezeigt. Alle Posts anzeigen

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

Mittwoch, 1. Mai 2013

PWM Signal Einlesen mit dem Netduino

PwmSignal_Netduino2
Der Empfänger am Netduino

Es gibt zwei Lösungen, wie man ein PWM Signal einlesen kann. Über eine RC Schaltung mit der “AnalogInput” Klasse oder vollständig programmatisch. Wenn keine Bauteile wie Widerstand und Kondensator vorhanden ist, dann erübrigt sich das letztere. Beim Arduino kennt man bereits aus der Library die Methode ‘pulseIn()’. Leider wurde das für den Netduino noch nicht umgesetzt. Alternativ bleibt die Möglichkeit, die sich ändernden Pulszustände zeitlich zu messen und das geht hervorragend mit der “InterruptPort” Klasse.

/// <summary>
/// Dieses Klasse ermöglicht das genaue Einlesen des eingehenden Pulssignals
/// </summary>
private static InterruptPort _IntPort = new InterruptPort(
    Pins.GPIO_PIN_D0,
    true,
    Port.ResistorMode.Disabled,
    Port.InterruptMode.InterruptEdgeBoth);

/// <summary>
/// Wird verwendet um den Startzeit des Pulssignals zu merken
/// </summary>
private static long _HighTicks = 0;
/// <summary>
/// Kann verwendet werden um einen Servo anzusteuern
/// </summary>
private static PWM _PwmOutput = new PWM(Cpu.PWMChannel.PWM_0, 20000, 1500, PWM.ScaleFactor.Microseconds, false);

public static void Main()
{
    // PWM Ausgang starten
    _PwmOutput.Start();
    // Event zuweisen
    _IntPort.OnInterrupt += new NativeEventHandler(_IntPort_OnInterrupt);

    while (true)
    {
        Thread.Sleep(1000);
    }
}
/// <summary>
/// Wird ausgeführt, wenn sich der Zustand am Eingang geändert hat.
/// </summary>
private static void _IntPort_OnInterrupt(uint data1, uint data2, DateTime time)
{
   if (data2 == 1)
    {
        // Startzeit des Pulssignals merken
        _HighTicks = time.Ticks;
    }
    else
    {
        // Mit Ende des High Zustands wird die aktuelle
        // Zeit mit der begin Zeit abgerechnet und erhält hier
        // die Pulslänge des High Signals

        double result = time.Ticks - _HighTicks;

        // Werte werden zwischen 10.000 bis 20.000 ausgegeben
        Debug.Print(result.ToString());

       if (result < 20000)
        {
            // Das Pulssignal darf nur zwischen 1000 bis 2000 sein
            _PwmOutput.Duration = (uint)(result / 10);
        }
    }
}

Zum einlesen eines PWM Signals

Über die PWM Klasse gebe ich das eingelesene Signal wieder aus, um z.B. einen Servo oder Regler anzusteuern. Sinn ergibt dies jedoch, wenn der Wert noch verarbeitet wird, bevor es weiter gegeben wird.

Solution zum Downloaden: ExampleReadPwm

Sonntag, 3. Februar 2013

UART WiFi Server Client Module kann auch senden

Netduino_WiFi_01
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)
{
      byte[] message = Encoding.UTF8.GetBytes("DateTime: " + DateTime.Now.ToString());
      _SerialPort.Write(message, 0, message.Length);
      Thread.Sleep(1000);
}

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.

image
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)
{
     byte[] buffer = new byte[1024];

     while (_Socket != null && buffer.Length > _Socket.Receive(buffer, SocketFlags.None))
     {
          string message = Encoding.UTF8.GetString(buffer).Replace('\0', ' ').Trim();
          ReceiveEvent(message);
          buffer = new byte[1024];
     }
}

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);
public event NetworkReceiveEventHandler NetworkReceiveEvent;
public virtual void ReceiveEvent(string message)
{
    if (NetworkReceiveEvent != null & !string.IsNullOrEmpty(message))
    {
         NetworkReceiveEvent(this, new NetworkStatusEventArgs(message.Trim()));
    }
}

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()
{
    InitializeComponent();

    _Client.NetworkReceiveEvent += new ClientController.NetworkReceiveEventHandler(_Client_NetworkReceiveEvent);
}

private void _Client_NetworkReceiveEvent(object sender, NetworkStatusEventArgs e)
{
    Dispatcher.BeginInvoke(new WriteReceiveHandler(WriteReceive), new object[] { e.Message });
}

private delegate void WriteReceiveHandler(string message);

private void WriteReceive(string message)
{
    textBlockDataReceive.Text = 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. Zwinkerndes Smiley

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:

Sonntag, 27. Januar 2013

UART WiFi Server Client Module am Netduino

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

image
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;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using System.Text;
using System.IO.Ports;
using Microsoft.SPOT;

namespace SerialPortExample
{
    public class Program
    {
        private static SerialPort _SerialPort;

        public static void Main()
        {
            Thread.Sleep(6000);

            _SerialPort = new SerialPort(SerialPorts.COM2, 115200);
            _SerialPort.DataReceived +=
new SerialDataReceivedEventHandler(_SerialPort_DataReceived);
            _SerialPort.Open();

           while (true)
           {
               Thread.Sleep(1000);
           }

        }

        private static void _SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;

            byte[] buffer = new byte[sp.BytesToRead];

            if (sp.Read(buffer, 0, buffer.Length) > 1)
            {
                char[] ca = Encoding.UTF8.GetChars(buffer);

                string reading = string.Empty;
               foreach (char item in ca)
                {
                    reading += item.ToString();
                }

                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.

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

image
“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;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace NetworkClient
{
    public class ClientController
    {
        private Socket _Socket = null;

        private int _Timeout = 5000;
        private Thread _Thread;
        private ManualResetEvent _ClientDone = new ManualResetEvent(false);
        private string _OperationResult = string.Empty;

        public string Connect(string hostAddress, int port)
        {
            _Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            _Socket.ConnectAsync(
                CreateOperationEvent(
                new DnsEndPoint(hostAddress, port)));

            _ClientDone.WaitOne(_Timeout);

           return _OperationResult;
        }

        public void Send(byte[] data)
        {
           if (_Thread == null || !_Thread.IsAlive)
            {
                _Thread = new Thread(new ParameterizedThreadStart(Send_InThread));
                _Thread.Start(data);
            }
        }

        private void Send_InThread(object obj)
        {
            SocketAsyncEventArgs socketEvent = CreateOperationEvent(_Socket.RemoteEndPoint);
            socketEvent.SetBuffer((byte[])obj, 0, ((byte[])obj).Length);
            _Socket.SendToAsync(socketEvent);
            _ClientDone.WaitOne(_Timeout);
            StatusEvent(_OperationResult);
        }

        private SocketAsyncEventArgs CreateOperationEvent(EndPoint remoteEndPoint)
        {
            _OperationResult = "Operation Timeout";
           SocketAsyncEventArgs socketEvent = new SocketAsyncEventArgs();
            socketEvent.RemoteEndPoint = remoteEndPoint;

            socketEvent.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
            {
                _OperationResult = e.SocketError.ToString();
                _ClientDone.Set();
            });

            _ClientDone.Reset();

            return socketEvent;
        }

        public void Close()
        {
            if (_Socket != null)
            {
                if (_Socket.Connected)
                {
                    _Socket.Disconnect(true);
                    _Socket.Close();
                }
            }
        }

        public bool IsSending
        {
            get
            {
                if (_Thread != null && _Thread.ThreadState == ThreadState.Running)
                {
                    return true;
                }

                return false;
            }
        }

        public bool IsConnected
        {
            get {
           try{ return _Socket.Connected; }
            catch{ return false; }
                  }
        }

        public delegate void NetwokrStatusHandler(object sender, NetworkStatusEventArgs e);

        public event NetwokrStatusHandler NetworkStatus;

        public virtual void StatusEvent(string message)
        {
            if (NetworkStatus != null)
            {
                NetworkStatus(this, new NetworkStatusEventArgs(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.

image
Beispiel Anwendung das über Socket Klasse den Text übermittelt.
image
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:

Gehäuseentwurf für Signalleuchten (ESP32)

RGB LEDs und LIPO Akkus sind bestellt. Weil ich bereits die Abmessungen habe, kann ich schon mal mit dem Gehäuseentwurf in Blender anfangen....