Click here to Skip to main content
15,891,670 members
Articles / All Topics

Fun on Microsoft Azure with Windows 10 IoT Core, NETMF, Raspberry Pi 2, Oxygen, Hydrogen and Teensy

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
11 Jul 2015CPOL7 min read 12.9K   2  
CodeProject What an adventure! Azure, Windows 10 IoT Core, the Raspberry Pi, Oxygen, Hydrogen and Teensy working together to measure the current temperature and receive commands via Bluetooth LE or a USB Serial connection! That’s the power of trail & error, creativity and an awesome commu

This article is an entry in our Microsoft Azure IoT Contest. Articles in this section are not required to be full articles so care should be taken when voting.


What an adventure! Azure, Windows 10 IoT Core, the Raspberry Pi, Oxygen, Hydrogen and Teensy working together to measure the current temperature and receive commands via Bluetooth LE or a USB Serial connection! That’s the power of trail & error, creativity and an awesome community around cloud and IoT based topics!

Build a Windows 10 IoT Core compatible USB Serial Device

After reading this post on MSDN-Forums: How to enable a USB-to-Serial converter on Raspberry PI 2 I wanted to try to connect the RPI 2 running Windows 10 IoT Core to a USB2Serial adapter. Because I had no adapter, I checked the boards that I already had and found the Teensy 3.1. It is a USB-based micro-controller development system. The USB connection on the Teensy can basically be any kind of USB device – and of course it can be a USB2Serial device as well. I knew from my tests with the ESP8266 (a very cheap & cool Wifi-Module) that there was an article available that helped me to connect directly with the ESP8266 using the Teensy and a very small but handy Arduino sketch: A Guide To Using ESP8266 With TEENSY 3 And here is the C-Sketch written by a user named Wozzy:

//**** Using a Teensy 3.1 to Connect an ESP8266 to PC USB Serial *******
//     Compiled with Arduino 1.60 and Teensyduino 1.21b6
//     ESP8266 Firmware: AT21SDK95-2015-01-24.bin


long LED_14_TimeOn=0;
long LED_15_TimeOn=0;

void setup() {
  
      pinMode(14, OUTPUT);  // YELLOW LED - SENDING
      pinMode(15, OUTPUT);  // RED LED - RECEIVING

    // Setup computer to Teensy serial
    Serial.begin(115200);

    // Setup Teensy to ESP8266 serial
    // Use baud rate 115200 during firmware update
    Serial1.begin(115200);

}

void loop() {

    // Send bytes from ESP8266 -> Teensy to Computer
    if ( Serial1.available() ) {
         digitalWriteFast(14, HIGH);   // set the LED on
         LED_14_TimeOn = millis();
        Serial.write( Serial1.read() );
    }

    // Send bytes from Computer -> Teensy back to ESP8266
    if ( Serial.available() ) {
        digitalWriteFast(15, HIGH);   // set the LED on
        LED_15_TimeOn = millis();
        Serial1.write( Serial.read() );
    }

    if (millis() - LED_14_TimeOn > 20) {
    digitalWriteFast(14, LOW);   // set the LED off
    }
    if (millis() - LED_15_TimeOn > 20) {
    digitalWriteFast(15, LOW);   // set the LED off
    }

}

The code explains itself very well and it should not really be a problem to understand what it is all about. Basically it moves bytes from the serial connections on the Teensy back and forth between the other connected device (PC, or RPI2) and device that is connected to the Teensy, for example an ESP8266 Wifi-Module.

After uploading the sketch to the Teensy, I connected the Teensy to the RPI2 to check if the device would be recognized:

Window

 

The above screen shows the Devices node on your RPI2 when Windows 10 IoT Core was installed. You just have to browse to http://[YOUR RPI2 HOSTNAME]:8080, enter the username and password and click on the Devices node. So far so good. The Teensy was successfully recognized as USB Serial Device. Now it was time to actually be able to access the device from code and to transfer data back and forth. That way I would be able to connect other devices like temperature sensors that require analog pins (RPI does not have analog pins) or other devices like bluetooth modules that support the serial protocol.

