Category Archives: Gadgets

Controlling Relays from the web using a Pi, OWIN, Mono and SignalR

In my previous article I built a C# library to communicate with the GPIO ports of the Raspberry Pi 2 (and Raspberry Pi B+). We also built a small console application to trigger the ports. While the console application was a nice proof of concept, the real fun is when you are able to flip switches from remote locations (when not at home, over phone etc. etc.) As a first attempt at this I built a OWIN based self hosting web site that communicates with the Pi over HTTP using SignalR.

The Idea

The idea is pretty simple, the GPIOManager is embedded into a Console application that is also a SignalR client.

The SignalR client has SwitchOn, SwitchOff methods taking GPIOPinIds as parameters and call upon the GPIOManager to do so.

Any web application can host the SignalR Hub and a SignalR web client. The web client relays the actions to the remote client. Simple!

Before we start

In reality I built the sample app first and then did the refactoring but now that the code is already refactored might as well mention it beforehand.

The PiOfThings.net

I got so involved with this whole IoT things, that I decided to go the whole nine yards

– Bought the domain www.piofthings.net. It is currently the Github.io page for the piofthings account. I’ll eventually move it to docs.piofthings.net and replace the www with something more interesting Winking smile 
– Created a new Github account http://www.github.com/piothings.  
– Refactored code and checked it into Github
– Created Nuget Packages PiOfThings.GpioCore and PiOfThings.GpioUtils and uploaded to www.Nuget.org
– So now you can install the dependencies using Nuget Package Manager

install-package PiOfThings.GpioCore

install-package PiOfThings.GpioUtils

As you can guess from the namespaces the refactoring involved separating the helper classes into a separate DLL. This is because I wanted to refer the utility enumerations on the Web application but the web application didn’t need the manager. So now you can install the Core which has the manager and it will install GpioUtils automatically. Or if you want the Utils only, just install the PiOfThingsUtils directly.

With all the refactoring in place, we are not ready to take the next step.

Creating the SelfHosted Owin Web App

I started with a Console App in Mono and added the following Packages

Microsoft.Owin

Microsoft.Owin.SelfHost

Microsoft.Owin.Host.HttpListener

Microsoft.AspNet.SignalR.Core

Microsoft.AspNet.SignalR.JS

and of course PiOfThings.GpioUtils

These all install certain sub-dependencies so you’ll end up with a bigger list of packages

My final packages.config looks like this

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="jQuery" version="2.1.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.JS" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Cors" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Diagnostics" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.FileSystems" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.SelfHost" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.StaticFiles" version="3.0.1" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
  <package id="PiOfThings.GpioUtils" version="0.1.0" targetFramework="net45" />
</packages>

Adding a SignalR Hub

Added a new class called IoTHub that inherit from Microsoft.AspNet.SignalR.Hub. Added a method Handshake that simply returns true. This is for the client to check if the server is there or not when it starts off.

Next we add two methods switchOn and switchOff, both take the GpioId as input parameter. All that this method does is calls the switchOff or switchOn function on all other clients.

The final Hub class is as follows:

using System;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using PiOfThings.GpioUtils;

namespace IoTWeb
{
    [HubName("IoTHub")]
    public class IoTHub : Hub
    {
        public bool Handshake()
        {
            return true;
        }

        public void SwitchOn(GpioId gpioPinId)
        {
            Console.WriteLine("Switching ON - " + gpioPinId.ToString("D"));
            Clients.Others.switchOn(gpioPinId);
        }

        public void switchOff(GpioId gpioPinId)
        {
            Console.WriteLine("Switching OFF - " + gpioPinId.ToString("D"));

            Clients.Others.switchOff(gpioPinId);
        }
    }
}

Setting up SignalR in the OWIN pipeline

We add new class called IoTStartup and add decorate it with the OwinStartup attribute.

using System;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(IoTWeb.IoTStartup))]

namespace IoTWeb
{
	public class IoTStartup
	{
		public IoTStartup ()
		{
		}
	}
}

Next we add a method Configuration with an input parameter of type IAppBuilder. A function with an input parameter of type IAppBuilder is the standard convention for chaining OWIN components.

We setup SignalR in the OWIN pipeline as follows

public void Configuration(IAppBuilder app)
{
	app.UseCors (CorsOptions.AllowAll);
	app.MapSignalR ();		
}

Getting it hosted

Now to host SignalR. We go back to the Program.cs and add update it as follows:

using System;
using Microsoft.Owin.Hosting;

namespace IoTWeb
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			string baseUrl = "http://localhost:5000";
			using (WebApp.Start<IoTStartup>(baseUrl))
			{
				Console.WriteLine("Press Enter to quit.");
				Console.ReadKey();

			}
		}
	}
}

We are using the WebApp to host all other OWIN components. The WebApp is hosted at the provided URL (localhost:5000) We could have used SignalR self hosting too, but you’ll see in a minute why I used Web App.

Build the application and run from the console


pi@raspberry ~/projects/IoTLightbulb/IoTWeb/bin/Debug $ sudo mono IoTWeb.exe

