Dustin Horne

Developing for fun...

Getting Started With My Netduino Plus

I love to get involved with a variety of technologies.  Recently I became interested in the .NET Micro Framework.  My knowledge of electronics is very basic at most but I'm interested in what types of home automation I can potentially accomplish with a micro controller.  Having a .NET background, I figured the .NET Micro Framework was a great place to start, so I picked up a Netduino Plus and dove in.  I found the basic "Turn on the built in LED" projects to be too simple for my taste so I'm going to show you my first project.

Morse Code via LED

For my project, I decided I wanted to take some text and convert it to equivalent morse code and blink that code out on the LED.  I used the Morse Code Wikipedia Entry as a guide to do the conversion.  Given that a "dot" (or "dit") is a specific length, I used the chart to determine that the length between dots and dashes was the length of a dot.  The "silence" between letters was equal to three dots, a dash was equal to 3 dots, and the gap between words was equal to the length of 7 dots.  Each letter can be represented then by a series of "ons" and "offs" each representing one dot.  I also automatically add three "offs" to the end of each letter.  If that letter represents the end of the word I add 4 more "off" characters. 

Given what we know above, I created a quick utility struct that would return a byte array containing 1's and 0's which represent the dots, dashes and silences.  The struct is immutable and constructed via a static FromChar method that accepts a character and converts it to a byte array.  This is a simple implementation to avoid storing the morse for an entire message in the microcontroller's limited memory at once, though beware that it could be subject to garbage collection hiccups, but it works great for small to medium sized messages.

The struct to do the morse code conversion is as follows:

namespace MFTestApp1
{
    public struct MorseChar
    {
        public readonly byte[] Code;
    
        private MorseChar(char c)
        {
           switch (c)
            {
               case 'A':
               case 'a':
                   Code = new byte[] { 1,0,1,1,1,0,0,0 };
                   break;
               case 'B':
               case 'b':
                   Code = new byte[] { 1,1,1,0,1,0,1,0,1,0,0,0 };
                   break;
               case 'C':
               case 'c':
                   Code = new byte[] { 1,1,1,0,1,0,1,1,1,0,1,0,0,0 };
                   break;
               case 'D':
               case 'd':
                   Code = new byte[] { 1,1,1,0,1,0,1,0,0,0 };
                   break;
               case 'E':
               case 'e':
                   Code = new byte[] { 1,0,0,0 };
                   break;
               case 'F':
               case 'f':
                   Code = new byte[] { 1,0,1,0,1,1,1,0,1,0,0,0 };
                   break;
               case 'G':
               case 'g':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,0,0,0 };
                   break;
               case 'H':
               case 'h':
                   Code = new byte[] { 1,0,1,0,1,0,1,0,0,0 };
                   break;
               case 'I':
               case 'i':
                   Code = new byte[] { 1,0,1,0,0,0 };
                   break;
               case 'J':
               case 'j':
                   Code = new byte[] { 1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case 'K':
               case 'k':
                   Code = new byte[] { 1,1,1,0,1,0,1,1,1,0,0,0 };
                   break;
               case 'L':
               case 'l':
                   Code = new byte[] { 1,0,1,1,1,0,1,0,1,0,0,0 };
                   break;
               case 'M':
               case 'm':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,0,0 };
                   break;
               case 'N':
               case 'n':
                   Code = new byte[] { 1,1,1,0,1,0,0,0 };
                   break;
               case 'O':
               case 'o':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case 'P':
               case 'p':
                   Code = new byte[] { 1,0,1,1,1,0,1,1,1,0,1,0,0,0 };
                   break;
               case 'Q':
               case 'q':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,0,1,1,1,0,0,0 };
                   break;
               case 'R':
               case 'r':
                   Code = new byte[] { 1,0,1,1,1,0,1,0,0,0 };
                   break;
               case 'S':
               case 's':
                   Code = new byte[] { 1,0,1,0,1,0,0,0 };
                   break;
               case 'T':
               case 't':
                   Code = new byte[] { 1,1,1,0,0,0 };
                   break;
               case 'U':
               case 'u':
                   Code = new byte[] { 1,0,1,0,1,1,1,0,0,0 };
                   break;
               case 'V':
               case 'v':
                   Code = new byte[] { 1,0,1,0,1,0,1,1,1,0,0,0 };
                   break;
               case 'W':
               case 'w':
                   Code = new byte[] { 1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case 'X':
               case 'x':
                   Code = new byte[] { 1,1,1,0,1,0,1,0,1,1,1,0,0,0 };
                   break;
               case 'Y':
               case 'y':
                   Code = new byte[] { 1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case 'Z':
               case 'z':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,0,1,0,0,0 };
                   break;
               case ' ':
                   Code = new byte[] { 0,0,0,0 };
                   break;
               case '1':
                   Code = new byte[] { 1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case '2':
                   Code = new byte[] { 1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case '3':
                   Code = new byte[] { 1,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               case '4':
                   Code = new byte[] { 1,0,1,0,1,0,1,0,1,1,1,0,0,0 };
                   break;
               case '5':
                   Code = new byte[] { 1,0,1,0,1,0,1,0,1,0,0,0 };
                   break;
               case '6':
                   Code = new byte[] { 1,1,1,0,1,0,1,0,1,0,1,0,0,0 };
                   break;
               case '7':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0 };
                   break;
               case '8':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,0 };
                   break;
               case '9':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0 };
                   break;
               case '0':
                   Code = new byte[] { 1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0 };
                   break;
               default:
                   Code = new byte[0];
                   break;
            }
        }

