Zapalmy diodę LED

Raspberry Pi jest małym komputerem. To co go wyróżnia od komputerów, z jakimi mieliście do czynienia, to jest tak zwane złącze GPIO. Ten zestaw pinów pozwala Tobie łatwo podłączyć do Raspberry różne elementy elektroniczne (takie jak przyciski, lampki LED i inne elementy). To, plus prosty sposób na kontrolowanie tych złącz, daje Tobie możliwości, które w zwykłych komputerach są niemożliwe bez licznych elementów dodatkowych.

Złącze GPIO w Raspberry Pi

Na początek nauczymy się zapalać i gasić lampki LED.

W tym artykule oprócz Starter Kitu dla Raspberry Pi używamy zestawu diod LED ale możesz to zastąpić dowolnymi diodami LED i rezystorami (od 220 do 470 ohm powinny być OK).

Przygotowanie płytki stykowej

Do Starter Kitu od Nettigo dołączone są również płytka stykowa i elementy pozwalające bezproblemowo podłączyć się do złącza GPIO.

Podłaczenie GPIO do płytki stykowej. Zwróć uwagę, z której strony jest biały przewód na czarnej taśmie.

Podłącz czarną taśmę, wchodzącą w skład Starter Kitu do Raspberry Pi. Zwróć uwagę, że jedna strona taśmy oznaczona jest białym paskiem. Do przejściówki dla płytki stykowej da się włożyć ją tylko w jeden sposób, ale od strony Raspberry Pi musicie pilnować, aby dobrze została włożona.

Przejściówkę do płytki stykowej od teraz będziemy nazywać cobblerem. Ma on opisane na krawędziach nazwy sygnałów. Bardzo ułatwia to podłączanie układów na płytce stykowej do Raspberry.

Montujemy układ

Podłączymy lampkę LED, korzystając z tego schematu.

Zasada działania jest następująca. Programowo włączymy napięcie na wyjściu GPIO, zadziała ono jak bateryjka i lampka będzie świecić. Gdy wyłączymy napięcie na wyjściu GPIO, lampka przestanie świecić.

Schemat podłączenia lampki LED do Raspberry

Jeden przewód jest podłaczony do tego samego rzędu otworów na płytce stykowej, gdzie jest oznaczenie 18. Drugie przewód w miejsce gdzie jest wyprowadzone GND.

Dla ułatwienia montażu zdjęcie fizycznie zmontowanego układu.

Na powyższym zdjęciu na czerwono zaznaczyliśmy, jak płytka stykowa uzupełnia połączenia, tworząc obwód.

Lampka LED (dioda) ma jedną nóżkę krótszą, w naszym układzie trzeba ją podłączyć razem z rezystorem. Jako podpowiedź – zdjęcie, z wyjętą lampką, widać, z której strony jest krótsza nóżka. Podłączona odwrotnie nie będzie świecić, nawet jak włączymy napięcie na wyjściu GPIO.

Krótsza nóżka od strony rezystora

Niech stanie się jasność

Mając podłączony układ, możemy zacząć pisać już nasz pierwszy program. Migniemy dwa razy diodą. Zapisz następujący program jako plik led.py:

#deklaracje
import RPi.GPIO as GPIO
from time import sleep

#Konfiguracja
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)

#Właściwe działanie   
GPIO.output(18,GPIO.HIGH)
sleep(1)
GPIO.output(18,GPIO.LOW)
sleep(1)

GPIO.output(18,GPIO.HIGH)
sleep(1)
GPIO.output(18,GPIO.LOW)
sleep(1)

Program jest napisany w języku Python. Znak # rozpoczyna komentarz. Komentarze wyznaczają w naszym programie trzy sekcje.

Pierwsza to deklaracje. Pierwsze polecenie import pozwala nam korzystać z biblioteki do obsługi GPIO w Pythonie. Dzięki niej będziemy mogli zapalić lampkę LED. Drugie daje nam dostęp do funkcji sleep, pozwalającej odczekać sekundę z zapaloną lampką.

Druga sekcja to konfiguracja. Pierwsze polecenie wybiera sposób numerowania wyjść GPIO w naszym programie. Opcja GPIO.BCM oznacza używanie takiego samego nazewnictwa jak na cobblerze. Dzięki temu wyjście 18 w programie to jest to samo co 18 na cobblerze. Drugie polecenie ustawia tryb pracy pinu 18-go jako wyjście.

Trzecia sekcja to kolejno wysyłanie na wyjście stanu wysokiego i niskiego w odstępach 1 sekundy. Stan wysoki oznacza napięcie na wyjściu 18 - wtedy lampka będzie świecić. Przy stanie niskim napięcie jest zero i lampka nie będzie świecić. Przetestuj:

sudo python3 led.py

To chyba najkrótszy film w naszym kanale na YT...

