Raspberry Pi to niewielkie, ale potężne urządzenie, które pozwala na naukę programowania oraz budowanie zaawansowanych projektów elektronicznych. Jednym z najważniejszych aspektów pracy z Raspberry Pi jest umiejętność sterowania portami GPIO (General Purpose Input/Output – uniwersalne wejście/wyjście ogólnego przeznaczenia) za pomocą Pythona. W tym artykule dowiesz się, jak wykorzystać możliwości tej miniaturowej płytki do tworzenia interaktywnych aplikacji, sterowania urządzeniami zewnętrznymi oraz budowania autonomicznych systemów.

Co to jest GPIO?

GPIO to zestaw uniwersalnych pinów wejścia-wyjścia, które stanowią fizyczny interfejs między Raspberry Pi a zewnętrznymi komponentami elektronicznymi. Porty te umożliwiają komunikację między płytką a różnymi urządzeniami, takimi jak diody LED, przyciski, czujniki czy silniki. Dzięki GPIO możesz zarówno odczytywać sygnały (wejścia), jak i sterować urządzeniami (wyjścia).

Python – idealny język do sterowania GPIO

Oto kluczowe powody, dla których Python świetnie sprawdza się na Raspberry Pi:

  • prosty, czytelny i intuicyjny składniowo,
  • ma rozbudowany ekosystem bibliotek, w tym RPi.GPIO do obsługi pinów,
  • jest natywnie wspierany w Raspberry Pi OS i ma wygodne środowisko Thonny IDE,
  • idealnie nadaje się zarówno dla początkujących, jak i zaawansowanych użytkowników.

Podstawy składni Pythona

Zanim przystąpisz do sterowania GPIO, poznaj krótko podstawy składni Pythona.

Zmienne i typy danych

Tak definiujesz zmienne bez deklarowania typu:

nazwa = "Raspberry Pi"
liczba_pinow = 40
temperatura = 25.5

Pętle i iteracje

Pętla for z funkcją range() pozwala wygodnie iterować po sekwencji liczb:

for x in range(5):
print(x)

Powyższy kod wypisze liczby od 0 do 4.

Warunki logiczne

Instrukcje warunkowe wykonują różne operacje w zależności od stanu:

if GPIO.input(pin) == GPIO.HIGH:
print("Pin jest w stanie wysokim")
else:
print("Pin jest w stanie niskim")

Import biblioteki RPi.GPIO

Aby rozpocząć pracę z pinami, zaimportuj bibliotekę RPi.GPIO oraz, w razie potrzeby, moduł czasu:

import RPi.GPIO as GPIO
import time

Dzięki aliasowi GPIO wywołujesz metody w postaci GPIO.nazwa_metody.

Konfiguracja trybu pinów

Raspberry Pi oferuje dwa sposoby numeracji pinów. Wybierz jeden na początku programu i trzymaj się go w całym skrypcie.

GPIO.BOARD – numeracja fizyczna

Tryb GPIO.BOARD odnosi się bezpośrednio do numeru pinu na złączu 40-pinowym:

GPIO.setmode(GPIO.BOARD)

W tym trybie pin o numerze fizycznym 36 zawsze oznacza pin 36 – niezależnie od modelu płytki.

GPIO.BCM – numeracja logiczna

Tryb GPIO.BCM korzysta z numerów linii GPIO w układzie SoC (Broadcom) i jest powszechnie używany w dokumentacji:

GPIO.setmode(GPIO.BCM)

BOARD vs BCM – szybkie porównanie

Różnice między trybami numeracji możesz przejrzeć w poniższej tabeli:

Tryb Co oznacza Kiedy używać Przykład
GPIO.BOARD numer fizyczny pinu na złączu gdy kierujesz się mapą złącza i okablowaniem GPIO.setmode(GPIO.BOARD)
GPIO.BCM numer logiczny linii GPIO w układzie SoC gdy korzystasz z dokumentacji i bibliotek w BCM GPIO.setmode(GPIO.BCM)

Konfiguracja pinów jako wejście lub wyjście

Po ustawieniu trybu wybierz konkretne piny i określ ich rolę.

Ustawianie wyjścia (output)

Aby sterować urządzeniem (np. zaświecić diodę LED), ustaw pin jako wyjście:

dioda = 40
GPIO.setup(dioda, GPIO.OUT)

Możesz też zainicjalizować pin z określonym stanem początkowym:

GPIO.setup(21, GPIO.OUT, initial=GPIO.HIGH)

Ustawianie wejścia (input)

Aby odczytywać stan urządzenia (np. przycisku), ustaw pin jako wejście:

przycisk = 36
GPIO.setup(przycisk, GPIO.IN)

Rezystory podciągające i ściągające

Przy przyciskach stosuj rezystory podciągające lub ściągające, aby uniknąć stanów nieustalonych (drgań, przypadkowych odczytów).

Tak włączysz rezystory wewnętrzne:

# Rezystor podciągający do +3V3
GPIO.setup(numer_pinu, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Rezystor ściągający do masy (GND)
GPIO.setup(numer_pinu, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

Sterowanie pinami wyjściowymi

Ustawianie stanu pinu

Do ustawiania stanu wysokiego lub niskiego użyj GPIO.output():

GPIO.output(numer_pinu, GPIO.HIGH) # stan wysoki (włączenie)
GPIO.output(numer_pinu, GPIO.LOW) # stan niski (wyłączenie)

GPIO.HIGH odpowiada około 3.3 V (logiczna jedynka), a GPIO.LOW to około 0 V (logiczne zero).

Odczytywanie pinów wejściowych

Stan pinu wejściowego sprawdzisz tak:

stan_pinu = GPIO.input(numer_pinu)

Funkcja zwraca GPIO.HIGH lub GPIO.LOW.

PWM – modulacja szerokości impulsu

PWM (Pulse Width Modulation) pozwala płynnie sterować mocą lub jasnością – np. diod LED i silników. Zamiast prostego włącz/wyłącz możesz regulować wypełnienie sygnału (duty cycle) w procentach.

Tworzenie sygnału PWM

Przykładowa inicjalizacja PWM z częstotliwością 1000 Hz i wypełnieniem 50% wygląda tak:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.OUT)

# Inicjacja sygnału PWM na pinie 21 z częstotliwością 1000 Hz
pwm21 = GPIO.PWM(21, 1000)

# Uruchomienie PWM z wypełnieniem 50%
pwm21.start(50)

input("Naciśnij klawisz, aby zatrzymać: ")

# Zatrzymanie sygnału PWM i sprzątanie
pwm21.stop()
GPIO.cleanup()

Praktyczne przykłady

Przykład 1 – włączanie diody LED

Najprostszy projekt to zaświecenie diody na 5 sekund:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.OUT)

try:
# Włączenie diody
GPIO.output(21, GPIO.HIGH)
time.sleep(5)
# Wyłączenie diody
GPIO.output(21, GPIO.LOW)
finally:
# Wyczyszczenie GPIO niezależnie od błędów
GPIO.cleanup()

Przykład 2 – sterowanie diodą za pomocą przycisku

Program sprawdza stan przycisku i włącza/wyłącza diodę. Używamy rezystora podciągającego PUD_UP, aby przycisk był stabilnie odczytywany.

import RPi.GPIO as GPIO
import time

LED = 21
BTN = 20

GPIO.setmode(GPIO.BCM)
GPIO.setup(LED, GPIO.OUT)
GPIO.setup(BTN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # stan spoczynkowy: HIGH

try:
while True:
if GPIO.input(BTN) == GPIO.LOW: # wciśnięty (zwarty do GND)
GPIO.output(LED, GPIO.HIGH)
print("Przycisk wciśnięty")
else:
GPIO.output(LED, GPIO.LOW)
print("Przycisk zwolniony")
time.sleep(0.02) # lekkie odciążenie CPU i podstawowe anti-bounce
finally:
GPIO.cleanup()

Przykład 3 – reagowanie na przycisk (tryb BOARD)

Przykład w trybie GPIO.BOARD: dioda świeci, gdy przycisk jest wciśnięty, po puszczeniu następuje zakończenie:

import RPi.GPIO as GPIO
import time

ledPin = 40
btnPin = 5

GPIO.setmode(GPIO.BOARD)
GPIO.setup(ledPin, GPIO.OUT)
GPIO.setup(btnPin, GPIO.IN)

# Sprawdzenie stanu przycisku
btnState = GPIO.input(btnPin)
if btnState:
print("Przycisk nie jest wciśnięty")
else:
print("Przycisk jest wciśnięty")

# Zaświecenie diody w zależności od stanu przycisku
GPIO.output(ledPin, not btnState)

# Czekanie na puszczenie przycisku
while GPIO.input(btnPin) == GPIO.LOW:
pass

GPIO.cleanup()
print("Koniec programu")

Ważne funkcje i komendy

Poniżej znajdziesz skrót najważniejszych wywołań w bibliotece RPi.GPIO:

  • GPIO.setmode(GPIO.BCM) – ustawienie konwencji numeracji pinów (BCM lub BOARD);
  • GPIO.setup(# pinu, GPIO.IN) – konfiguracja pinu jako wejścia;
  • GPIO.setup(# pinu, GPIO.OUT) – konfiguracja pinu jako wyjścia;
  • GPIO.input(# pinu) – odczyt bieżącego stanu pinu (HIGH/LOW);
  • GPIO.output(# pinu, stan) – ustawienie stanu pinu wyjściowego (HIGH/LOW);
  • GPIO.cleanup() – przywrócenie domyślnych ustawień i zwolnienie zasobów.

Uruchamianie skryptów Pythona

Aby uruchomić skrypt w terminalu, wpisz:

python nazwa_skryptu.py

Oto szybki przykład z plikiem testowym:

echo "print('Witaj, świecie')" > hello_world.py
chmod +x hello_world.py
python hello_world.py

Czyszczenie zasobów – GPIO.cleanup()

Zawsze na końcu programu wywołuj GPIO.cleanup(), aby przywrócić piny do stanu domyślnego i uniknąć konfliktów przy kolejnym uruchomieniu. To prosta praktyka, która oszczędza czas podczas debugowania i zwiększa niezawodność projektu.

Dobre praktyki pracy z GPIO

Stosuj te wskazówki, aby pracować bezpiecznie i stabilnie:

  • zawsze wybieraj i konsekwentnie stosuj jeden tryb numeracji (BCM lub BOARD),
  • dla przycisków ustaw PUD_UP lub PUD_DOWN i rozważ filtrację drgań styków,
  • nie podłączaj bezpośrednio urządzeń wymagających większego prądu – używaj tranzystorów, MOSFET-ów lub driverów,
  • planując PWM, dobierz częstotliwość do obciążenia (LED: setki–tysiące Hz; silniki: zależnie od sterownika),
  • zapewnij GPIO.cleanup() w bloku finally, aby zawsze posprzątać zasoby.