Promocja: 40% rabatu na wszystkie książki drukowane HELION (elektronika, programowanie) + darmowa dostawa. Polecane tytuły »

RFM12B – #3 – zaawansowana komunikacja

RFM12B – #3 – zaawansowana komunikacja

W ostatniej części naszego kursu, transmisji bezprzewodowej na RFM12B, zajmiemy się obsługą nadawania oraz odbierania w tle.

Na koniec wreszcie uruchomimy komunikację w obu kierunkach.

« Poprzedni artykuł z serii

RFM12B i przerwania

Aby umożliwić programowi wykonywanie innych czynności w czasie nadawania powinniśmy poszukać możliwości sprawdzania stanu układu RFM12B bez konieczności ciągłego kontrolowania sygnału linii MISO.

Taką możliwość daje nam linia nIRQ – przyjmuje ona stan niski, gdy RFM zasygnalizuje różne zdarzenia wewnętrzne – nas interesować będą 2 z nich:

  • odebranie 8 bitów (ich ilość konfigurowaliśmy, o czym wspominałem wcześniej)
  • możliwość nadawania (zapisania do bufora nadawczego) kolejnego bajta z danymi.

W związku z tym podpinamy linię nIRQ do dowolnego pinu przerwania zewnętrznego, które skonfigurujemy na wyzwalanie przy stanie niskim. W przykładzie użyłem przerwania INT0 ulokowanego na pinie PD2 układu ATMega644p.

Linia nIRQ pozostanie w stanie niskim do momentu odczytu statusu układu, w związku z czym plan naszego działania będzie następujący:

  1. Ustawić parametry nadawania/odbioru, aktywować w procesorze przerwanie
  2. Po wystąpieniu przerwania odczytać status i sprawdzić, czy przerwanie wywołało interesujące nas zdarzenie
  3. Jeśli tak to wykonujemy działania dotyczące nadania/odbioru kolejnego bajta danych
  4. Po zakończeniu odbioru/nadawania wyłączamy przerwanie i wyłączamy układ RFM12B

Parę słów o transmisji

Musimy zacząć zastanawiać się nad organizacją transmisji – na razie przesyłaliśmy 1 bajt danych – co jednak, jeśli będziemy chcieli nadać inną ilość danych? I w dodatku różną przy różnych transmisjach? W takiej sytuacji warto zdefiniować sobie sposób w jaki będziemy kodować dane – u nas:

  1. Przyjmiemy, że dane przesyłać będziemy tylko w kodowaniu ASCII
  2. Pozostałe znaki niedrukowane wykorzystamy do sterowania programem
  3. Dodatkowo ustalmy, że znak o wartości 0x03 będzie oznaczał koniec transmisji

Tak więc nadawana ramka będzie mieć postać:

Zaczynamy

Na początku musimy zdefiniować funkcje wyłączającej układ RFM12B i dezaktywujące przerwanie:

Nie wymaga ona dodatkowego komentarza, w związku z czym zajmijmy się teraz funkcjami inicjalizacji nadawania i odbioru.

Najpierw ustawiamy w odpowiedniej zmiennej informację, że RFM będzie nadawał. Następnie, tak jak poprzednio, aktywujemy nadajnik, wcześniej resetując ewentualne przerwania, które wystąpiły przed wywołaniem tej funkcji. Kolejnym krokiem jest ustawienie wskaźnika aktualnie nadawanego bajta na początek bufora i na samym końcu aktywujemy przerwanie.

Zwrócę jeszcze uwagę na to, że w funkcji inicjalizacji włączamy również podciąganie linii przerwania.

Bardzo podobnie wygląda funkcja inicjalizująca odbiór:

Podobnie zapisujemy w odpowiedniej zmiennej informację o tym, że teraz RFM jest skonfigurowany do odbioru danych, po czym włączamy odbiornik, resetujemy synchronizację. Po tym upewniamy się, że linia nIRQ nie wygeneruje przerwania resetując ewentualne zdarzenia, które wystąpiły przed wywołaniem tej funkcji. Następnie ustawiamy wskaźnik odbioru na początek bufora i aktywujemy przerwanie.

Ponadto definiujemy trzy funkcje:

Pierwsza z nich służy do odczytu aktualnego stanu układu RFM, druga zaś kopiuje dane z bufora i liczbę odebranych bajtów danych do zmiennych w naszym programie.

Trzecia funkcja oprócz skopiowania danych z bufora programu do naszego bufora nadawczego i ustawienia liczby bajtów, które będą nadane dodaje do danych elementy stałe – czyli bajty synchronizacji (w tym ten definiowany) oraz bajty kończące transmisję.

Obsługa przerwania

Wreszcie możemy przyjrzeć się samej procedurze obsługi przerwania:

