Raspberry Pi UART w 2024 – przewodnik


Jak korzystać z konsoli szeregowej dostępnej dla Raspberry Pi?

UART, konsola szeregowa, RS-232 albo połączenie po serialu – różne nazwy, nie wszystkie do końca poprawne ale mówiące o tym samym. Uruchomienie interfejsu szeregowego jest podstawą i jednym z pierwszych kroków w prawie każdym projekcie embedded. Równie popularne w systemach bare-metal (bez systemu operacyjnego albo z minimalistycznym kernelem) jak i w embedded Linuxie.

Dlaczego?

Jest to najprostsza metoda na komunikację ze sprzętem – możemy użyć normalnej konsoli systemowej, zobaczyć logi z bootowania, porozumieć się z bootloaderem itp. Bez tego będzie nam bardzo ciężko zrobić ciekawsze rzeczy jak np. postawienie stosu sieciowego i łączenie się przez SSH.

Wielokrotnie korzystałem z interfejsu UART na Raspberry Pi 2, 3 i 4 (na 5 jeszcze nie było okazji). Nie jest to trudne ale niestety na tyle skomplikowane, że za każdym razem wymagało dłuższego grzebania po forach, github issues i rozsianych dokumentach. Postanowiłem stworzyć ten poradnik, który skutecznie doprowadzi do podłączenia się po serialu.

Uwaga: Opisane tutaj metody powinny działać tak samo na platformach Raspberry Pi 2, 3, Zero, 4, 5. Na wczesnych platformach (Rev 1, Rev 2) będzie inaczej – schemat GPIO jest inny.

Jeśli jesteś tu tylko po to żeby skopiować potrzebne komendy, bez czytania prozy – przejdź do rozdziału “Szybka referencja” na samym dole strony. Znajdziesz tam również opis GPIO w Raspberry Pi

Jak działa i dlaczego UART?

Na początek trochę teorii. W uproszczeniu – UART jest najpopularniejszym interfejsem do przewodowej komunikacji tekstowej ponieważ:

  • jest bardzo prosty i tani w implementacji,
  • wymaga użycia niewielkiej liczby przewodów,
  • ma bardzo stabilne wsparcie oprogramowania (sterowniki, firmware itp.)

Jeśli ciekawi Cię jak dokładnie działa interfejs szeregowy – polecam zapoznanie się z tym artykułem: link. Jest bardzo dobrze napisany i wzbogacony przejrzystymi ilustracjami. Niestety nie udało mi się znaleźć równie dobrego źródła w języku polskim – daj koniecznie znać jeśli ty takie znasz! (napisz na karol@linuxdev.pl)

Jeżeli nie masz czasu na czytanie – tutaj pigułka wiedzy o interfejsie szeregowym:

  • Interfejs jest asynchroniczny – nadawca (Tx) i odbiorca (Rx) muszą z tego powodu z góry ustalić parametry transmisji np. jej prędkość,
  • Ramka transmisji zawiera bit startu, bit stopu, bity danych oraz opcjonalnie bit parzystości (parity bit),
  • Interfejs jest dość wolny, jego szybkość określa się w tzw. “baud rate” – popularnymi wartościami są 9600 i 115200. Baud rate 9600 oznacza że możemy przesłać maksymalnie 9600 bitów na sekundę,
  • Istnieją bardziej zaawansowane wersje interfejsu szeregowego np. RS-485, bardziej odporne na zakłócenia i bardziej skomplikowane w implementacji. Często używane w środowiskach przemysłowych

Mając podstawową wiedzę w UART możemy zabrać się za część praktyczną – komunikację z Raspberry Pi z naszego komputera.

Co potrzebujemy

Będziemy potrzebować następujących rzeczy:

  • Raspberry Pi 4 z wlutowanymi goldpinami
  • Zasilacz do Raspberry Pi
  • Karta SD np. link
  • Adapter do karty SD: np. link
  • Konwerter USB-UART np. link
  • Komputer z portem USB – Linux lub Windows
  • kabelki jak do płytki stykowej
  • Oprogramowanie – na Linuxie picocom, minicom lub screen, na Windowsie Putty. O programach więcej w dalszej części artykułu.

Nie jestem powiązany z żadnym z wymienionych sklepów – można także bez problemu użyć zamienników.

Podłączenie

Konwerter USB-UART podłączamy do komputera, go gniazda USB:

Raspberry Pi konsola szeregowa konwerter

Kabelkami łączymy piny pomiędzy Raspberry a konwerterem:

RX ↔ TX,

TX ↔ RX,

GND ↔GND

Raspberry Pi połączenie szeregowe z komputerem

Jeżeli na naszym konwerterze jest zworka – należy ustawić ją w położeniu 3.3V

UWAGA – należy zwrócić szczególną uwagę na połączenie naprzemienne pinów RX i TX. Jest to zdecydowanie najczęstsza przyczyna niepoprawnego działania interfejsu.

Poglądowy schemat przedstawiający połączenie:

Pinout Raspberry Pi z oficjalnej dokumentacji – link. Zaznaczyłem interesujące nas piny obsługujące UART:

Konfiguracja na Raspbianie

Przechodzimy do bardziej zaawansowanych zagadnień. Żeby nie komplikować, użyję domyślnego oprogramowania na malinę, czyli Raspbiana. Jest to system Embedded Linux, dostosowany dla potrzeb początkującego ale nie dajmy się zwieść – konfiguracja nie zawsze jest prosta i mnóstwo narzędzi używanych tutaj ma również zastosowanie w konfiguracji zaawansowanych, komercyjnych Linuxów.

System jest odczytywany przez Raspberry poprzez kartę pamięci, więc zanim zaczniemy musimy wgrać na nią odpowiedni system (Raspbian Bookworm 64bit). Jeżeli nie wiesz jak to zrobić, tutaj znajdziesz oficjalny poradnik: LINK

Na partycji bootfs możemy zauważyć plik config.txt – musimy do niego dodać następującą zmienną:

enable_uart=1

Podczas bootowania ta wartość zostanie przekazana do wbudowanego firmware’u w procesorze na Raspberry i przez to zostanie zainicjalizowany odpowiedni sterownik i odblokowane połączenie szeregowe.

Dlaczego nie jest domyślnie włączone?

Powodów może być kilka, ale najważniejszym jest bezpieczeństwo. Jeśli umieścilibyśmy nasz produkt oparty na Raspberry Pi w miejscu publicznym i zapomnielibyśmy wyłączyć połączenia szeregowego, ktokolwiek z konwerterem usb-uart, odrobiną wiedzy i komputerem mógłby zhakować naszą płytkę.

Uwaga: należy zwrócić szczególną uwagę żeby enable_uart=1 znajdował się w sekcji [all]. Jeżeli umieścilibyśmy go np. w sekcji [cm4], nasz interfejs by nie wstał – sekcja zadziała, ale dla innej wersji malinki.

Możemy również uzyć skróconej komendy:

$ echo enable_uart=1 >> config.txt

Warto po zmianach na karcie SD wywołać komendę:

$ sync

Powoduje ona, że wszystkie dane w buforach zostają wpisane do pamięci nieulotnej. Dzięki temu zapobiegniemy sytuacji, że zmieniliśmy zawartość pliku na karcie, wyjęliśmy ją z portu a wartość docelowa się nie zmieniła.

Jeżeli mamy pod ręką klawiaturę, myszkę, monitor i kabel mini HDMI↔HDMI, możemy również włączyć interfejs UART przez narzędzie raspi-config w samym systemie.

To kończy konfigurację od strony Raspberry – teraz zajmiemy się konfiguracją na hoście, czyli naszym komputerze.

Konfiguracja na hoście (Linux)

Przed podłączeniem konwertera USB-UART do gniazda USB wywołaj komendę:

$ dmesg -w

Alternatywnie możemy najpierw podłączyć konwerter a następnie wywołać:

$ dmesg | tail

Ta komenda pozwala nam odczytać zapis logów z bufora kernela. Kernel jest między innymi odpowiedzialny za zarządzanie sprzętem. Jeśli podłączymy nowe urządzenie np. do portu USB, taka informacja zostanie odnotowana przez kernel, który załaduje odpowiedni sterownik i pozwoli nam komunikować się z modułem. Po podłączeniu konwertera powinniśmy zobaczyć podobny log:

[41172.021421] cp210x 1-1:1.0: cp210x converter detected
[41172.024125] usb 1-1: cp210x converter now attached to ttyUSB0

Interesuje nas /dev/ttyUSB0 – to jest tzw. device node, czyli w uproszczeniu plik, który jest abstrakcyjnym ucieleśnieniem UARTa w linuxie. Jak wiadomo, wszystko w Linuxie jest plikiem – nie inaczej będzie w tym przypadku. U Ciebie ten plik będzie nazywać się inaczej, ale na pewno będzie w katalogu /dev

Do połączenia się oprócz nazwy device node potrzebujemy również prędkości (baud rate). Jak ją ustalić?

Baud rate interfejsu ustawia kernel opierając się na informacjach zawartych w pliku cmdline.txt. Ten plik zawiera listę argumentów (command line arguments), która jest przekazywana do jądra. Domyślnie prędkość jest zdefiniowana na samym początku pliku:

console=serial0,115200

Wiedząc pod jakim node’m podłączył się nasz konwerter, możemy użyć narzędzia picocom:

$ picocom -b 115200 /dev/<TTY>

Żeby otworzyć połączenie z raspberry. <TTY> zastąp pozycją odczytają z dmesg.

Jak sprawić żeby nie trzeba było wywoływać sudo za każdym razem?

Wystarczy dodać obecnego użytkownika do odpowiedniej grupy, w tym wypadku UARTem zarządza dialout:

$ sudo usermod -a -G dialout $USER

Jeśli jeszcze nie włączyliśmy Raspberry, po odpaleniu picocom powinniśmy zobaczyć taki napis w terminalu:

Type [C-a] [C-h] to see available commands
Terminal ready

Po włączeniu zasilania do maliny po kilkunastu sekundach zobaczymy log z bootowania płytki:

[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]

Po czym powinien pokazać nam się prompt z logowaniem

Debian GNU/Linux 12 rpi ttyS0
rpi login:

Login i hasło są konfigurowane przez RPi Imager, na etapie wgrywania OS na kartę SD.

I to wszystko! Połączyliśmy się skutecznie raspberry pi ze światem zewnętrznym

Konfiguracja na hoście (Windows)

Na Windowsie nie mamy dostępu do kernela – poradzimy sobie używając menedżera urządzeń oraz programu Putty.

Po podłączeniu konwertera otwieramy menedżer urządzeń w panelu sterowania. W zakładce Ports powinna pokazać się pozycja “USB to UART Bridge”. W nawiasie będzie informacja pod który port COM zostało podpięte nasze urządzenie. W moim przypadku jest to COM6.

Następnie, otwieramy Putty i ustawiamy odpowiednie opcji, jak na obrazku poniżej:

Klikamy przycisk OPEN i to wszystko – połączenie powinno działać.

Najczęstsze problemy (i rozwiązania)

Nic się nie wyświetla

Najczęściej pomieszanie RX, TX, poluzowane kable, brak podłączenia GND – sprawdzić dokładnie połączenie

OS został wgrany nieprawidłowo – spróbować wgrać ponownie

Wyświetlają się znaczki ale nie przypominają żadnego ludzkiego języka

Zły baud rate, np 9600 zamiast 115200

Brak urządzenia /dev/ttyUSBX lub wpisu w menedżerze urządzeń

Brak sterowników w systemie – wyszukać w internecie używając nazwy naszego konwertera

Dym wydobywający się z maliny

Podłączyliśmy się do 5V zamiast GND

Szybka referencja

echo "enable_uart=1" >> config.txt
dmesg -w
dmesg | tail 
picocom -b 115200 /dev/ttyUSBX
dmesg | grep -i -e " Linux " -e uart # przydatna komenda do debugowania problemów z UARTem


Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *