Digi XBee Pro 900 XSC U.FLRecently, I began working on a project I call “OSPhone”. It’s basically an open source cellphone that uses cheap, off-the-shelf parts to build a user connected network to provide free calls between phones via the internet. I plan on writing an article about that project within the next couple of days. So, be sure to check back for it. Anyways, while deciding on what hardware to use, I experimented with several different wireless chips and one of them happened to be my good buddy the XBee (via Sparkfun). I’ve used the XBee for several robotic projects and even some industrial purposes. However, I’ve always used embedded microcontrollers to control them. Since I’ve been on a bit of a C# binge for the last couple of years, I decided to see what would be involved in communicating wirelessly between 2 XBee chips via C#. And now I’m going to share what I found with you.

Before we get started, you will need to purchase 2 XBee chips and either a USB dongle for each or one of the USB cables. Either way, you basically need a way to connect the XBee chip to your USB port. Depending on what you plan to do with your project will influence which XBee chip you decide to work with. Sparkfun has a few XBees that are capable of high throughput, but have short distances such as a few hundred feet or up to a mile even. They also have models that are capable of up to 15 miles, but have very little throughput. For the purposes of this tutorial, you can go with whatever you want as our payload size will be extremely small. Once you have selected the XBee chips you want to work with, you will need to download and install the drivers for the XBee model you selected. You can get the drivers from the Digi support page (http://www.digi.com/support/supporttype.jsp?tp=1).

After you have installed your XBee module and drivers, it’s time to fire up Visual C# and create a new Windows Application. We’ll begin our application by setting up our Form components first. To do that, double-click “Form1.cs” in your Solution Explorer. You should see a blank form in your window when you do. If so, go ahead and add the same components as shown in my example below. The first is a combobox that will store our port names. The second is a rich text box that we’ll use to display the incoming text. The third is a simple text box that we’ll use to type our outgoing messages into. And the rest are the buttons that tie all of this together.

XBee Communicator Form

Before you leave your Form editor view, you will need to add 2 more components not shown in the image above. The first is a timer object. When we bind a successful connection, we will update our rich text box (incoming message) on specified intervals by using the timer object. The next component you will need to add is a new serial port control. This will be what we use to talk to our XBee modules.

Once you have your form setup like mine, swap over to the Form1.cs code view. From there, you’ll need to add a new reference to “System.IO.Ports” with your using statement like this:

using System.IO.Ports;

Next, you will need to define a global StringBuilder variable which we’ll be used to store any data that is received from our XBee module. To keep it simple, I named my StringBuilder object “receivedData”.

private StringBuilder receivedData = new StringBuilder();

The next thing we need to do is to fill in that combobox we added to our form. For that, we will add a new event listener for form load by double-clicking on the form. Inside the form load event handler, we’ll need to iterate over all of the ports that our SerialPort object can see. For that, we’ll simply call the “GetPortNames()” function and add each port name to the Items array of our combobox. While we’re at it, we’ll go ahead and tell our Timer object to start up as well.

foreach (string portname in SerialPort.GetPortNames())
{
cmbCOMPort.Items.Add(portname);
}
timer1.Start();

Now that we have a list of our available ports, we need to use one. For that, we will double-click on our “Open Port” button to add a new click event handler. The first thing we need to do is to tell our Serial Port object which port we plan on using. We can do that by simply grabbing the text from our combobox and assigning it to the PortName of our serial port object. After that’s done, we’ll want to check if that port is already open and if it’s not to go ahead and open it.

serialPort1.PortName = cmbCOMPort.Text;
if (!serialPort1.IsOpen) serialPort1.Open();

Now that we have an open port, we need to add a way to close it. To do that, double-click on your “Close Port” button to give it a new click event handler. Inside that handler, you’ll check to see if the port is open and close it if it is. While you’re at it, you’ll also probably want to add this same code to your form’s FormClosing event so that if your port is open and you close the application, it will go ahead and close the port for you to prevent port failures next time you open the app.

if (serialPort1.IsOpen) serialPort1.Close();

So far, so good. The next thing you need to do is to add some code to your “Send Data” button so that when you type a message you’ll have a way to transmit it. So, go ahead and double-click your “Send Data” button to give it a click event handler. In there, check that your port is open. If the port is open, you’ll need to grab the text from your message text box and pass it to the serial port’s “Write” function like you see below. You’ll also notice that I’ve appended “\n\r” to the end of the text. This is to tell the serial port that all of the data is ready to be transmitted.

if (serialPort1.IsOpen)
{
serialPort1.Write(DataOut.Text + “\n\r”);
}

Next, you’ll need to add an event handler to your serial port for DataReceived. As the serial port receives messages from another XBee, the data will be appended to the end of the StringBuilder object we created earlier. For simplicity, we’ll only be transmitting text messages. But, you can easily transmit complete objects as long as they’re serialized properly before transmission.

recievedData.Append(serialPort1.ReadExisting());

As you recall, I mentioned earlier that we’ll be using the timer object to update our output window with the text that comes in from our serial port. So, go ahead and add a Tick event handler to your timer object along with the following code:

OutputWindow.Text = recievedData.ToString();

Assuming you did everything correctly, you should now be ready to test your application. It’s best that you do this by compiling your application and loading it onto 2 different computers, each having their own XBee connected. If you do not have access to 2 computers, you can still test the application by connecting both XBees to your 1 computer and running 2 instances of the application. When you do, make sure that you select different ports in each application. If you go with the option to test the application on 1 computer by running 2 instances of the application, you should see something like this if everything worked accordingly:

XBee Communicator Test

(Note: I had to resize the image to fit in the window. Click the image to see an enlarged image.)

As you can see, in the first window I selected “COM8″ and clicked the “Open Port” button. In the second window, I selected “COM14″ and clicked the “Open Port” button. Then, in the first window I typed the message “Hello?” and clicked the “Send” button. When I did, the message was sent from 1 XBee to the second where the second application received it and wrote the text to the window.

Here is the complete code for your viewing pleasure:

using System;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace XBee
{
    public partial class Form1 : Form
    {
        private StringBuilder recievedData = new StringBuilder();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (string portname in SerialPort.GetPortNames())
            {
                cmbCOMPort.Items.Add(portname);
            }
            timer1.Start();
        }

        private void OpenPort_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = cmbCOMPort.Text;

            if (!serialPort1.IsOpen)
                serialPort1.Open();
        }

        private void ClosePort_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Close();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Close();
        }

        private void SendData_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
               serialPort1.Write(DataOut.Text + "\n\r");
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            recievedData.Append(serialPort1.ReadExisting());
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            OutputWindow.Text = recievedData.ToString();
        }
    }
}

