.net, Making, Raspberry Pi 3

Programming the Adafruit PWM/Servo Hat for Raspberry Pi in C# to power several servos

This will be a fairly short post, and it’ll continue with the theme of using servos with the Raspberry Pi 3. Previously I’ve been trying to drive a single small servo from my Raspberry Pi – it has been powerful enough to drive this, but if I was to add more than one servo, I’d expect to see odd behaviour, such as brown-outs.

The solution to this is to use a servo driver for the Raspberry Pi, on a kind of shield known as a “Hat” (which is an abbreviation for “Hardware Attached on Top“).

I chose to use the Adafruit servo driver. This connects to the GPIO pins, and provides an alternative set of output pins and sockets. It’s also driven by its own power supply, which is strong enough to power a number of servos.

My servo hat arrived in parts which needed to be soldered together.

WP_20160514_16_18_14_Pro

Adafruit supply a helpful C# solution to get you up and running – this includes a sample project, and a library to assist with PWM control. Interestingly, Adafruit use a frequency of 60Hz in their servo sample (rather than what I thought was the more usual 50Hz).

After soldering the parts to the board, I secured it to the Raspberry Pi 3, and connected four 9g Tower Pro servos.

WP_20160517_22_10_21_Pro

After that, I connected it to my PC by USB, my router by a CAT-5 cable, and finally I connected an external 6v power supply to the Servo Hat.

I had to remember to change my Raspberry Pi 3’s settings – I had previously configured the Default Controller Driver in the web interface Devices tab to be the Direct Memory Mapped Driver, but for this hat to work I needed to convert it back to the standard Inbox Driver.

screenshot.1462663123

I wanted to connect 4 servos to the servo hat, so my code looked like the code below. This causes 4 servos to wipe from side to side for 10 seconds, with a delay of 1 second between wipes:

using (var hat = new Adafruit.Pwm.PwmController())
{
    DateTime timeout = DateTime.Now.AddSeconds(10);
    hat.SetDesiredFrequency(60);
    while (timeout >= DateTime.Now)
    {
        hat.SetPulseParameters(0, 290false);
        hat.SetPulseParameters(1290false);
        hat.SetPulseParameters(2, 290false);
        hat.SetPulseParameters(3290false);
 
        Task.Delay(TimeSpan.FromSeconds(1)).Wait();
 
        hat.SetPulseParameters(3530false);
        hat.SetPulseParameters(2530false);
        hat.SetPulseParameters(1530false);
        hat.SetPulseParameters(0530false);
 
        Task.Delay(TimeSpan.FromSeconds(1)).Wait();
    }
}

That’s it – I had expected it to be more complex, but I literally cloned the code from here, compiled it and deployed it to my Pi 3, and it just worked.

Next time, I’m going to blog with Part 5 of my series about building a robotic hand – I now have the ability to control 4 servos using C#, so hopefully I’ll be able to get 4 fingers on the hand working.

.net, Clean Code, Making, Raspberry Pi 3

A servo library in C# for Raspberry Pi – Part #3: Implementing the interface

Last time, I developed an interface that would allow me to control a servo directly from my Raspberry Pi 3 which is hosting Windows 10 IoT Core. In this post, I’ll describe an implementation of this interface. The code will a cleaner implementation of the code I got working in Part #1 of the series.

Let’s look at the interface I described last time:

public interface IServoController : IDisposable
{
    int Frequency { get; set; }
 
    double MaximumDutyCycle { get; set; }
 
    double MinimumDutyCycle { get; set; }
 
    int ServoPin { get; set; }
 
    Task Connect();
 
    void Go();
 
    IServoController SetPosition(int degree);
 
    IServoController AllowTimeToMove(int pauseInMs);
}

Implementing the interface

The code implementation is quite straightforward – I needed to specify the control pin for the servo, and to check that the Lightning provider is being used – so I put these items in the constructor.

public ServoController(int servoPin)
{
    if (LightningProvider.IsLightningEnabled)
    {
        LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
    }
 
    ServoPin = servoPin;
}

When I set the position of the servo, I have to calculate what duty cycle is necessary to move the servo’s wiper to that position. This is a very simple calculation, given that we know the duty cycles necessary to move to the minimum (0 degree) and maximum (180 degree) positions. The difference between the two extreme duty cycle values divided by 180 is the incremental value corresponding to 1 degree of servo movement. Therefore, we just multiply this increment by the number of degrees we want to move from the starting position, add the minimum duty cycle value, and this gives us the duty cycle corresponding to the servo position we want.

public IServoController SetPosition(int degree)
{
    ServoGpioPin?.Stop();
 
    // For example:
    // minimum duty cycle = 0.03 (0.6ms pulse in a period of 20ms) = 0 degrees
    // maximum duty cycle = 0.12 (2.4ms pulse in a period of 20ms) = 180 degrees
    // degree is between 0 and 180
    // => 0.0005 per degree [(0.12 - 0.03) / 180]
 
    var pulseWidthPerDegree = (MaximumDutyCycle - MinimumDutyCycle) / 180;
 
    var dutyCycle = MinimumDutyCycle + pulseWidthPerDegree * degree;
    ServoGpioPin.SetActiveDutyCyclePercentage(dutyCycle);
 
    return this;
}