Next launch browser and go to localhost:5000/SignalR/hubs you should see the generated Hub proxy. To ensure it’s correctly generated, scroll down till you can see your Hub’s name (IoTHub) and the three functions you created in your hub (handshake, switchOff and switchOn

image

Great, we have a SignalR hub that can issue commands. Now we need two things, a UI to issue the commands and a client connected to this hub to receive those commands. Let set these up.

Setting up a simple Static File Host using OWIN

In real life we would build a nice ASP.NET MVC around the SignalR app, but today we are only demoing stuff. All we need is an HTML page, some JavaScript so lets use simple static file hosting and host an HTML file and required JavaScript.

1. Update the jQuery dependency (you got from installing the Microsoft.AspNet.SignalR.JS) from 1.6.4 to the latest using Update package feature of Mono from the solution itself.

2. Add a folder called Web in your project and move the Scripts folder package under Web. It should look something like this

image

3. Now right click on the min.js files one at a time, go to quick properties and check the ‘Copy to Output Directory’

image

Do the same for Index.html. This will ensure the Web folder is create under wherever the exe file is generated and contain the HTML and required JavaScript files.

4. Under Web add an Html file – Index.html and add the following markup

<!DOCTYPE>
<html>
	<head>
		<title>IoT Web</title>
		<script type="text/javascript" src="/Web/Scripts/jquery-2.1.3.min.js"></script>
		<script type="text/javascript" src="/Web/Scripts/jquery.signalR-2.2.0.min.js"></script>
		<script type="text/javascript" src="/signalr/hubs"></script>
	</head>
	<body>
		<h1>Controlling Relays from the web using SignalR </h1>
		<button id="turnOn1">Turn On 1</button>
		<button id="turnOff1">Turn Off 1</button> 

		<script type="text/javascript">
		$(function() 
		{
			var hub = $.connection.IoTHub;

			$.connection.hub.start().done(function () 
			{
				$('#turnOn1').click(function(){
					hub.server.switchOn(17);
				});
				$('#turnOff1').click(function(){
					hub.server.switchOff(17);
				});
			});
		});
		</script>
	</body>

</html>

We have basically done the following:

– Added reference to jQuery, SignalR client (jQuery.SignalR) and the SignalR hub

– Added two buttons with the ids turnOn1 and turnOff1

– Initialized the hub and once the connection started attached a click handler to each button.

– Each click calls the respective switchOn and switchOff method. The number 17 basically implies GPIO 17 that we are trying to turn on an off

5. Finally in the IoTStartup.cs add two lines of code in the Configuration function to initialize static hosting

public void Configuration(IAppBuilder app)
{
	app.UseCors (CorsOptions.AllowAll);
	app.MapSignalR ();		
	string exeFolder = System.IO.Path.GetDirectoryName (System.Reflection.Assembly.GetExecutingAssembly ().Location);
	string webFolder = System.IO.Path.Combine (exeFolder, "Web");
	Console.WriteLine ("Hosting Files from : " + webFolder);
	app.UseStaticFiles ("/Web");
}

All set with the Web page then. Run it again and navigate to http://localhost:5000/Web/Index.html . You should see something similar:

image

Cool. Now lets build the client that will communicate with this server

Creating SignalR client to communicate with GPIO ports

Lets start with another console application, I have called it RelayControllerService. This service does the following:

Create a SignalR HubProxy, a GpioManager and establish a connection with the SignalR server.

Once setup it does the handshake and then wait for commands from the server.

When it receives SwitchOn or SwitchOff command, it uses the GpioManager to write to the appropriate GPIO pin.

Before we get started we add references to the following packages:


install-package Microsoft.Owin
install-package Microsoft.AspNet.Cors
install-package PiOfThings.GpioCore

This should setup all other required dependencies. My packages.config is as follows:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.Client" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Diagnostics" version="3.0.1" targetFramework="net45" />
  <package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
  <package id="PiOfThings.GpioCore" version="0.1.0" targetFramework="net45" />
  <package id="PiOfThings.GpioUtils" version="0.1.0" targetFramework="net45" />
</packages>

Now that we are all set, let’s look at the code for the RelayControllerService.

The Constructor

using System;
using Microsoft.AspNet.SignalR.Client;
using PiOfThings;
using PiOfThings.GpioCore;
using PiOfThings.GpioUtils;

namespace RelayControllerService
{
	public class RelayControllerService
	{
		readonly GpioManager _manager = new GpioManager ();

		private IHubProxy IoTHub { get; set; }

		private HubConnection IoTHubConnection { get; set; }

		public RelayControllerService (string url)
		{
			IoTHubConnection = new HubConnection (url);
			IoTHub = IoTHubConnection.CreateHubProxy ("IoTHub");

			IoTHub.On<GpioId> ("SwitchOn", OnSwitchedOn);

			IoTHub.On<GpioId> ("SwitchOff", OnSwitchedOff);

			Console.Read ();
		}

 

We are setting up our service by initializing the GpioManager, ProxyHub and HubConnection. We are also assigning an event handler for the SwitchOn and SwitchOff events that will be invoked someone clicks on the buttons on our website.

The Event handlers

The event handlers have the same code from our previous sample console application. Whenever a switchOn or switchOff is received, we first check if the _manager’s current pin is the same as the pin requested, if not it is selected. Once selected we write the Low or High appropriately.

        private void OnSwitchedOn(GpioId gpioPinId)
        {
            Console.WriteLine("SWITCH ON RECIEVED " + gpioPinId);
            if (_manager.CurrentPin != gpioPinId)
            {
                _manager.SelectPin(gpioPinId);
            }
            _manager.WriteToPin(GpioPinState.Low);
        }

        private void OnSwitchedOff(GpioId gpioPinId)
        {
            Console.WriteLine("SWITCH OFF RECIEVED " + gpioPinId);

            if (_manager.CurrentPin != gpioPinId)
            {
                _manager.SelectPin(gpioPinId);
            }
            _manager.WriteToPin(GpioPinState.High);
        }

Connection Initialization and termination

Our service is setup and ready to provide event handlers. All we have to do is start connection and wait for server. Also when user wishes they can stop the connection.

The StartConnection creates an async task that attempts to connect to the server. Once connected to the server is calls our HandShake method and reports that the Handshake was successful. In future the Handshake will be more involved with the device sending specific device identifiers to the server so that the server can keep track of which device is connected and connect to that particular device only.

The StopConnection simply calls the GpioManager’s Release all function to release all the GPIO pins and then calls a SignalR Stop to gracefully close the connection.

using System;
using Microsoft.AspNet.SignalR.Client;
using PiOfThings;
using PiOfThings.GpioCore;
using PiOfThings.GpioUtils;

namespace RelayControllerService
{
    public class RelayControllerService
    {
        readonly GpioManager _manager = new GpioManager();

        private IHubProxy IoTHub { get; set; }

        private HubConnection IoTHubConnection { get; set; }

        public RelayControllerService(string url)
        {
            IoTHubConnection = new HubConnection(url);
            IoTHub = IoTHubConnection.CreateHubProxy("IoTHub");

            IoTHub.On<GpioId>("SwitchOn", OnSwitchedOn);

            IoTHub.On<GpioId>("SwitchOff", OnSwitchedOff);

            Console.Read();
        }

        private void OnSwitchedOn(GpioId gpioPinId)
        {
            Console.WriteLine("SWITCH ON RECIEVED " + gpioPinId);
            if (_manager.CurrentPin != gpioPinId)
            {
                _manager.SelectPin(gpioPinId);
            }
            _manager.WriteToPin(GpioPinState.Low);
        }

        private void OnSwitchedOff(GpioId gpioPinId)
        {
            Console.WriteLine("SWITCH OFF RECIEVED " + gpioPinId);

            if (_manager.CurrentPin != gpioPinId)
            {
                _manager.SelectPin(gpioPinId);
            }
            _manager.WriteToPin(GpioPinState.High);
        }

        public void StartConnection()
        {
            //Start connection
            IoTHubConnection.Start().ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    Console.WriteLine("There was an error opening the connection:{0}",
                        task.Exception.GetBaseException());
                }
                else
                {
                    Console.WriteLine("Connected");

                    IoTHub.Invoke<string>("HandShake").ContinueWith(joinGroupTask =>
                    {
                        if (task.IsFaulted)
                        {
                            Console.WriteLine("There was an error calling send: {0}",
                                task.Exception.GetBaseException());
                        }
                        else
                        {
                            Console.WriteLine("Handshake successful - " + joinGroupTask.Result);
                        }
                    });
                }

            }).Wait();
        }

        public void StopConnection()
        {
            _manager.ReleaseAll();
            IoTHubConnection.Stop();
        }
    }
}

