joyshield + stringi + nRF24

Dziś nowy gadget:

czyli joy-shield. Co to ten „shield”? To rozszerzenie, z różnymi modułami, które nadrukowane są na płytkę PCB i nie wymagają płytki stykowej i masy przewodów. Taką płytkę „wtyka” się w piny Arduino, tworząc „kanapkę”. Ten shield ma „gierkowe” przeznaczenie – choć my go wykorzystamy do sterowania pojazdem, ale są też inne (do internetu przez kabel eRJotkę, przez sieć bezprzewodową, z kartą SD do zapisu danych, z obsługą silników i inne). Warto łapać okazję na allegro lub podobnych, bo ja swój shield kupiłem za 25 zł! A co on ma w sobie?

  • Joystick (dwie osie + przycisk)
  • cztery przyciski z kolorowymi klawiszami
  • dwa dodatkowe przyciski microswich
  • złącze dla modułów transmisji radiowych:
    — nRF24xx
    —  xbee
    — APC200
  • stabilizator napięcie 3.3V (do zasilania układów radiowych)

Oczywiście moduł (=shield) przeznaczony do współpracy z płytkami Arduino UNO, MEGA, LEONARDO itp. Warto zwrócić uwagę na jakość wykonania – mój ma fajne opisy w łatwo dostępnych miejscach.

Obsługa joysticka – shielda

Okazuje się banalnie prosta. Czytamy położenie dwóch osi (x i y) – czyli porty analogowe A0 i A1 (cóż, ten shield je sobie „rezerwuje” i nie mamy ich możliwosci wykorzystywania). Wszystko ładnie opisane na płytce. Podobnie z przyciskami.

void setup() {
Serial.begin(9600);
}
int x,y;
void loop() {
  x=analogRead(A0);
  y=analogRead(A1);
  Serial.print(x);
  Serial.print("  ");
  Serial.print(y);
  if (digitalRead(5)==1)
    Serial.print(" niebieski");
  if (digitalRead(4)==1)
    Serial.print(" bialy");
  if (digitalRead(3)==1)
    Serial.print(" czerwony");
//i tak dalej
  Serial.println();
  delay(100);
}

Zwracam uwagę na „sprytne” granie metodą print oraz println wraz ze spacjami tak, aby wszystko mieściło się w jednej linii i nie było „pozlepiane”.

A odczytywanie przycisków – skoro używam funkcji digitalRead(pin) to dlaczego nie ma wcześniej pinMode(pin, INPUT)? Otóż domyślnie piny ustawione są w trybie INPUT, dlatego właśnie nic nie dopisywałem. Jesto to warte zapamiętania, co powino nie być trudne – w końcu dla wejść analogowych nie ustawialiśmy w tryb INPUT, czyli z wejściami cyfrowymi jest tak samo.

Stringi = napisy

Temat rzeka… trzeba zacząć, czym są tablice w C. Zauwazyłem, że godnym polecenia jest artykuł na oficjalnej stronie Arduino. Ja dołączam „zrzut ekranu” z zajęć.

Jak zmienić nasz poprzedni kod, aby działał na napisach?

void setup() {
   Serial.begin(9600);
}

String napis;
void loop() {
  napis=String(analogRead(A0));
  napis = napis + "  ";
  napis = napis + String(analogRead(A1));
  if (digitalRead(5)==1)
    napis = napis + String(" niebieski");
  if (digitalRead(4)==1)
    napis += String(" bialy");
  if (digitalRead(3)==1)
    napis += String(" czerwony");
  //i tak dalej
  Serial.println(napis);
  delay(100);
}

Oczywiście nic tutaj nie zyskaliśmy, a nawet gorzej – obsługa klasy String w Arduino jest zasobożerna – czyli mocno powiększa nasz kod, ale tym się jeszcze nie przejmujemy. Na uwagę zasługuje łatwe dodawanie (łączenie) ze sobą napisów – realizuje to zwykły operator + (plus)

Joyshield + nRF24L01+

Łączymy poznane dziś rzeczy z poprzednimi zajęciami i nadajemy to, co robimy na naszym kontrolerze. Właśnie dlatego użyliśmy wersji Stringowej kodu do joysticka, bo radyjko nadawało właśnie napisy – a nawet napisy z maksymalną długością 32 znaków (bajtów). Poniżej kod:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>

RF24 radio(9, 10);//CE, CS

uint8_t rxAddr[6] = "grzyb";

void setup(){
  Serial.begin(9600);
  Serial.print("nRF24 INIT=");
  bool ok=radio.begin();
  Serial.println(ok);
  printf_begin;
  radio.printDetails();
  radio.setRetries(15, 15);
  radio.openWritingPipe(rxAddr);
  
  radio.stopListening();
}

