Jeroen Swart

.NET Architect

NetDuino - Getting Started with RS232

A common communication protocol is RS232. This is a serial protocol, which uses two wires to transmit data in both directions one bit at a time. A port using this protocol is usually simply called a serial port, because it’s one of the most commonly used protocols for serial communication.

Connecting two devices using RS232 can be as simple as connecting 3 wires between them: transmitted data (TxD), received data (RxD) and ground. It is also possible to connect up to 6 more wires, which handle the handshake part of the RS232 protocol. Handshaking is used to synchronize the communication between the devices: e.g. to let the other device know data was sent or it’s ready to receive data. With 3 wires, and no handshaking, both sides must agree upon the details of the communication: the speed and the number of data-, start- and stop-bits.

What makes using the RS232 protocol difficult in standard digital electronics, is that the protocol uses different voltage levels. Instead of using 0V for a low level or ‘0’ and using the supply voltage (3.3V or 5V) for a high level or ‘1’, the RS232 protocol uses +3V to +15V to signal a ‘0’ and -3V to -15V to signal a ‘1’.

The conversion of RS232 signals and voltage levels is such a common task, that special chips (like the MAX232 or MAX3232) are available to handle this. They even make -12V and +12V out of a 5V or 3.3V power supply. Another option is to use a USB to RS232 converter, like the FT232 chip. This chip presents itself (at its USB side) as a USB serial port to your PC, which is recognized by Windows and a driver is automatically installed. You then have a virtual serial port (usually COM3 or higher) which you can use as if it was a regular RS232 serial port. Whatever you send to this virtual serial port will be present on the RS232 side of the FT232 chip, in logical 0’s and 1’s, and vice versa.

When connecting two microcontroller devices (e.g. two Netduino’s or a Netduino with an Arduino), there is no need to translate the signals. The appropriate ports of each microcontroller can simply be connected directly, or through any type of connector.

Another important thing to know is that the protocol was originally designed for computers and device communication. In this configuration the computer transmits over the TxD line and the device listens to the same line. When connecting two computers, or microcontrollers, to communicate with RS232, both are transmitting over the TxD line and listening on the RxD line. Therefore the lines must be connected across: TxD to RxD and RxD to TxD. When using the ‘real’ RS232 protocol, you can use a special null modem cable, where the TxD and RxD lines are crossed inside. When connecting without such a cable, e.g. between microcontrollers, just remember to connect TxD on one to RxD on the other.

If you want to know more about RS232, check out this Wikipedia article.

The microcontroller on the Netduino has 2 serial ports and both are available through the Netduino headers. Because my laptop has no serial port, I’m using a ‘USB BUB’ board. It’s nothing more than a simple board with a RL232 chip and some supporting components. It’s made by Modern Device, but I ordered mine from JeeLabs, together with some JeeNodes (an Arduino-compatible board).

To setup the hardware part of the example, connect the USB BUB to a PC with a USB cable. It will automatically install the necessary driver and show up as a USB Serial Port in the device manager as shown below.

The ‘LOGIC LVL’ jumper on the USB BUB should be in the 3.3V position, since that’s what the Netduino is working with, but 5V will also work. Connecting the Netduino to the USB BUB takes 3 wires as shown in the picture below. The black wire connects the ground of both boards. The green wire connects the RxD of the Netduino (D0) to the TxD of the USB BUB. The white wire connects the TxD of the Netduino (D1) to the RxD of the USB BUB.

The D0 (RxD) & D1 (TxD) pins of the Netduino headers are connected to the first serial port of the microcontroller, or COM1 for Micro .NET as we will see in code. The second serial port, or COM2, is connected to D2 (RxD) and D3 (TxD) of the Netduino. The first serial port doesn’t provide handshaking. The second serial port does provides handshaking (using CTS & RTS only), but you’re not required to use it.

Below is the code for the Netduino. It sets up a serial port to use COM1 and adds an event handler for when data is received. When data is received, a single byte is read and send back as long as there is data in the buffer to read. You need to add a using statement for the System.IO.Ports namespace. If you want to use COM2 instead, connect the USB BUB to D2 & D3 instead of D0 & D1 and change SerialPorts.COM1 in the code below to SerialPorts.COM2.

public class Program
{
    static SerialPort serial;

    public static void Main()
    {
        // initialize the serial port for COM1 (using D0 & D1)
        serial = new SerialPort(SerialPorts.COM1, 9600, Parity.None, 8, StopBits.One);
        // open the serial-port, so we can send & receive data
        serial.Open();
        // add an event-handler for handling incoming data
        serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);

