Pierwsze kroki z Raspberry Pi: obsługa magistrali 1-Wire
Konfiguracja systemu Linux do obsługi magistrali 1-Wire
System wbudowane działające w oparciu o system operacyjny Linux umożliwiają organizację magistrali 1-Wire na kilka sposobów: wykorzystanie konwerterów interfejsów USB na 1-Wire (np. za pomocą scalonego interfejsu DS2490), I2C na 1-Wire (np. układ DS2482) lub podłączenia układów peryferyjnych bezpośrednio do portów GPIO procesora. Dwa pierwsze z wymienionych rozwiązań wymuszają zastosowanie dodatkowych układów zewnętrznych oraz zwiększają powierzchnię zajmowaną przez urządzenie, dlatego też stosowane są głównie w rozwiązaniach, w których użytkownik nie ma bezpośredniego dostępu do portów GPIO. Komputer Raspberry Pi posiada bardzo wygodny dostęp do portów GPIO, które zostały wyprowadzone na złącze szpilkowe 2×13, dlatego też w dalszej części artykułu skupimy się na rozwiązaniu realizującym obsługę magistrali poprzez port wejścia/wyjścia ogólnego przeznaczenia.
Jedną z wielkich zalet systemu Linux jest bardzo wygodny w użyciu dla użytkownika poziom abstrakcji warstwy sprzętowej – wszystko jest plikiem. Nie inaczej jest również w przypadku magistrali 1-Wire. Każdy czujnik podłączony do urządzenia master jest reprezentowany przez zbiór plików umożliwiających konfigurację pracy i odczyt danych z urządzenia. Aby jednak zapewnić w systemie poprawną obsługę magistrali 1-Wire należy załadować do systemu odpowiednie moduły jądra, lub jeśli moduły te nie są dostępne dokonać samodzielnej jego konfiguracji i kompilacji.
Załadowanie gotowych modułów jądra
Większość dostarczanych wraz z komputerem jednopłytkowym Raspberry Pi dystrybucji systemu posiada zainstalowane, gotowe moduły do obsługi magistrali 1-Wire. W takim przypadku załadowanie modułów jądra w systemie ogranicza się do dwóch prostych instrukcji:
sudo modprobe w1-gpio sudo modprobe w1-therm
Pierwszy z załadowanych modułów umożliwia obsługę magistrali 1-Wire poprzez porty wejścia/wyjścia ogólnego przeznaczenia, drugi natomiast umożliwia łatwy odczyt danych z cyfrowych czujników temperatury (jak np. DS18B20). Załadowane moduły są dostępne w systemie do czasu ponownego uruchomienia komputera, dlatego też warto wymusić w systemie ich automatyczne ładowanie przy starcie Raspberry Pi . W tym celu w pliku /etc/modules dodajemy wpisy:
w1-gpio w1-therm
System jest już gotowy do podłączenia czujników. Jeśli proces załadowania modułów przebiegł poprawnie możesz Czytelniku przejść do lektury podrozdziału ” Obsługa magistrali 1-Wire w systemie Linux „. W przypadku gdy napotkałeś błędy, które najprawdopodobniej wynikają z braku wyżej wymienionych modułów w systemie, należy dokonać samodzielnej konfiguracji i kompilacji jądra systemu.
Kompilacja jądra systemu Linux włączoną obsługą magistrali 1-Wire
W przypadku gdy budujemy własną dystrybucję systemu lub korzystamy z ogólnodostępnych dystrybucji, które nie posiadają włączonej obsługi magistrali 1-Wire, należy dokonać samodzielnej konfiguracji i kompilacji jądra systemu Linux. Na szczęście cały proces, choć jest długotrwały, nie jest skomplikowany. Warto więc również dla celów dydaktycznych przeanalizować poniższe etapy konfiguracji systemu. Kompletny opis przygotowania narzędzi kross-kompilacji dla zestawu Raspberry Pi (nazwanych raspberrypi-tools ) oraz pobrania kodu źródłowego jądra systemu Linux został w sposób szczegółowy przedstawiony na stronie.
W niniejszym opisie skupimy się wyłącznie na konfiguracji wybranej wersji jądra pod kątem obsługi magistrali 1-Wire.
Po poprawnym skonfigurowaniu narzędzi kompilacji oraz pobraniu kodu źródłowego jądra systemu Linux przystępujemy do jego konfiguracji. W tym celu w katalogach z kodem źródłowym jądra wywołujemy polecenie:
make menuconfig
które uruchomi pseudo-graficzny interfejs użytkownika. Z dostępnych opcji wybieramy kategorię Device drivers , włączamy opcję Dallas’s 1-wire support (poprzez wciśnięcie przycisku 'Y’) i w kategorii 1-wire Slaves wybieramy opcję Thermal family implementation .
Device Drivers ---> <*> Dallas's 1-wire support ---> 1-wire Slaves ---> <*> Thermal family implementation
Rys. 7. Konfiguracja jądra systemu Linux – układy slave
W następnym kroku konfigurujemy tryb pracy układu master – ponieważ wybieramy opcję sterowania magistralą przez porty GPIO, z gałęzi 1-wire Bus Masters zaznaczamy opcję GPIO 1-wire busmaster .
Device Drivers ---> <*> Dallas's 1-wire support ---> 1-wire Bus Masters ---> <*> GPIO 1-wire busmaster
Rys. 8. Konfiguracja jądra systemu Linux – układ master
Po zapisaniu wprowadzonych zmian i zakończeniu pracy z narzędziem menuconfig ostatnim etapem jest deklaracja odpowiednich struktur i definicji w pliku ../arch/arm/mach-bcm2708/bcm2708.c . W edytowanym pliku dołączamy dyrektywę:
#include <linux/w1-gpio.h>
oraz definiujemy numer wyprowadzenia GPIO, które będzie pełniło rolę linii danych (np. GPIO 4):
#define W1_GPIO 4
Następnie deklarujemy poniższe struktury:
#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) static struct w1_gpio_platform_data w1_gpio_pdata = { .pin = W1_GPIO, .is_open_drain = 0, }; static struct platform_device w1_device = { .name = "w1-gpio", .id = -1, .dev.platform_data = &w1_gpio_pdata, }; #endif
Zadeklarowane struktury rejestrujemy w funkcji void __init bcm2708_init(void) poprzez dodanie wpisu:
#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) platform_device_register(&w1_device); #endif
Po zapisaniu zmian w pliku bcm2708.c możemy przystąpić do kompilacji jądra według wskazówek zawartych na stronie www.elinux.org .
Obsługa magistrali 1-Wire w systemie Linux
W poprzednim podrozdziale zakończyliśmy etap przygotowania jądra systemu do obsługi magistrali 1-Wire. Przed przystąpieniem do obsługi czujników po stronie przestrzeni użytkownika, dołączmy do zestawu Raspberry Pi dowolną liczbę sensorów DS18B20. Sposób podłączenia czujników został przedstawiony na rysunku 9 (numer portu GPIO 4 został zdefiniowany na etapie kompilacji jądra i jest to także domyślny numer portu przy wykorzystaniu gotowego modułu w1-gpio ).
Rys. 9. Schemat podłączenia czujnika DS18B20 do zestawu Raspberry Pi
Jak wspomniano we wstępie artykułu, jądro systemu Linux dostarcza wysoki poziom abstrakcji dołączonego do Raspberry Pi sprzętu. Po skonfigurowaniu jądra każdy dołączony do magistrali czujnik reprezentowany jest poprzez katalog w lokalizacji /sys/bus/w1/devices o nazwie będącej połączeniem kodu rodziny układu i jego numeru identyfikacyjnego. Liczba katalogów w lokalizacji /sys/bus/w1/devices informuje nas więc o liczbie podłączonych sensorów:
cd /sys/bus/w1/devices ls -l
W odpowiedzi:
lrwxrwxrwx 1 root root 0 May 15 15:09 28-000002f1af7c lrwxrwxrwx 1 root root 0 May 15 15:09 28-000002f203e3 lrwxrwxrwx 1 root root 0 May 15 15:09 28-000002f218f8 lrwxrwxrwx 1 root root 0 May 15 15:09 w1_bus_master1
Każdy folder oznaczony numerem identyfikacyjnym sensora zawiera szereg plików, spośród których z punktu widzenia użytkownika najważniejszy jest w1_slave . Zawartość pliku jest tworzona przez jądro systemu w momencie odczytu i zawiera informację o wartości temperatury oraz sumie kontrolnej CRC. Odczyt temperatury z wybranego czujnika może zostać zrealizowany w następujący sposób:
cat 28-000002f1af7c/w1_slave
Przykładowa odpowiedź:
a5 01 4b 46 7f ff 0b 10 f7 : crc=f7 YES a5 01 4b 46 7f ff 0b 10 f7 t=26312
Ponieważ jądro systemu Linux nie operuje na liczbach zmiennoprzecinkowych, wskazywaną wartość temperatury należy podzielić przez 1000, czyli t = 26312/1000 = 26,312°C.
Jądro dostarcza również kilku prostych mechanizmów umożliwiających sterowanie pracą układu mastera. Konfiguracja pracy odbywa się poprzez zapis/odczyt plików umieszczonych w katalogu w1_bus_master1 . Typowe i najważniejsze możliwości konfiguracji przedstawiono poniżej:
- Sprawdzenie liczby podłączonych czujnikówcat /sys/bus/w1/devices/w1_bus_master1/w1_master_slave_count
- Odczyt numerów ID podłączonych czujnikówcat /sys/bus/w1/devices/w1_bus_master1/w1_master_slaves
- Jednokrotne skanowanie magistrali po dołączeniu/odłączeniu nowych czujnikówecho 1 > /sys/bus/w1/devices/w1_bus_master1/w1_master_search
- Wyrejestrowanie z systemu czujnika o numerze ID 28-000002f1af7cecho 28-000002f1af7c > /sys/bus/w1/devices/w1_bus_master1/w1_master_remove