And that’s it, we are done. Compile the project, open a terminal, change directory to the /bin/Debug folder and execute


sudo mono RelayControllerService.exe

Initially you should see a successful handshake

image

Next click on the ‘Turn On 1′ button and give it about a second to see the response on the RelayController window

image

If you had the relay circuitry setup as shown in my previous article, the LED would have gone bright red and the relay clicked.

Now click on the Turn Off 1 button and the service should respond accordingly.

image

And we are done for today !!!

Conclusion

We stepped up from connecting to GPIO from the console to connecting using a Web page. So we are one step closer to the ‘Internet’ in ‘Internet of Things’. From here on, how you want to build your service to be able to connect to your Pi is entirely up to you. I’ll keep you posted with my progress! Cheers!

Code is up at the same repository https://github.com/sumitkm/IoTLightbulb

Tagged ,

Getting started with Internet of things using a Raspberry Pi 2 and Mono

Some of you may have spotted my previous experiments with the $35 wonder computer that’s the Raspberry Pi. I have since then added two more Raspberry Pies to my collection. One goes into the amazeballs Diddyborg (by @Pi_Borg) and the other one is a the latest and greatest Raspberry Pi 2 bought on the day of launch in early February.

The Diddyborg is nice kit created by PiBorg.org. It showcases their motor controller which can control 6-8 motors at a time per controller. It also has the ‘batt bot’ board included which works towards prolonging the battery life for the Diddborg. It comes with a bunch of sample programs like ball follow that uses optical image recognition via the Pi Camera module. It was a nice fun project that I did with junior over Christmas. I also ended up doing a small keyboard driver using python for it. The current code for it is up here (not the best Python ever written, you have been warned). There are lots of experiments planned with it, but that’s for another day.

I have been sitting on the sidelines of the Internet of Things (IoT) buzz for a while now and waiting for the ‘right moment’. Apparently the trigger was launch of the rather capable Raspberry Pi 2 early in February this year. With the bump in spec to a Quad Core 900MHz processor with 1 Gig of RAM, the Raspi 2 is about as capable as mid-market contemporary smartphone. At 25GBP it’s a steal!!! Along with the Pi I bought a microcontroller controlled 8 relay board. Idea was to toggle lightbulbs on/off from my phone Smile. There are ready made kits, ready made bulbs already in the market. So it’s not ground breaking, but hey, where’s the fun in that right!

Anyway, I missed the first lot of Pi deliveries but manage to squeak into the second lot. The microcontroller board arrived quickly enough but the female-female jumper connectors took forever to arrive from Hong Kong. Here’s the entire kit:

1. Raspberry Pi 2 + Power Supply + 16Gig SD card (went big assuming Win IoT would be a massive hog).
2. 5V 10A, 8 Relay microcontroller board by Anoder. The relays are not opto-coupler (aka solid state relays) and are ON when low meaning the connection is ON without any input. You have to provide an input to turn it off. This is good in a way that you can expect your lights to remain on (and in control of the mains switch) if your Pi crashes. However it also means while programming it, you have to send in a 1 to turn it off and 0 to turn it on. Kinda reversed!
3. 40 pin Female-Female jumper cables.
4. Optionally I bought a breadboard and a bunch of breadboard connection wires.

Wiring things up

After untold warnings on the internet about not working on mains power I decided to heed to people’s warning and play with my LED Christmas lights that already had a 220 – 12V step down. (NOTE: I am not a certified electrical engineer in UK, but I DO know my way around electrical boards, supplies and wiring and have had enough ‘shocking’ experiences as a kid to not treat 240V mains supply lightly). So this blog will not show you stuff beyond driving the relay. What you connect to the other side of the relay is up to you. I used a Christmas light that works off a 5V DC supply provided by a built in control unit.

To run this code you don’t need anything on the other end of the relays. You can hear the Relays click quite distinctly and there is an indicator LED that will also give you ample hint that the relays are working.

Pin Outs