        // wait forever...
        Thread.Sleep(Timeout.Infinite);
    }

    static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // create a single byte array
        byte[] bytes = new byte[1];

        // as long as there is data waiting to be read
        while (serial.BytesToRead > 0)
        {
            // read a single byte
            serial.Read(bytes, 0, bytes.Length);
            // send the same byte back
            serial.Write(bytes, 0, bytes.Length);
        }
    }
}

Next is the code for a simple console application. It uses COM3 which you might need to change depending on what your USB BUB is connected as; check your device manager. The application lets you type a string and sends it out. When data is received, it is shown. As with the Netduino code, you need to add a using statement for the System.IO.Ports namespace.

class Program
{
    static SerialPort serial;

    static void Main(string[] args)
    {
        // provide some usage information
        System.Console.WriteLine("enter some text and hit ENTER.");
        System.Console.WriteLine("enter 'x' and hit ENTER to exit.");
        System.Console.WriteLine();

        // initialize the serial port for COM3 (could be other port, depends on system)
        serial = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
        // open the serial-port, so we can send & receive data
        serial.Open();
        // add an event-handler for handling incoming data
        serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived);

        // this will hold each line entered
        string line = string.Empty;

        // as long as an x is not entered
        while (line.ToLowerInvariant() != "x")
        {
            // read a single line from the console
            line = System.Console.ReadLine();

            // convert the line to bytes
            byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(line);

            // send the bytes over the serial-port
            serial.Write(utf8Bytes, 0, utf8Bytes.Length);
        }
    }

    static void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // wait a little for the buffer to fill
        System.Threading.Thread.Sleep(100);

        // create an array for the incoming bytes
        byte[] bytes = new byte[serial.BytesToRead];
        // read the bytes
        serial.Read(bytes, 0, bytes.Length);
        // convert the bytes into a string
        string line = System.Text.Encoding.UTF8.GetString(bytes);

        // write the received bytes, as a string, to the console
        System.Console.WriteLine("echo: " + line);
        System.Console.WriteLine();
    }
}

Notice how the code for initializing the serial port, sending & receiving data and even for converting of bytes to a string and back, is exactly the same for both platforms! How cool is that.

Next: working with I2C.

