Raspberry odbiera dane z NRF24L01

Jak odebrać dane z tinyBrd na Raspberry

Jak działa program odbierający dane z tinyBrd na Raspberry Pi?

W artykule o testowaniu połaczeń z tinyBrd znajdziesz instrukcję jak zainstalować bibliotekę pyNRF od Nettigo oraz przykładowy program testowy.

Jeżeli zajrzysz do wnętrza connectionTester.py przekonasz się, że odbiór danych z tinyBrd jest bardzo łatwy do oprogramowania. Dzięki naszej bibliotece w Pythonie obsługującej NRF24L01+ na Rasbperry Pi niezbędnę jest tylko kilka czynności. Jeśli chcesz się z nim teraz zpoznać, jest na GitHubie

Pierwszą jest rozpoczęcie nasłuchiwania:

    radio = Radio(bytes([0,0,3]),100)

Potrzebne są dwa argumenty, pierwszy to adres pod jakim ma nasłuchiwać Raspberry na pakiety od tinyBrd, a drugi to nr kanału. Oczywiście te dane musza pasować do adresu odbiorcy i kanału jakiego będą używać tinyBrd.

Klasa Radio jest dostępna po zaimportowniu modułu tinybrd:

from tinybrd import Radio

Następnie wystarczy sprawdzić czy są dane do odebrania i jeżeli są, to je odczytać.

if radio.available():  
    data = radio.read()

Nasz biblioteka pyNRF jak i jej odpowiednik dla tinyBrd wspiera domyślnie tzw dynamiczny rozmiar pakietu (dynamic payload). Oznacza to, że klienci mogą wysyłać dowolne struktury (tak długo jak się mieszczą w 32 bajtach).

W naszym testerze sprawdzamy, czy rozmiar odpowiada oczekiwanemu i jeżeli tak, to przekształca go ciąg wartości. Robi to korzystając z funkcji unpack, która zamienia blok bajtów w tablicę wartości. Jakie to są typy wartości określamy w argumencie przekazywanym do unpack. Jeżeli masz jeszcze otwarte Arduino IDE sprawdź kod szkicu testowego wgranego na tinyBrd. Definicja struktury, którą wysyłamy do Raspberry wygląda tak:

struct Payload
  {
  byte id;
  unsigned int battery;
  unsigned int seq;
  byte retry;
  unsigned int lost;
} data;

Raspberry odbiera blok bajtów będący tą strukturą, z taką samą kolejnością. Czyli mamy kolejno 1 bajt na identyfikator (data.id), 2 bajty na napięcie zasilajace (data.battery), 2 bajty na numer pakietu (data.seq), 1 bajt na numer kolejnej próby doręczenia pakietu (data.retry), 2 bajty na łączną liczbę zagubionych pakietów (data.lost). Łacznie 8 bajtów - dlatego najpierw sprawdzamy czy tyle odebraliśmy. Jeżeli tak, to konwertujemy dane do tablicy wartości.

Tabelka w dokumentacji Pythona będzie pomocna, aby dobrać odpowiedni symbol do typu danych. Dla typu byte użyjemy B, dla unsigned int użyjemy I.

if radio.available():
    data = radio.read()
    if (len(data)==8): 
        value = struct.unpack('=BIIBI', data)

Jeżeli pakiet ma 8 bajtów, zostanie zamieniony na na tablicę, która będzie miała kolejno liczby tak jak podaliśmy w formacie przekazanym do unpack. Znak = jest potrzebny, by unpack nie próbował uzupełniać danych dodatkowymi bajtami.

Jeżeli zmienisz pola w strukturze Payload to oczywiście zmień format przekazany do unpack. Na przykład gdy zamiast ostaniej wartości (data.lost) chciałbyś mieć w tym miejscu np temperaturę, jako liczbę zmiennoprzecinkowa (float) to do rozpakowania paczki danych na Raspberry użyć powinieneś formatu =BIIBf. Reszta symboli dostepna w tabelce w linku powyżej. Pamiętaj, że często znaczenie ma czy dana wartośc jest ze znakiem czy bez (jest różnica między b a B).

Pisząc programy na mikrokontrolery takie jak Arduino, tinyBrd i inne staraj się unikać typów danych zmiennoprzezcinkowych (float, double). Użycie takich zmiennych zwiększy objętość Twojego programu i go spowolni. Operacje na takich liczbach nie są wspomagane sprzętowo. Niektóre większe procesory mają moduł do takich obliczeń. W małych, 8-mio bitowych mikrokontrolerach raczej ich nie spotkasz.

W tym momencie już masz do dyspozycji dane odberane z tinyBrd. Dla ułatwienia warto sobie je przypisać do zmiennych o jednoznacznych nazwach. Jeżeli bedziesz używał dalej w kodzie zapisu typu value[3] to narażasz się na kilka niedogodności. Pierwsza jest taka, że łatwo się pomylić i użyć złego indeksu. Takie błędy nie zawsze są potem łatwe do namierzenia. Druga jest taka, że jeżeli zmienisz kolejność pól w strukturze, to wszystkie indeksy w kodzie programu musisz ręcznie poprawić. To też prowadzi do błedów w kodzie. Dlatego my w naszym przykładzie zapisujemy wartości w zmiennych o czytelnych nazwach:

sensor_id = value[0]
battery = value[1]  
seq_no = value[2]   
retry = value[3]    
lost_cnt = value[4]

Reszta programu nie jest już związana z odbieraniem danych z tinyBrd, więc nie będziemy go dokładniej omawiać. Wkrótce przygtujemy więcej przykładów jak Raspberry może się komunikować przez NRF24L01 z tinyBrd.