Raspberry Pi – Sterowanie portami GPIO w Pythonie
Kiedy postawiliśmy już system na malince oraz zabezpieczyliśmy kartę pamięci przed zbyt szybkim zużyciem pora na krótki wstęp do sterowania portami GPIO. W dzisiejszym artykule poznamy podstawową składnię języka Python (np. jak stworzyć zmienną, funkcję lub napisać pętlę) a także dowiemy się w jaki sposób Python może pomóc nam sterować portami GPIO (czyli np. zaświecić diodę LED lub wykryć wciśnięcie przycisku).
Podstawy Pythona
Aby uruchomić interpreter Pythona, który będzie na żywo przetwarzał nasze polecenia wystarczy wpisać w konsoli Raspberry polecenie python
. Aby opuścić program możemy wywołać funkcję exit()
Komentarze
Komentarz zaczyna się znakiem # (pod warunkiem, że nie jest on pomiędzy cudzysłowami – wtedy jest to normalnie część stringa)
# oto przykładowy komentarz :) x = 5 # to też jest komentarz y = "# to nie jest komentarz :("
Zmienne
Python jest językiem typowanym dynamicznie, dlatego przy tworzeniu zmiennej nie musimy podawać jej typu.
calkowita = 5 zmiennoprzecinkowa 9.6 ciag_znakow = "To jest ciag znakow" ciag_znakow2 = 'To tez jest ciag znakow'
Należy zauważyć, że stringi w Pythonie możemy wpisywać używająć cudzysłowu ( ” ) lub apostrofu ( ’ ).
Wcięcia, wcięcia jeszcze raz wcięcia
Przed omówieniem pętli i funkcji warto zwrócić uwagę na to, że w Pythonie nie używamy średników ani klamerek otwierających i zamykających bloki kodu { }. Zamiast tego używamy odpowiedniej indentacji. W ten sposób mając np. dwie zagnieżdżone pętle zawartość pierwszej będzie wcięta jednym tabem, natomiast zawartość drugiej dwoma tabami. Za chwilę zobaczycie o co chodzi na realnym przykładzie :)
Pętla for
Pętla for w Pythonie jest w zasadzie pętlą foreach znaną z innych języków. Iteruje ona po danym zbiorze, a nie według warunku pętli.
Dla zademonstrowania o co chodzi użyjemy funkcji range(x), która zwraca nam zbiór liczb całkowitych od 0 do x-1.
>>> range(5) [0, 1, 2, 3, 4]
Tworząc pętlę for iterującą zmienną x od 0 do 4 w języku Python wpiszemy następującą formułkę:
for x in range(5): print x
Jak widać linijka print x
jest wcięta jedną tabulacją.
Gdybyśmy chcieli zagnieździć w sobie dwie pętle for ciało drugiej pętli musiałoby być wcięte o kolejny tabulator:
output = "" for x in range(3): for y in range(4): output += str(x*y) + " " print output output = ""
W ten sposób na wyjściu uzyskamy
0 0 0 0 0 1 2 3 0 2 4 6
Funkcja range może przyjmować także więcej parametrów. Jeżeli przekażemy jej dwa argumenty x oraz y to zwróci zbiór liczb całkowitych od x do y-1.
>>> range(1,5) [1, 2, 3, 4]
W przypadku wywołania range(x, y, z) otrzymamy zbiór od x do y-1 z krokiem do z.
>>> range(1, 10, 2) [1, 3, 5, 7, 9]
Z racji tego, że for jest foreachem i może przyjmować dowolny zbiór spróbujmy takiej sztuczki:
zbior = [1,1,2,3,5,8,13] output = "" for x in zbior: output += str(x) + " " print output
Jak się zapewne domyślacie na wyjściu otrzymamy
1 1 2 3 5 8 13
Tak jak w przypadku innych języków z pętli możemy wyjść przed jej planowanym końcem słówkiem kluczowym break
, oraz przejść do kolejnej iteracji słowem continue
.
Ponadto możemy użyć klauzuli else
na końcu pętli. Wykona się ona w przypadku kiedy zbiór po którym pętla iteruje się wyczerpie, ale nie kiedy pętla została przerwana przez break
.
Przykładowo wykonując kod
for x in range(5): print x break else: print "Koniec zbioru"
Program wypisze nam na wyjście tylko 0. Jeżeli jednak zakomentujemy linijkę ze słowem break to na wyjściu otrzymamy
0 1 2 3 4 Koniec zbioru
Instrukcja warunkowa
Chcąc sprawdzić jakiś warunek wystarczy, że napiszemy
x = 10 if x > 5: print "x jest wiekszy od 5"
i już :) Jeżeli jednak chcemy nieco rozbudować naszą instrukcję warunkową możemy użyć klauzul elif
oraz else
.
x = 10 if x > 5: print "x jest wiekszy od 5" elif x < 5: print "x jest mniejszy od 5" else: print "x jest rowny 5"
Pętla while
Pętla while także może zawierać klauzulę else
. Wykona się ona w przypadku kiedy warunek pętli będzie fałszywy, nie wykona się natomiast kiedy sami przerwiemy pętlę.
x = 5 while x < 10: print x x += 1 break else: print "Warunek petli falszywy"
Wynik: 5
Kiedy zakomentujemy break na wyjściu otrzymamy
5 6 7 8 9 Warunek petli falszywy
Funkcje
Własną funkcję możemy utworzyć według następującej składni: def nazwa_funkcji(argument1, argument2):
Przykładowo funkcja wypisująca na wyjście wynik mnożenia liczb a i b, zwraca ten wynik w postaci liczby oraz jej wywołanie:
def pomnoz(a, b): wynik = a * b print str(a) + " x " + str(b) + " = " + str(wynik) return wynik pomnoz(3,4) wynik = pomnoz(5,5) print wynik
Wynik tych operacji to:
3 x 4 = 12 5 x 5 = 25 25
Plik wykonywalny pythona
Aby używac Pythona nie musimy za każdym razem uruchamiać interpretera i wpisywać w nim ręcznie wszystkich poleceń. Możemy utworzyć plik z rozszerzeniem .py oraz nadać mu prawa do wykonywania, a następnie wykonać za pomocą komendy python nazwa_skryptu
Przykład:
krupson@raspberrypi:~ $ echo "print 'Hello World'" > hello_world.py krupson@raspberrypi:~ $ chmod +x hello_world.py krupson@raspberrypi:~ $ python hello_world.py Hello World
Sterowanie GPIO w RaspberryPi
Znamy już podstawy pythona na tyle, żeby móc wysterować porty wejścia wyjścia w malince.
Pierwsze co musimy zrobić w naszym pliku ze skryptem to zaimportowanie biblioteki do sterowania portami GPIO. W tym celu na początku piszemy
import RPi.GPIO as GPIO
Dzięki temu będziemy mogli się dostać do metod klasy RPi.GPIO odwołując się do nich przez GPIO.nazwa_metody.
Następnie musimy ustalić tryb w jakim będziemy odwoływali się do pinów. Może to być:
- GPIO.BOARD – odwołanie bezpośrednio do numeru pinu w złączu, zalecam ten tryb ze względu na to, że jest uniwersalny dla wszystkich malinek.
- GPIO.BCM – odwołanie do numeru pinu na procesorze – może być różne w różnych wersjach Raspberry.
tryb ustawiamy za pomocą GPIO.setmode(GPIO.BOARD)
Teraz możemy wybrać któryś z pinów i ustalić czy będzie wjeściem, czy wyjściem (odpowiednik funkcji pinMode() z Arduino).
przycisk = 36 dioda = 40 GPIO.setup(przycisk, GPIO.IN) #pin 36 bedzie wejsciem GPIO.setup(dioda, GPIO.OUT) #pin 40 bedzie wyjsciem
Możemy także ustawić pin jako wejście z rezystorem podciągającym lub ściągającym. WYstarczy wywołać
GPIO.setup(numer_pinu, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Rezystor podciagajacy do +3V3 # lub GPIO.setup(numer_pinu, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Rezystor sciagajacy do masy
Stan pinu wyjściowego możemy ustalić przy pomocy
GPIO.output(numer_pinu, GPIO.HIGH) # stan wysoki # lub GPIO.output(numer_pinu, GPIO.LOW) # stan niski
Natomiast odczytujemy w następujący sposób:
GPIO.input(numer_pinu)
Wynik tej metody możemy porównać do GPIO.HIGH lub GPIO.LOW.
Po wszystkim możemy po sobie posprzątać resetując ustawienia GPIO do domyślnych za pomocą
GPIO.cleanup()
opcjonalnie podając numer pinu, który chcemy przywrócić do stanu domyślnego. Jeżeli tego nie zrobimy wyzerowane zostaną wszystkie piny.
Przykładowy program
Dla zademonstrowania działania portów GPIO na żywym organizmie napisałem prosty program, który sprawdzi czy przycisk jest wciśnięty. Jeżeli tak to zaświeci diodę i będzie czekał na puszczenie przycisku. Wtedy zgasi diodę i zakończy działanie. Jeżeli przycisk nie będzie wciśnięty to tylko o tym poinformuje i natychmiast zakończy działanie.
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) btnState = GPIO.input(btnPin) if btnState: print 'Przycisk nie jest wcisniety' else: print 'Przycisk jest wcisniety' GPIO.output(ledPin, not btnState) while GPIO.input(btnPin) == GPIO.LOW: pass GPIO.cleanup() print 'Koniec programu'
Przycisk podłączyłem do pinu 5 podciągając go rezystorem do pinu 3.3V. Dioda LED podłączona jest do pinu numer 40.
Należy pamiętać, aby pod żadnym pozorem nie podłączyć do żadnego pinu Raspberry napięcia 5V. Natychmiast zabije to dany pin.
PROTIP: Piny 5V sąsiadują ze zobą, więc żeby przypadkiem nie podłączyć tam nic tworząc połączenia można założyć na nie zworkę i zdejmować ją tylko wtedy, gdy świadomie potrzebujemy użyć napięcia 5V. Niestety wpadłem na ten pomysł dopiero po tym jak nieumyślnie upaliłem dwa piny w swojej malinie :D
Na poniższej grafice przedstawiono numery pinów zgodnie z trybem GPIO.BOARD:
Grafika pochodzi ze strony https://www.raspberrypi.org/documentation/usage/gpio-plus-and-raspi2/ gdzie możecie poczytać więcej o GPIO w Raspberry.