Comments (10) -

  • student

    9/25/2011 5:16:44 PM |

    What about connecting more than 2 micro controllers and establishing a Master /Slave  communication..... i.e One Master Netduino and Multiple Slave Netduino,s....
    Is this possible with RS-232

    • Jeroen

      9/25/2011 8:27:38 PM |

      No, it isn't. You can connect more than 2 microcontrollers, but not with RS232. The RS232 protocol can only be used to connect 2 devices (e.g. a PC with a modem or printer, 2 PC's or 2 microcontrollers). There is a bus version of the RS232 protocol, I think it's called RS485, which allows you to connect multiple devices using the same voltage-levels and data-stream (startbit, databits and stopbits).

      However, the easiest way of connecting multiple microcontrollers is the I2C bus. I've written about the I2C bus here: blog.codeblack.nl/.../...ing-Started-with-I2C.aspx, but that was not about connecting multiple microcontrollers.
      I haven't been able to find much information on how to setup a Netduino as a I2C slave, but it shouldn't be that hard. As soon as I have some time, and enough Netduino's Wink I'll give it a try and post my results.

  • Courtney Wilson

    11/28/2011 12:43:01 AM |

    I am trying to send data from a Netduino to a Fez Panda II (essentially another Netduino) using the SerialPort class (.Net Micro Framework 4.2).

    This is something I expected to be pretty easy, esp. as I am already using the SerialPort class to read data from a 64 Button shield and that is working just fine.

    What I am running into is simply, anytime I try to do a SerialPort.Write, I get an System.Exception "Exception was thrown: System.Exception".  That's it.  No further information: No InnerException, nothing of importance in the stack trace.

    I simplified my project to a Netduino Console Application and the following code:

    using System;
    using Microsoft.SPOT;
    using System.IO.Ports;

    namespace TestCom
    {
        public class Program
        {
            public static void Main()
            {
                byte[] buffer = new byte[1] { 1 };

                SerialPort port = new SerialPort("COM2", 4800, Parity.None, 8, StopBits.One);

                try
                {
                  
                    port.Handshake = Handshake.None;
                    port.WriteTimeout = System.Threading.Timeout.Infinite;
                    port.ReadTimeout = System.Threading.Timeout.Infinite;
                    port.Open();

                    port.Write(buffer, 0, buffer.Length);
                }
                catch (Exception ex)
                {
                    string msg = ex.Message;
                }
                finally
                {
                    port.Close();
                    port.Dispose();
                }
            } // Main
        }
    }

    As soon as hit the port.Write() statement, I drop into the exception handler and get the "Exception was thrown: System.Exception" exception.

    I further simplified the code by removing the Handshake, ReadTimeout, and WriteTimeout lines, so I am basically down to create a SerialPort, Open the port, and Write.  Same error.

    I also tried "port.WriteByte((byte)1);" with the same results.

    As you have obviously worked with the Netduino and SerialPort class before, I was wondering if you have ever experienced this issue, or do you see anything I might be missing?

    Any insight would be great!

    Thanks

    p.s. Some additional info.  My .Net Micro Framework 4.2 console application has it's project properties "Transport" set to USB and the "Device" is "Netduino_Netdunio".  

    I have pin 2 of the Netduino wired to pin 3 of the Fez Panda and pin 3 of the Netduino wired to pin2 of the Fez Panda.  Although technically I will only be sending data from the Netduino to the Fez Panda (the panda will not be sending data back).

    I have also tried pins 0 and 1 and modified the Port constructor call to use "COM1" with the same error result Frown

    • Jeroen

      12/4/2011 11:35:43 AM |

      I have never experienced any issues with serial ports. I also don't see any issues with your code; as far as I can see, that should just work.

      Pin wiring should not be an issue, at least it shouldn't cause an exception to be thrown. Of course, you will not receive any data on the other end.

      The only issue I can think of, is that you're using Micro .NET 4.2 while the Netduino runs on Micro .NET 4.1 by default. Although I'm not sure if that affects the serial ports in any way.
      You can try a 4.1 console application projects, which should still be available in the 4.2 SDK. Or upgrade your Netduino (for some help, see forums.netduino.com/.../).

      If all still fails, try your luck with asking this question on the Netduino forum: http://forums.netduino.com.

      • Courtney

        1/22/2012 7:46:41 AM |

        Funny I ran across my own post looking for something related so I thought I would add a follow up post.

        Not that many people will run across the serial port error that I did, but for completeness I thought I would post that the serial port crash I mentioned above was eventually fixed.

        Turns out that I was using an early release of .Net Micro framework 4.2.  I installed the 4.2 RC3 Netduino firmware and the NETMF 4.2 RTM, and the problem went away (thanks to Chris Walker of Secret Labs for fixing the issue for me).  Apparently, there was a serial port bug in the .Net MF 4.2 beta.

        For further completeness, I was also able to send bytes from my Netduino to my Fez Panda II quite easily.  

        The steps were:
        1. Connect pins 0 & 1 on the Netduino to the Panda
        2. Open a serial port COM1 9600 N81 on both devices
        3. Set up a serial port interrupt on the Panda to signal that bytes were received.  In the interrupt method, do a serial port Read
        4. Do a serial port Write on the Netduino

        I was under the impression that both my devices had to share a common ground which I did not do (directly).  However both devices were connected to my PC via USB cables so I suppose technically they are sharing the same power source and thus a common ground.

        The only other curious thing is that this is not working with COM2. So far I can only get COM1 to work.

        What is nice is I am able to debug both devices at the same time on one PC running two copies of Visual Studio.

  • aldrin roxas

    3/10/2012 2:27:18 AM |

    How can I get a decimal value using rs232 and a sensor? All I get is a binary value.

  • Salvador

    5/2/2012 11:13:21 PM |

    Hi,

    I tried to set up bidirectional communication using SerialPort, it worked out fine in test environment but it breaks on netduino using MF 4.1

    See my code:
        public class Program
        {
            public static void Main()
            {
                SerialPort _serialPort = new SerialPort("COM1");
                String s = "abc";
                byte[] b;
                int i = 0;
                UTF8Encoding enc = new UTF8Encoding();
                b = enc.GetBytes(s);
                if (!_serialPort.IsOpen)
                {
                    _serialPort.Open();
                }
                // i is zero
                i = _serialPort.BytesToRead;
                _serialPort.Write(b, 0, b.Length);
                // i is three now !
                i = _serialPort.BytesToRead;
            }
        }

    I think this is a bug isn't it?

    Thanks for some help

  • vishnu

    6/4/2012 7:29:33 AM |

    I just want to connect Rs232 with my system having windows XP.My device driver is not providing any indication while I connected the same. Pls Let me know should i need to do any system settings for that..

  • clay

    11/25/2012 3:33:26 AM |

    Thanks for posting.  You made it super easy for me to test out a cheap bluetooth shield I acquired. joe.blog.freemansoft.com/2012/11/using-cheap-bluetooth-shield-on-netduino.html

  • Max

    1/20/2013 4:09:57 PM |

    Great Article.
    If the USB-RS232 and the netduino are connected to the same PC, you do not need the ground connection.

Pingbacks and trackbacks (2)+

Comments are closed