How to use the USB Serial Device from C# and Visual Studio

To actually accomplish this mission, I looked up some Windows Universal sample on GitHub: Custom Serial Device Example. It compiled fine for ARM (The RPI2 has ARM based processors) and I was able to run it on the RPI2. It worked for writing data to the Teensy and the discovery of the Teensy, but I was not able to read data from it, which was absolutely necessary to be able to read data from other connected modules. The settings in the manifest file (which really differ from the official documentation here on MSDN) worked out of the box as well, so I could use the settings from the sample, otherwise it would not be possible to connect to the Teensy:

<Capabilities>
    <DeviceCapability Name="serialcommunication">
      <Device Id="any">
        <Function Type="name:serialPort" />
      </Device>
    </DeviceCapability>
  </Capabilities>
  
</Package>

Reading data from the Teensy (USB Serial Device) was actually accomplished by some trail & error testing:

private async Task ReadSerialPort()
        {
            
            var device = SerialDevice.GetDeviceSelectorFromUsbVidPid(0x16C0, 0x0483);
            var teensyDevices = await DeviceInformation.FindAllAsync(device);

            var currentDevice = teensyDevices.FirstOrDefault();
            SerialDevice realDevice;
            try
            {
                try
                {
                     realDevice = await SerialDevice.FromIdAsync(currentDevice.Id);
                }
                catch (Exception ex)
                {

                    throw;
                }



                StringBuilder commandBuilder = new StringBuilder();

                while (true)
                {
                    var rbuffer = (new byte[1]).AsBuffer();
                    await realDevice.InputStream.ReadAsync(rbuffer, 1, InputStreamOptions.Partial);

                    if ((char)rbuffer.ToArray()[0] != '\n')
                    {
                        commandBuilder.Append((char)rbuffer.ToArray()[0]);
                    }
                    else
                    {
                        string temp = "";

                        try
                        {
                            temp = Math.Round(double.Parse(commandBuilder.ToString().Split(':')[1]), 2).ToString();
                        }
                        catch (Exception)
                        {

                            temp = "ERROR";
                        }
                        //Write the value to an Azure Table
                        await WriteTemperatureToAzureTable("Reutlingen", temp);
                        commandBuilder.Clear();
                    }



                }
            }
            catch (Exception ex)
            {

                throw;
            }
        }

The key was to read only one single byte from the stream at once that is connected to the serial device. Everything else did not work for me. As this API’s are under heavy changes, it could happen that my method will not work anymore with the next release of Windows 10 IoT core. If you don’t know how to actually access and enumerate devices on the UWP platform take a look at the first few lines of the above method. The two hex-values represent (from left to right) the vendor-id and the product-id. You can find this information’s by browsing your RPI2 on port 8080 like you have seen before (the first screenshot in this blog-post). Or you can use  the devcon.exe utility (on your RPI2) when you are connected to via SSH or PowerShell. Please see the resources at the end of this post, you will find all the necessary information’s there. Within the source you will find also a small commented snippet that demonstrates how to write to the USB Serial Device using the headless template from Visual Studio:

//HOW TO WRITE TO THE USB SERIAL DEVICE
            //var stream = realDevice.OutputStream.AsStreamForWrite();

            //for (int i = 0; i <= 100; i++)
            //{

            //    await stream.WriteAsync(Encoding.UTF8.GetBytes(buffer), 0, buffer.Length);
            //    stream.Flush();
            //    //await stream.FlushAsync();
            //    // await realDevice.OutputStream.FlushAsync();
            //}

This worked for me. The sample code did not, when I used the headless template. The headless template represents a special kind of UWP app, that only runs on a background task. You can compare it with an console application for Windows. At the end of the blog-post you will find all the necessary information where to download this template. It needs to be installed separately. And you need Visual Studio 2015 RC.

Putting it all together

The basic idea was a simple communication between a temperature sensor and the RPI2. But because the RPI2 has no analog pins, I chose the Oxygen board, which is an excellent little (very small form-factor, 33.02x 20.32mm) .NET Micro-Framework board. It is capable to communicate on its own with any kind of network-resources and Microsoft Azure. But it also has analog pins:

