Jetson TK1 okiem robotyka – #3 – Programowanie

Jetson TK1 okiem robotyka – #3 – Programowanie

Pora na trzeci artykuł z cyklu o Jetson TK1, którego tematem są interfejsy komunikacyjne. Zaczniemy od prostej kontroli stanu pinów GPIO. Następnie przejdziemy przez interfejs UART, a zakończymy na magistrali I2C.

Poznanie tych interfejsów w praktyce jest ważne, a nawet niezbędne, jeśli chcemy wykorzystać opisywaną platformę przy budowie robotów.

Jetson TK1 - Prosta kontrola wejść/wyjść

Piny ogólnego przeznaczenia mogą być kontrolowane poprzez mechanizm sysfs systemu Linux. Sysfs jest to wirtualny system plików zapewniony przez jądro linuxa, który umożliwia korzystanie z niskopoziomowych urządzeń oraz interfejsów z poziomu przestrzeni użytkownika.

Zaczniemy od prostego wykorzystania tego mechanizmu: z poziomu powłoki tekstowej ustawimy logiczną jedynkę na pinie PGIO_PH1 (pin numer 57). Nie będę tutaj opisywał całej funkcjonalności mechanizmu sysfs. Opowiem o podstawowych mechanizmach, które mogą być przydatne w robotyce. Na początku musimy przejść w tryb superużytkownika:

KursJetson_3_1

Zbliżenie złącza oraz sygnałów IO (po lewej GND / pin 2, zaś po prawej PGIO_PH1 / pin 50).

Tak jak już zostało wspomniane sysfs działa z wykorzystaniem wirtualnych plików, więc przejdziemy do odpowiedniej lokalizacji i poprosimy jądro Linuxa o to, by wyeksportowało kontrolę nad pinem numer 57 do przestrzeni użytkownika, czyli:

Możemy zauważyć, że w danej lokalizacji pojawił się folder o nazwie gpio57:

Teraz poinformujemy komputer o kierunku działania naszego pinu poprzez wpisanie in lub out do pliku direction oraz ustawimy stan wysoki na tym pinie:

KursJetson_3_2

Zdjęcie odczytu napięcia na GPIO_PH1 / pin 50.

Możemy podejrzeć aktualne wartości poprzez wyświetlenie pliku /sys/kernel/debug/gpio:

Aby mieć pewność możemy zmierzyć miernikiem - na pinie 57 mamy napięcie około 1.8V (jest to napięcie zasilania procesora Tegra K1). Następnie, aby udowodnić, że to my mamy kontrolę nad tym pinem ustawiamy stan niski i ponownie mierzymy napięcie:

KursJetson_3_3

Zdjęcie odczytu napięcia na GPIO_PH1 / pin 50.

Aby zakończyć pracę w tym trybie należy posprzątać po sobie, czyli oddać kontrolę nad pinem z powrotem dla jądra linuxa:

Szybkie i łatwe!
Mechanizm sysfs umożliwia zaawansowaną kontrolę wejść/wyjść ogólnego przeznaczenia, ale jest to odpowiednio bardziej skomplikowane i nie będzie w pełni opisane w tym artykule.


Warto zauważyć, że w internecie jest wiele gotowych bibliotek implementujących mechanizm sysfs w C++, dla przykładu biblioteka libgpio. Aby ją zainstalować potrzebne są następujące kroki:

Jak już mamy zainstalowaną bibliotekę możemy skorzystać z programiku napisanego w C.

Program ma za zadanie wczytać znak z klawiatury i w zależności od tego czy będzie to "1" czy "0" ustawić odpowiedni stan na pinie numer 57 oraz wyjść jeżeli będzie to znak "q". Można go rozbudowywać, ale to już zależy od konkretnego zastosowania i kreatywności programisty.

Komunikacja UART z Jetson TK1

W procesorze TK1 dostępne są 4 niezależne instancje interfejsu UART (ciekawskich zapraszam do schematu Jetson TK1):

  • UART1 - złącze J3A2 (piny 41 oraz 44), rejestrowany w systemie jako /dev/ttyTHS0
  • UART2 - złącze J3A2 (piny 65 oraz 68), rejestrowany w systemie jako /dev/ttyTHS1
  • UART3 - brak wyprowadzeń, rejestrowany w systemie jako /dev/ttyTHS2
  • UART4 - wyprowadzony w postaci interfejsu RS232 na złącze J1A2 (typu dsub DB9), rejestrowany w systemie jako /dev/ttyS0

Jak już wcześniej wspomniano procesor TK1 zasilany jest napięciem 1.8V, dlatego możemy mieć problemy przy próbie połączenia z urządzeniem zasilanym innym napięciem. Aby tego uniknąć należy wykorzystać prosty dwukierunkowy konwerter poziomów logicznych.


Jeżeli chodzi o wykorzystanie prawdziwych UARTów, to wszystko jest już praktycznie gotowe - nie trzeba nawet nadawać uprawnień do czytania i pisania plików ttyTHSx, ponieważ domyślnie użytkownik ubuntu należy do grupy dialout, która ma dostęp do tych plików. Nic tylko programować!

Jest on rejestrowany w linuxie jako interfejs ttyS0, który jest wykorzystywany przez getty jako standardowa konsola poprzez mechanizm serwisów włączanych przy starcie systemu. Aby jednorazowo odzyskać kontrolę nad tym interfejsem należy zastopować odpowiedni serwis:

Aby permanentnie wyrzucić serwis z grona serwisów startowych wystarczy wykorzystać właściwy mechanizm, czyli stworzyć odpowiedni plik przykrywający ten standardowy:

