-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new GPIO tutorials from Jonathan
- Loading branch information
Showing
23 changed files
with
1,722 additions
and
1 deletion.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,356 @@ | ||
--- | ||
title: Get Started with SplashKit GPIO | ||
description: General-purpose input/output, or GPIO, pins are a type of pin found on many microcontrollers that can be used for a variety of purposes. In this guide we use them to control the state of an LED | ||
category: Guides | ||
author: Jonathan Tynan | ||
lastupdated: Apr 27 2024 | ||
--- | ||
|
||
import { Tabs, TabItem } from "@astrojs/starlight/components"; | ||
|
||
**{frontmatter.description}** | ||
Written by: {frontmatter.author} | ||
_Last updated: {frontmatter.lastupdated}_ | ||
|
||
--- | ||
|
||
:::caution[Before you begin:] | ||
When working with Raspberry Pi GPIO pins, it's crucial to handle the | ||
setup and cleanup processes carefully. | ||
|
||
- Always ensure that the GPIO pins are properly initialised before use and cleaned up afterwards to | ||
prevent any damage to your Raspberry Pi | ||
- Be mindful of static electricity which can pose a serious risk to the sensitive electronic | ||
components on the board | ||
- Before touching the Raspberry Pi or any connected components, ground yourself to eliminate any | ||
static charge that may have accumulated. | ||
|
||
These precautions help to ensure your device is protected from potential harm caused by electrostatic | ||
discharges. | ||
::: | ||
|
||
General-purpose input/output, or GPIO, pins are a type of pin found on many microcontrollers that | ||
can be used for a variety of purposes. These pins can be used to receive signals from sensors, or | ||
send them to control LEDs or motors, and so much more. The ability to effectively use these | ||
interfaces enables a huge range of interesting projects with real-world impact. In this guide, | ||
we cover the basics of GPIO pins and how to use them in your projects. | ||
|
||
In a Raspberry Pi all pins are digital and individual GPIO pins are defined with two unique numbers, | ||
the physical pin number and the Broadcom SOC Channel (BCM) pin number. They can be found on the | ||
internet by searching for a "Raspberry Pi Pinout". In SplashKit, we use the physical pin numbers to | ||
reference the GPIO pins. | ||
|
||
:::tip[Digital Signals] | ||
As mentioned previously, the GPIO pins on a Raspberry Pi are all digital, this means that it can | ||
either be powered at a certain voltage or unpowered, which can then be read as a one or zero. In | ||
analog signals the voltage continuously varies, however this needs particular hardware which the | ||
Raspberry Pi lacks and is out of the scope of this guide. | ||
::: | ||
|
||
## Components | ||
|
||
### Breadboard | ||
|
||
Breadboards are reusable devices used to build and test circuits. They are made up of a number of | ||
holes that are connected by hidden metal strips. Along the top and bottoms are the ground and power | ||
rails, and in the middle there are two sections separated by a channel. Each hole in a section is | ||
connected to the adjacent vertical holes. More information can be found at | ||
[How to Use a Breadboard](https://learn.sparkfun.com/tutorials/how-to-use-a-breadboard/all). | ||
|
||
### LED | ||
|
||
An LED (Light Emitting Diode) is a device that emits light when an electric current passes through | ||
it. They feature two legs, a longer positive leg (the [anode](https://en.wikipedia.org/wiki/Anode)) | ||
and a shorter negative leg (the [cathode](https://en.wikipedia.org/wiki/Cathode)). The longer leg is | ||
often kinked so that both legs protrude the same distance from the LED. To use it we connect the positive | ||
lead to the GPIO pin and the negative lead to a ground pin. More information can be found at | ||
[Light-Emitting Diodes (LEDs)](https://learn.sparkfun.com/tutorials/light-emitting-diodes-leds/all) | ||
|
||
### 220 Ω Resistor | ||
|
||
The power that the Raspberry Pi can provide is actually too much for these LEDs. To prevent the LED | ||
from burning out, we must add a resistor to the circuit. The resistor limits the current that | ||
flows through the LED, preventing it from burning out. The exact value of the resistor is not | ||
critical, but too high a value does not allow enough illumination of the LED. A resistor in the | ||
range of 220 Ω to 1 kΩ should work well. More information on resistors can be found at | ||
[Sparkfun - Resistors](https://learn.sparkfun.com/tutorials/resistors/all) | ||
|
||
:::tip[Resistor Colour Code] | ||
The colours on a resistor indicate the resistance value. Each coloured band corresponds to specific | ||
numbers and multipliers which can be used to calculate the resistance value. More information | ||
can be found at [Electronic Colour Code](https://en.wikipedia.org/wiki/Electronic_color_code) | ||
::: | ||
|
||
### Jumper Wires | ||
|
||
Jumper Wires, or DuPont wires, are used to make a temporary connection different components. They | ||
can be M/M, M/F, or F/F. We are using M/F jumper wires in this guide. | ||
|
||
## The Circuit | ||
|
||
Below we can see the circuit diagram for this project. We have the cathode of the LED connected to | ||
GPIO Pin 11, while the anode is connected to ground pin 6 through a resistor. | ||
|
||
![Circuit Diagram for Blinking an LED](./images/circuits/blinkled.png) | ||
|
||
And the physical circuit looks like the following image, in which we've connected an M/F jumper wire | ||
from Pin 11 to the cathode of the LED. The anode of the LED is connected to the resistor, which is | ||
then connected to the ground pin through another M/F jumper wire. | ||
|
||
![Photograph of a circuit to blink an LED](./images/circuits/blink_led_circuit.jpg) | ||
|
||
## Starting the Daemon | ||
|
||
:::tip[Daemons] | ||
A daemon is a background process that runs continuously, waiting for requests to | ||
perform some action. In this case, the daemon is waiting for requests to change the state of the | ||
GPIO pins. This allows us to run multiple programs that interact with the GPIO pins. | ||
::: | ||
|
||
Underneath SplashKit we use the [Pigpio library](https://abyz.me.uk/rpi/pigpio), specifically its | ||
daemon. To interface with this daemon, it must be running. If it is not running we can expect | ||
some output like the following: | ||
|
||
```shell | ||
gpio_init() must be called before any other GPIO functions | ||
``` | ||
|
||
We can check if its running by using the following command: | ||
|
||
```shell | ||
ps aux | grep pigpiod | ||
``` | ||
|
||
If the daemon is not running, we can start it by using: | ||
|
||
```shell | ||
sudo pigpiod | ||
``` | ||
|
||
To stop the daemon from running we can use the command: | ||
|
||
```shell | ||
sudo killall pigpiod | ||
``` | ||
|
||
## The Code | ||
|
||
After the daemon is running, we can then create our program. Below is an example program that | ||
blinks an LED on and off. | ||
|
||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```cpp | ||
#include "splashkit.h" | ||
|
||
int main() | ||
{ | ||
raspi_init(); | ||
pins led_pin = PIN_11; | ||
raspi_set_mode(led_pin, GPIO_OUTPUT); | ||
|
||
open_window("dummy_window", 1, 1); | ||
while(!any_key_pressed()) | ||
{ | ||
process_events(); | ||
raspi_write(led_pin, GPIO_HIGH); | ||
delay(500); | ||
raspi_write(led_pin, GPIO_LOW); | ||
delay(500); | ||
} | ||
|
||
close_all_windows(); | ||
raspi_cleanup(); | ||
return 0; | ||
} | ||
``` | ||
</TabItem> | ||
<TabItem label="C#"> | ||
```csharp | ||
using SplashKitSDK; | ||
using static SplashKitSDK.SplashKit; | ||
RaspiInit(); | ||
Pins ledPin = (Pins)11; | ||
RaspiSetMode(led_pin, (PinModes) 1); | ||
OpenWindow("dummy_window", 1, 1); | ||
while(!AnyKeyPressed()) | ||
{ | ||
ProcessEvents(); | ||
RaspiWrite(led_pin, (PinState) 1); | ||
Delay(500); | ||
RaspiWrite(led_pin, (PinState) 0); | ||
Delay(500); | ||
} | ||
CloseAllWindows(); | ||
RaspiCleanup(); | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
### Understanding the code | ||
|
||
To understand this code better, lets break it down and explore each section. | ||
|
||
1. | ||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```cpp | ||
raspi_init(); | ||
pins led_pin = PIN_11; | ||
raspi_set_mode(led_pin, GPIO_OUTPUT); | ||
``` | ||
|
||
</TabItem> | ||
<TabItem label="C#"> | ||
|
||
```csharp | ||
RaspiInit(); | ||
Pins ledPin = (Pins)11; | ||
RaspiSetMode(led_pin, (PinModes) 1); | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
In this bit of the code we're setting up the hardware, we call [Raspi Init](/api/raspberry/#raspi-init) to initialise the GPIO pins, | ||
and then we define the specific pin we're using which is Pin 11 in this case and it is of the [Pins](/api/types/#pins) type. | ||
|
||
We pass this value to [Raspi Set Mode](/api/raspberry/#raspi-set-mode) along with `GPIO_OUTPUT` which sets the pin to be ready to output a signal on our command. The `GPIO_OUTPUT` value is one of the [Pin Modes](/api/types/#pin-modes) that can be set. Each pin has alternative modes but we are only interested in the output mode for now. | ||
|
||
2. | ||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```cpp | ||
open_window("dummy_window", 1, 1); | ||
while(!any_key_pressed()) | ||
{ | ||
process_events(); | ||
... | ||
} | ||
|
||
``` | ||
|
||
</TabItem> | ||
<TabItem label="C#"> | ||
|
||
```csharp | ||
OpenWindow("dummy_window", 1, 1); | ||
while(!AnyKeyPressed()) | ||
{ | ||
ProcessEvents(); | ||
... | ||
} | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
This is a small trick we can do to recognise keyboard inputs. We open up a dummy window using [Open Window](/api/windows/#open-window) and this initialises the backend so that we can detect input. We'll create a loop that runs while [Any Key Pressed](/api/input/#any-key-pressed) returns false. We use [Process Events](/api/input/#process-events) at the start of the loop to actually detect any user input. We can now press a key to end the program and ensure we cleanup correctly. | ||
|
||
3. | ||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```cpp | ||
raspi_write(led_pin, GPIO_HIGH); | ||
delay(500); | ||
raspi_write(led_pin, GPIO_LOW); | ||
delay(500); | ||
``` | ||
|
||
</TabItem> | ||
<TabItem label="C#"> | ||
|
||
```csharp | ||
RaspiWrite(led_pin, (PinState) 1); | ||
Delay(500); | ||
RaspiWrite(led_pin, (PinState) 0); | ||
Delay(500); | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
Now that we've setup our pins and defined our end condition, we can now manipulate the LED. Inside the while loop we first use [Raspi Write](/api/raspberry/#raspi-write) to change the output of our pin to `GPIO_HIGH`, one of the [Pin Values](/api/types/#pin-values). Doing this provides electricity to the LED and turn it on. We then wait for half a second using [Delay](/api/utilities/#delay). Then we turn our LED off using [Raspi Write](/api/raspberry/#raspi-write), but now we use `GPIO_LOW`, and wait for another half-second. | ||
|
||
4. | ||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```cpp | ||
close_all_windows(); | ||
raspi_cleanup(); | ||
return 0; | ||
``` | ||
|
||
</TabItem> | ||
<TabItem label="C#"> | ||
|
||
```csharp | ||
CloseAllWindows(); | ||
RaspiCleanup(); | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
Finally, as we exit the program we must ensure that we cleanup our program properly. We must first close the dummy window we opened use [Close All Windows](/api/windows/#close-all-windows). We then call [Raspi Cleanup](/api/raspberry/#raspi-cleanup) to ensure our pins are turned off and cleaned. | ||
|
||
:::tip[Program Shutdown] | ||
It is crucial we plan for the program's shutdown procedure, because if we instead used `CTRL + C` to stop the program then cleanup is not performed and the GPIO pins remain in the same state they were in when the program was stopped. We do not want to unintentionally keep pins active. | ||
::: | ||
|
||
### Build and run the code | ||
|
||
We can build this program with the following command: | ||
|
||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```shell | ||
g++ led_blink.cpp -l SplashKit -o led_blink | ||
``` | ||
|
||
</TabItem> | ||
<TabItem label="C#"> | ||
|
||
```shell | ||
dotnet build | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
Then we run the program with the following command: | ||
|
||
<Tabs syncKey="code-language"> | ||
<TabItem label="C++"> | ||
|
||
```shell | ||
./led_blink | ||
``` | ||
|
||
</TabItem> | ||
<TabItem label="C#"> | ||
|
||
```shell | ||
dotnet run | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
This code blinks the LED on and off as you can see below. This continues until the 10 seconds has | ||
elapsed, and after we exit the while loop, [Raspi Cleanup](/api/raspberry/#raspi-cleanup) is | ||
called and the GPIO pins are reset. | ||
|
||
![A GIF of the LED blinking on and off.](/gifs/guides/gpio-tutorial-gifs/blink_led.gif) |
Oops, something went wrong.