Raspberry Pi — dodajemy cyfrowe i analogowe złącza GPIO
31.05.2016 | aktual.: 31.05.2016 08:28
Choć samo Raspberry Pi posiada w większości przypadków wystarczającą ilość złącz GPIO, może się zdarzyć, że po jakimś czasie po prostu nam ich zabraknie lub zechcemy skorzystać ze złącz analogowych. Choć same Raspberry Pi nie posiada złącz analogowych, możemy za pomocą zewnętrznych układów (Expander) poszerzyć funkcjonalność naszej maliny. W tym celu pomóc mogą nam układy PCF8574 i PCF8591, które możemy podłączyć po magistrali I2C i w prosty sposób wysterować je za pomocą biblioteki wiringPi.
PCF8574 - bo chce więcej
Układ PCF8574 pozwala na rozszerzenie o dodatkowe 8 pinów cyfrowych przez podłączenie go za pomocą I2C do naszej maliny.
Za pomocą nóżek A0‑A2 możemy zmienić adres urządzenia na magistrali I2C od 0x20, dzięki czemu możemy podłączyć 8 takich samych układów dzięki czemu dostaniemy aż 64 dodatkowe piny GPIO. Nóżki P0‑P7 są naszymi pinami gpio, które możemy sterować. Jedynym ograniczeniem w porównaniu do zwykłych gpio z maliny jest maksymalny prąd, który ma na wyjściu tylko 300 µA, zaś na wejściu ma już 25mA. Układ możemy zasilić napięciem od 2,5 V do 6 V więc bez problemu możemy podłączyć zasilanie 3,3V z naszej maliny do złącza Vcc i podłączyć I2C bez dodatkowych układów.
Poniżej prezentuję schemat podłączenia układu PCF8574 do Raspberry Pi z adresem 0x20 (GND na wszystkie piny A)
Tak przygotowanym układem z maliną możemy zacząć zabawę ze sterowaniem z użyciem biblioteki wiringPi. Poniżej zaprezentowałem przykładowy program, który ustawia wszystkie piny jako wyjściowe i ustawia po kolei je na stan wysoki a następnie zmienia ich stan na niski.
#include <stdio.h> #include <wiringPi.h> #include <pcf8574.h> int main (void) { int i, bit, wart ; wiringPiSetup () ; pcf8574Setup (100, 0x20) ; for (i = 0 ; i < 8 ; ++i){ pinMode (100 + i, OUTPUT) ; } printf ("Ustawiamy piny na stan wysoki\n") ; for (bit = 0 ; bit < 8 ; ++bit){ digitalWrite (100 + bit, 1) ; wart = digitalRead(100+bit); printf ("Stan pinu nr P%d wartosc: %d\n", bit ,wart ) ; delay (200) ; } delay(1000); printf ("\nUstawiamy piny na stan niski\n") ; for (bit = 7 ; bit >= 0 ; --bit){ digitalWrite (100 + bit, 0) ; wart = digitalRead(100+bit); printf ("Stan pinu nr P%d wartosc: %d\n", bit ,wart ) ; delay (200) ; } return 0; }
Po zapisaniu programu np do pliku test.c kompilujemy go
gcc -Wall -o test test.c -lwiringPi
a następnie odpalamy program
sudo ./test
Oprócz pisania kodu w C można również skorzystać z narzędzia gpio z flagą -x i sterować modułem z linii poleceń np odczytując stan pinu za pomocą komendy
gpio -x pcf8574:100:0x20 read 100
Jak wspominałem wcześniej wyjścia pinów dają tylko 300 µA co do większości rzeczy nie jest wystarczające. Ale bez problemu można sterować pinami w trybie INPUT, które mają już 25mA. Zatem jeśli chcielibyśmy wysterować np. diodami LED musielibyśmy podłączyć je odwrotnie tj. do katody (‑) zaś anodę bezpośrednio do zasilnia. Wtedy możemy sterować i załączać diody ustawiając piny na stan niski (w trybie input) przez co prąd przepłynie przez diodę do naszego układu.
Gotowy moduł z PCF8574
Dla mniej doświadczonych użytkowników oraz dla wygodnych polecam użycie gotowego modułu z układem PCF8574, dzięki któremu podłączymy go do maliny za pomocą zwykłych kabelków i obejdziemy się bez płytek stykowych lub lutowania. Moduł można kupić w kilku polskich sklepach jak i na allegro za około 14zł.
Moduł pozwala na ustawianie adresu za pomocą zworek oraz możliwe jest podłączanie kolejnego modułu do złącza żeńskiego z prawej strony. Z lewej strony mamy męskie 4 pinowe złącze z zasilaniem i i2C. Na samej górze mamy 8 pinów I/O którymi możemy sterować.
PCF8591 - analogi w akcji
Układ PCF8591 pozwala nam na rozszerzenie o 4 wejściowe piny analogowe oraz 1 wyjściowy (8‑bitowe przetworniki analogowo-cyfrowy i cyfrowo-analogowy).
Tak samo jak wcześniejszy układ mamy 3 nóżki A0‑A2 które służą do adresowania naszego układu od 0x48 , zaś układ zasilamy albo 3,3V lub 5V, więc bez najmniejszych problemów również możemy podłączyć go do maliny zasilając układ 3.3V. Do dyspozycji mamy cztery nóżki z wejściowymi złączami analogowymi AIN0-AIN3, oraz jednym wyjściowym AOUT. Przy odczytywaniu wartości z pinów otrzymujemy wartości od 0 do 255 i takie same wartości ustawiamy, gdy chcemy wysterować pin wyjściowy.
Poniższy kod przetwarza odczytane wartości z pinów i przelicza na rzeczywiste napięcie w woltach, do którego został użyty wzór
[code=]napięcie wejściowe = wartość_odczytu * 3.3 ÷ 255[/code]
#include <stdio.h> #include <wiringPi.h> #include <pcf8591.h> #define PINY 120 int main (void) { int temp, pin ; wiringPiSetup () ; pcf8591Setup (PINY, 0x48) ; printf ("Wartość odczytów z pinów w Voltach\n") ; for (;;) { for (pin = 0 ; pin < 4 ; ++pin) { temp = analogRead (PINY + pin) ; printf (" %5.2f", (double)temp * 3.3 / 255.0) ; } printf ("\r") ; fflush (stdout) ; delay (100) ; } return 0 ; }
Po zapisaniu programu np do pliku volt.c wykonujemy kompilację
gcc -Wall -o volt volt.c -lwiringPi
a następnie uruchamiamy
sudo ./volt
tak samo jak w pierwszym module cyfrowym istnieje możliwość sterowania poleceniem w terminalu za pomocą narzędzia gpio z opcją aread możemy odczytywać wartości z pinów AIN0-AIN3
gpio -x pcf8591:120:0x48 aread 120
jak również używając opcji awrite ustawiać pin AOUT
gpio -x pcf8591:120:0x48 awrite 120 127
Jak zauważyliście pin wyjściowy AOUT jest pod tym samym pierwszym pinem co AIN0, ale oba piny nie sa w żaden sposób blokowane względem drugiego i możemy równocześnie odczytywać z pinu wejściowego jak również ustawiać wartość na pinie wyjściowym
Przy wyliczaniu ustawianego napięcia na pinie wyjściowym można użyć wzoru
[code=]napięcie wyjściowe = wartość_ustawiona * 255 ÷ 3.3[/code]
Gotowy moduł PCF8591
Tak samo jak w przypadku cyfrowego modułu dostępny jest moduł dla układu analogowego. Oprócz wyprowadzanych pinów posiada również potencjometr podłączony do wejść z możliwością konfiguracji za pomocą zworki. Koszt tego modułu to około 15‑30zł w zależności od producenta.
Poniżej prezentuję przykładowe zastosowanie przetwornika analogowego do odczytu wychylenia joysticka [youtube=https://www.youtube.com/watch?v=SbC4E7jiJL8]
I jeszcze kod programu wyświetlającego odczyty z joysticka
#include <stdio.h> #include <wiringPi.h> #include <pcf8591.h> #define PINY 120 int main (void) { int x, y; wiringPiSetup () ; pcf8591Setup (PINY, 0x48) ; printf ("Położenie Joysticka \n") ; for (;;) { x = analogRead (120) ; y = analogRead (121) ; printf ("x: %d y: %d ", x, y) ; printf ("\r") ; fflush (stdout) ; delay (10) ; } return 0 ; }
Oba układy i moduły mogą być podłączone i sterowane również na innych mikrokoputerach m.in. Banana Pi, Orange Pi, LM Guitar oraz innych mających przeportowaną bibliotekę WiringPi