In my previous post, I installed Ubuntu 16.04 onto a Raspberry Pi 3 and installed .NET Core 2 as well – finishing the post by creating and deploying a simple hello world application. This time, I’d like to investigate how to interact with the GPIO pins, first using the command line – and then using .NET Core 2.

Changing GPIO pin status

gpiopinsv2withpi

If I wanted to change the status of a pin (let’s say pin 26):

  • First I need to write “26” to a file named export at the location /sys/class/gpio
  • After this, a folder named gpio26 will be created at /sys/class/gpio/gpio26
  • This directory also has some files, including two named direction and value.
  • Since I want this pin to be an output, I write the text out to the file named direction.
  • Finally to switch the pin on, I write the text 1 to the file named value.

See here and here for more information.

So if I try to run the first step and echo “26” to /sys/class/gpio/export file, I’m denied permission – this is because I can only alter the GPIO status as root.

screenshot.1491343962

Instead, I can run this command within its own shell using:

sudo sh -c "echo 26 > /sys/class/gpio/export"

After running this, if I inspect the contents of the /sys/class/gpio folder, there is a new folder called gpio26.

screenshot.1491344603

And if I inspect the contents of gpio26, I can see a number of files, including ones named “direction” and “value“.

screenshot.1491344729

I can write different values to the “direction” and “value” files to set the direction of the pin and set whether it’s on or off.

# Set Pin 26 as an output pin
sudo sh -c "echo 'out' > /sys/class/gpio/gpio26/direction"

# Set Pin 26 to a status of 'High'
sudo sh -c "echo '1' > /sys/class/gpio/gpio26/value"

# Set Pin 26 to a status of 'Low'
sudo sh -c "echo '0' > /sys/class/gpio/gpio26/value"

# Remove access to GPIO 26
sudo sh -c "echo 26 > /sys/class/gpio/unexport"

Using .NET Core 2 to activate GPIO pins

Given we now know how to switch pins on and off, we can recreate this function in .NET. The code below shows three steps – open pin 26, specify the direction of the pin as out, and switch the pin on or off (depending on the argument passed in, which will be a 1 or 0).

using System;
using System.IO;
 
namespace GpioSwitch
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                throw new ArgumentNullException("You must specify a logic level for Pin 26");
            }
            else
            {
                if (args[0] != "1" && args[0] != "0")
                {
                    throw new ArgumentOutOfRangeException("Unknown logic level");
                }
            }
 
            // about to open pin 26 - test if it's already open
            if (!Directory.Exists("/sys/class/gpio/gpio26"))
            {
                Console.WriteLine("...about to open pin 26");
                File.WriteAllText("/sys/class/gpio/export", "26");
            }
            else
            {
                Console.WriteLine("...pin is already open");
            }
 
            Console.WriteLine("...specifying direction of Pin 26 as OUT");
            File.WriteAllText("/sys/class/gpio/gpio26/direction", "out");
 
            Console.WriteLine("...setting output level to " + args[0]);
            File.WriteAllText("/sys/class/gpio/gpio26/value", args[0]);
        }
    }
}

This is obviously not an example of clean code – it’s really just to clarify how to use .NET code to interact with the Ubuntu mechanism to control the GPIO pins.

I can compile this code in VS2017, and then from a command prompt I can run the command below to publish the code.

dotnet publish -r ubuntu.16.04-arm

This command publishes to the “\GpioSwitch\bin\Debug\netcoreapp2.0\ubuntu.16.04-arm\publish” directory. Now I can use pscp to move this compiled C# code to my Raspberry Pi 3 (as described in this post) – first I make a project directory on my Raspberry Pi 3 using the command below:

mkdir /home/ubuntu/GpioSwitch

Then I run the command below from the Windows machine that I build the GpioSwitch project on to move it from the Windows machine to the Raspberry Pi 3 (at 192.168.1.110).

pscp -r * ubuntu@192.168.1.110:/home/ubuntu/GpioSwitch

Once the project files are transferred to my Raspberry Pi 3, I change the permissions of the files in this directory to allow them to be executed as root using the command:

sudo chmod u+x,o+x *

Now I can run the command below to switch on an LED connected to Pin 26

sudo /home/ubuntu/GpioSwitch/GpioSwitch 1

WP_20170405_20_37_22_Pro

And I can run the command below to turn it off again.

 sudo /home/ubuntu/GpioSwitch/GpioSwitch 0

WP_20170405_20_37_54_Pro

Hopefully this is useful to anyone wondering how to control GPIO pins on the Pi 3 with .NET Core.