The full code for the class is below – it’s also available here.

public class ServoController : IServoController
{
    public ServoController(int servoPin)
    {
        if (LightningProvider.IsLightningEnabled)
        {
            LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
        }
 
        ServoPin = servoPin;
    }
 
    public int Frequency { getset; } = 50;
 
    public double MaximumDutyCycle { getset; } = 0.1;
 
    public double MinimumDutyCycle { getset; } = 0.05;
 
    public int ServoPin { getset; }
 
    public int SignalDuration { getset; }
 
    private PwmPin ServoGpioPin { getset; }
 
    public async Task Connect()
    {
        var pwmControllers = await PwmController.GetControllersAsync(LightningPwmProvider.GetPwmProvider());
 
        if (pwmControllers != null)
        {
            // use the on-device controller
            var pwmController = pwmControllers[1];
 
            // Set the frequency, defaulted to 50Hz
            pwmController.SetDesiredFrequency(Frequency);
 
            ServoGpioPin = pwmController.OpenPin(ServoPin);
        }
    }
 
    public void Dispose()
    {
        ServoGpioPin?.Stop();
    }
 
    public void Go()
    {
        ServoGpioPin.Start();
        Task.Delay(SignalDuration).Wait();
        ServoGpioPin.Stop();
    }
 
    public IServoController SetPosition(int degree)
    {
        ServoGpioPin?.Stop();
 
        // For example:
        // minimum duty cycle = 0.03 (0.6ms pulse in a period of 20ms) = 0 degrees
        // maximum duty cycle = 0.12 (2.4ms pulse in a period of 20ms) = 180 degrees
        // degree is between 0 and 180
        // => 0.0005 per degree [(0.12 - 0.03) / 180]
 
        var pulseWidthPerDegree = (MaximumDutyCycle - MinimumDutyCycle) / 180;
 
        var dutyCycle = MinimumDutyCycle + pulseWidthPerDegree * degree;
        ServoGpioPin.SetActiveDutyCyclePercentage(dutyCycle);
 
        return this;
    }
 
    public IServoController AllowTimeToMove(int pauseInMs)
    {
        this.SignalDuration = pauseInMs;
 
        return this;
    }
}

Using this code

There are three key things to remember:

  1. Enable the Microsoft Lightning Provider’s “Direct Memory Mapped Driver” through the Pi’s web interface – described under the “Runtime Requirements” heading at the URL: https://developer.microsoft.com/en-us/windows/iot/win10/LightningProviders.htm
  2. In your Windows UWP project, change your package.appxmanifest to enable the necessary capabilities. Change the Package root node to include the xmlns.iot namespace, and add “iot” to the Ignorable Namespaces, i.e.
    <Package
        xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
        xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
        xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
        xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
             IgnorableNamespaces="uap mp iot">

    b. Add the iot:Capability and DeviceCapability to the capabilities node, i.e.

    <Capabilities>
        <iot:Capability Name="lowLevelDevices" />
        <DeviceCapability Name="109b86ad-f53d-4b76-aa5f-821e2ddf2141" />
    </Capabilities>
  3. In your Windows UWP project:
    • Open the Reference Manager (to open the reference manager, right click on your project’s references and select “Add reference…”);
    • Expand “Universal Windows”;
    • Select “Extensions”;
    • Enable the “Windows IoT Extensions for the UWP”;
    • Click “OK”.

I’ve packaged the code into a NuGet package which is available here. I’ve also included a ReadMe for this library here.

So assuming that you’ve connected your servo’s control line to Pin GPIO 5 (pin 29 on the Pi 3) – then you can call a method like the one below to move to the 90 degree position:

private async void MoveServoToCentre()
{
    using (var servo = new ServoController(5))
    {
        await servo.Connect();
 
        servo.SetPosition(90).AllowTimeToMove(1000).Go();
    }
}

Conclusion

So that’s it for this series – obviously this is still Alpha code and I’ve only tested it on my own 9g Tower Pro servo. But hopefully this code and implementation will provide some inspiration for other makers out there who are trying to get a servo working with a Raspberry Pi 3 and Windows 10 IoT Core.

In the future, I’m planning to use the Adafruit servo driver to control several servos at once – this wouldn’t be possible with just the Raspberry Pi as it’s not powerful enough to drive numerous devices like a servo. I’ll write about this soon.

 

.net, Clean Code, Making, nuget, Raspberry Pi 3, UWP

A servo library in C# for Raspberry Pi – Part #2: Designing the interface, IServoController

Last time I posted an article describing a proof of concept for how to control a servo using a Raspberry Pi 3. This time, I want to improve the code so it’s better than just a rough proof of concept – I’d prefer to write a re-usable library. So the first step of my design is to build an interface through which I can talk to the servo.

There were a few principles that I wanted to adhere to:
1. Make the interface fluent (where it was sensible to do so);
2. Make the interface as small as possible;
3. Add public properties so this could be used for servos which have slightly different profiles.

Finally, I wanted to implement the IDisposable interface – this would be useful to close any connections if that was necessary.

Connecting to the servo

There are a couple of things that need to be done when setting up the servo:
1. Specify the GPIO pin on the Raspberry Pi which is going to output a PWM signal;

int ServoPin { getset; }