I connected two of the 8 relays to GPIO 17 and GPIO 22. So the connections were like this

GPIOtoRelay

The board on the left is a not-to-scale representation of the Raspberry Pi 2 as seen from the CPU side. The GPIO ports take up more space on my diagram than in the actual board, but you get the point.

I have only labeled some of the pins to keep the diagram clean (actually to get it done quickly enough). Here is a complete pin out if you need one handy!

Like the Pi board, the Relay board diagram is representative and not to scale too. The blue boxes are the relays and the Red diode symbols represent the LEDs on board.

Connections

IO Pin 2 is what is powering the relay controller. So it’s connected to the VCC pin of the Relay board (Brown wire on my connector strip).
IO Pin 6 ground is connected to the ground (first pin) of relay board (Green wire on my connector strip)
IO Pin 11 represents GPIO 17 (blame Broadwell the CPU makers for the weirdness in numbering schemes). A 0 or 1 to GPIO 17 will drive the first relay hence it’s connected to In 1 on the relay board using the red wire from the connector strip.
IO Pin 15 represent GPIO 22. I’ve connected it to In 2 on the relay board using the blue wire from the connector strip.

That covers the wiring between the Pi and the Relay board.

Switching Relays using Python

To test the controller board out, I first tried a sample Python program. The source is here. As you can see it’s pretty rudimentary but it did what it was asked to do. Switch the lights off for 20 seconds.

But I wanted more. I wanted to direct the GPIO ports over the web. I tried reading up on making web services in Python and realized there wasn’t a quick way out. That’s when I came across Jan Tielens’ excellent series on getting started with .NET on Raspberry Pi.

This article by Jan will get the Pi Setup with Mono + MonoDevelop. Jan starts with a barebones Pi and walks you all the way up to the Mono Setup. If you just want to setup Mono here is the gist:

1.Update Wheezy package list to the latest

sudo apt-get update

2. Upgrade Wheezy to latest and greatest

sudo apt-get upgrade

3. Retrieve and install key for the mono GPG key

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF

4. Next add repository reference to apt-get. This is where the mono-repositories are (two repository references).

echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list

echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list

5. Repeat step 1 and 2 to make sure all dependencies are in place.

6. Install Mono (finally)!!!

sudo apt-get install mono-complete

7. Install MonoDevelop (for on Pi development)!

sudo apt-get install monodevelop

A lot of people develop on Visual Studio and deploy on the Pi. But MonoDevelop is a very capable IDE and I wanted to develop on device. So I opted to use MonoDevelop for my Pi development.

Once I had C# running on Pi, the world was my oyster. I realized how brave a path Miguel Icaza had blazed when he started the Mono project. I am no OSS fanatic, but I am no shill either. Heartfelt thanks to the Mono Team for sticking around against lots and lots of odds. Yes, now I believe you guys love C# more than Microsoft itself does!

Talking to GPIO pins using C#

Once I had C# going, I followed some more of Jan’s tutorials to see how you could communicate with GPIO pins. Turns out the GPIO port is registered as a folder (like most devices on Linux), and all I had to do was write appropriate ‘text’ to appropriate files in assorted folder. Since this all sounded very easy I assumed someone had already done the hard work. Indeed there are two nice libraries on Github. However when I tried to use RaspberryGPIOManager I found it was locking itself up (on the Raspberry Pi 2). So my friend Raj and I got busy following Jan’s tutorial and write the code ourselves. Sure enough, Raj had the code going in about 45 minutes and were were able to talk to one of the GPIO ports and do the same thing the Python program was doing.

Next day I sat down and wrote up a rudimentary library in line with RaspberryGPIOManager and now it’s a neat reusable component.

Show me the code

Okay, enough rambling, time to see some code.

I started with a simple Console application on Mono and split up the reusable component into a separate class library. So essentially I have two projects

1. My IoT library (PiOfThings) that for now has the GPIO interaction library (GPIOManager) and

2. Sample code (GpioCs).

GPIO Manager

The GPIO Manager project has two files GPIOManager.cs which is the actual driver and GPIOPinReferences.cs a bunch of helpers and enumerations.

GPIOPinReferences.cs

This file has two static classes and two enums. The GPIOPinState enum does what it says, encapsulates the Pin statuses which is essentially 0 or 1 with 3 indicating error/unknown condition.

public enum GPIOPinState
{
	Low = 0,
	High = 1,
	Unknown = 3
}

The second enum called GPIOId maps directly to the pin numbers on the Raspberry Pi 2 (or B+) I/O port. GPIOUnknown is assigned the value -1 for any non GPIO pins.

public enum GPIOId
{
	GPIOUnknown = -1,
	GPIO02 = 2,
	GPIO03 = 3,
	GPIO04 = 4,
	GPIO07 = 7,
	GPIO08 = 8,
	GPIO09 = 9,
	GPIO10 = 10,
	GPIO11 = 11,
	GPIO14 = 14,
	GPIO15 = 15,
	GPIO17 = 17,
	GPIO18 = 18,
	GPIO22 = 22,
	GPIO23 = 23,
	GPIO24 = 24,
	GPIO25 = 25,
	GPIO27 = 27
}

Next we have a helper class that maintains two dictionaries of pin number-to-port and port-to-pin number.

public static class GPIOPinMapping
{
	private static Dictionary&amp;lt;GPIOId, int&amp;gt; GPIOToPin = new Dictionary&amp;lt;GPIOId, int&amp;gt;
	{
		{ GPIOId.GPIO02, 3 },
		{ GPIOId.GPIO03, 5 },
		{ GPIOId.GPIO04, 4 },
		{ GPIOId.GPIO07, 26 },
		{ GPIOId.GPIO08, 24 },
		{ GPIOId.GPIO09, 21 },
		{ GPIOId.GPIO10, 19 },
		{ GPIOId.GPIO11, 23 },
		{ GPIOId.GPIO14, 8 },
		{ GPIOId.GPIO15, 10 },
		{ GPIOId.GPIO17, 11 },
		{ GPIOId.GPIO18, 12 },
		{ GPIOId.GPIO22, 15 },
		{ GPIOId.GPIO23, 16 },
		{ GPIOId.GPIO24, 18 },
		{ GPIOId.GPIO25, 22 },	
		{ GPIOId.GPIO27, 13 }
	};

