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

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:

Sonntag, 6. Mai 2012

UART WiFi Server Client Module (TLG10UA03)

image
Kabel, USB UART, Antenne und das WiFI Modul(TLG10UA03)

Letzte Woche habe ich das Modul UART WiFi Server Client Module aus China erhalten. Es war zwar relativ günstig, dafür muss man allerdings ca. 3 – 4  Wochen warten. Der Versand ist kostenfrei.

In Ebay bin ich nach zahlreichen Suchen von Modulen auf diese WLAN Lösung gestoßen, und dachte mir, das ist genau das Richtige: Dinge über Funk zu steuern. Die Beschreibung des Artikels zeigte die technischen Daten und einige Inhalte aus der Konfiguration Oberfläche. Aufgeregt nahm ich das Paket mit den chinesischen Schriftzeichen auseinander. Eine Anleitung hat man sich aus Gewichtsgründen gespart (denke ich). Gut verpackt mit Luftpolstern und antistatischen Tüten entnahm ich schließlich das Modul.

Wie jeder, so wollte auch ich zunächst die Funktionalität prüfen. Also erst mal zurück auf die Webseite und nach der Anleitung sehen. Dies war nötig, um festzustellen, wo die Kabel eigentlich verbunden werden. An dem USB UART sind die Pins alle gekennzeichnet. Auf das WiFi Modul traf dies leider nicht zu, wobei der Platz für einen Aufdruck recht gering ist.

Alles verbunden, lud ich das Programm UART WiFi herunter. Ich dürfte wohl nicht der Einzige sein, der behauptet, dass dieses Programm einige Verbesserungen vertragen könnte. Dennoch sollte das für die Konfiguration keinen Abbruch tun. Als ich soweit war, versuchte ich die Verbindung herzustellen, aber ohne Erfolg.

image image
Unter Windows XP Unter Windows 7

Ich prüfte die Steckverbindung, nahm ein anderes USB UART Modul, stellte Diagnosen mit einem Serial Monitor an. Kein Hinweis, nur dass keine Antwort kam. Der Tipp mit dem Arduino Tool und dem Serial Monitor, um “+++” zu senden funktionierte auch nicht.

Enttäuscht schrieb ich dem Support des Händlers. Hier ein Lob, sehr schnelle Antwortzeiten selbst an einem Sonntag und hilfsbereit. Leider haben die Tipps nicht geholfen. Ich wollte das Modul schon zurück senden, um es austauschen zu lassen, doch ich konnte nicht glauben, dass das Modul nicht in Ordnung sein sollte. Nach dem “try and error” - Prinzip versuchte ich jede serielle Einstellung und hatte damit auch Erfolg. Ich erhielt mit einmal eine Antwort vom Modul, als ich die richtige Bautrate fand. Nach der Anleitung wird die Baudrate 115200 vorgeschlagen. Anscheinend wurde nach dem Test des Moduls die letzte eingestellte Bautrate nicht auf den Standard Wert gesetzt. In meinem Fall war es 9600 Baut.

image
Wenn die richtig Einstellung gesetzt ist, dürfte nach dem klicken des “Exit”-Buttons dieses Popup erscheinen.

Die Verbindung konnte nun mit dem UART WiFi Tool hergestellt werden und die Optionen wurden frei gegeben. Jetzt konnte es los gehen. Da ich zu diesem Zeitpunkt unterwegs war, hatte ich keinen kompatiblen WLAN Access Point da, um auf die Weboberfläche des Moduls zu zugreifen. Selbst die Internetfreigabe auf dem Smart Phone bietet leider nicht die gewünschte Unterstützung an.

image
Die Meldung erscheint nach dem klicken des Search-Buttons, wenn die Verbindung zum Modul hergestellt wurde.

Endlich zuhause, konnte ich die Konfiguration fortsetzen. Da zeigte sich mir, welche Verschlüsselungsarten wirklich funktionierten. Zwar hat das Modul WPA2, allerdings nur mit TKIP und nicht AES. Dafür hat mein WLAN WPA(1) mit TKIP. Ein kleiner Rückschritt, der allerdings zu verschmerzen ist. Wer sich mit der WLAN Verschlüsselung auskennt, weiss, wie wahrscheinlich jemand die WLAN Verbindung entschlüsseln könnte. Ich gab alle erforderlichen Daten ein und speicherte dies auf dem Modul. Anschließend nochmal in das UART WiFi Tool, um die Verbindung zum WLAN herzustellen. Dies geschieht auf dem zweiten Karteireiter, in dem man auf den Button für “Connect” klickt. Dies klappe allerdings nicht auf Anhieb, und es war im nachhinein nicht wirklich nachvollziehbar, warum man auf dem einen USB Port gerade keine Verbindung bekam, auf dem anderen widerum schon.

image
Verbindung zum WLAN herstellen

Der nächste Schritt bestand darin, auf die Weboberfläche zu zugreifen und den Rest einzustellen. Um dort hin zu gelangen, müssen die Verbindungen für TX und RX getrennt werden. Von meinem Router erfuhr ich die IP Adresse, die dem Modul zugewiesen wurde. Geht auch mit dem Befehl “AT+LKSTT” im UART WiFi Tool.