Co to za błąd

Jeżeli ponownie uruchomisz program, by zobaczyć to mruganie jeszcze raz, zobaczysz taki komunikat:

pi@raspberrypi ~/sk_1 $ sudo python3 led.py 
led.py:7: RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
  GPIO.setup(18, GPIO.OUT)

By pozbyć się tego komunikatu, na zakończenie programu z miganiem trzeba dokonać programowego 'sprzątania' po sobie. Robi to funkcja GPIO.cleanup(), także cały program teraz wygląda tak:

#deklaracje
import RPi.GPIO as GPIO
from time import sleep

#Konfiguracja
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)

#Właściwe działanie
GPIO.output(18,GPIO.HIGH)
sleep(1)
GPIO.output(18,GPIO.LOW)
sleep(1)

GPIO.output(18,GPIO.HIGH)
sleep(1)
GPIO.output(18,GPIO.LOW)
sleep(1)

#Porządki na koniec
GPIO.cleanup();

Na zakończenie działania, program dokona poprawnego odłączenia się od GPIO. Kolejne uruchomienie już nie będzie zwracać tego błędu. Uruchom dwa razy poprawiony program by się o tym przekonać.

Niech miga wiecznie

Teraz, spróbujmy zmienić działanie programu tak, by lampka migała bez końca. W języku Python konstrukcja while True: zapewnia wykonywanie następnego bloku poleceń bez końca.

Jak zaznaczamy blok poleceń? Wcięciami. Wszystkie następne polecenia mające większe wcięcie niż obecna linia traktowane są jako jeden blok. Pierwsza linia o mniejszym wcięciu przerywa blok.

Zmodyfikowany o użycie while True: przykład wygląda teraz tak:

#deklaracje
import RPi.GPIO as GPIO
from time import sleep

#konfiguracja
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)

#działanie właściwe
while True:
    GPIO.output(18,GPIO.HIGH)
    sleep(1)
    GPIO.output(18,GPIO.LOW)
    sleep(1)

#Porządki na koniec
GPIO.cleanup();

Jak widać zmiana nastąpiła w sekcji działania właściwe. Zapisz przykład jako led2.py i uruchom go sudo python3 led2.py. Lampka miga bez ustanku, aby przerwać działanie skryptu musisz użyć Ctrl+C. W ten sposób przerywasz natychmiast działanie programu.

Spróbuj uruchomić program jeszcze raz. Jaki jest rezultat?

Czemu pojawił się błąd, mimo GPIO.cleanup() na końcu? Kluczem jest zrozumienie znaczenia przerwać natychmiast. Gdy naciśniesz Ctrl+C jest wykonywany kod gdzieś w bloku instrukcji po while. Skoro przerywasz działanie natychmiast, nigdy nie dojdzie do wykonania umieszczonego na końcu polecenia GPIO.cleanup().

Naciśnięcie przez Ciebie Ctrl+C jest niespodziewanym zdarzeniem (z punktu widzenia programu). W Pythonie takie zdarzenia reprezentuje się przez wyjątki.

Jeżeli określimy w kodzie, jak program ma się zachować, gdy zdarzy się wyjątek, to uda się nam wybrnąć z tej sytuacji. W języku Python służy do tego słowo kluczowe try, po którym następuje blok poleceń (pamiętamy, wydzielony wcięciem), w którym możemy się spodziewać wyjątków. W tym przykładzie nie będziemy zastanawiać się, jakie niespodziewane wydarzenia mogą mieć miejsce, chcemy mieć pewność, że GPIO.cleanup() zostanie wykonane niezależnie od tego, co za zdarzenie było przyczyną zakończenia pracy.

Po modyfikacji nasz program wygląda tak:

#deklaracje
import RPi.GPIO as GPIO
from time import sleep

#konfiguracja
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)

#działanie właściwe
try:
    while True:
        GPIO.output(18,GPIO.HIGH)
        sleep(1)
        GPIO.output(18,GPIO.LOW)
        sleep(1)
finally:
    #Porządki na koniec
    GPIO.cleanup();

Zapisz go jako led3.py i uruchom sudo python3 led3.py. Działa i po naciśnięciu Ctrl+C i przy ponownym uruchomieniu nie ma komunikatu o błędzie.

Na co zwrócić uwagę?

Po pierwsze — cały blok while został wcięty 'bardziej` z zachowaniem swojej struktury wcięć. Dzięki temu obejmuje go działanie try. Z kolei finally jest na tym samym poziomie co try i jest niejako dokończeniem try. Znaczenie finally jest dokładnie takie, że blok po nim, wykona się zawsze, niezależnie czy w bloku po try był jakiś wyjątek, czy zakończył się normalnie.

Czego się własnie nauczyłeś

W tym artykule przedstawiliśmy następujące zagadnienia