	private static readonly Dictionary&amp;lt;int, GPIOId&amp;gt; PinToGPIO = new Dictionary&amp;lt;int, GPIOId&amp;gt;
	{
		{ 1, GPIOId.GPIOUnknown },
		{ 2, GPIOId.GPIOUnknown },
		{ 3, GPIOId.GPIO02 },
		{ 4, GPIOId.GPIO04 },
		{ 5, GPIOId.GPIO03 },
		{ 6, GPIOId.GPIOUnknown },
		{ 7, GPIOId.GPIOUnknown },
		{ 8, GPIOId.GPIO14 },
		{ 9, GPIOId.GPIOUnknown },
		{ 10, GPIOId.GPIO15 },
		{ 11, GPIOId.GPIO17 },
		{ 12, GPIOId.GPIO18 },
		{ 13, GPIOId.GPIO27 },
		{ 14, GPIOId.GPIOUnknown },
		{ 15, GPIOId.GPIO22 },
		{ 16, GPIOId.GPIO23 },
		{ 17, GPIOId.GPIOUnknown },
		{ 18, GPIOId.GPIO24 },
		{ 19, GPIOId.GPIO10 },
		{ 20, GPIOId.GPIOUnknown },
		{ 21, GPIOId.GPIO09 },
		{ 22, GPIOId.GPIO25 },
		{ 23, GPIOId.GPIO11 },
		{ 24, GPIOId.GPIO08 },
		{ 25, GPIOId.GPIOUnknown },	
		{ 26, GPIOId.GPIOUnknown },
		{ 27, GPIOId.GPIOUnknown },
		{ 28, GPIOId.GPIOUnknown },
		{ 29, GPIOId.GPIOUnknown },
		{ 30, GPIOId.GPIOUnknown },
		{ 31, GPIOId.GPIOUnknown },
		{ 32, GPIOId.GPIOUnknown },
		{ 33, GPIOId.GPIOUnknown },
		{ 34, GPIOId.GPIOUnknown },
		{ 35, GPIOId.GPIOUnknown },
		{ 36, GPIOId.GPIOUnknown },
		{ 37, GPIOId.GPIOUnknown },
		{ 38, GPIOId.GPIOUnknown },
		{ 39, GPIOId.GPIOUnknown },
		{ 40, GPIOId.GPIOUnknown },
	};


Two static methods help you get the appropriate values out of the dictionaries depending on what you are looking for (pin number or GPIO id).

	public static int GetPinNumber (GPIOId gpioNumber)
	{
		return GPIOToPin [gpioNumber];
	}
	public static GPIOId GetGPIOId(int pin)
	{
		if (pin &amp;gt; 0 &amp;amp;&amp;amp; pin &amp;lt;= 40)
		{
			return PinToGPIO [pin];
		}
		else
		{
			throw new ArgumentOutOfRangeException (&amp;quot;pin&amp;quot;, string.Format (&amp;quot;Invalid pin {0}. Please enter value between 1 and 40 (both inclusive).&amp;quot;, pin));
		}
	}
}

The Driver (GPIOManager.cs)

Overview of communication mechanism

A GPIO pin like any digital connection can represent either 0 or 1. ‘Talking’, ‘connecting’, ‘sending signal’ or ‘communicating’ to a GPIO port simply means you are either reading values (0 or 1) or writing values (0 or 1). Since the Linux OS represents the I/O ports as streams you can using any File System based APIs and a direct your output to specific folders to write to appropriate files.

For GPIO communication on the Pi, the specific folder is as follows

/sys/class/gpio/gpio{pin id}/value

Here {pin id} is the GPIO pin number as specified in the GPIOId enum above

This destination can be used to write “0” or “1” for sending low or high signals to the pin.

To read, you use the same destination but instead of Writing to it, you read from it using FileSystem.

Before you can communicate with a particular pin you need to make sure no one else is communicating with it, so you should try to ‘Reserve’ the pin and then set “Direction” of communication. Again all this can be done by writing appropriate values to the ports via the file system.

So the API that we are writing as the following calls:

1. Select (Reserve) a pin

2. Write to pin

3. Read from pin

4. Release pin

The actual code

I’ll break up the actual code into the above mentioned calls. You can refer to the entire thing together on Github.

The GPIOManager has a readonly GPIO_ROOT_DIR folder that can be passed in the constructor if you want to mock the PI and run the manager when the actual GPIO pins are not available.

The Manager has an internal list of Pins that have been selected and hence are busy. Note the Manager is not a singleton so this list may not be the single source of truth on the Pi.

You call the SelectPin method and provide the GPIOId identifying the pin that needs to be selected.

If successful, the CurrentPin property on GPIOManager is set to the pin you requested for, else it throws an exception.

The private call to ReservePin function is what actually selects the Pin. All it does is writes to the ‘export’ stream, value of the Pin that’s selected.

Once you have Selected a pin you can write to the pin using the WriteToPin call.

public bool WriteToPin (GPIOPinState state)
{
	try
	{
		File.WriteAllText (String.Format (&amp;quot;{0}gpio{1}/direction&amp;quot;, GPIO_ROOT_DIR, CurrentPin.ToString (&amp;quot;D&amp;quot;)), GPIOPinDirection.Out);
		File.WriteAllText (String.Format (&amp;quot;{0}gpio{1}/value&amp;quot;, GPIO_ROOT_DIR, CurrentPin.ToString (&amp;quot;D&amp;quot;)), state.ToString (&amp;quot;D&amp;quot;));
		return true;
	}
	catch (Exception ex)
	{
		Console.WriteLine (&amp;quot;Failed to WriteToPin: &amp;quot; + CurrentPin.ToString (&amp;quot;D&amp;quot;) + &amp;quot; &amp;quot; + ex.Message + &amp;quot;\n&amp;quot; + ex.StackTrace);
	}
	return false;
}