String napis;

void loop(){
  napis = String("Heniek "); 
  napis += String(analogRead(A0));
  napis += " ";
  napis += String(analogRead(A1));
  if (digitalRead(5)==1)
    napis += String(" niebieski");
  if (digitalRead(4)==1)
    napis += String(" bialy");
  if (digitalRead(3)==1) 
    napis += String(" czerwony");
  //i tak dalej<br>
  radio.write(napis.c_str(), napis.length());
  Serial.println(napis);
  delay(100);
}

Na uwagę zasługuje linia nr 37, gdzie musiałem użyć nowej metody klasy String o nazwie c_str(), której zadaniem jest stworzenie napisu w stylu języka C (nieobiektowego). Wymuszone jest to przez metodę write() klasy radio. Dodatkowo, długość napisu w klasie String uzyskujemy za pomocą metody length() – a nie sizeof(napis), gdyż to by zwróciło tylko rozmiar obiektu (a nie danych wewnątrz tego obiektu).

Z kolei w linii 26 rozpocząłem nasz napis imieniem (fikcyjnym) uczestnika koła Fi-BOT tak, aby uruchomiony przeze mnie program odbiornika nRF mógł łatwo zidentyfikować kto mi nadaje (Tosiek, Heniek czy Ziuta — także fikcyjne imiona).

Co dalej?

Wydawać by się mogło, że trzeba teraz tak przygotowany kod uruchomić do sterowania pojazdem. Nieprawda. Było by to baaaardzo kłopotliwe. Problem polega na tym, że trzeba odczytać napis w odbiorniku nRF umieszczonym w pojeździe, a potem odczytać aktualne wychylenie osi X i Y joya, i przyciski. Ale to trudne! Nawet przy pomocy funkcji toInt() zamieniającej napis na liczbę całkowitą – bo najpier należało by podzielić nasz napis na części – może przecinkami, jakoś tak:

123,512,czerwony,zielony

Czyli wówczas przecinek (kropka, myślnik – cokolwiek) by nam oddzielał jedną informację od drugiej, co by było do wykorzystania w połączeniu z metodą indexOf() z klasy String. Cała procedura mogła by wyglądać jakoś tak:

  • odczytujemy napis w pojeździe, przesłany przez joyshield (z przecinkami)
  • skupiamy się na pierwszej części napisu, aż do pierwszego przecinka – wiemy, że ma to być pozycja na osi X – funkcja StringSubstring() i/lub wspomniana indexOf()
  • zamieniamy ten krótki podciąg (od zera do 4 znaków) na liczbę całkowitą – metoda toInt() – i mamy już oś X
  • kasujemy/wyrzucamy z napisu pierwszą część do przcinka, przechodzimy do pozycji na osi Y
  • robimy podobnie, a potem
  • jeśli napis nie jest jeszcze pusty (bo ciągle kasowaliśmy informację o osi X i Y), to znaczy, że mamy jakieś przyciski
  • jeśli jest przecinek, to znaczy, że są nawet dwa (lub więcej) wciśniętych przycisków
  • tworzymy pierwszy podciąg aż do pierwszego przecinka, porównujemy czy jest to „zielony”, „czerwony” itd…
  • po odczytaniu przycisku kasujemy z napisu tą informację
  • jeśli napis niepusty, to są kolejne przyciski…

Proszę zwrócić uwagę, jakie to zagmatfane! Dlatego na kolejnych zajęciach będziemy wysyłać z nadajnika nie napisy (Stringi), ale bajty z informacjami. Dwa bajty wystarczą do podania osi X, kolejne dwa do osi Y, a jeszcze jeden – tylko jeden – do podania stanu wszystkich 7 przycisków na naszym shieldzie. Stworzymy własny protokół danych – podobny do tego, jakiego używaliśmy przy omawianiu oscyloskopu. Dlatego zachęcam do ponownego wczytania się w tamten wpis i opis protokołu danych. Właśnie to nas czeka na następnych zajęciach! Ekscytujące, nieprawdaż? 😉

Przypominam o spotkaniu w ten piątek 19-maja o 14:15 w sprawie XV Festiwalu, a kolejne zajęcia we wtorek 23 maja o godz. 16:15. Nie wiem, czy będziemy mieć siły na 22 więc od razu uprzedzam, że w poniedziałek 22 maja, podczas imprezy Festiwalowej, ustalimy termin kolejnego spotkania Fi-BOTa. Zapraszam!

 

Posted in FiBot and tagged , , , , , , , .