Na samym początku rzecz jasna sprawdzamy, czy linia nIRQ przyjęła stan niski z powodu zdarzenia, które nas interesuje. W przeciwnym wypadku sprawdzamy jeszcze czy zdarzenie to nie jest spowodowane błędami nadajnika lub odbiornika.

Jeśli odpowiedź na pierwsze pytanie jest twierdząca to w zależności od tego czy nadajemy czy odbieramy podejmujemy odpowiednie działania.

W czasie odbioru:

  1. Odczytujemy odebrany bajt danych
  2. Jeśli jest to bajt kończący transmisję to sygnalizujemy zakończenie odbioru i wyłączamy odbiornik
  3. W przeciwnym razie zapisujemy odebrany bajt do bufora, o ile ten nie został przepełniony
  4. W przypadku przepełnienia bufora także sygnalizujemy taką sytuację i wyłączamy RFM

W czasie nadawania:

  1. Jeśli nie nadaliśmy wszystkich danych to wysyłamy kolejny bajt
  2. Po nadaniu wszystkich bajtów z bufora wyłączamy nadajnik i sygnalizujemy zakończenie nadawania

Teraz program nadajnika znacznie się uprościł:

Po standardowej inicjalizacji w pętli głównej postępujemy jak poprzednio, z tym, że dane do nadania kodujemy w zapisie heksadecymalnym i nadajemy jako 2 bajty w kodzie ASCII, po czym czekamy dopóki trwa nadawania. Normalnie zamiast tej pustej pętli while moglibyśmy wykonywać zupełnie inne zadania i jedynie w razie konieczności nadawania sprawdzać, czy poprzednia transmisja została ukończona lub nie wystąpiły błędy.

Podobnie dużo prostszy będzie program odbierający dane:

Tu także po standardowych przygotowaniach dokonujemy inicjalizacji odbioru danych. Dalej w pętli głównej sprawdzamy stan mechanizmu odbiorczego, po wykryciu zakończonego odbioru odczytujemy dane i przygotowujemy się do odbioru następnej paczki danych, po czym wyświetlamy odebrane dane. W przypadku błędu jedynie re-inicjalizujemy mechanizm odbiorczy.

Proste? Mam nadzieję, ze tak, bo zaraz przechodzimy do czegoś trudniejszego!

Drugi stopień wtajemniczenia…

…czyli o zakłóceniach i zmienia kierunku transmisji informacji.

Jak już zapewne zauważyliście układ RFM12B może albo nadawać albo odbierać dane – stanowi to pewne ograniczenie – teraz w razie konieczności wymiany danych w obu kierunkach musimy odpowiednio sterować „kierunkiem pracy” komunikujących się modułów, tak aby jeden z nich był nadajnikiem, a drugi odbiornikiem.

Najlepiej wyznaczyć wtedy jeden z układów jako nadrzędny, który będzie prosił inne układy o informacje, a te będą nadawały tylko i wyłącznie po otrzymaniu takiej prośby.

W związku z tym warto wprowadzić jakiś mechanizm zabezpieczający – w naszym przykładzie zastosuję generowanie sumy kontrolnej crc8, która będzie przesyłana na końcu ramki z danymi. Do wyliczanej sumy kontrolnej wplotę też adres układu, gdyż on także może ulec przekłamaniu, a dzięki temu będziemy mogli odrzucić ramkę z przekłamanym adresem (oczywiście istnieje prawdopodobieństwo tak niefortunnego zbiegu okoliczności, w którym odpowiednio przekłamana zostanie też dana kontrolna crc8, jednak prawdopodobieństwo takiego zdarzenia jest znikome).

Przykład ten jest już dosyć rozbudowany, ale jak poprzednio niemalże każda linijka została skomentowana, w związku z tym serdecznie zachęcam do jego samodzielnej analizy. Odpowiednie pliki projektów znajdują się w załączniku.

Dodatkowo możemy wykonać dwa układy slave i zaobserwować jak sprawdza się możliwość adresowania kilku urządzeń pracujących na tym samym kanale.

W robotyce

Na koniec pora na garść inspiracji gdzie w robotyce można wykorzystać taką komunikację:

  1. Wydawanie poleceń robotowi (np.: start/stop)
  2. Monitorowanie pracy robota
  3. Kalibracja sensorów
  4. Komunikacja między kilkoma robotami
  5. i wiele innych

Mam nadzieję, ze artykuły te nieco przybliżyły Wam komunikację radiową i pozwolą na sprawne stosowanie modułów RFM12B w robotyce. W komentarzach czekam na Wasze pomysły, jak wykorzystać taką komunikację w robocie.

Powodzenia!

« Poprzedni artykuł z serii

bezprzewodowa, komunikacja, moduł, RFM12B, SPI

Trwa ładowanie komentarzy...