As you can see the WriteToPin call is essentially creating a File handle using the Fire.WriteAllText helper and first setting the Direction in the ‘direction’ stream.

Next writing the actual value  (0 or 1) to the ‘value/[pin]’ stream.

Similarly if you are reading from the GPIOPin, after you have selected the pin you use the ReadFromPin API.

public GPIOPinState ReadFromPin (GPIOId pin)
{
	GPIOPinState currentState = GPIOPinState.Unknown;
	try
	{
		string state = File.ReadAllText (String.Format (&amp;quot;{0}gpio{1}/value&amp;quot;, GPIO_ROOT_DIR, pin.ToString (&amp;quot;D&amp;quot;)));
		currentState = (state == &amp;quot;1&amp;quot; ? GPIOPinState.High : GPIOPinState.Low);			
	}
	catch (Exception ex)
	{
		Console.WriteLine (&amp;quot;Failed to ReadFromPin: &amp;quot; + pin.ToString (&amp;quot;D&amp;quot;) + &amp;quot; &amp;quot; + ex.Message + &amp;quot;\n&amp;quot; + ex.StackTrace);
	}
	return currentState;
}

ReadFromPin API again uses the File handle at the ‘value/[pin]’ stream and reads the value, that is either “0” or “1” and returns the appropriate GPIOPinState value.

Once Read/Write operation is done you have to Release the pin by calling the ReleasePin API, that needs the GPIOId of the pin you want to release. There is a helper method that Releases the CurrentPin selected.

public bool ReleasePin (GPIOId pin)
{
	try
	{
		File.WriteAllText (GPIO_ROOT_DIR + &amp;quot;unexport&amp;quot;, pin.ToString (&amp;quot;D&amp;quot;));
		_busyPins [pin] = false;
		CurrentPin = GPIOId.GPIOUnknown;
		return true;
	}
	catch (Exception ex)
	{
		Console.WriteLine (&amp;quot;Failed to ReleasePin: &amp;quot; + pin.ToString (&amp;quot;D&amp;quot;) + &amp;quot; &amp;quot; + ex.Message + &amp;quot;\n&amp;quot; + ex.StackTrace);
	}
	return false;
}
public bool ReleasePin ()
{
	return ReleasePin (CurrentPin);
}

That completes our GPIOManager API. Lets write a sample to use it.

A Sample Console Application

I added a simple console project to the mix and wrote the following in the Program.cs’ main function.

All it does is sends a Low on GPIO pin 17 and 22 and waits for a ‘return’ on the console. Once you hit return it cleans up by releasing the pins and exits.

namespace GpioCs
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			try
			{
				GPIOManager gpioManager = new GPIOManager();
				gpioManager.SelectPin(GPIOId.GPIO17);
				gpioManager.WriteToPin(GPIOPinState.Low);
				Console.ReadLine();
				GPIOPinState state = gpioManager.ReadFromPin(gpioManager.CurrentPin);
				Console.WriteLine(&amp;quot;Current Pin 17: &amp;quot; + state);

				gpioManager.SelectPin(GPIOId.GPIO22);
				gpioManager.WriteToPin(GPIOPinState.Low);
				Console.ReadLine();
				GPIOPinState state22 = gpioManager.ReadFromPin(gpioManager.CurrentPin);
				Console.WriteLine(&amp;quot;Current Pin 22: &amp;quot; + state22);


				Console.WriteLine(&amp;quot;Press enter to close!&amp;quot;);
				Console.ReadLine();
				gpioManager.ReleasePin(GPIOId.GPIO17);
				gpioManager.ReleasePin(GPIOId.GPIO22);
				Console.WriteLine (&amp;quot;Completed without errors&amp;quot;);
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
			}
		}
	}
}

In my case this flips on the first and second relays. So even if you don’t have anything connected to the relays you’ll hear them ‘click’ on and off. The LED indicator on the board for each relay will glow as well.

Conclusion

With this simple code we have opened up a plethora of opportunities for us. Next step would be to bundle the code inside a service and then respond to web requests. My idea is to make the service a SignalR client that will connect to a CnC server on the Web/Cloud. The CnC server will have a Web interface allowing you to switch each relay on or off. Now once you connect the relays to appropriate electrical devices you are good to control those devices from the web.

Code on Github.

Tagged , ,

Nokia X: The illegitimate lovechild of AOSP and MS Services

So Nokia finally released the Nokia X series of Android phones, and at MWC no less. First up I have to own up that Ben Thompson was right about Nokia’s Android intentions, and I was wrong. Though I still believe the deal does make sense from MS’ perspective. Without Lumia brand WP is dead in the water. Whether MS should abandon Windows Phone is different topic (and if you must ask, I would say NO).

After my initial indignation was over I have come to conclusion that X is pretty much the lever that Nokia used to sell its Windows Phone business to Microsoft. If we trace the timeline of when Nokia may have started working on X (Android Jellybean code base), we’ll see that having jumped off the burning platform Nokia found itself entangled in the Windows Phone parachute and the rescue boats (WP updates) were taking way too long to come by for it to stay afloat. It thus started project X as a life boat (I speculate it was a code name to start with, fact that it is still called the same shows the bastardized nature of the project, they didn’t bother with a marketing name) till the end. But building a lifeboat when you are in water already seems rather stupid and yet we have Nokia X series now 😐.

Android Open Source Project (AOSP) is the publicly available kernel + services that form the core of Android OS. This is free and Nokia X builds on top of it. Most Android devices however bundle GMS or Google Mobile Services that device manufacturers have to pay to use and get permission from Google. You can read up why GMS is the heart of Android ecosystem in Peter Bright’s write up at ARS Technica.