        public static MorseChar FromChar(char c)
        {
            return new MorseChar(c);
        }
    }
}

Listening for Messages 

The second requirement I had for my program was that I was able to send messages to it remotely.  I created a MorseListen method that binds to the Netduino Plus' IP Address and listens for incoming messages.  You can use the MFDeploy.exe tool to set the IP Address for your Netduino Plus.  I set mine to a static IP Address so I could easily hit it from my desktop machine.  My program immediately calls MorseListen which binds the IP address and starts a program loop to listen for messages.  If you are using DHCP, beware that the Netduino may not yet have acquired it's IP address, so you'll need to make sure the IP address has been acquired before binding.

Next my loop checks for socket connections and upon finding one it turns on the LED, accepts the message, turns off the LED for 2 seconds, and then blinks the message out in morse code on the built in LED.  Here is my entire Program.cs contents:

using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
using System.Collections;

namespace MFTestApp1
{
    public class Program
    {
        public static void Main()
        {
            // write your code here
            MorseListen();
        }

        private static void MorseListen()
        {
            var currentIp = IPAddress.Parse(Microsoft.SPOT.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0].IPAddress);
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
            socket.Bind(new IPEndPoint(currentIp, 9999)); 
            socket.Listen(10);
            
            var message = new ArrayList();
            var led = new OutputPort(Pins.ONBOARD_LED, false);
            while(true)
            {
                using (var client = socket.Accept())
                {
                    //If connected, turn on the LED
                    if (SocketConnected(client))
                    {
                        led.Write(true);

                        //Get the data from the connection
                        while (SocketConnected(client))
                        {
                            var availablebytes = client.Available;
                            var buffer = new byte[availablebytes];
                            client.Receive(buffer);

                            if (buffer.Length <= 0) continue;

                            var received = Encoding.UTF8.GetChars(buffer);

                            //Add the received chars to our message array list
                            for (var i = 0; i < received.Length; i++)
                                message.Add(received[i]);
                        }

                        //Done receiving, turn off the LED and wait 2 seconds
                        led.Write(false);
                        Thread.Sleep(2000);

                        //Do the morse Code
                        for (var i = 0; i < message.Count; i++)
                        {
                            Debug.Print(message[i].ToString());
                            var code = MorseChar.FromChar((char)message[i]);

                            for (var j = 0; j < code.Code.Length; j++)
                            {
                                var bval = (code.Code[j] != 0);
                                led.Write(bval);
                                Thread.Sleep(75);
                            }
                        }

                        //Clear the array list
                        message.Clear();

                        Thread.Sleep(5000);
                    }
                }  
            }
        }

        static bool SocketConnected(Socket s) 
        {            
            return !(s.Poll(1000, SelectMode.SelectRead) & (s.Available == 0));
        }
    }
}

Connecting From the Client

Now that we have our Netduino Plus listening for incoming connections, we need a way to send messages to it. You could use a console app, a web app, or anything of your choosing.  I threw together a simple WinForms app with a textbox and a button.  Below is all that's needed to send the contents of the textbox to the Netduino.  Make sure you replace "192.168.0.100" with the IP address you assigned to your Netduino Plus (alternately, if your PC has a static IP, you could have the netduino broadcast it's IP address to the PC and initiate the connection itself):

private void button1_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrWhiteSpace(textBox1.Text))
                return;

            using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) 
            {
                var hostAddress = System.Net.IPAddress.Parse("192.168.0.100"); 
                var endpoint = new IPEndPoint(hostAddress, 9999); 
                try
                {
                    socket.Connect(endpoint); 
                    socket.Send(Encoding.UTF8.GetBytes(textBox1.Text)); 
                    socket.Close();
                } 
                catch (SocketException se)
                {
                    Debug.Print("Unable to connect to Netduino"); 
                    Debug.Print(se.ToString());
                } 
            }             
        }

Conclusion

The .NET Micro Framework is a simple version of .NET.  It is easy and fun to code for and there are different options for hardware to run on.  I chose the Netduino Plus for it's built in SD card reader and ethernet.  It has the same form factor and pinout as the Arduino, meaning most shields developed for the Arduino will work with the Netduino Plus.  If you're interested in diving into the .NET Micro Framework, I would highly recommend these boards:

NETDUINO: http://www.netduino.com/

FEZ Panda II: http://www.ghielectronics.com/catalog/product/256

There are various options both for features and pricing and you can pick what fits your needs.