image
Webseite des Moduls.

Als dies auch so weit war, war nun mein Arduino an der Reihe; schnell “Copy and Paste” ich den Beispielcode vom Artikel und stellte die Kabelverbindungen her. Hierbei muss der Arduino vom USB getrennt werden, damit keine serielle Verbindung zum PC besteht.

image image image
WiFi Modul USB UART Modul Arduino Nano
Rot – 3,3V (Pin 5)
Braun – TX (Pin 6)
Weiß – RX (Pin 7)
Schwarz – GND (Pin 8)
Rot – VDD
Schwarz – GND
Braun – TX (Pin TX1)
Weiß – RX (Pin RX0)

Zusammengesteckt, nochmal auf Reset, um den Code auf dem Arduino neu zu starten und im Browser staunen. Mit dem Staunen musste ich mich allerdings noch zurück halten, da mein Browser nur das Ladesymbol am Tab zeigte. Es blieb bei einer weissen Seite, oder wie jemand anderer dies beschrieb: “Ein Überbelichtetes Foto in einem Schneesturm.”

Irgendwas haute nicht hin, und es hätte jetzt eigentlich funktionieren müssen. Ich ging nochmal alles durch. WLAN Verbindung Check, Kabelverbindung Check, auszuführenden Quellcode, den ich auf den Arduino übertrug, che… , erst jetzt sah ich, dass der Code nicht funktionieren konnte. Wahrscheinlich hat der Händler nicht gewusst, wie man im HTML bestimmte Zeichen eingibt. In der “If” Bedingungen war das “Char” für Zeilenumbruch ‘n’ geschrieben, was allerdings so ‘\n’ geschrieben wird. Naja, und ich ging weiter im Code und reduzierte den für den Test auf 2 Zeilen in der Schleife bzw. die “void loop()” Methode, mit Serial.println(“Hello World!!!”) und delay(1000).

image image
Vorher Nachher
Einige Zeichen fehlen im Code, was durch das Copy n paste entstand. Für einen Test absolut ausreichend.

Erneut den Arduino beschrieben und anschließend wieder die Kabelverbindungen hergestellt. Dann Browser aufgerufen und die Adresse des Moduls eingeben, und siehe da, es steht “Hello World!!!”.

image
Durch den loop wieder holt sich der Text Hello World immer hinzufügend.


Kurzfassung zur Konfiguration:
  1. UART Modul den Jumper für 3,3 Volt setzen.
  2. Kabel Verbindung herstellen von UART auf das WiFi Modul. (*1)
  3. USB Verbindung zum PC herstellen
  4. Prüfen welche COM Verbindung (*2)
  5. Das Tool UART-WiFi starten und COM Verbindung auswählen.
  6. COM Set Einstellungen prüfen (*3)
  7. Suchen Button klicken und auf das Popup warten.
  8. WLAN Einstellungen vor nehmen. (*4)
  9. Modify Button Klicken. Ein Popup erscheint mit dem Hinweis dass das Modul neu gestartet wird.
  10. Verbindung zum Modul wieder herstellen. (Punkt 4 und 5)
  11. Zweiten Tab Reiter und Connect Button klicken. Warten bis die Verbindung hergestellt wurde.
  12. IP Adresse auslesen, durch den Befehl “AT+LKSTT”
  13. RX und TX Kabel Verbindung trennen.
  14. IP Adresse in die Adresszeile des Browsers eingeben und warten bis die Anmeldung erscheint. (Benutzername: Admin; Passwort: 000000)
  15. Aktuelle IP Adresse oder andere IP Adresse festlegen und speichern.
  16. Auto Workmode Einschalten und Save Button klicken. (ProtocolType:TCP, C/S Mode: Server, Port:8090)
  17. Arduino mit dem Test Code beschreiben. (*5)
  18. Arduino von der USB Verbindung trennen und an eine externe Stromversorgung anschließen.
  19. Kabel Verbindungen zwischen Arduino und dem WLAN Modul herstellen.

(*1) Kabel Verbindung image
(*2) Kann über den Geräte Manager ermittelt werden image
(*3)
11520 BAUT
Data 8
Parity None
Stop 1
Es kann sein, das diese ab Werk auch eine andere Einstellung hat, wie zum Beispiel war bei mir die Baut Rate von 9600 erforderlich, zudem war auch der Transparenz Modus akiv, so das ich über die Serielle Verbindung “+++” senden musste um dies zu beenden
(*4)
SSID
Verschlüsselungsalgorithmus
Schlüssel
IP Adresse Automatisch beziehen (kann später geändert werden)
(Erweitere Einstellungen “Advance” kann in der Regel belassen werden, ggf. siehe weitere Beschreibung dazu)
(*5) void setup()
{
   Serial.begin(115200);
}

void loop()
{
    Serial.print("<h1>Hello World!!</h1>");
    delay(1000);
}

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