Why launch it after it has served its purpose?

This was the question that made me most angry. I am fine with the lever, everyone does it (Motorola had threatened to sue other Android OEMs on patent issues before Google bought it for a whopping load of money). Only a few reasons come to mind so my rant begins here:

A desperate stab at leveraging the success of Android

Given that they had spent considerable effort with the phone before MS began acquisition negotiations, Nokia was desperate to achieve success on its own in a vain attempt to prove (to itself?) that it still had the chops for runaway hits. This seems a little childish and vain to me and launching it at MWC seems a little over the top, there has to be a better reason. But then, spare a thought for the team working on the project. For them release is a kind of closure. As a dev I certainly understand that.

Also the Symbian based Pureview launch happened after the WP deal was struck, probably because the project was initiated earlier and had to reach a closure. Though I see the point of the hardware (41MP camera) release and its subsequent adoption into 1020, but I see no such path for project X.

Kick Microsoft in the balls to get ‘Engineering brownie points’ post-merger

Microsoft has dug itself into a hole with the separate paths for Windows RT and Windows Phone 8. While it is still plugging away at Windows Phone 8.1, Nokia took project X to completion to show off its engineering prowess that might come in handy post-merger when there will be two system engineering teams who between them have developed at least a dozen OSes. That would explain the old Android code base, as in, once the project was released, it would have served its purpose. But the confidence of building a complete ecosystem experience would have stayed on.

Clean slate reboot and future ambitions

Nokia may not have the Asha and Lumia names post-merger, but remember Vertu, high end Nokia phones that went Android? Project X could be easily re-released as a new line sans Nokia/Lumia/Asha brand name. This would add to reasons for the high profile launch which could be leveraged later. The X+ and XL models hint at these ambitions.

Whatever their reason it was a tacit acknowledgement of a few telling things:

  1. MS’ Windows Phone adventure is horribly off track.
  2. MS’ WP ecosystem is ‘different’ enough to put it in ‘good to have’ category and not consider it for launch of a new Application/Service/Startup. In other words, might as well have Android sans Google Mobile Services so that one can coax devs into recompiling (against MS services), instead of hoping that dev will eventually build a WP version. Can’t fault Nokia for feeling that way, given the hard time Instagram gave it before launching a half assed WP version of their app.
  3. MS’ WP developer ecosystem is not growing as expected. This is tied to number 2 above. WP is a third choice at best for app developers. The dedicated hoard of WP dev are jaded from the WP7 to WP8 experience where they had to nearly do everything from scratch. There is a healthy dose of skepticism around what WP 8.1 will bring amongst outsiders like me. However 8.1 technically is MS’ third major WP release and MS is ‘famous’ for getting it right the third time (at a minimum). So there are high hopes.

Microsoft supported outside attempt to gain quick traction in name of Android

This is the scariest of all thoughts. If this was paid for by MS then it shows a serious lack of commitment or confusion or both on MS’ part with respect to their own WP platform. If that happens to be the case, MS is in way bigger trouble than it cares to think about and will definitely face Dev community revolt when this happens. I am scared to think or write about it anymore.

It is not meant to be a vehicle for MS services.

Unlike what’s claimed by many, project X isn’t meant to bring hordes of users to Microsoft services. Given that Lumia low end platform performs better than X based devices, why would anyone buy this Frankenstein device? Why not just buy into MS ecosystem directly? People who buy Android make a conscious choice most of the time. Ignore the knowledge and ability of your customers at your own peril. A dual SIM option doesn’t automatically open doors for a half assed device experience. If anything, Android’s association with Google is well known enough and not having Google will be a constant source of negative word-of-the mouth publicity.

The services part was probably the last piece that Nokia attempted and MS services served two purposes,

  1. Placate MS, who I am sure is hopping mad at the release inspite of putting forth a brave face at the moment
  2. MS services provide a near perfect feature replacement for Google services and were easy to integrate rather than build from scratch.

Future of Windows Phone?

Initially I felt this marked the beginning of the end for Windows phone OS. If MS keeps this project alive this will be true. However, I now see WP moving to a respectable third position by solidly replacing BlackBerry. In other words WP is set to become the Linux of the desktop world. Meaning that it will be a solid, dependable platform restricted to a niche user base of enthusiasts and business users most of whom carry two phones, the other one being an Android or iPhone.

Android meanwhile is equivalent to Windows of the desktop world. It has reached a level of ubiquity in terms of a mobile platform. However, the name itself is supposed to sell the device is a rather naïve thought process given that there is going to be a boatload of competition offering the ‘real’ Android as opposed to AOSP based device. So end users when faced with the choice are likely to opt for the ‘real’ thing. (Treating your users as a bunch of n00bs is a bad idea). Microsoft has every reason to kill project X post-merger, and I hope it does and at the same time I hope it also addresses the concerns that led to project X in the first place.

Juicing up a dated MacBook Pro

It’s fair to say, my MBP is dated and well past it’s prime. It’s a Mid 2009 13” Core 2 Duo that I purchased new in Jan 2010. It was my very first personal laptop and has worked flawlessly for the last 3 years. I’ve taken good care and given it three updates (before this week), Memory Upgrade from 4 Gig to 8 Gig, HDD Upgrade from the default 270 (or so) Gig to a 1 TB Western Digital Caviar Blue. The third upgrade was from OSX Snow Leopard to OSX Lion.

This week I gave it another upgrade, added an SSD in the CD Drive slot. The components involved were

IMG_4133

I had initially zeroed in on the Samsung EVO 250 Gigs drive, but ultimately settled for the Kingston which I’ve (a good) experience with.

Swapping the Parts

Step 1: Flip your MacBook Pro and unscrew the 10 or so screws. Start from the top right corner and go anti-clockwise, the first three screws will be the longer than the rest.

