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:

Kommentare

Beliebte Posts aus diesem Blog

Arduino Control (Teil 5) - PWM Signal einlesen

Angular auf dem Raspberry Pi

RC Fahrtenregler für Lego Kettenfahrzeug