How to use Raspberry Pi GPIO pins with Ubuntu
This tutorial originally appeared on William Wilson’s (jawn-smith) blog and was contributed and modified here with permission.
As of Linux kernel 5.11, the old methods of communicating with header pins on the Raspberry Pi no longer work. This means packages such as RPi.GPIO no longer function properly with newer kernels. This post by Dave Jones (waveform) explains the reasons for the changes. But fear not, there is a new package in Ubuntu 21.04 called LGPIO that allows full control over the header pins with the latest kernel version. This tutorial covers some basic functionality of LGPIO, including examples using basic GPIO control, I²C, PWM, and SPI.
If you already have Ubuntu 21.04 or newer set up on a Raspberry Pi, you are ready for this tutorial. Otherwise, please see how to install Ubuntu Server on your Raspberry Pi and make it 21.04.
What you’ll learn
- How to install and get started with GPIO pins on Ubuntu
- Basic GPIO operations
- Basic I2C operations
- Basic PWM operations
What you’ll need
Optionally for the examples:
- A simple breadboard
- 7x 330ohm resistors
- A single red, green or blue LED
- 10 male jumper wires
- 20 female to male jumper wires
- An Arduino Uno
- 5V PWM fan
- A RGB LED
- A rotary encoder
- An MCP3008 analog to digital converter
2. Installing GPIO
Installing LGPIO is easy! Ensure that your software repositories are up to date with:
And install the Python LGPIO library with:
sudo apt install python3-lgpio
3. Basic GPIO example
The first example is the classic “blink an LED” example. The sample script uses GPIO pin 23 on the Raspberry Pi, so we’ll wire it up with a 330-ohm resistor according to the following diagram:
If wired correctly, the following script will turn the LED on and off for one second each until it receives a keyboard interrupt signal (Ctrl+C)
# Blink an LED with the LGPIO library # Uses lgpio library, compatible with kernel 5.11 # Author: William 'jawn-smith' Wilson import time import lgpio LED = 23 # open the gpio chip and set the LED pin as output h = lgpio.gpiochip_open(0) lgpio.gpio_claim_output(h, LED) try: while True: # Turn the GPIO pin on lgpio.gpio_write(h, LED, 1) time.sleep(1) # Turn the GPIO pin off lgpio.gpio_write(h, LED, 0) time.sleep(1) except KeyboardInterrupt: lgpio.gpio_write(h, LED, 0) lgpio.gpiochip_close(h)
The line h = lgpio.gpiochip_open(0) opens /dev/gpiochip0 . Then lgpio.gpio_claim_output(h, ) sets the pin as an output. The lgpio.gpio_write() function drives the GPIO pin to HIGH or LOW to turn the LED on or off.
4. I2C example
The I²C example I have created makes use of the Raspberry Pi as the leader and an Arduino Uno as the follower. It uses I²C to have the Arduino Uno blink its onboard LED. The I²C pins on the Raspberry Pi are GPIO 2 and 3. We wire the Pi and Arduino together as follows:
In order to have the Arduino act as an I²C follower, run the following sketch on it:
#include // use the built in LED const int ledPin = 13; void setup() < // Join I2C bus as follower Wire.begin(0x8); Wire.onReceive(receiveEvent); // Setup initial state for pin 13 pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); >void receiveEvent(int howMany) < while (Wire.available()) < char c = Wire.read(); digitalWrite(ledPin, c); >> void loop()
This sketch joins the I²C bus at address 8. To test that it is working properly, run i2cdetect -y 1 on your Raspberry Pi. The output should look something like this:
0 1 2 3 4 5 6 7 8 9 a b c d e f 00: 08 -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
If you see the 08 in the first row as above, the Arduino is awaiting instructions over I²C. If you are new to Arduino boards and are unfamiliar with how to compile and upload the sketch, click here for more information.
To have the Raspberry Pi send instructions to the Arduino over I²C, run the following Python script:
# Raspberry Pi Leader for Arduino Follower # Uses lgpio library, compatible with kernel 5.11 # Connects to Arduino via I2C and periodically blinks an LED # Author: William 'jawn-smith' Wilson import lgpio import time addr = 0x8 # bus address h = lgpio.i2c_open(1, addr) while True: try: lgpio.i2c_write_byte(h, 0x0) # switch it off time.sleep(1) lgpio.i2c_write_byte(h, 0x1) # switch it on time.sleep(1) except KeyboardInterrupt: lgpio.i2c_write_byte(h, 0x0) # switch it off lgpio.i2c_close(h) break
If run successfully, the built-in LED on the Arduino Uno will blink on and off for one second each. As you can see, the LGPIO code is as simple as lgpio.i2c_open(1, addr) to open the I²C device and lgpio.i2c_write_byte(, ) to send the data.
5. PWM example
For a PWM example I have a Noctua 5V PWM fan that can be controlled via the Raspberry Pi header pins. The fan can be directly powered by the Raspberry Pi 5V and GND pins. No resistor is needed for the PWM pin, which is GPIO 18 in the example script. The fan model I am using has an open-collector circuit design (as do most fans), so a 1kΩ pull-up resistor is needed. NOTE: The pull-up resistor must be connected to one of the 3.3V pins on the Raspberry Pi. If it is connected to a 5V pin, the Pi could be severely damaged. See the wiring diagram below as an example:
After connecting the fan and Raspberry Pi, run the following Python script to control the speed of the fan with PWM.
# Control a 5V PWM fan speed with the lgpio library # Uses lgpio library, compatible with kernel 5.11 # Author: William 'jawn-smith' Wilson import lgpio import time # Configuration FAN = 18 # pin used to drive PWM fan FREQ = 10000 h = lgpio.gpiochip_open(0) try: while True: # Turn the fan off lgpio.tx_pwm(h, FAN, FREQ, 0) time.sleep(10) # Turn the fan to medium speed lgpio.tx_pwm(h, FAN, FREQ, 50) time.sleep(10) # Turn the fan to max speed lgpio.tx_pwm(h, FAN, FREQ, 100) time.sleep(10) except KeyboardInterrupt: # Turn the fan to medium speed lgpio.tx_pwm(h, FAN, FREQ, 50) lgpio.gpiochip_close(h)
As you can see, the GPIO chip is opened the same way as in the basic GPIO example. Rather than just setting the GPIO to LOW/HIGH, we use the LGPIO library to set PWM transactions that control the speed of the fan. This example sets the speed to 0%, 50%, and 100% for 10 seconds each.
6. That’s all!
In Will’s original post the tutorial ended with a homework assignment where he challenges you to modify the PWM script to monitor the CPU temperature and set the speed of the fan accordingly. If you want to give it ago and see more information head over to his blog and read on.
Now you’re done and, hopefully, you’ve had a chance to play around with GPIO on Ubuntu on Raspberry Pi. If this tutorial helped you and you go on to make things using GPIO on Ubuntu on a Pi, whatever it may be, let us know. Either comment below on this tutorial or find your way over to the Raspberry Pi forum, we lurk over there too.
If you do end up building a project off the back of this tutorial and you would like to share it with the Ubuntu community as a blog post or even as a tutorial for this very site, reach out to a member of the Ubuntu Community team and we’ll get something going!
.NET Core, Ubuntu & Raspberry Pi GPIO
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.
- 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:
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: