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.