0000005_oxygen

 

At first I wanted to connect a DHT11 temperature sensor, but to keep it simple, I ended up with a TMP36 sensor that I got from the Arduino Starter Kit that I bought for my daughter. She agreed and so I used it. The pins labeled AN0-ANx are the analog pins. I connected the TMP32 and downloaded some additional libraries (you will find everything at the end of the blog-post), created a new .NET Micro Framework 4.3 project on another machine and wrote the code to read the temperature data, that is directly sent to the first serial port on the Oxygen. To communicate (for a later blog-post) with the tiny BLE113 module (Bluegiga chip, very powerful and simple to program) I connected the Hydrogen module (called Molecule in IngenuityMicro language) that is the carrier for the BLE113. Here is how it looks like on the breadboard:

 

This coniguration allows me to connect any sensor or third party board to the RPI2 running Windows 10 IoT Core. It’s more than a workaround. I would call it an extension. Here is the code that drives the Oxygen board:

using System;
using Microsoft.SPOT;
using IngenuityMicro.Molecule;
using Oxygen;
using System.Threading;
using Toolbox.NETMF.Hardware;
using static Microsoft.SPOT.Hardware.Cpu;

namespace OxygenBLECommander
{
    public class Program
    {
        private static Hydrogen _ble;
        private static SimpleSerial _serial;
        static Timer _tempTimer;
        static AnalogChannel _tempInput;
        static double _temperature;
        static Tmp36 _tempSensor;

        public static void Main()
        {

            _tempInput = AnalogChannel.ANALOG_0;

            _tempSensor = new Tmp36(_tempInput);
            
            _tempTimer = new Timer(new TimerCallback(ClockTimer_Tick), null, 100, 5000);


            //enable RF power
            Oxygen.Hardware.EnableRfPower();

            _serial = new SimpleSerial("COM1", 115200);
            _serial.Open();

            _ble = new Hydrogen();
            _ble.DataReceived += _ble_DataReceived;

            Thread.Sleep(Timeout.Infinite);


        }

        static void ClockTimer_Tick(object sender)
        {
            _temperature = _tempSensor.Temperature / 10;
            _serial.Write("TMP:"+_temperature.ToString()+"\n");
        }

        private static void _ble_DataReceived(string val)
        {
            if (val != "")
            {
                _serial.Write("BLE:" + val + "\n");

                Oxygen.Hardware.BlinkUserLed();
            }
        }
    }
}

Nice small little piece of code that initializes the RF-Power (needed to enable the Hydrogen), initializes a driver class for the TMP36 sensor and opens the serial port for communications to the Teensy (could be any other serial protocol capable device). A timer is initialized that calls the ClockTimer_Tick-Method every five seconds to push the temperature via the serial-port out to the Teensy. This data is then read on the RPI2 and sent out to Azure Storage (save into an Azure Storage Table).

Finally doing something useful – pushing the temperature data to Azure

The last challange (like in most of the time, when you have to handle embedded stuff), was to check if the current release of the Azure Storage libraries will work on Windows 10 IoT Core. Well, the libraries actually work, with exactly this configuration of NuGet packages (this is valid only for headless apps):

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Bcl" version="1.1.10" targetFramework="win81" userInstalled="true" />
  <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="win81" userInstalled="true" />
  <package id="Microsoft.Data.Edm" version="5.6.5-beta" targetFramework="win81" userInstalled="true" />
  <package id="Microsoft.Data.OData" version="5.6.5-beta" targetFramework="win81" userInstalled="true" />
  <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="win81" userInstalled="true" />
  <package id="System.Numerics.Vectors" version="4.1.0-beta-23019" targetFramework="win81" userInstalled="true" />
  <package id="System.Spatial" version="5.6.5-beta" targetFramework="win81" userInstalled="true" />
  <package id="WindowsAzure.Storage" version="4.4.1-preview" targetFramework="win81" userInstalled="true" />
</packages>

