tinyBrd 2.0: Omówienie komunikacji na podstawie przykładu ping-pong

Wiemy już jak wstępnie skonfigurować płytki tinyBrd do pracy ze środowiskiem Arduino, więc najwyższa pora, żebyśmy zabrali się za to, co w tinyBrd najważniejsze, czyli komunikację bezprzewodową.

Żeby nie wymyślać koła od nowa i nie stawiać na sam początek zbyt wysokiej poprzeczki postanowiłem omówić krok po kroku co dzieje się w szkicu o nazwie ping-pong z repozytorium z przykładowymi programami. W kolejnych artykułach będziemy modyfikować ten szkic dodając do niego nowe funkcjonalności (niektóre pisane od zera, a niektóre częściowo kopiowane z innych przykładów).

Zestaw testowy

Programy ping i pong uruchomiłem na konfiguracji z poniższego zdjęcia.

Jak widać do płytki po lewej stronie dołączony jest przycisk podpięty do pinu D2. Na tę płytkę będziemy wgrywali program o nazwie ping. Pong natomiast będzie wgrany do płytki po prawej stronie, do której nie musimy podłączać absolutnie nic.

Drobne modyfikacje

Szkice możemy wgrać niemalże takie jakie są na repozytorium. Jedyna zmiana jakiej musimy dokonać to numery pinów. W obu programach stałą LED ustawiamy na wartość 10 (jest to wbudowana dioda na płytce tinyBrd), natomiast w programie ping dodatkowo zmieniamy wartość stałej BUTTON na 2. Tak przygotowane programy możemy zuploadować na płytki i sprawdzić jak działają. Pożądanym działaniem będzie jeżeli po wciśnięciu przycisku na płytce ping płytka pong zgasi diodę najpierw na 100 ms, a następnie na 400 ms, po czym płytka ping zgasi swoją diodę na jedną sekundę. Jeżeli tak się nie stanie, to prawdopodobnie mamy coś nie tak z modułami radiowymi.

Najważniejsze bloki kodu

Przejdźmy więc do analizy kodu programów. Już na pierwszy rzut oka widać, że są one niemalże identyczne. Jedyna różnica jest właściwie taka, że radia mają inne adresy i płytka ping posiada dodatkowy kod do obsługi przycisku. Co jednak decyduje o poprawnej komunikacji?

Załączenie bibliotek

Jako, że radia podłączone są do mikrokontrolera za pomocą interfejsu SPI poza biblioteką do obsługi modułów musimy załączyć plik nagłówkowy SPI.h

#include <SPI.h>
#include <Radio.h>

Inicjalizacja radia

Aby rozpocząć komunikację radiową musimy zainicjować moduły w programie. Czynność tę wykonujemy w funkcji setup za pomocą takich oto dwóch linijek kodu:

byte address[3] = {1, 0, 0};
Radio.begin(address, 100);

W zmiennej address przechowujemy unikalny adres naszego urządzenia, natomiast drugi parametr metody Radio.begin (liczba 100) oznacza kanał na któym będzie odbywałą się komunikacja. Kanał taki może być liczbą od 0 do 125 i wszystkie modemy, które chcą ze sobą „rozmawiać” muszą pracować na tym samym kanale.

Wysyłanie danych

W przypadku wysyłania danych musimy przekazać do metody Radio.write dwa parametry. Adres odbiornika oraz dane, które chcemy wysłać. Następnie wywołujemy metodę flush, która domyślnie zablokuje nam procesor do momentu wysłania danych.

byte pongAddr[3] = {1, 0, 0};
byte payload = 66;

[...]

Radio.write(pongAddr, payload);
Radio.flush();
delay(50);

W tym przypadku do płytki pong wysyłamy liczbę 66.

Odbieranie danych

Odcyt danych jest trochę podobny do odczytu danych z portu szeregowego. Podobnie jak tam musimy posłużyć się metodą Radio.available, a następnie Radio.read w celu właściwego odczytanai danych.

byte received;

[...]

if (Radio.available()) {
  received = 0;
  Radio.read(&received);
  if (received == 99) {
    lightOn();
  }
}

W tym przypadku jeżeli nasz modem odebrał jakieś dane to zostają one odczytane do zmiennej typu byte o nazwie received. Znak & przed nazwą zmiennej w wywołaniu metody Radio.read oznacza referencję, czyli przekazanie do funkcji miejsca w pamięci, gdzie jest wpisana jakaś wartość, zamiast samej wartości, która się w tej pamięci znajduje. Pozwala to na modyfikowanie zmiennych przekazanych jako parametry przez funkcję.

To wszystko na dziś

W następnym artykule zmodyfikujemy ten przykład tak, żeby wysyłał nieco bardziej skomplikowane dane niż tylko pojedyncze bajty.