Be sure to leave me a message in the comments below if you found this article helpful. Also, be sure to post any questions in the comments below and I’ll answer you ASAP. As always, HAPPY CODING!

Related Posts

Tagged with:  

5 Responses to Wireless Communication with XBee and C#

  1. hellokitty9999 says:

    Hi, this article is helpful to me, but right now i have some problem which is my program can’t send or recived any data. I have connected the 2 xbee using two PC, but my program can’t send any data. Could you help me??

    Thank you.

    • LuCuS says:

      I will try my best to help. To do that, I have a few questions.
      1) Are both of your Xbees the same model?
      2) Did you download and install the drivers as mentioned in the article above?
      3) After installing the drivers on both computers, do the computers recognize the devices?
      4) If your devices are being recognized, are you selecting the correct ports? To test this, run the app above and take note of which devices are listed in the ports. Then, plug your device in and re-launch the program. The new port that appears will be your device.
      5) What kind of data are you transmitting? Is it text like in the article? Is it audio? Video? Images? Other binary?
      6) Have you made any changes to the Xbees using the X-CTU client?
      7) What model Xbees are you using?

  2. hellokitty9999 says:

    Hi, I’m using xbee pro S2. both using the same model. What i have program seems working fine. I would like to ask does this program works with sensor?

    For example: the first xbee collect sensor data and it sends to the second xbee. Sending in hex address.

    • LuCuS says:

      If I’m understanding your question correctly, yes, you can collect data from any type of sensor and send it to another Xbee. For example, in my OSCellphone project, I collect audio input from a microphone and process it into data using a Microcontroller that then sends that processed input to another OSCellphone via XBee modules. Once the other XBee has received the data, it passes it thru its microcontroller where the data is processed back into audio and played over the speaker of the device. So, to sum things up, you can transmit pretty much any kind of data you want via XBees. That data can come from any kind of sensor or other input device. In fact, depending on what sensors you’re working with, some data doesn’t even need to be pre-processed before being transmitted between XBees. Instead, you can just pass the raw data itself from XBee to XBee.

  3. hellokitty9999 says:

    Sorry for the late reply. For my circuit, I didn’t use any microcontroller. I’m using a diffuse sensor(PZ2-42 keyence sensor). And only one XBee is connecting to the pc. The second XBee are connected with the sensor on the breadboard.

Leave a Reply