Step 2: Before we remove the Optical drive we have to unhook two flat cables. First one connects the optical drive to the MoBo and the second one connects the HDD to the MoBo. Use a plastic spludger or your nails to gently lift them up as shown below.

IMG_4134

Step 3: There are three screws that hold it in place, and there is a connector cable to the motherboard that we have to remove. The first screw is under the cable towards the center of the system. You have to push the cable up, to reveal the screw.

IMG_4135

Step 4: The next screw is on the Top Left corner of the system and easily accessible

IMG_4136

Step 5: The Final screw is near the middle on the Left hand edge, again easily accessible

IMG_4137

Step 6: Next lift up the Optical drive from the bottom left corner gently. It will come up only about a centimeter then pull it towards yourself. If you encounter resistance bend the battery sticker and the straighten the HDD flat cable, they are stiffer than they look.

IMG_4138

Step 7: Once you have extracted the Optical Drive there is a hook attachment that you need to unscrew and screw it back to the HDD caddy.

IMG_4139

Step 8: The flat cable that we removed from the Motherboard earlier goes into the Optical drive via another adapter. Gently pull it out as well, after you have put in your new HDD into the HDD caddy, you can put this adapter back into the HDD Caddy.

IMG_4140

Step 9: Once you have snapped the HDD into the caddy, flip the caddy over and put in two screws (the Caddy came with a bunch of screws, pick the right size)

IMG_4141

Step 10: Here on it’s the inverse process of Step 6 and go back carefully, till your MacBook is bolted up.

Notes and Caveats

You are probably wondering why I put the new SSD into the HDD caddy instead of the Hard Drive bay because OSX can’t boot off a drive in the Optical Drive bay.

Well, I use Windows 8.1 via VMWare Fusion more often than I use the native OSX, and running the VMs off the same drive as the OS was really stretching it. OSX would literally be rendered useless when the VMs was running. I moved the VM to an external USB drive, that improved things but had it’s own set of issues with the VMs crashing after going into Sleep mode and so on.

I want the SSD to be where my VMs are run off. After the installation, OSX is slightly more useful with the Win8.1 VM running and the Win8.1 VM simply screams. It is almost as fast as Windows on SSD natively. I moved the VMWareFusion.app to the SSD as well.

Enabling TRIM

Sometimes we just hate OSX for being a ‘*****’. The case here being TRIM support for Apple installed SSDs only. YES! OSX Lion supports TRIM but only for Apple installed SSDs not third party SSDs. After you have ‘Initialized’ your drive using Disk Utility tool, get yourself Chameleon SSD Optimizer or some other similar third party product and enable TRIM on your SSD without fail. YMMV so use it at your own risk. The Disk Utility Tool will pop up and ask you to Initialize the disk first time you boot up and it detects the SSD.

Conclusion

Things are going well so far. Near native Windows performance and OSX can be used in parallel. Most people do the opposite by putting the OS on the SSD and moving everything else off it. In my case I don’t need OSX to run any faster than it is at the moment. I needed a stable and better performing Windows VM. I got that. This is a strictly temporary situation until I get my Haswell computer together and the SSD might be repurposed there, but that story is for later.

P.S. Amazon decided that I could wait for the Optical Drive enclosure so it has scheduled it for delivery in December Surprised smile. Till then the Optical Drive is wrapped away in bubble wrap. Once the drive enclosure arrives I’ll be able to use the Optical Drive as an external USB drive.

Tagged , ,

Windows RT, Surface and Courier – What could have been

image

Today’s announcement of Nokia Lumia 2520 made me happy briefly before I realized the inevitability – Microsoft has bought Nokia’s Lumia brand so once the acquisition goes through, either the Surface RT or the Lumia tablet would be canned. As a Surface RT owner and admirer of the Lumia brand it’s not a good scenario, but that’s not what this post is about, the thought of one of the products getting canned rekindled memories of the Courier. Microsoft’s parallel tablet OS experiment that lost out to Windows 8.

If you have never heard of the The Courier, you can see the concept here and read how it didn’t make it.

As you can see, it was an ‘innovative’ idea. But it lost out to Windows 8. At the time I didn’t know about Windows RT and was in general bought into the idea of continuing with the Windows lineage. But then months later, Microsoft Announced Windows RT and the Surface RT.

When Surface RT launched there was an OUTCRY from the tech bloggers as to it was ‘confusing’ because it was Windows that didn’t work with ‘old’ Windows apps. I am pretty sure these are all Apple/Google fanbois who use a Mac or Chromebook (pun intended) for their day to day work!. I bought an RT fully knowing what it is not and I am sure the ‘very few’ people who bought it, knew what they were doing.

But knowing what I knew, I was still surprised how much Windows baggage Windows RT contained and probably the biggest drawback was battery life. Jeff Atwood (of StackExchange fame) had a scathing take on it a few days back and I wrote about it myself in my Surface RT reviews. Much as we would have liked it Windows RT wasn’t a reboot but a re-compile with unnecessary pieces weeded out! But 18 years of an OS shows and it takes much longer to ‘weed out’ un-necessary gremlins. Would a fresh/ground up Courier OS for ARM tablets have been better? I am not saying Windows RT is not touch friendly, but it’s definitely not battery friendly and neither is it flying off the shelves after being bracketed as an iPad wannabe!!!

So after looking at Nokia’s apps for Photos etc. and thinking about the past few days of blogosphere I was thinking what if Surface RT was the Courier and Windows RT was Courier OS? Surface Pro could have been the productivity tablet, while Courier was the entertainment oriented branding! I am not even saying it should have been a split screen form-factor, a clean start, a different branding, hit battery life and some of the Courier features of course!!! Vendors could have used the Windows Phone 8 ecosystem to launch Tablets while the Courier would have been MS’ niche product.

Well, one can dream!!!

Tagged , ,
Follow

Get every new post delivered to your Inbox.

Join 1,408 other followers

%d bloggers like this: