Programowanie Nettigo tinyBrd

Przekonaj się jak łatwo wykorzystać atuty tinyBrd

Najważniejsze zalety tinyBrd

Płytka tinyBrd powstała jako rezultat naszych prac z bezprzewodowymi sensorami. Potrzebowaliśmy modułu, który pozwoli skoncentrować się na ważniejszych aspektach budowania prototypu. Oszczędność energii, transmisja radiowa musiały być dostępne od ręki.

Oprogramowanie to jest to, co czyni tinyBrd naprawdę użytecznym. Przygotowaliśmy podczas naszych prac szkielet oprogramowania, które jest:

W innym artykule pokazaliśmy jak łatwo można zbudować bezprzewodowy czujnik temperatury z tinyBrd. Teraz omówimy dokładniej jak działa oprogramowanie użyte tam oprogramowani i jak je możecie modyfikować na własne potrzeby.

Zakładam, że zainstalowałeś Nettigo tinyBrd Core i przykłady do niego tak jak tam jest to opisane.

Najnowsze wersje

Wszystkie szkice znajdują się na GitHubie: https://github.com/nettigo/tinyBrd

Wersja 1.0 przynosi kilka zmian, które znacznie uprościły cały program. Po pierwsze, niezbędne biblioteki zostały zintegrowane z Nettigo tinyBrd Core. Instalując go, masz od razu biblioteki Radio (komunikacja przez NRF), Battery (tryby uśpienia), biblioteka SPI dla ATtiny84, oraz Storage (do zapisu i odczytu danych z EEPROM).

Nadawnie danych z tinyBrd

Ponieważ do programowania tinyBrd używamy Arduino IDE, główna część programu składa się z dwóch funkcji setup i loop. Oprócz nich znajdziemy tam definicję struktury do wysyłania danych.

Definicje

Pierwszym krokiem jest włączenie odpowiednich bibliotek

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

Od wersji 1.0 Nettigo tinyBrd Core biblioteki te są dostępne po zainstalowaniu obsługi tinyBrd w Arduino IDE.

Następnie definujemy naszą strukturę:

struct SensorData
  {
  byte id;
  long battery;
  byte status;
  float payload;
  byte seq;
  byte retry;
} data;

Struktura to sposób na zgrupowanie kilku zmiennych w jednym opakowaniu. Tu wsadziliśmy następujące zmienne:

Konfiguracja

W setup kolejno są wywoływane funkcje niezbędne do startu modułu.

void setup()
{
  data.id = 6;

  data.status = temperature_setup();

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

W pierwszym kroku ustawiamy ID jakiego będzie używał nasz tinyBrd podczas wysyłania danych. Jeżeli masz więcej niż jedno urządzenie nadające w sieci, jest to metoda na ich rozróżnienie.

temperature_setup odpowiada za skonfigurowanie czujnika temperatury. Jeżeli będziesz chciał podłączyć jakiś własny czujnik, to tutaj musisz wstawić kod niezbędny do uruchomienia czujnika. Wartość zwrócona przez tę funkcję będzie wysyłana do modułu centralnego, jako pole status. W ten sposób będzie mógł on stwierdzić czy dane wysyłane przez sensor są po jego poprawnej inicjalizacji.

W przykładzie użyty został czujnik DS18B20. Komunikuje się on przez protokół OneWire, jeżeli tinyBrd nie nawiąże komunikacji podczas startu, temperature_setup zwróci kod błedu i taki będzie wysyłany do odbiornika. W skrócie - jeżeli wartośc pola status jest różna od 0, wówczas odbiornik wie, że dane wysyłane przez moduł nie są poprawne.

Konfiguracja modułu NRF odbywa się przez polecenie Radio.begin(address,100);. Używany tutaj adres, to adres pod jakim tinyBrd może odbierać dane. W naszym przykładzie nie robimy tego, więc jego wartość nie ma znaczenia, musi być tylko różna od adresu modułu centralnego (ten podamy podczas wysyłania). Liczba 100 to numer kanału na którym nadaje tinyBrd. Numer ten musi się zgadzać z numerem kanału używanym przez odbiornik.

Główna pętla

W loop są trzy części. Pierwsza gromadzi dane do wysłania, druga wysyła dane, a trzecia przechodzi w tryb uśpienia i zapewnia powrót z niego.

void loop()
{
  //get data
  if (data.status) {
    data.payload=0;
  } else {
    data.payload = temperature_read();
  }
  data.battery = batteryRead();

  //send data
  radioWrite(data);

  //go to sleep
  Radio.off();
  sleep(15000);
}

Pierwszy if sprawdza czy czujnik został zainicjowany poprawnie i jeżeli tak (data.status równe 0), odczytuje temperaturę wywołując funkcję temperature_read (o niej za chwilę).

Następnie zapisujemy wartość napięcia zasilającego. batteryRead to funkcja odczytująca napięcie zasilania. Dzięki temu można okreslić czy sensor może jeszcze pracować, czy czas wymienić baterie. Funkcja ta pochodzi z biblioteki Battery, która wchodzi w skład Nettigo tinyBrd Core.

Jakie napięcie oznacza konieczność wymiany baterii? To zależy od użytych elementów. Sam tinyBrd wraz z modułem radiowym będzie poprawnie pracował nawet przy zasilaniu 1,9 V. W naszym przykładzie używamy do pomiaru temperatury DS18B20. Wg noty katalogowej wymaga on napięcia 3 V do pracy i to powinno być napięcie, przy którym wymienimy baterie. Jednak z naszej praktyki wynika, że większość czujników DS pracuje poprawnie zasilane już 2,5 V.

Mając zgromadzone dane, tinyBrd je wyśle, wywołując funkcję radioWrite. Po wysłaniu danych nie pozostaje nic jak przejść w tryb uśpienia. Najpierw wyłaczamy nadajnik (Radio.off()) a następnie cały procesor przechodzi w tryb uśpienia. sleep przyjmuje jako argument liczbę milisekund. Na tyle czasu tinyBrd pozostanie w uśpieniu. Pobór prądu w takim trybie jest na poziomie 9-10 µA - naprawdę niedużo.

Czas uśpienia nie jest precyzyjny! Czas podany funkcji sleep nie jest dokładną wartością. W naszym przykładzie wpisaliśmy 15 sekund, ale rzeczywisty czas uśpienia będzie się nieznacznie różnić.

Wysyłanie danych

Funkcja radioWrite realizuje wysyłanie danych zapisanych w strukturze. Sam interfejs biblioteki Radio przyjmie dowolną strukturę (o rozmiarze max 32 bajty) i ją wyśle do odbiornika. My tutaj chcemy kontrolować nieco dokładniej, co się dzieje z transmisją.

Samo wysyłanie danych to po prostu:

Radio.write(addressRemote,data);

addressRemote to 3 bajtowa tablica zawierająca adres odbiorcy, data to dowolna struktura do wysłania (nie większa niż 32 bajty).

Po wywołaniu tej funkcji procesor na module NRF zaczyna nadawać dane do odbiorcy, a program wykonuje się dalej. Radio.flush() pozwala nam sprawdzić jaki status ostatniej transmisji. I tak, jeżeli zwróci nam RADIO_WAITS, znaczy, że jeszcze nie skończyło nadawać. RADIO_LOST oznacza, że mimo określonej liczby prób nie zostały dane doręczone. RADIO_SENT znaczy, że dane zostały wysłane i moduł NRF odebrał potwierdzenie od odbiorcy.

Tutaj mała uwaga - RADIO_LOST znaczy dokładnie tyle, że nie zostało odebrane potwierdznie doręczenia. Czyli może być tak, że dane nie dotarły do odbiorcy, ale możliwy jest też inny scenariusz. Dane dotarły do odbiorcy, tylko potwierdznie nie zostało odebrane przez nadawcę.

Dla zwiększenia niezawodności, gdy program dostanie odpowiedź RADIO_LOST, wywoływana jest ponownie funkcja radioWrite, ze zwiększonym licznikem retry. Proces wysyłania danych jest powtarzany:

    switch(Radio.flush()){
      case RADIO_SENT:
        data.seq++;
        return;
      case RADIO_LOST:
        radioWrite(data,retry+1);
        return;
    }

Na początku funkcji mamy test:

  if (retry == 5) {
    //we have failed transmit..
    data.seq ++;
    return;
  }

Gdy funkcja jest wywoływana 6 raz z rzędu (bo retry liczymy od 0) już nie próbuje wysłać kolejny raz, tylko wychodzi z funkcji. Kontrola wykonania programu jest przekazywana do miejsca gdzie zostało wywołane radioWrite,

Przebieg dla nieudanej transmisji

Przebieg dla transmisji wysłanej za trzecim razem

Gdy wywołujsze funkcję z niej samej (tak robimy z radioWrite) nazywa się to rekurencją. Przy tej metodzie ważne jest zagwarantowanie sobie, że w końcu przestaniemy wywoływać sami siebie. Dlatego ten warunek na początku funkcji jest konieczny.

Odczyt temperatury

Odczyt temperatury odbywa się w funkcji temperature_read(), która po prostu wykorzystuje naszą bibliotekę do DS18B20 w wersji dla ATtiny.

Czego się nauczyliśmy

tinyBrd jest elastycznym narzędziem, świetnie nadającym się do budowy własnych czujników bezprzewodowych. Ten artykuł powinien uzmysłowić Wam, że modyfikacja kodu tinyBrd by zaimplementować własne rozwiązania nie jest trudna.

Po przeczytaniu tego artykułu powinniście wiedzieć: