Posted on

Hummingbird tutorial II: Visual C# .NetMf 4.2 and Zigbee series 2

Overview

1.   Connect to VivaPlanet

This next step is a bit more complex and requires some C# and visual studio with the Gagetter software from GHI Installed.  This will take some time…persist it will be worth it in the end…There are a lot of great tutorials out there on how to get this installed on your machine so I won’t go into that here. I spent some time getting all the right references so I’ve taken a screen shot of all the references I’m using in this script.This is a two part post. This post covers the initial libaries, setup and some of the XBee packet handling.

Figure 1: References to be used in Visual Studio

Now we’ll start the teardown of the code.  I’m going to put my commentary in order of how it appears within the code. So to really understand what’s going on you’ll need to read through it at least twice. I’m taking a XBee packet and writing it’s ADC values to a file. Then I’m reading this packet from the file to the serial output. I’m doing this every 5 seconds. There are several of debug points in this script and I’ve left them in. You can literally use this code and get some real time data analytics from your sensor system. You can even send pictures. But this is more complex and may be in a different project all together.

2.   Getting the right headers.

First we need to make sure we have all the system essential headers. This will be a multi-threaded application so we need System.Threading and we’ll have a serial port output so we’ll also need the System.Io libraries.

using System;
using System.Collections;
using System.Threading;
using System.Text;
using System.Security.Cryptography ;
using System.IO; //for series 2
using System.IO.Ports;
Next we’ll need to add some Microsoft libraries to support the hardware. The most important are Microsoft.SPOT and SPOT.hardware. The rest don’t need to be there yet. There will be functionality in the future for these libraries so I chose to leave them.
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;
using Microsoft.SPOT.IO;
Lastly the API’s need to be added. This includes GHI’s libraries, some xbee libraries and the netmf toolbox library. I spent a lot of time finding these libraries so please use them!
using GHIElectronics.Gadgeteer;
using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.OpenSource;
using Gadgeteer.Modules.GHIElectronics;
using GHI.OSHW.Hardware;
using NETMF.OpenSource.XBee.Api;
using NETMF.OpenSource.XBee.Api.Common;
using Toolbox.NETMF;
using NETMF.OpenSource.XBee.Api.Zigbee;
using NETMF.OpenSource.XBee.Util;
The main program namespace I call VivaPlanetEmbedded. This namespace handles all of the datarouting on the embedded system. Right now it has Xbee functionality and serial out functionality. In the future we’ll add some Ethernet and camera functionality as well.
namespace VivaPlanetEmbedded
{
The first class is a manager class of sorts. It takes a packet listener and makes it publicly available to other classes. This was really a key learning for me to add this class. It works very well and makes the code stable.
    public classIOSampleDecodedEventArgs : EventArgs
    {
        public string DecodedPacket { get; set; }
        publicIOSampleDecodedEventArgs(string myString)
        {
            this.DecodedPacket = myString;
        }
    }
The IOSampleListener class handles the incoming Xbee packets. I am using two XBees in my system but I’m sure it can take more.  Let’s walk through this class.
public class IoSampleListener : IPacketListener
    {
        public bool Finished { get { return false; } }
        public XBeeResponse[] Packets;
        UsbSerial usbSerial = new UsbSerial(1);
        static bool flash = true;
        public event EventHandler IOSampleDecoded;
Here we initialize the variables for the class. I have a ‘finished’ flag to make sure that I know when the packets are done.  The UsbSerial variable is for debug. It doesn’t have to be here but it sure helps. We need an public event handler and a packet variable to put the packets somewhere. Keep in mind most of these datatypes come from the XBee API at Github. There is some documentation there but some of this I had to learn myself and ask others.
        public void ReportPacket(string packet)
        {
            EventHandler handler =IOSampleDecoded;
            if (handler != null)
            {
                handler(this, new IOSampleDecodedEventArgs(packet));               
            }
        }
This method passes the received string to the even handler to do something with it. The string is formatted as an xbee packet which makes it really nice. I don’t have to do any fancy parsing.
        public voidProcessPacket(XBeeResponse packet)
        {
            if (packet is IoSampleResponse)
            {
                IoSampleResponse myPackets =ProcessIoSample(packet as IoSampleResponse);
            }
        }
        public IoSampleResponse ProcessIoSample(IoSampleResponse packet)
        {
            DateTime time = new DateTime(2007, 06, 21, 00, 00, 00);
            Utility.SetLocalTime(time);
            try
            {
                for (int ii = 0; ii < 5; ii++)
                {  
               //String format: Address HasData DataId SensorType TimeValue
                    string s = “^” + packet.SourceAddress.Address.ToString() + “^” + “true” + “^” + “0” + “^” + ii.ToString() + “^” + time.TimeOfDay.ToString() + “^” + packet.Analog[ii].ToString() + rn;
                    ReportPacket(s);           
                }
            }
            catch (Exception e) //Catch any exceptions
            {
                Debug.Print(e.ToString()); //print the error to the debug ouput
            }
            return packet;
        }
This method is the meat-and-potatoes of the Xbee portion. We format the string and the ‘report’ the packet to the ReportPacket Class. This enables other classes within this namespace to access the Xbee data.
        private void DebugPrint(string str)
        {
            flash = !flash;
            Debug.Print(str + rn);
            try
            {
                usbSerial.SerialLine.Write(str + rn);
            }
            catch (Exception e)
            {
                Debug.Print(“USB Not enabled” + rn);
                Debug.Print(e.ToString() + rn);
            }
        }
        This method is just a debug script. It is very helpful.
        public XBeeResponse[] GetPackets(int timeout)
        {
            throw newNotImplementedException();
        }
    }
Below we can see the main portion of the .NetMF class. First it is important to note there is a lot of autogenerated code in .Netmf. So this class is only a partial class. The other portion of it is hidden.
    public partial class Program
    {
        public const string DeviceSerialNumer = “17564321”;
        private string _root; //volume
        bool flash = true;
        bool newPackets = false;
        //set up the Xbee                    
        const string serialPortName = “COM1”;
        const Cpu.Pin resetPin = GHI.Hardware.FEZCerb.Pin.PB0;
        const Cpu.Pin sleepPin = GHI.Hardware.FEZCerb.Pin.PC13;
        XBee xBee = new XBee(serialPortName, resetPin, sleepPin) { DebugPrintEnabled = true };       
There are some more variables declared here up front. The most important part here is setting up the Xbee. This code affects the onboard Xbee on the FEZCerbuino Bee. It enables the reset and sleep functions as well as the serial functions.  I have a lot of comments in this next portion that describe what the code is doing so I’m going to rely on them until the next method.
        // This method is run when the mainboard is powered up or reset.  
        void ProgramStarted()
        {
            Debug.Print(“Viva Planet!”);
            try //both usbSerial.Configure and usbSerial.Open()have different exceptions but it is rare that they will triggered in this specific code
            {
                //mount the SD card
                GHI.OSHW.Hardware.StorageDev.MountSD();
                //configure the usbSerial port
                usbSerial.Configure(9600, GT.Interfaces.Serial.SerialParity.None, GT.Interfaces.Serial.SerialStopBits.One, 8);
                //if the port is not open then open it
                if (!usbSerial.SerialLine.IsOpen)
                {
                    usbSerial.SerialLine.Open();
                    DebugPrint(“opened the serial port”);
                }
                if (VolumeInfo.GetVolumes()[0].IsFormatted)//check to make sure the SD card is formatted
                {
                    _root = VolumeInfo.GetVolumes()[0].RootDirectory;
                    DebugPrint(“SD Card is formatted: “ + _root);
                }
                else
                {
                    DebugPrint(“SD Card is not formatted”); //print the error to the debug output
                }             
            }
            catch (Exception e) //Catch any exceptions
            {
                DebugPrint(e.ToString()); //print the error to the debug output
            }
           
            //Gets the command data from the intertubes. This is interrupt driven.            usbSerial.SerialLine.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(SerialLine_DataReceived);
            //Implement the interface member
            IoSampleListener sample = new IoSampleListener();  //created 1x only
            sample.IOSampleDecoded +=sample_IOSampleDecoded;  //every time the event is raised (report packet)
            //add the listener
            xBee.Api.AddPacketListener(sample);
            // initialize the loop timer and send a file to the server
            GT.Timer timer = new GT.Timer(5000);
            //set the interrupt
            timer.Tick += new GT.Timer.TickEventHandler(timer_Tick);
            timer.Start(); 
        }
        //this method is an event handler that decodes the packet within this class
        private voidsample_IOSampleDecoded(object sender, EventArgs e)
        {
            IOSampleDecodedEventArgs eventargs = (IOSampleDecodedEventArgs)e;
            string packet = eventargs.DecodedPacket;
            writeToFile(packet); //write the packet to file
            newPackets = true;
        }
        private void writeToFile(string packet)
        {           
            //initialize variables
            string fileName = Path.Combine(_root, “file.txt”);
            Stream stream;
            try
            {
                //write it to file
                if (File.Exists(fileName))
                {
                    stream =File.OpenWrite(fileName);
                    stream.Position = stream.Length;
                }
                else
                {
                    stream =File.Create(fileName);
                }
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine(packet);
                    DebugPrint(“wrote:  “ + packet);
                }
                stream.Dispose();
            }
            catch (Exception e)
            {
                DebugPrint(e.ToString());
            }
        }

This is the timer event handler. It fires at the designated time and allows the code to run in an endless loop on the embedded device. It is better than using a while loop for a lot of different reasons.