Wysokopoziomowe wykorzystanie interfejsu UART można przeprowadzić z wykorzystaniem mechanizmu termios wbudowanego w linuxa. Najpierw jednak połączymy sygnał UART_RX z UART_TX, by przetestować poprawność działania na przykładzie poniższego programu:

Program ma za zadanie wczytać znak z klawiatury i w zależności od tego czy będzie to "1" czy "0" wysłać go poprzez UART, a skoro sami połączyliśmy UART_TX oraz UART_RX, to od razu zgłosi się przerwanie zgłaszające gotowość danych. Jeżeli zostanie wysłany znak "q", to przy odebraniu go program wyczyści wszystkie zasoby i wyjdzie.

KursJetson_3_4

Po lewej UART2_RXD / pin 65, zaś po prawej UART2_TXD / pin 68.

Jetson TK1 - Interfejs I2C

W procesorze TK1 jest dostępnych sześć różnych szyn I2C. Z tego cztery są wyprowadzone na złącza J3A1 oraz J3A2. Należy jednak zwracać szczególną uwagę pod jaką nazwą rejestrowana jest konkretna szyna w jądrze Linuxa oraz na poziomy napięć konkretnych szyn.

Poniżej przedstawiono podstawowe informacje o wszystkich dostępnych dla robotyka interfejsach I2C w płytce deweloperskiej Jetson TK1.

KursJetson_3_5

Tabelka przedstawiająca wszystkie wyprowadzone interfejsy I2C.

Aby nie tracić czasu od razu zaczynamy zabawę z płytką od instalacji pakietu:

Na początku sprawdzamy zainstalowane w linuksie szyny I2C:

Na razie wszystko gra i już na obecnym etapie możemy podejrzeć jakie urządzenia są podłączone do danej szyny I2C procesora za pomocą komendy:

Gdzie ostatni parametr komendy oznacza skanowany numer szyny. Na powyższym listingu widać, że domyślnie na płytce do szyny 0 dołączone są 3 urządzenia i są nimi (ciekawscy mogą odnaleźć je na schemacie elektrycznym płytki):

  • kodek audio o adresie 0x1c,
  • sensor temperatury o adresie 0x4c,
  • pamięć EEPROM o adresie 0x56.

Oprócz tego domyślnie do szyny o numerze 4 dołączony jest również moduł zarządzania zasilaniem o adresie 0x40. Możemy teraz podejrzeć wartości wszystkich dostępnych rejestrów urządzenia za pomocą programu i2cdump:

Teraz spróbujmy ustawić wartość rejestru 0x58 na 0x04:

A następnie go odczytać:

Teraz czas na bardziej zaawansowane użycie tego interfejsu i pokażę to z wykorzystaniem modułu cyfrowego akcelerometru z wyjściem cyfrowym, którego sercem jest układ LIS35DE.

Układ jest zasilany napięciem od 2.16V do 3.6V, dlatego zachodzi konieczność użycia szyny GEN2_I2C, czyli i2c-1. Po podłączeniu sprawdzimy, czy układ jest wykrywany w Linuksie.

Jak widać moduł jest wykrywany pod adresem 0x1d. Mamy wszystko, by zrealizować cykliczne czytanie wartości przyspieszenia z czujnika. Można byłoby zrealizować to poprzez skrypt basha z wykorzystaniem wyżej przedstawionych narzędzi.

Jednak nie będziemy mieli wtedy pełnej kontroli nad częstotliwością odczytu. Z tego względu najlepiej jest wykorzystać wbudowane mechanizmy Linuksa do komunikacji z urządzeniami I2C.

KursJetson_3_6

Zbliżenie złącza oraz sygnałów IO (od lewej GND /pin 14, 3V3 / pin 16, GEN2_I2C_SCL / pin 18 oraz na końcu GEN2_I2C_SDA / pin 20).

W tym celu proponuję ściągnąć przygotowany przeze mnie program do odczytu wartości przyspieszenia z modułu KAmodMEMS2:

Program ma za zadanie połączyć się z płytką oraz cyklicznie, co 10 milisekund, odczytać i wyświetlić wartość przyspieszenia w osi x.


Obsługa interfejsu I2C wymaga jeszcze słowa komentarza odnośnie adresowania urządzeń I2C. Muszę przyznać, że z tymi adresami w Linuksie jest małe zamieszanie i dużo czasu spędziłem zanim zrozumiałem o co chodzi.

Programy wchodzące w skład paczki i2c-tools podają adres bez uwzględnienia najmniej ważnego bitu (LSb), który jest ustawiany na 0 lub 1 w zależności czy jest to akcja czytania, czy zapisania do urządzenia. Dlatego przeczytaliśmy wartość 0x1d.

Podsumowanie

Ktoś może zauważyć, że w tym wszystkim zabrakło miejsca dla SPI i muszę przyznać, że sam byłem zawiedziony, że Jetson nie ma łatwego dostępu do tego interfejsu. W chwili obecnej L4T ma domyślnie wyłączony moduł SPI. Aby go włączyć należałoby przekompilować jądro. Można znaleźć w sieci opis tej procedury, wydaje mi się jednak, że łatwiejszym rozwiązaniem będzie wykorzystanie urządzenia z interfejsem I2C.

Nawigacja kursu

To już koniec podstawowej wersji artykułu. Za pomocą przedstawionych mechanizmów można zintegrować porządnie działający system robotyczny, co postaram się pokazać w następnej, czwartej części. CUDAownego budowania robotów!

Autor kursu: Daniel (danioto) Koguciuk
Redakcja: Damian (Treker) Szymański

cuda, embedded, jetson, linux, recenzja, tk1

Trwa ładowanie komentarzy...