If you install the above packages, you should have no problems accessing Azure Storage in exactly the same way you would with pure .NET. Here is the code that sends the temperature data received sent from the Oxygen board, to the Teensy and from there to the RPI2:

private async Task WriteTemperatureToAzureTable(string location, string temperatureValue)
        {
            if (_account == null)
            {
                var credentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
                          "[YOUR STORAGE ACCOUNT NAME HERE]", "[YOUR STORAGE KEY HERE]");
                _account = new CloudStorageAccount(credentials, true);

            }

            if (_tableClient == null)
            {
                _tableClient = _account.CreateCloudTableClient();
            }
            var tableReference = _tableClient.GetTableReference("temperature");


            await tableReference.CreateIfNotExistsAsync();

            var tableData = new TemperatureTable("Reutlingen", DateTime.Now.ToFileTimeUtc().ToString());
            tableData.Location = location;
            tableData.Temperature = temperatureValue;

            try
            {
                TableOperation insertOperation = TableOperation.Insert(tableData);
                await tableReference.ExecuteAsync(insertOperation);
            }
            catch (Exception ex)
            {
                
                throw;
            }

Nothing fancy to see here. It just works. First credentials are needed to authorize against Azure Storage. Then to write,read and create Tables a TableClient is needed. To create the table a TableReference is instantiated and then data is written to the table using a class that inherits from the TableEntity class. The location and the current temperature value are assigned to properties of the TableEntity before the current entity is actually written to the Azure Table. And it works really well.

A short demo video

Here is the actual proof that it really works, a short video demonstrating the solution:

<iframe width="560" height="315" allowfullscreen="allowfullscreen" frameborder="0" src="https://www.youtube.com/embed/grahz027Ma8"></iframe>

Useful Resources

Microsoft Azure

Free Azure Trail – Sing up and deploy your first solution in under 5 Minutes

Azure Storage Documentation

Board Vendors

Oxygen – InguenityMicro

Teensy

Raspberry PI (Click on Shop on the right hand-side)

Used Libraries

Oxygen SDK and Molecule Libraries

.NET Micro Framework Toolbox (driver for the TMP36 sensor and lot’s more of very useful stuff

Windows 10 IoT Core

Windows 10 IoT Core Command Line Utils

Raspberry PI 2 Pin Mappings

Headed and Headless mode

Code Samples (C#, Python and Node.js)

Visual Studio

Visual Studio 2015 RC Community Edition Download (or any other preferred version)

Windows IoT Core Project Templates extension for Visual Studio 2015 RC

.NET Micro Framework

.NET Micro Framework Homepage

Demo Source

AzureIoTDemo Source

OxygenBLECommanderSource

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer ExGrip LCC
Germany Germany
Working as professional freelancer for the last 5 years. Specialized on and addicted to .NET and a huge fan of Windows Azure from the beginning. Socializing people of all areas, from CEO's to co-workers. Consider myself as a social architect.

Now the proud owner of ExGrip LLC - building mobile cloud experiences. Our latest product "Tap-O-Mizer" is shortly in Beta2. It enables you to see what really needs to be changed in your Windows Phone 8 or Windows 8 app (in real-time, if needed), to ensure customer satisfaction.

Started authorship for "Pluralsight - Hardcore Developer Training" and going to publish the first course on Windows Azure soon.

A few years ago I made a major shift from developer to "devsigner".Focusing my creativity also on great user experiences on Windows, Windows 8 and Windows Phone. Utilizing Expression Design, Expression Blend, Photoshop and Illustrator.

I started developing my first programs on a Commodore C64 (basic and assembly) at the age of fourteen years. Later on an Amiga 500 (C++). After that I made the shift to DOS and Windows from version 3.11 and up.

To me the most important part of developing new experiences is to work with creative and outstanding people and to bring new, exciting ideas to life.

I strongly believe that everyone can be a hero if he/she get's pushed and motivated and valued. Therefore, and that under any circumstances: "People first!"

Specialties:Extremely motivated and pushing people to create results.

Comments and Discussions

 
-- There are no messages in this forum --