2. Once we have specified the pin, we need to open a connection. I knew from my proof of concept code that this used asynchronous methods, so I needed the return type to be a Task (as asynchronous methods cannot return void in C#).

Task Connect();

Moving the servo wiper

The first and most obvious thing to tell a servo to do is move to a particular rotational position. This position would be most commonly measured in degrees.

However, one issue is that the source program has no means of knowing when the servo’s blade has reached position. In Arduino code, I’ve seen this handled by just putting a delay in after the instruction to move to a particular position.

I liked the idea of a chain of commands, which would tell the servo the position to move to, specify the amount of time allowed to move to this position, and then go.

// This moves to 45 degrees, allowing 500ms to reach that position
servo.SetPosition(45).AllowTimeToMove(500).Go();

So this ideal chain told me that I needed to have the methods:

void Go();
 
IServoController SetPosition(int degree);
 
IServoController AllowTimeToMove(int pauseInMs);

Altering frequency duty cycle properties

My research told me that servos usual expected duty cycles of 5% to 10% to sweep from 0 to 180 degrees. However, I also found some people who found these are idealised figures – in fact, with my own servos, I found that a better range of duty cycle went from 3% to 12%. So I realised that any servo controller probably needed to have public properties to set frequency, and minimum and maximum duty cycle values.

int Frequency { getset; }
 
double MaximumDutyCycle { getset; }
 
double MinimumDutyCycle { getset; }

The finished interface

So that described what I wanted my servo controller interface to look like – I’ve pasted the code for this below.

public interface IServoController : IDisposable
{
    int Frequency { getset; }
 
    double MaximumDutyCycle { getset; }
 
    double MinimumDutyCycle { getset; }
 
    int ServoPin { getset; }
 
    Task Connect();
 
    void Go();
 
    IServoController SetPosition(int degree);
 
    IServoController AllowTimeToMove(int pauseInMs);
}

Publishing the interface as a library

The final step I wanted to take was to publish this interface to NuGet. I decided to publish the interface in a separate package to the implementation, so that it would be easy to swap out the implementation if necessary.

Presently this interface is available here, and it can be downloaded from NuGet using the command:

Install-Package Magellanic.ServoController.Interfaces -Pre

It’s presently in an alpha (pre-release) status so the “-Pre” switch is needed for the moment.

Next time, I’ll write about how to implement this interface, and I’ll write a simple UWP app to test this.

.net, Making, Raspberry Pi 3, Visual Studio

A servo library in C# for Raspberry Pi 3 – Part #1, implementing PWM

Windows IoT Core is a young project – and whereas there are already a lot of good tutorials and examples on the internet, and there’s a lot more work to be done before the libraries available can compare with the work done by the Arduino community.

I’ve managed to make servo motors work in the past with Arduino – there’s already a servo project packaged with the Arduino development environment, and that just works out of the box. I was interested to see if I could do this in C# with the Raspberry Pi 3, and I couldn’t find any simple pre-existing code for this. Since I like an interesting technical challenge, I thought this would be a good problem to solve.

First – how do servos work?

A servo is more than just a simple motor which accepts a power supply and spins round – it’s possible to precisely control how much a servo turns. It’s able to do this because the servo is basically made up of a motor, a potentiometer, and a controller. A very simple explanation of how it works is:

  • The controller chip is given a signal – for example, turn the motor to the 90 degree position;
  • The motor’s output spindle is connected to a potentiometer – since the controller chip is able to measure the resitance between terminals of the potentiometer, therefore it’s able to infer the current position of the motor;
  • The controller only powers the motor until the resistance of the potentiometer matches the value it expects when the spindle is at the 90 degree position.

So this explains the mechanical operation of a servo – but what about the signal which is sent to the controller chip? How do we tell it to move to 0 degrees, 90 degrees, or 180 degrees?

It turns out there’s quite a simple answer to this – we send a series of pulses to the controller, which have different widths for different motor positions – this works like this:

  • The controller chip expects a series of digital pulses at a particular frequency;
  • The frequency describes how many pulses are sent per second – so for example, if the time between pulses starting needs to be 20ms, then we’d need to send 50 per second (50 cycles x 20ms = 1000ms).
    • There for the frequency is 50 pulses per second – also called 50Hz.
  • Each signal is made up of two logic states – logic 1 (5 volts) and logic 0 (0 volts);
    • The ratio of time in each cycle spent at logic 1 to the total length of the cycle is called the duty cycle.
    • For example, if the time between pulses starting is 20ms, and the pulse is 2ms at logic 1, then the duty cycle is 10% (2ms/20ms x 100%);

My research suggested that most servos expect pulses at a frequency of 50Hz. They will move to:

  • 0 degree position with a duty cycle of 5% (1ms of logic 1 in a 20ms pulse);
  • 180 degree position with a duty cycle of 10% (2ms of logic 1 in a 20ms pulse);

So my challenge was to find a way for the Raspberry Pi to generate a series of variable width pulses.

This technique of changing the width of pulses is is known as pulse width modulation (PWM).

This is easier said than done with the Raspberry Pi. Whereas the Arduino has several pins that output PWM signals, there are no pins in the Raspberry Pi that obviously output PWM.

Next – can I simulate PWM using C# code?

Well…I gave it a go. My theory was that I could set a pin to logic 1, and then wait for a certain number of milliseconds to pass before setting the pin back to logic zero.

I connected the three wires of the servo to my Raspberry Pi – the 5v wire to Pin 2, the ground wire to Pin 39, and the control wire went to Pin 29 (which was GPIO 5).

rp2_pinout

In order to develop a Windows app for the Raspberry Pi, I created a blank Windows UWP app, and added a reference to the Windows IoT Extensions.

screenshot.1462650773

I then added the code below to the MainPage.xaml.cs file.

This code didn’t work – I’m just including this as part of the path that I followed.

var gpioController = GpioController.GetDefault();
var gpioPin = gpioController.OpenPin(5);
gpioPin.SetDriveMode(GpioPinDriveMode.Output);
    
var _stopwatch = new Stopwatch();
_stopwatch.Start();
    
// number of system ticks in a single millisecond
var ticksPerMs = (ulong)(Stopwatch.Frequency) / 1000;
 
// length of pulse is 20ms (which equates to a frequency of 50Hz)
var pulseDuration = 20;
 
// let the pin sit at logic 1 until 2ms have passed
var logicOneDuration = 2;
 
while (true)
{
    var ticks = _stopwatch.ElapsedTicks;
 
    gpioPin.Write(GpioPinValue.High);
    
    while (true)
    {
        var timePassed = _stopwatch.ElapsedTicks - ticks;
 
        if ((ulong)(timePassed) >= logicOneDuration * ticksPerMs)
        {
            break;
        }
    }
    
    gpioPin.Write(GpioPinValue.Low);
    
    while (true)
    {
        var timePassed = _stopwatch.ElapsedTicks - ticks;
 
        if ((ulong)(timePassed) >= pulseDuration* ticksPerMs)
        {
            break;
        }
    }
}

This experiment wasn’t really successful – theoretically it was sound, but practically I don’t think this method of “bitbanging” is really good enough to give the accuracy necessary for a servo controller. I found this made the servo twitch, but not much else.

I tried a different way – rather than looping until a certain time passed, I thought I’d try blocking the thread for the a number of milliseconds after setting the GPIO pin to high or low…this didn’t really work either, giving more-or-less the same results as the original code (i.e. the servo twitched, but didn’t consistently move in the way I expected it to).

public MainPage()
{
    this.InitializeComponent();
 
    var gpioController = GpioController.GetDefault();
    var gpioPin = gpioController.OpenPin(5);
    gpioPin.SetDriveMode(GpioPinDriveMode.Output);
            
    while (true)
    {
        gpioPin.Write(GpioPinValue.High);
        Task.Delay(2).Wait();
        gpioPin.Write(GpioPinValue.Low);
        Task.Delay(18).Wait();
    }
}

I needed to find another way to generate PWM from a Raspberry Pi 3. Fortunately, Microsoft have provided a technology which solves this problem.

Using Microsoft Lightning Providers to generate PWM

Lightning is new software from Microsoft that implement some new functions, including SPI and PWM support. It’s pretty easy to enable this software – there’s few simple steps.

This learning process was helped by the set-up guide from Microsoft and from the blog post from Lee P. Richardson here.

Change the default controller driver

I opened the online administrative interface for the Pi at http://minwinpc:8080, and navigated to the Devices tab of this interface. This has a dropdown at the top of the page showing the “Default Controller Driver”, which was set to “Inbox Driver”. I opened this dropdown, and selected the second value which is “Direct Memory Mapped Driver”. Once I selected this, I clicked on the button titled “Update Driver”, and was prompted to reboot my Pi.

screenshot.1462663123

When I rebooted the Pi, I looked at the Devices tab of the interface again, and saw that my option was selected.

Download the lightning providers from Nuget

I right clicked on the Windows app project in VS2015, and selected “Manage Nuget Packages…”. This opened the Nuget package manager, and I searched for “Microsoft.IoT.Lightning”. This returned two packages:

  • Microsoft.IoT.Lightning (presently v1.0.4), and
  • Microsoft.IoT.Lightning.Providers (presently v1.0.0);

screenshot.1462663411

Change the package.appxmanifest file to add the new capabilities

I had to make a couple more changes to enable device capabilities. There were changes to the package.appxmanifest file. I needed to make these changes directly to the XML, so I right clicked on the file in VS2015, and selected “View Code”.

First, add the IOT property to the Package node, and add “iot” to the ignoreable namespaces.

<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" 
         xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" 
         xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" 
         xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10" 
         IgnorableNamespaces="uap mp iot">

Next, add the new iot and DeviceCapabilities.

  <Capabilities>
    <Capability Name="internetClient" />
    <iot:Capability Name="lowLevelDevices" />
    <DeviceCapability Name="109b86ad-f53d-4b76-aa5f-821e2ddf2141" />
  </Capabilities>

Add the PWM code for a servo

I found the code worked well – obviously this is proof of concept code, but I found it moved the servo from 0 degrees, to 90 degrees, and then to 180 degrees.

public MainPage()
{
    this.InitializeComponent();
 
    Servo();
}
        
private async void Servo()
{
    if (LightningProvider.IsLightningEnabled)
    {
        LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
    }
 
    var pwmControllers = await PwmController.GetControllersAsync(LightningPwmProvider.GetPwmProvider());
    if (pwmControllers != null)
    {
        // use the on-device controller
        var pwmController = pwmControllers[1];
 
        // Set the frequency, defaulted to 50Hz
        pwmController.SetDesiredFrequency(50);
 
        // Open pin 5 for pulse width modulation
        var servoGpioPin = pwmController.OpenPin(5);
 
        // Set the Duty Cycle - 0.05 will set the servo to its 0 degree position
        servoGpioPin.SetActiveDutyCyclePercentage(0.05);
 
        // Start PWN from pin 5, and give the servo a second to move to position
        servoGpioPin.Start();
        Task.Delay(1000).Wait();
        servoGpioPin.Stop();
 
        // Set the Duty Cycle - 0.1 will set the servo to its 180 degree position
        servoGpioPin.SetActiveDutyCyclePercentage(0.1);
 
        // Start PWN from pin 5, and give the servo a second to move to position
        servoGpioPin.Start();
        Task.Delay(1000).Wait();
        servoGpioPin.Stop();
    }
}

In the Part 2, I’ll design an interface for the servo library and refine the implementation code.

.net, Making, Raspberry Pi 3

How to see your Raspberry Pi’s display without an HDMI device

I’ve previously blogged about how to set up a Raspberry Pi 3 with the new Windows IoT Core system. One of the things I recommended was that you should connect your Pi to a display device via an HDMI connection.

I chose to use my TV set as the HDMI device – but it became a bit painful to use this after a while, and I’d much rather be able to use my Pi with my Windows 10 laptop as the monitor. Recently, I discovered a way that this is actually possible.

There’s a great guide here – but I’ll run through the steps I went through, and include a few screenshots to describe my experience.

Step 1 – Set up your Raspberry Pi with Windows IoT Core

I posted my experience of doing this here (both successes and failures!). As I wrote in the post, I think it’s necessary to have the Pi connected to a display device during the setup.

Take a note of your Pi’s name – the default is minwinpc, though if you’ve already set up your machine you might have changed this name.

Step 2 – Set up your Pi for remote access

This is a simple step – from your internal network, browse to your Pi’s dashboard through a browser at http://minwinpc:8080. You’ll see a screen like the one below (you might have to enter a username and password, the default is “Administrator” and “p@ssw0rd”):

screenshot.1462568585

In the menu on the left, there’s an item called “Remote” – click on this item to see a screen like the one below. Tick the box named “Enable Windows IoT Remote Server”.

screenshot.1462568635

Step 3 – Download and set up the Windows Store App

You can download the Windows Store App from here – presently this app is only available by a link, so you can’t search for it in the store, but if you click on the link here Windows will open the Store to allow you to download the IoT app.

screenshot.1462569511

Once you’ve downloaded this, open it on your Windows 10 device to see a screen like this:

screenshot.1462569576

You should be able to open the dropdown list of discovered devices, and select your Raspberry Pi. If the item isn’t listed, you can ping your device using a command prompt to get the IP address, and manually enter it into the lower text box.

screenshot.1462569623

Click the “Connect” button. The store app should show the usual Windows spinner, and after a few seconds, you should see a screen like the one below:

screenshot.1462570242

Your resolution might not be as high as the one below – this is 1280 x 800 – you can change the Pi’s resolution through the web administrative interface at http://minwinpc:8080, the supported resolutions are near the bottom of the Home page (see below).

screenshot.1462570443

Summary

You can use a Windows 10 Store app to use a device on your network act as a display for your Raspberry Pi – and this device can also act as a mouse, and a keyboard too. This is an amazingly useful utility if you’re doing Raspberry Pi development – I recommend you check it out.

.net, Making, Raspberry Pi 3

Windows 10 IoT and the Raspberry Pi 3 – installation, failure, and eventually success

The Raspberry Pi 3 was released recently (February 2016). I’ve worked a lot with different types of Arduino before, but I’ve never worked with the Pi, so I decided to buy one to experiment. Since I’ve started to become interested in Windows UWP apps recently, I was particularly keen to try the Raspberry Pi 3 with a Windows operating system.

Since purchasing my Raspberry Pi 3, I’ve followed instructions on how to install Windows 10 from online guides, and watched a few installation guides on YouTube – each time, the installation was reported as very straightforward. This wasn’t my experience (and judging from forums and newsgroups, I’m not alone) and I hate admitting defeat. That said, once I worked out a process, I found it easy to install Windows 10 onto the Pi 3 (and got WiFi working too). So I’ve written this post to include all the mistakes I made, as well as the things I learned. Expert Raspberry Pi users might look at some of the things I’ve done here and say they’re unnecessary – this might be correct, but rightly or wrongly these were the steps I followed to get to a working install.

Remember that I’m describing how to get started with the Pi 3 with Windows 10 IoT Core. Getting Windows 10 to work with the Raspberry Pi 2 could be a very different process – I don’t have a Pi 2 so I haven’t experimented. Additionally, the items I discuss here might not be relevant for setting up the Pi 3 with operating systems other than Windows.

Last things – apologies for the poor quality photos throughout this post – I couldn’t take screenshots from my TV set so had to photograph the relevant screens. This is one of my longest posts, and I think this points to how complex the end to end process was.

Getting started

As well as a Raspberry Pi 3, there are a few other things you need which usually aren’t included with the Pi:

You need a micro SD card to hold the operating system that the Pi 3 will run – and not just any old micro SD card

For Windows, only certain micro SD cards are “Microsoft Verified“. I don’t pretend to understand the underlying differences between brands, but my experiences were that:

  • a Kingston 64GB SDXC didn’t work for me,
  • a SanDisk 64GB SDXC didn’t work for me,
  • a SanDisk 16GB Ultra SDHC did work (which is Microsoft Verified), and
  • a SanDisk 8GB Ultra SDHC did work in certain circumstances (and this card is not Microsoft Verified).

Of course, I’m not saying that the first two cannot work – there might be a step that I’ve missed – it’s just that they didn’t work for me.

I’ll go into a bit more detail about my experiences with these cards later in the post.

For Windows 10 to run on the Pi 3, you must format your card as FAT32 – it won’t work if it’s formatted as NTFS, or exFAT.

The Pi 3’s bootloader only has support for reading from FAT filesystems.

There is an official “SDFormatter” application, which I found worked for none of my cards (and ultimately this application proved irrelevant – I was able to use the built in Windows disk formatter to make things work on the 8GB and 16GB cards).

There’s an application called guiformat which allows you to format a 64GB microSD card as FAT32 – however, I wasn’t able to get Windows 10 to run on the Pi 3 from a 64GB card, so this really is just background information.

You need a display device with an HDMI port (and obviously an HDMI cable to connect the display device and the Pi 3).

I think it’s practically impossible to install the Windows IoT OS without having some form of visual feedback.

I needed a USB Keyboard.

If you’re installing by downloading from the internet, you’ll need to enter your Windows Insider username and password – if you’re installing from an image flashed onto your microSD card, you’ll still need to configure your Pi 3’s language settings.

And life is a lot easier if you have a USB mouse as well.

For a Windows 10 IoT install, I needed to be able to directly connect my Pi to an ethernet port.

Theoretically I shouldn’t have needed this – the Pi 3 has WiFi for online installs, and if you flash the OS onto your microSD card, everything should be on there. But I found a hard-wired connection to be critical to getting to the end of the process. There were times when the installation process failed, and after only one change of connecting the ethernet cable between my router and Pi 3, the installation worked.

You’ll possibly need to be able to supply the board with 5v and at least 1.0A through a micro USB connection.

I’ve read a few reports online of people saying installations failed because the Pi 3 wasn’t getting enough power. I’m not sure I entirely buy this explanation – I was able to successfully set up a Pi 3 with power coming from a regular USB port – however, your mileage may vary.

Use either NOOBS Lite, or use the Windows IoT Dashboard to load the flash.ffu file onto your SD card.

I found these tools were most consistent in getting a positive result. The Windows IoT Core Image Helper did work for me sometimes, but there are reasons why I prefer the IoT Dashboard (which I’ll go into later).

Don’t waste your time trying to use the Windows 10 installation for the Raspberry Pi 2.

Raspberry Pi 2 installers for Windows don’t work on the Pi 3. If you flash the Pi 2 image onto a disk and use it in a Pi 3, you’ll not see the Pi’s onboard green light flash when the device boots up (signifying it hasn’t found anything it can start booting from). I know this because at one point, my installation attempts had failed so many times that I was desperate enough to try this.

You need patience

There’s going to be a bit of waiting, especially after starting your Pi 3 for the first time, so don’t give up too quickly. Later in the post, I’ll provide the timings that I measured.

The wrong way (don’t do this)

After I ordered my Raspberry Pi 3, I ordered a 64GB SDXC Kingston SD Card (bad start – unverified microSD card). I formatted it using a Windows 10 machine, all in one partition using the default exFAT format (another mistake – it needed to be FAT32).

I download the Windows Insider ISO for the Raspberry Pi 3, mounted the ISO on my machine and double clicked the MSI file. This created a file on my machine called flash.ffu in the location “C:\Program Files (x86)\Microsoft IoT\FFU\RaspberryPi2” (this was about the only thing during my first attempt that I got right).

I found that the tools for installing this flash.ffu onto the micro SD card weren’t on this ISO, so I downloaded the ISO for the Raspberry Pi 2, mounted and installed that, and this gave me the “Windows IoT Core Image Helper” application. I then re-ran the ISO for the Pi 3 to get the correct flash.ffu file (there’s a much easier tool for doing this – the Windows IoT Dashboard).

I then flashed the SD card using the “Windows IoT Core Image Helper” application, which happily reported success. I put this card into my Raspberry Pi 3, switched it on, and the usual Windows start up screen appeared. It stayed there. After waiting 30 minutes I decided that it probably wasn’t going to boot.

A better way

Later, I found that only certain micro SD cards are “Microsoft Verified” – my Kingston 64GB microSD card was not on this list.

I don’t pretend to understand why a Kingston SD card is different from a SanDisk SD card – but I decided to get try with a couple of SanDisk SD cards, an 8GB Ultra (not Microsoft Verified) and a 16 GB Ultra (apparently Microsoft Verified).

First I tried the SanDisk 16GB SDHC Ultra (Microsoft Verified) – successful

For this disk, I decided to try to use “NOOBS Lite” to install Windows. For anyone who doesn’t know what NOOBS is, this is a piece of software which you can download, unzip, and copy to the root of your micro SD card. Then you can insert this SD card into your Raspberry Pi 3, power it up, and see a selection of operating systems which are available for download and install.

The steps I followed were:
1. Format the 16GB disk as FAT32;
2. Connect the Raspberry Pi 3 to your router using a CAT5 cable;
3. Connect a USB keyboard and mouse to the Raspberry Pi 3 ;
4. Insert the SD card into the Raspberry Pi 3;
5. Connect the Raspberry Pi 3 to a display device using an HDMI cable;
6. Finally, connect it to power using a powered USB socket (ideally delivering 5v and 1A, or better).

Once powered on, the display shows a screen with the Raspberry Pi logo, and a window saying that the micro SD card is being re-partitioned.

initial screen

After this, it will show you a window with the operating systems that you can download – Windows 10 is one of these systems.

choose operating system

I selected Windows 10, entered my WiFi details, and hit “i” to install. This immediately started downloading the Windows 10 system, and I was quickly challenged for my Insider user id and password. Once I supplied these, I was able to select the version of the ISO that I wanted to install, and download that to my Pi 3.

choose insider build

During the installation, I got a warning message to say the speed of my card may not be fast enough. I got this warning for every micro SD card that I tried, even for ones that ultimately worked.

warning message about speed

I found that I needed to click Yes to continue quickly – if I left this dialog open for more than a few seconds, the process presented me with a critical error message and aborted the download and installation.

So after clicking yes on the warning dialog above, the Windows 10 OS downloaded to my system, and reported success.

os installed successfully message

Once I clicked ok, the Pi 3 rebooted, and the usual Windows screen appeared with a spinner.

After about 4 minutes 40 seconds, the device appeared in my Windows IoT Device Dashboard with an allocated IP address (although what was being displayed on my TV screen did not change at this point).

After 14 minutes, the screen showed a critical error – CRITICAL_PROCESS_DIED – and automatically rebooted.

After it rebooted, about 1 min 30 secs later, it appeared on my Windows IoT dashboard, and then after another 30 seconds, I was shown an image of a red Raspberry Pi briefly, followed by Windows 10 IoT Core for Pi 3 set up screen.

This took me through a fairly standard set up process before I finished with the default screen for Windows 10 on the Raspberry Pi 3.

Pi 3 screen from 16GB SanDisk

Next – the SanDisk 8GB SDHC Ultra (not Microsoft Verified) – successful

I tried following the above process for an 8GB SanDisk microSD card – formatted as FAT32, with NOOBS Lite copied to the root. However, when I selected the Windows 10 OS, I saw an error appear – 7765MB were needed, and only 7424MB were available. Therefore I would not be able to install Windows 10 onto an 8GB card using NOOBS Lite.

error message for SanDisk 8GB

However, I didn’t want to give up on this microSD card yet – I thought I could flash an offline version of Win10IoT onto it. However, the 8GB microSD card had been partitioned by NOOBS Lite already, and I needed to remove these partitions.

I found the easiest way to do this was to use DISKPART – this is a disk partitioning tool which ships with Windows. The steps I followed were:

  1. Open a command prompt as Administrator;
  2. I typed “diskpart” to start the DiskPart application;
  3. Listing the available disks with the command “list disk”;
  4. Selecting the disk I wanted to work with using “select disk 1”;
  5. Cleaning this disk using “clean” (sometimes this gives an error – just running “clean” again often removes the error);
  6. Make this a single primary partition using “create partition primary”;
  7. Finally activate this partition using “active”.

disk part

(This image above shows the process I followed while cleaning my 64GB card, but it’s an identical process for the 8GB microSD card).

At this point, the 8GB microSD card was ready to be formatted by Windows into a single partition using FAT32 (to get to the Windows format tool, right click on the microSD card’s entry in Windows Explorer, and choose the Format option, highlighted in a red box in the image below).

format menu

Next, I installed the Windows IoT Dashboard, and browsed to the Insider ISO version 14322 of Flash.ffu (you can get the most up to date versions here), and flashed this onto the 8GB disk. Remember to select “Custom” from the Device Type drop down and choose the Flash.ffu image file location.

screenshot.1462221497

The process above will probably change when the image for the Raspberry Pi 3 is promoted from the Windows Insider Program to General Release – bear in mind this article was written in early May 2016.

One reason I prefer to use the Windows IoT Dashboard is that the tool it uses for flashing the image onto the microSD card is signed with a verified publisher (see the photo below). This tool is called “DISM” – this stands for “Deployment Image Servicing and Management”.

signature screen

I’ve found that the alternative tool provided by Microsoft – the “Windows IoT Core Image Helper” also uses DISM, but this version is reported by Windows as unsigned.

unsigned DISM

I inserted the flashed microSD card into the Pi 3, booted it up, and after about 2 mins 30 seconds, the Pi 3 entered setup mode, challenging me to select the device language.

One interesting thing that I noticed was that about a minute after I booted the Pi 3, the device appeared on my IoT Dashboard’s list of devices.

windows iot dashboard

When you try to open the device using the Windows IoT dashboard, you’re challenged for a username and password. The Pi 3 instructions specify that these username/password credentials are Pi and Raspberry respectively – however, this doesn’t work for the Windows install. The default username and password are “Administrator” and “p@ssw0rd” – change these as soon as possible!

Does WiFi work?

I found that Windows 10 IoT does support the Pi 3 onboard WiFi chip – this is contrary to what a lot of people are reporting right now. However…it works on my machine.

As an update to this, I read on this forum that the WiFi works on Element 14 manufactured devices (which mine is) – not sure about other manufacturers.

I didn’t have to do anything special – whilst setting up the Raspberry Pi 3 device, I was invited to set up internet connectivity, and shown the screen below. “Kobol” is the name of my family’s wireless network (we’re big BSG fans).

wireless setup screen

I was able to configure the network, and it was visible on the default Dashboard. I’ve disconnected the hard wired connection from my Raspberry Pi 3 and highlighted it in the photo below – the wireless connection is showing up in the default dashboard on my TV set.

pi with wireless

I was able to confirm this worked wirelessly by deploying one of the sample applications from the Windows IoT Dashboard (internet radio).

Conclusion

After a lot of hassle, I was able to successfully install Windows 10 IoT core on two microSD Cards – both from SanDisk – for Raspberry Pi 3. There are a lot of opportunities to trip up in this process, and I’ve documented all the ones that tripped me up. I think the process of flashing an image onto FAT32 microSD card is the best way to install Windows 10 IoT Core, though using NOOBS Lite does work also. Finally, I’ve found that in version 14322, on-board WiFi is working for my device, which is manufactured by Element 14.


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net, Computer Vision, Making

How to read and create barcode images using C# and ZXing.NET

I’ve written a few posts recently on computer vision and optical character recognition. This time, I thought I’d write about a more traditional way of allowing computers to read printed information – barcode scanning.

I’ve run across a few instances in my career where applications have a need for this – for example, scanning stock inventory in and out of a warehouse. The traditional way of doing this would be to use a hardware barcode scanner connected to a computer.  These are basically the same technology as you’d see at your local supermarket – the scanner is pointed at the item’s barcode (usually a 1-D barcode), and when a valid barcode is detected, the textual representation of the code is piped to the computer’s cursor (often finishing with a newline character).

WP_20160402_20_05_41_Pro_LI

In the barcode scanner shown above, I didn’t need to install any software to my Windows 10 computer – not even a driver, or an SDK. Getting this to work was easy – open notepad, point the scanner at the barcode, squeeze the scanner’s trigger and the numeric representation of the barcode appears in notepad, with a newline character at the end.

What about reading and writing barcodes in C#?

A barcode scanner might not be always be suitable for our applications – you may already have a digital image, and want to know what this barcode represents in English text. Also, this scanner only reads 1-D barcodes, which hold a small amount of data. 2-D barcodes (sometimes known as QR codes) are now common, which can hold a lot more data.

There’s several .NET solutions available to allow us to read barcodes from an image- the one I’m going to look at today is ZXing.NET. This is a .NET port of a Java project, and it’s available on Nuget under the Apache 2 licence at a beta status.

Let’s look at some examples and code.

Reading Barcodes with ZXing.NET in C#

First thing is to import the ZXing.NET nuget package into your project.

Install-Package ZXing.Net 

Next, let’s get a barcode – I’ve uploaded a PNG of the QR barcode that I want to decode.

qrimage

We can use the code below to read from this image from my desktop:

static void Main(string[] args)
{
    // create a barcode reader instance
    var barcodeReader = new BarcodeReader();
 
    // create an in memory bitmap
    var barcodeBitmap = (Bitmap)Bitmap.FromFile(@"C:\Users\jeremy\Desktop\qrimage.bmp");
 
    // decode the barcode from the in memory bitmap
    var barcodeResult = barcodeReader.Decode(barcodeBitmap);
 
    // output results to console
    Console.WriteLine($"Decoded barcode text: {barcodeResult?.Text}");
    Console.WriteLine($"Barcode format: {barcodeResult?.BarcodeFormat}");
}

The output on the console shows that this barcode contains a link to my twitter feed, and correctly identifies the format as a QR code:

Decoded barcode text: https://twitter.com/jeremylindsayni
Barcode format: QR_CODE

There’s more about the different barcode formats here.

The code above isn’t an example of best practice – it’s simply just to show how to read a barcode.

Writing Barcodes with ZXing.NET in C#

Let’s suppose we want to programmatically generate a barcode in C# – it’s pretty easy to do this as well.

Say we want to generate a QR code of a link to my blog –

static void Main(string[] args)
{
    // instantiate a writer object
    var barcodeWriter = new BarcodeWriter();
 
    // set the barcode format
    barcodeWriter.Format = BarcodeFormat.QR_CODE;
 
    // write text and generate a 2-D barcode as a bitmap
    barcodeWriter
        .Write("https://jeremylindsayni.wordpress.com/")
        .Save(@"C:\Users\jeremy\Desktop\generated.bmp");
}

The output shown below:

generated

Conclusion

I hope this is helpful to anyone trying to read or generate barcodes – the code is pretty simple. As I mentioned above, ZXing.NET is licenced under the Apache 2 licence and is open sourced at Codeplex. One more thing that is worth mentioning is that at the time of writing, it’s still in beta and the present nuget package – version 0.14.0.1 – hasn’t been updated since April 2014.