Raspberry Pi 4 Model B with 4GB of RAM is really one very nice small device. In this blog post I will present how easy it is to use GPIO (general-purpose input/output) from .NET Core 3 and C# running on Ubuntu and Raspberry Pi4.
I will show how to use Raspberry Pi4 GPIOs from .NET Core on my simple “Siren Light” demo example. Basically, I have two LEDs (red and blue) and I will interchangeably power them on and off.
So, let’s start with “cables”!
Hardware & wiring
My breadboard wire-schema looks like this.
List of components:
- Raspberry Pi 4 Model B, 4GB of RAM,
- Breadboard,
- 2 x LEDs,
- 2 x 220 Ohm resistors,
- 3 wires.
All latest Raspberry Pi devices have a 40-pin GPIO header. It’s very versatile and very feature rich. I will not go into details, but you can find more about Raspberry Pi GPIO specification here: https://www.raspberrypi.org/documentation/usage/gpio
Software
From software perspective, my Pi is running Ubuntu 18.04 LTS with Desktop enabled. For my experimenting I like desktop version, because I like to be able to access GNOME desktop if needed. This is nice, at least for experimenting, but in any real-life (production) configuration I recommend Ubuntu Core or something lighter.
I installed .NET Core 3.1 runtime (installed via SDK) on my device. I simply follow instructions here: https://dotnet.microsoft.com/download/dotnet-core/thank-you/sdk-3.1.102-linux-arm64-binaries.
At the end, when everything is set up and running my device configuration is as follows:
For development, I installed Visual Studio Code on my Pi, but in general I prefer remote ssh access to my PI device. Visual Studio Code has awesome remote development user experience.
The code
As I said, for this demo I will use Visual Studio Code for development, but in general you can use also console with some Linux build in editor (e.g. nano). So let’s start.
I open my Visual Studio Code and connect to my Pi device via ssh, e.g.
Then, via VS Code Terminal, I create new .NET Core Console application and put some NuGet packages:
NuGet packages I used are:
Iot.Device.Bindings
andSystem.Device.Gpio
These two NuGet packages contain all the functionality for accessing GPIO. Anyway, my project now looks like this:
In general, talking to GPIO from C# is very simple. I create new instance of GpioController
, open pin and wrote value on it. For example, here is C# pseudo code:
1 2 3 4 5 |
var gpioController = new GpioController(); gpioController.OpenPin(<PinNumber>, <PinMode>); gpioController.Write(<PinNumber>, <PinValue>); |
and concrete example how to use GPIO pin 2:
1 2 3 4 5 |
var gpioController = new GpioController(); gpioController.OpenPin(2, PinMode.Output); gpioController.Write(2, PinValue.High); |
I extend my demo code by putting some extra magic and my code for my Siren Lights demo is here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
using System; using System.Device.Gpio; using System.Threading; using System.Threading.Tasks; namespace Jenx.SirenLights { class Program { // check pin ids: https://www.raspberrypi.org/documentation/usage/gpio/ private static int _gPioPinBlueLight = 17; private static int _gPioPinRedLight = 2; private static GpioController _controller; private static bool _run = true; public static void Main(string[] args) { _controller = new GpioController(); _controller.OpenPin(_gPioPinBlueLight, PinMode.Output); _controller.OpenPin(_gPioPinRedLight, PinMode.Output); Console.CancelKeyPress += new ConsoleCancelEventHandler(CancelKeyPressEvent); int powerOnRedLightInMilliSec = 2000; int powerOnBlueLightInMilliSec = 1000; while (_run) { _controller.Write(_gPioPinBlueLight, PinValue.Low); _controller.Write(_gPioPinRedLight, PinValue.High); Console.WriteLine($"BLUE OFF, RED ON for {powerOnRedLightInMilliSec} ms"); Thread.Sleep (powerOnRedLightInMilliSec); _controller.Write(_gPioPinBlueLight, PinValue.High); _controller.Write(_gPioPinRedLight, PinValue.Low); Console.WriteLine($"BLUE ON, RED OFF for {powerOnBlueLightInMilliSec} ms"); Thread.Sleep (powerOnBlueLightInMilliSec); } } private static void CancelKeyPressEvent(object sender, ConsoleCancelEventArgs e) { Console.WriteLine("Shutting down Siren Lights..."); _run=false; _controller.Write(_gPioPinBlueLight, PinValue.High); _controller.Write(_gPioPinRedLight, PinValue.High); } } } |
I start the app by dotnet run, but wait, I get IOException
.
For accessing my device’s hardware my app needs admin rights, so, sudo -s
command fixes this problem:
My “Siren Lights” app is up and running.
Conclusion
Raspberry Pi 4 is one awesome little beast. It’s much more powerful and useful then my old Pi2. And Pi4, Ubuntu and .NET Core just work fine together.
In this blog post I presented a simple example how to talk to Raspberry PI GPIO ports with .NET Core.
In the future blog post I will investigate some more advanced features and try to work with other sensors. Until then happy coding.
Cheers.
3 thoughts on “.NET Core, Ubuntu & Raspberry Pi GPIO”
I just have one question about your use of VS Code and Linux. How do you debug your project?
I have tried, but never got it to work properly
Checkout my blog post: https://www.jenx.si/2020/06/19/dot-net-core-remote-debugging-raspberry-pi/
Thank you for the share !