        private void timer_Tick(GT.Timer timer)
        {
               DebugPrint(“tick”);
               if (newPackets)
               {
                   //populate the device struct with the measurements
                   DeviceReport device = readPacketData();
                   //Send the data
                   NotifyServiceQueue(device, null);
                   newPackets = false;
               }
               else
               {
                   DebugPrint(“no new packets”);
               }
        }
 Stay tuned for the next update. We’ll finish going over the code and show some working output.

Posted on

Hummingbird tutorial I: The Hardware

Overview

Hummingbird is a hardware scheme designed to interface with a free data-analysis engine: VivaPlanet (http://www.vivaplanet.io/) . Hummingbird will send information about the health of it’s environment to the VivaPlanet data-analysis engine to allow the user to predict and better understand the health of the environment of Hummingbird.  Anyone can use an ethernet, GPRS or WiFi enabled Internet of Things or wearable device to interface with the VivaPlanet data analysis engine. These are the instructions on how to build a simple serial interface to this engine.

There are three major parts to this project. There is the free VivaPlanet data-analysis engine, the coordinator node and the sensor node. The senor node(s) send information to the coordinator node. The coordinator node manages inputs from various sensor nodes and sends this data periodically to VivaPlanet. The user can then go look at the big data analytics on their free VivaPlanet website.

We choose GHI (https://www.ghielectronics.com/) and Seeed (https://www.seeedstudio.com/) to purchase a lot of the hardware. GHI uses .NETMF capable hardware which is great. I’m using .NetMF 4.2 for this project.This means I can write embedded code in C# and have it cross-compile in Visual Studio 2012 and run on the GHI hardware. This is really great because I get all of the power and flexibility of C# when coding. There is some overhead in this on the hardware side but for a light weight application like this it is a really great way to quickly prototype.


Figure 1: This is an overview of how Hummingbird could be used to send information to VivaPlanet.

Step 1: Building the sensor node

A functional test can be easily constructed with 2 XBees and a BJT Oscillator (more details on how to do this are here: http://meca-labs.blogspot.com/2014/05/fun-with-xbe…) The sensor node is the easiest node to assemble it is shown in Figure 2 below. We hacked into a solar powered light and added a moisture sensor to the bottom. Then we ran a wire up to the top and stored the XBee (series 2) and power system. The XBee has 4 ADC converters and we used one of these to poll the moisture sensor and send the information to the coordinator node. We just used XTCU to program the sensor node.

 Figure 2: Functional example of 2 XBees sending ADC data from a BJT Oscillator to a coordinator node.

Figure 3: Sensor node deconstructed 
Figure 4: Sensor node in action

Step 2: The coordinator node

The coordinator node is also the same solar power set but it consists of a GHI CerbuinoBee an XBee (series 2) and some sort of way to connect to the internet. We’ve demonstrated this project with a GHI GPRS module, shown in figure 5, and a USB-Serial Module. Using the Serial interface in C# is really simple and that’s what we’ll focus on here. Getting the GPRS working is tricky and is another project in itself.

 Figure 5: Coordinator node with a SIM900 GPRS Module.

Step 3: Connect to VivaPlanet
Connecting to VivaPlanet is easy and mostly a software based task.

I’ll post the code in github and link it here. But for now there is a tutorial: https://blazestonetechnologies.com/2015/07/06/hummingbird-tutorial-ii-visual-c-netmf-4-2-and-zigbee-series-2/