Friday, February 23, 2018

Windows IoT on Raspberry Pi - GPIO

Understanding which GPIO are available.

Reference Doc for this post: Windows IoT - Raspberry Pi I/O

The above link has the basic of what it takes to write an a program that uses GPIO. In my case I wanted to reverse engineer some simple add-on boards aka hats. A quick reminder that Windows IoT actually runs on multiple hardware platforms so there are some features that don't work on the Raspberry Pi. So even if you are using a completely different board than the Raspberry Pi this post will be helpful.

The code for this post will exist in the main class file and I don't want this to be a screenshot step by step how to, I'll cover some of the differences and why.

New "Background Application (IoT) - Visual C#". If this is a personal project always pick the latest for both Min and Max target version. If you were making a commercial product and had to support existing installations the Min version would be useful.

I'll provide the code as snippets inline and the full code sample at the end of this post.

The first piece to understand is that Windows IoT is a multitasking operating system and have your code do a classic for(;;){} loop would not be playing nice with other programs. With out the following lines of code, your program will run and when the steps are done, it will close. Adding these lines tell it to remain running and it will then continue to use event handlers to respond to events.

private BackgroundTaskDeferral deferral;

public void Run(IBackgroundTaskInstance taskInstance)
{
deferral = taskInstance.GetDeferral();
}

The next thing we need is to learn about the pins that we have available, unlike other platforms were everything is in the datasheet in this environment we can loop through the I/O and query it for attributes.
        private void GpioConfiguration()
        {
            gpio = GpioController.GetDefault();
            int[] pins = new int[30];

            for (int idx = 0; idx < 30; idx++)
            {
                pins[idx] = idx;
            }

            pins[28] = 35; // RPi2 Only
            pins[29] = 47; // RPi2 Only

            foreach (var p in pins)
            {
                GpioOpenStatus openStatus;
                List<GpioPinDriveMode> supported = new List<GpioPinDriveMode>();
                if (gpio.TryOpenPin(p, GpioSharingMode.SharedReadOnly, out pin, out openStatus))
                {
                    foreach (GpioPinDriveMode driveMode in Enum.GetValues(typeof(GpioPinDriveMode)))
                    {
                        // test driveMode for Pin Details
                        if (pin.IsDriveModeSupported(driveMode))
                        {
                            supported.Add(driveMode);
                        }
                    }
                }
                
                Debug.WriteLine("GPIO: {0} Status: {1}   Supported Drive Modes: {2}", p, openStatus, (supported.Count == 0)? "0" : string.Join(",", supported));
            }

        }


Adding a few class variable declarations (see full code at the bottom). Then calling this method right after our "GetDeferral();" code will give us the overview on the I/O pins by using the debugger to view the 'results' variable.

Not to spoil anything but the highlights are:

  • 0, 1 are PinUnavailable
  • 14,15 are PinUnavailable
  • All pins support the following drive modes
    • Input (Hi-Z)
    • Output
    • InputPullUp
    • InputPullDown
The Details: 
GPIO: 0 Status: PinUnavailable   Supported Drive Modes: 0
GPIO: 1 Status: PinUnavailable   Supported Drive Modes: 0
GPIO: 2 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 3 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 4 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 5 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 6 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 7 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 8 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 9 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 10 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 11 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 12 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 13 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 14 Status: PinUnavailable   Supported Drive Modes: 0
GPIO: 15 Status: PinUnavailable   Supported Drive Modes: 0
GPIO: 16 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 17 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 18 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 19 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 20 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 21 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 22 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 23 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 24 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 25 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 26 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 27 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 35 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown
GPIO: 47 Status: PinOpened   Supported Drive Modes: Input,Output,InputPullUp,InputPullDown

Other testing has shown the following pins not working as expected 4, 17, 19. At this time I'm not sure why, it could easily be a solder short or other damage to those pins on my RPi2.

Complete Source Code

No comments:

Post a Comment