Jak wysyłać SMS-y za pomocą starych telefonów i Arduino

Zbiór wpisów o tym jak połączyć płytkę kontrolera Arduino do telefonu i wysyłać SMS-y.

Motorola C168i

Telefon ma wbudowany port komunikacji w gnieździe słuchawkowym mini-jack. Można połączyć je bezpośrednio z pinami Arduino.

Komunikacja odbywa się interfejsem szeregowym RS232 TTL, znanym w Arduino jako Serial. Rozkazy wydaje się za pomocą komend AT.

Nokia 6110, 6130, 6150, 6190, 5110, 5130, 5150, 5190, 3210, 3310

Nokia miała różnego typu własnościowe gniazdka zasilania/komunikacji. Trzeba znaleźć o nich informację. Gniazdo telefonu ma piny działające jako standardowy interfejs RS232 TTL (Serial) z poziomami logicznymi o napięciu 3,3 V.

Do podłączenia wystarczą 3 przewody RX, TX i GND oraz 2 rezystory dopasowujące poziomy logiczne z 5 na 3,3 V.

Telefony komunikują się za pomocą binarnego protokołu FBUS udokumentowanego przez projekt Gnokii.

O tym jak podłączyć Nokię 6150 do Arduino przeczytasz w poniższym wpisie:

Nokia 6310i

W tym telefonie podłączenie jest takie samo jak w poprzednich Nokiach. Różnica polega tylko na tym, że protokół został nieco zmieniony.

Informacje o podłączeniu i sposobie komunikacji uzyskasz w poniższym wpisie:

Telefony kupisz w jednym z popularnych portali aukcyjnych. Arduino zaś kupisz w Nettigo.pl 🙂

sprae

Adafruit Motor Shield v2 i silnik krokowy

Niedawno napisała do nas Roksana z pytaniami dotyczącymi sterowania silnikami krokowymi przez moduł Adafruit Motor Shield v2. W e-mailu wymieniłem tyle informacji, że warto podzielić się nimi z Tobą.

image

Do modułu można podłączyć 2 silniki krokowe. Pierwszy do złącz M1, M2, drugi do wyprowadzeń M3, M4.

image

Zdjęcie pochodzi ze strony Adafruit.com

Jeśli chodzi o część elektryczną to tyle.

Biblioteki sterujące silnikiem można pobrać ze strony Adafruit

Przykładowy program do sterowania silnikiem krokowym wygląda tak:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 

Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);

void setup() {
  AFMS.begin();  
  myMotor->setSpeed(10);
}

void loop() {
  myMotor->step(100, FORWARD, SINGLE); 
  myMotor->step(100, BACKWARD, SINGLE); 

  myMotor->step(100, FORWARD, DOUBLE); 
  myMotor->step(100, BACKWARD, DOUBLE);
  
  myMotor->step(100, FORWARD, INTERLEAVE); 
  myMotor->step(100, BACKWARD, INTERLEAVE); 
  
  myMotor->step(50, FORWARD, MICROSTEP); 
  myMotor->step(50, BACKWARD, MICROSTEP);
}

Najpierw w programie wybierane są biblioteki używane do sterowania silnikiem:

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Wire.h – to biblioteka magistrali TWI/i2c, bo sterownik silnika tak się komunikuje z Arduino.
Adafruit_MotorShield.h – biblioteka obsługi shieldu
utility/Adafruit_PWMServoDriver.h – pomocnicza biblioteka obsługująca sterownik silnika

Potem tworzone są obiekty reprezentujące shield i podłączony do niego silnik.

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 

Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);

Obiekt AFMS reprezentuje shield, wskaźnik obiektu *myMotor reprezentuje podłączony do niego silnik.
Argumenty metody zwracającej obiekt silnika są następujące:

AFMS.getStepper(200, 2);

Pierwszy to inlość kroków silnika na jeden obrót. W tym przypadku jest to 200 kroków na obrót.
Silniki mają różne oznaczenia. Czasem jest to ilość kroków na obrót, a czasem kąt obrotu na jeden krok.
Jeśli nasz silnik ma podany ten drugi parametr to obliczamy go następująco. Wiadomo, że cały obrót to 360 stopni. Jeśli jeden krok to 1,3 stopnia, to na cały obrót przypadnie 360 / 1,3 = około 277 kroków.

Drugim argumentem jest numer silnika. Jeśli byłaby tam wartość 1, to znaczy, że chcemy obiekt silnika podłączony do zacisków M1, M2. Wartość 2 odpowiada silnikowi podłączonemu do zacisków M3, M4.

W funkcji setup wykorzystywane są następujące elementy:
AFMS.begin() aktywuje shield. Domyślnie nie ma argumentu, ale można mu podać, jeśli się chce. Argument to częstotliwość impulsów PWM sterujących silnikiem. Domyślnie jest to 1600 Hz. Ale możesz wybrać liczby z zakresu od 23 do 2034 Hz.

myMotor->setSpeed(10) to ustawienie prędkości z jaką ma się poruszać silnik. W tym wypadku jest to 10 obrotów na minutę.

W funkcji loop znajdują się metody uruchamiające silnik.
myMotor->step(100, FORWARD, SINGLE) przekręca oś silnika o 100 kroków, zgodnie z obrotem wskazówek zegara, przy użyciu jednej cewki.

Pierwszy argument to liczba kroków obrotu. Jeśli silnik ma 200 kroków, to 100 oznacza połowę obrotu osi.

Drugi argument to kierunek obrotu.
FORWARD to zgodnie z obrotem wskazówek zegara
BACKWARD to ruch odwrotny, przeciwny ruchom wskazówek zegara

Ostatni argument to tryb pracy silnika
SINGLE to sterowanie za pomocą jednej cewki. W ten sposób można uzyskać największą szybkość obrotu. Ale za to silnik pracuje z mniejszą siłą.

DOUBLE to normalna praca silnika. Do obrotu wykorzystywane są 2 cewki, silnik porusza się ze standardową prędkością i używa maksymalnej siły momentu obrotowego.

INTERLEAVE to praca z przeplotem. Silnik wykorzystuje sztuczkę w której tworzy się dodatkowy krok między cewkami (gdy zasili się je na raz). W ten sposób mamy 2x więcej kroków. Kosztem tej sztuczki jest to, że ten krok pomiędzy ma siłę 70% mocy silnika.

MICROSTEP to praca silnika w której cewki są sterowane przez impulsy PWM. Mogą dzięki temu tworzyć dużą ilość kombinacji zasilania cewek. W ten sposób tworzy się dużo kroków pośrednich, zwiększając płynność obrotu silnika.
Biblioteka domyślnie ma wbudowane 16 mikrokroków.
Wadą tego rozwiązania jest to, że niektóre mikrokroki zapewniają dużo mniejszy moment obrotowy (nawet 10% mocy silnika), co może spowodować mniej dokładny ruch ciaśniejszych maszyn napędzanych silnikiem.

To tyle jeśli chodzi o bibliotekę. Teraz sztuczki.
Grzebiąc w plikach biblioteki można ustalić ilość mikrokroków. Do wyboru jest 8 lub 16. Wszystko zależy od twoich preferencji, czy bardziej płynny ruch i zmniejszenie siły niektórych kroków do 10%, czy mniej dokładny ruch, ale minimalna siła zmniejszona do 20%.

Opcja zmiany znajduje się w pliku biblioteki Adafruit_motorShield.h w linii 26. Ustawia się przez zmianę liczby przy definicji MICROSTEPS na 8 lub 16.

Ponieważ Arduino komunikuje się ze sterownikiem przy pomocy dość powolnej magistrali TWI/I2C, przy dużej ilości mikrokroków cięzko uzyskać dużą szybkość silnika. Arduino domyślnie ustawia prędkość magistrali TWI na 100 kHz. Można ją bez problemu przyspieszyć 4-krotnie.
W tym celu trzeba otworzyć plik biblioteki Wire.h, znajdujący się w
hardware/libraries/Wire/utility/twi.h
i zmieniasz w nim linię odpowiedzialną za prędkość z
#define TWI_FREQ 100000L

na
#define TWI_FREQ 400000L

Od tej chwili możesz cieszyć się zwiększoną prędkością przesyłania danych o obrotach do sterownika.

Moduł Adafruit Motor Shield v2 jak i silniki krokowe znajdziesz w Nettigo:

sprae

Świąteczna ozdoba na choinkę

Dawno dawno temu, mój wujek robił wymyślne ozdoby choinkowe na choinkę babci. Najciekawszą była gwiazda na szczycie choinki, podświetlana małymi żarówkami. Mrugały one w dość losowy sposób. Sterował nimi zwykły starter od świetlówek podłączony szeregowo.

Dziś mamy nowocześniejsze czasy i dostęp do kontrolerów.

Mikołaj Sochacki opisał na swoim blogu ciekawy projekt nowoczesnej gwiazdki na szczyt. 

Zbudował ją w oparciu o Arduino Pro Mini oraz pierścień składający się ze znanych lampek LED sterowanych szeregowo.

Napisał też do nich program z wymyślną iluminacją świetlną.

Jeśli też chciałbyś zbudować podobną ozdobę choinkową, części do niej możesz kupić w Nettigo.pl

sprae

Hackuj odkurzacz

Firma iRobot ma ciekawy pomysł na platformę robota. Postanowili wykorzystać do tego gotowy produkt masowej produkcji – inteligentny odkurzacz.
Jest to bardzo dobry pomysł, bo obniża koszty produkcji. Producent skorzysta też pewnie na tym, że pozna wiele ciekawych pomysłów na wykorzystanie/usprawnienie urządzenia.

image

Platforma robota iRobot Create 2 – zdjęcie pochodzi ze strony iRobot.com

Hackowanie zaczyna się fajnym motywem – trzeba wywiercić otwór w zielonej osłonie. Pod otworem znajduje się gniazdo z interfejsem szeregowym. 

Do gniazda można wpiąć przewód USB i sterować platformą za pomocą komputera. Można też podłączyć tam Arduino, Raspberry Pi lub dowolną inną płytkę kontrolera obsługującego RS232 o poziomach logicznych 5 V.

Sterowanie jest proste. Polega na wysyłaniu przez interfejs szeregowy odpowiednich poleceń i odbierania wyników ich działania. Poleceń jest mnóstwo na każdą okazję.

Proste polecenia składają się na rozkazanie odkurzania lub zaplanowania pór dnia i dni w których ma pracować, aż po rozkaz automatycznego wpięcia się do ładowarki.

Trudniejsze polecenia to przetworzone dane z czujników. Służą do nawigacji robotem. Niektóre z nich to wykrywanie kolizji ze ścianą, wykrywanie, że koła nie dotykają ziemi lub rzeczy związane z obliczaniem przejechanej trasy z dokładnością do milimetra i kątem obrotu.

Są też polecenia sterowania wbudowanym wyświetlaczem i lampkami LED oraz klawiszami. Platforma ma też możliwość odbierania danych w podczerwieni z akcesoriów pomagających w nawigacji lub ładowarki. 

Najbardziej zaawansowane polecenia to ręczne odbierani nieprzetworzonych danych z czujników i sterowanie silnikami. Można też zbadać ile każde z urządzeń pobiera prądu oraz ile zostało prądu w akumulatorze.

Platforma wydaje się świetna dla majsterkowiczów. Jest wyposażona w dużą ilość czujników, a producent nie szczędzi możliwości ich kreatywnego wykorzystania w każdy możliwy sposób.

Cena urządzenia u producenta ustalona jest na $200 USD. Niestety na razie platforma nie jest dostępna poza Stanami Zjednoczonymi 🙁

sprae

light_ws2812 – Nowa biblioteka do obsługi sterowanych szeregowo LED-ów

W Nettigo mamy dostępne LED-y RGB sterowane interfejsem szeregowym. Można za pomocą jednego cyfrowego pinu kontrolera sterować całym szeregiem takich diod i ustawiać każdej niezależnie kolor z 24 bitowej palety (17 mln barw).

image

Mamy też całą taśmę takich lampek LED. W jednym metrze mieści się ich 60. Taśma jest w osłonie wodoodpornej.

image

Myślę, że to fajny element zestawu majsterkowicza DIY do przyozdobienia domu lub choinki na święta z własnym niepowtarzalnym schematem świecenia.

Piszę o nich ponownie, gdyż pojawiła się nowa lepsza biblioteka do sterowania tymi lampkami. Nazywa się “light_ws2812” i dostępna jest w serwisie Github.

Biblioteka obsługuje procesory ARM, ATtiny oraz platformę Arduino.

Oto przykład jej zastosowania na platformie Arduino:

#include <WS2812.h>

WS2812 LED(1);
	
cRGB color;

void setup() {
  LED.setOutput(9);
}

void loop() {
  color.r = 255;
  color.g = 0;
  color.b = 0;
  LED.set_crgb_at(0, color);
  LED.sync();
  delay(500);
  
  color.r = 0;
  color.g = 255;
  color.b = 0;
  LED.set_crgb_at(0, color);
  LED.sync();
  delay(500);
  
  color.r = 0;
  color.g = 0;
  color.b = 255;
  LED.set_crgb_at(0, color);
  LED.sync();
  delay(500);
}

Na początku trzeba ustawić bibliotekę sterującą światełkami poprzez dyrektywę include:

#include <WS2812.h>

Potem tworzę obiekt o nazwie LED odpowiedzialny za sterowanie diodami:

WS2812 LED(1);

Jego pierwszy argument określa ilość LED-ów podłączonych w szeregu do wybranego pinu. Nadałem mu wartość 1 bo podłączyłem jedną diodę. 

Następnie tworzę zmienną o nazwie color typu cRGB:

cRGB color;

Służy ona do przechowywania wartości koloru składającej się z 3 barw podstawowych R – Red [czerwony], G – Green [zielony] i B- Blue [niebieski].

W funkcji setup za pomocą metody “setOutput” [ustaw wyjście] ustawiam pin do którego podłączyłem diody.

LED.setOutput(9);

Wybrałem pin cyfrowy 9.

W funkcji loop określiłem animację świecenia lampki. Polega ona na tym, że co pół sekundy zmienia się kolor pierwszej lampki na jeden z 3 podstawowych kolorów w pełnej jasności.

Najpierw ustawiam jasności poszczególnych składowych kolorów w zmiennej color:

color.r = 0;
color.g = 255;
color.b = 0;

W tym przypadku ustawiłem wartość g na 255, co daje maksymalną jasność dla koloru zielonego, natomiast inne składowe otrzymały najniższą wartość czyli 0. Możesz stosować dowolne kombinacje kolorów ustawiając odpowiednie wartości składowych jako liczby od 0 do 255.

Potem przypisuje ustawiony kolor do wybranej diody za pomocą metody “set_crgb_at”.

LED.set_crgb_at(0, color);

Jego pierwszy argument to numer diody w szeregu, której chcesz ustawić kolor. Drugim argumentem jest wartość koloru przechowywana w zmiennej color.

By wysłać dane o kolorze do lampki, trzeba użyć metody “sync”.

LED.sync();

I to tyle. Możesz teraz tworzyć własne unikalne animacje świetlne w prosty sposób.

O tym jak podłączyć diody do Arduino dowiesz się ze starszego wpisu:

Bibliotekę możesz ściągnąć z serwisu Github:

Diody w dwóch wersjach jak i wodoodporną taśmę kupisz w Nettigo.

sprae

Assert4a – assert dla Arduino IDE – szybkie libki

Ta biblioteka jest zajefajna i powstała dziś rano.

Pisanie programów to fajne zajęcie. Jednak od czasu do czasu zdarzają się chwile, że program nie chce działać tak jak tego oczekuję. Im dłużej to trwa tym bardziej projekt demotywuje.

Jednym z ciekawszych podejść do tego problemu jest pisanie programów opartych na testach. Najpierw pisze się program, który sprawdzi czy nasz program lub jego elementy działają dobrze. Potem pisze się właściwy program tak długo, aż ten testujący zakończy wszystkie testy jako prawidłowe.

W takich chwilach zwykle uruchamia się profesjonalne narzędzia typu debugger, którym analizuje działanie programu krok po kroku i sprawdzam jakie dane znajdują się w zmiennych. Jak znajdują się złe to zastawiam się czemu ;-).

Niestety w Arduino IDE nie ma debuggera. Trzeba sobie radzić amatorsko.
Najbardziej prymitywnym sposobem jest świecenie wbudowaną diodą L13, gdy następuje jakieś ważne/dziwne wydarzenie w programie.

int zmienna;

void setup() {
  pinMode(13, OUTPUT);

}

void loop() {
  zmienna++;
  if (zmienna < 0)
  {
    digitalWrite(13, HIGH);
  }
}

Tu program sprawdza czy zmienna jest mniejsza niż zero. Jeśli tak to świeci lampką L na płytce drukowanej Arduino.

Innym sposobem jest testowanie programu przez wysyłanie komunikatów do Monitora Portu Szeregowego w Arduino.

int zmienna;

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

void loop() {
  zmienna++;
  if (zmienna < 0)
  {
    Serial.println(zmienna);
    delay(1000);
  }
}

Gdy zmienna jest poniżej zera program wyśle jej wartość do komputera.

Fachowo takie sprawdzanie programu nazywane jest >>debug za pomocą print “dupa”<< 😉 i jest często powodem drwin profesjonalnych programistów.

Takie testowanie programu może być kłopotliwe przy bardziej rozbudowanych kodach. Upychasz coraz więcej print w różnych zakamarkach programu i na końcu Monitor Portu Szeregowego zaczyna wyświetlać tyle komunikatów, że przypomina to monitorowanie z filmu Matrix.

W wielu językach programowania wymyślono już ciekawe rozwiązania pomagające w takim testowaniu programu. Najpopularniejsze nazywa się “assert” [twierdzić/dowodzić czegoś].

Jego użycie w programie wygląda jak użycie normalnej funkcji. Z tym, że zamiast argumentu podajesz warunek. Warunek to określenie przy jakich parametrach program będzie działał prawidłowo. W przypadku naszego programu zapiszę to jako:

assert(zmienna >= 0);

Ponieważ zakładam twierdzenie, że funkcja będzie działała dobrze tylko wtedy, kiedy zmienna będzie większa lub równa zeru.

Jeśli wydarzy się coś w programie i warunek nie będzie spełniony (zmienna będzie miała wartość mniejszą niż zero) to dostaniemy komunikat informujący w którym pliku programu, w jakiej linii i jakiej funkcji warunek nie został spełniony. Program zostanie dla bezpieczeństwa zatrzymany.
Taka prosta funkcja funkcja, a zwraca wszystkie niezbędne informacje.

Standardowa biblioteka assert.h z języka C++ nie działa dobrze w Arduino IDE. Postanowiłem napisać bibliotekę poprawiającą jej działanie. Nazwałem ją Assert4a.h.

#include <Assert4a.h>

int zmienna;

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

void loop() {
  zmienna++;
  assert(zmienna >= 0);
}

W funkcji loop za pomocą assert, zakładam że program będzie dobrze działał, jeśli zmienna będzie miała wartość większą lub równą 0.
Gdy program nie spełni tego warunku, w Monitorze Portu Szeregowego otrzymam komunikat:

Assertion: ‘zmienna >= 0’ failed
   File ‘sketch_dec09a.ino’, at line 12, in function ‘loop’

Mówi on, że twierdzenie “zmienna >= 0” okazało się nieprawdziwe. Nieprawidłowość wystąpiła w pliku programu “sketch_dec09a.ino”, w linii 12, w funkcji “loop”.

Możesz obstawić dużą część programu takimi twierdzeniami i jak coś złego się stanie to będziesz miał informację gdzie i dlaczego.

Gdy przetestujesz już cały program nie musisz usuwać assert-ów żeby je wyłączyć. Wystarczy, że nad include z biblioteką napiszesz #define NDEBUG

#define NDEBUG
#include <Assert4a.h>

int zmienna;

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

void loop() {
  zmienna++;
  assert(zmienna > 0);
}

Gdy zajdzie potrzeba ponownego testowania, usuniesz define i bedziesz mógł dostawać komunikaty o błędnym działaniu.

By zainstalować bibliotekę, wystarczy pobrać plik zip, a potem w Arduino IDE wybrać menu Szkic -> Importuj bibliotekę… -> Dodaj bibliotekę…

PS. Zadanie domowe z gwiazdką – kto wytłumaczy w komentarzach czemu w pierwszym programie lampka L13 zaświeciła się?

sprae

Błąd programowania Arduino

Jeśli nie mogłeś zaprogramować swojego Arduino, a program wyświetlił taki błąd:

avrdude: stk500_getsync(): not in sync: resp=0x00
avrdude: stk500_disable(): protocol error, exprct=0x14, resp=0x51

To istnieje spora szansa na naprawę urządzenia.

Autor bloga redhotEngineer’s Blog miał podobny problem i postanowił podzielić się nie tylko rozwiązaniem, ale też sposobem jak do tego doszedł.

Najpierw trzeba sprawdzić, czy do kontrolera Arduino dochodzą sygnały z interfejsu szeregowego.
W tym celu trzeba przed podłączeniem do komputera:

  1. połączyć piny cyfrowe 0 (RX) i 1 (TX) ze sobą;
  2. połączyć pin RESET z GND w sekcji POWER.

Po podłączeniu Arduino do komputera płytka odeśle wszystko co do niej wyślesz w niezmienionej formie. Żeby to sprawdzić wystarczy włączyć Arduino IDE, potem Monitor portu szeregowego i coś wysłać. Jeśli to co było wysłane pojawi się w polu odebranych danych, to znaczy, że ustawiłeś dobry port, przewód USB oraz układy komunikacji są dobre.

Cała wina spada teraz na kontroler. Mógł zostać uszkodzony, jego program rozruchowy odpowiedzialny za programowanie może nie działać.
Jeśli program, który wgrałeś do Arduino wcześniej działa – miga diodami, steruje tym czym miał sterować to znaczy, że kontroler działa.

Autor odkrył, że w tych przypadkach kontroler z komputerem nie mogą się dogadać, bo port szeregowy nadaje z inną prędkością niż komputer chce odbierać. Uszkodzony okazał się rezonator kwarcowy, który ustala częstotliwość kontrolera.

Wystarczyło wymienić go na inny o częstotliwości 16 MHz i płytka wróciła do dawnej świetności.

sprae

Wykrywanie ilości szeregowych lampek LED

Wcześniej opisywałem sterowane interfejsem szeregowym lampki LED

Tim na swoim blogu cpldcpu przedstawił świetną koncepcję na wykrywanie ile jest podłączonych lampek LED do Arduino.

Koncepcja jest prosta i genialna czyli hackerska ;-). Wszystko opiera się na tym, że im więcej lampek świeci na biało tym większy spadek napięcia zasilania procesora Arduino.

Mierzenie napięcia zasilającego procesor opisywałem już wcześniej.

Można zastosować 2 strategie.

  • Zapalasz kolejne lampki, aż napięcie przestanie spadać – znaczy to, że już więcej nie ma. Autor odkrył, że można tak zbadać do 16 lampek.
  • Zapalasz kolejne lampki, gasząc poprzednią tak długo, aż napięcie wróci do poziomu przed włączeniem.


Wykres pochodzi z bloga Tim-a

W ten sposób można wykrywać nie tylko ilość, ale też gdzie się przepaliła dioda, albo gdzie jest zerwane połączenie.

Pojedyncze szeregowe lampki LED, jak i cały łańcuch kupisz w Nettigo. Dobre do zrobienia ozdób choinkowych lub własnego efektu na świąteczne przystrojenie domu.

sprae

Dekoder alfabetu Morse’a z Arduino

Alfabet Morse’a był stosowany za czasów telegrafu. Kiedy jeszcze nie umieliśmy przesyłać głosu za pomocą kabli i fal radiowych. Dziś jeszcze stosuje się go w krótkofalarstwie. Tam, gdzie możliwości przesyłu głosu są za słabe ze względu na zakłócenia lub dużą odległość.

Alfabet Morse’a przedstawia wszystkie litery alfabetu i cyfry za pomocą kombinacji dwóch znaków – kropki i kreski. Kropka oznacza zwykle nadanie krótkiego sygnału, a kreska długiego. Sygnał może być przedstawiany w formie światła – stosowane w statkach na morzu, prądu w przewodzie – stosowane w telegrafie lub nadawanie fali radiowej – w radiostacji.

Napis Nettigo w kodzie Morse’a będzie wyglądał następująco:

-. . - - .. --. ---
N E T T I G O

Więcej o tym kodzie możesz dowiedieć się z Wikipedii

Nicola Cimmino stworzył dekoder alfabetu Morse’a z Arduino.

Ukłąd dekoduje fale dźwiękowe przedtsawiające kropki i kreski na litery i przesyła je przez Serial do komputera. Autor zastosował tam ciekawe algorytmy detekcji fal i dekodowania alfabetu, które opisał na stronie projektu.

Połaczenie układu jest proste. Mikrofon wraz ze wzmacniaczem podłaczony jest do wejścia analogowego A0. Do pinów 2, 3 podłączone są światła LED sygnalizujące wykrycie kropki lub kreski. Wyjściem Serial/USB zdekodowane litery wędrują do komputera.

sprae

Modem radiowy nRF24L01 – zdalne sterowanie urządzeniem

Zdalne sterowanie przy użyciu modemu nRF24L01 jest proste. Zwyczajnie zamiast napisu program wysyła dane, które służą do włączania, albo wyłączania urządzeń podłączonych do pinów.

Program nadajnika, który realizuje taką możliwość wygląda tak:

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

RF24 radio(7, 8);

void setup()
{
  while (!Serial);
  Serial.begin(9600);
  
  radio.begin();
  radio.setRetries(15, 15);
  radio.stopListening();
}

void loop()
{
  if (Serial.available())
  {
    byte rxAddr[6] = {0};
    Serial.readBytesUntil(' ', rxAddr, 5);
    radio.openWritingPipe(rxAddr);
    Serial.read();
    
    byte command[2];
    command[0] = Serial.parseInt();
    Serial.read();
    command[1] = Serial.parseInt();
    Serial.read();
    
    radio.write(&command, sizeof(command));
  }
}

Zasada działania jest prosta. Wysyłasz do Arduino polecenia przez port USB za pomocą Monitora portu szeregowego. Arduino je przerabia na polecenia sterujące odbiornikiem i wysyła przez modem radiowy.

By wysyłać polecenia Monitor portu szeregowego musi być ustawiony na prędkość 9600 bodów i “Nowa linia” w dolnym pasku.

Przykładowe polecenie wygląda tak:

leds1 2 1

Pierwsze 5 znaków to adres odbiornika. Czyli dla programu można łatwo stworzyć sieć wielu odbiorników o różnych adresach, które będą sterowały urządzeniami w różnych miejscach w promieniu 100 metrów.

Kolejną cyfrą po spacji jest numer urządzenia. Arduino i inne płytki mają wiele pinów więc mogą sterować wieloma urządzeniami. Ta cyfra wybiera urządzenie.

Ostatnią cyfrą jest ustawienie urządzenia. 1 oznacza włączenie, 0 wyłączenie.

Elementy polecenia są oddzielone spacjami.

Możesz wydawać polecenia ręcznie lub napisać sobie program w dowolnym języku, który obsługuje port szeregowy PC i sterować zdalnie urządzeniami za pomocą programu.

Budowa programu przypomina wcześniejsze przykłady z poprzedniego rozdziału. Postanowiłem rozwinąć je ewolucyjnie, żebyś łatwiej zrozumiał co się zmieniło i jak wpłynęło na program.

Różnice zaczynają się w funkcji “loop”. Jest tam wykorzystana metoda “Serial.available();” [interfejs szeregowy.dostępne dane], która sprawdza czy port szeregowy Arduino coś odebrał. Jeśli odebrał, to wykonywana jest reszta programu w bloku “if”.

 byte rxAddr[6] = {0};
 Serial.readBytesUntil(' ', rxAddr, 5);
 radio.openWritingPipe(rxAddr);
 Serial.read();

Ta część odczytuje pierwszą część polecenia czyli adres modemu do którego będą wysyłane dane.

W tym fragmencie deklaruję tablicę typu “byte” o 6 elementach, wypełnioną zerami o nazwie “rxAddr”. Będzie ona przechowywała adres odbiornika.

Metoda “Serial.readBytesUntil(’ ’, rxAddr, 5);” [interfejs szeregowy.czytaj bajty dopóki] odczytuje dane z interfejsu szeregowego aż natknie się na znak spacji ’ ’ lub odczyta 5 znaków.

Pierwszy argument to do pojawienia jakiego znaku metoda ma czytać dane.

Drugim argumentem jest tablica do jakiej odczytane dane trzeba zapisać. W tym przypadku jest to tablica adresu odbiornika “rxAddr”.

Trzecim argumentem jest maksymalna liczba znaków do odczytania.

Po odczytaniu adresu, program ustawia modem na adres odbiornika za pomocą metody “radio.openWritingPipe”.

Metoda “Serial.read();” [interfejs szeregowy.odczytaj dane] jest tylko po to, żeby odczytać znak spacji rozdzielający argumenty polecenia. Nigdzie go nie zapisuje. Jest to tylko po to, żeby przyśpieszyć odczytywanie danych.

byte command[2];
command[0] = Serial.parseInt();
Serial.read();
command[1] = Serial.parseInt();
Serial.read();

Kolejny fragment odczytuje 2 kolejne argumenty polecenia – numer urządzeia i jego ustawienie.

Najpierw tworzę tablicę 2-elementową typu “byte” o nazwie “command” [rozkaz/polecenie], która będzie przechowywała polecenie wysyłane modemem do odbiornika.

Metoda “Serial.parseInt();” [interfejs szeregowy.zintepretuj liczbę całkowitą] zamienia tekstowe znaki liczby wysyłane z przez interfejs szeregowy z Monitora portu szeregowego na cyfrowe. Metoda składa liczbę z cyfr, aż natknie się na inny znak niż cyfra. Jeśli w interfejsie szeregowym nie odebrano cyfr, to ta metoda zwraca 0.

Zinterpretowane liczby zapisywane są w pierwszym i drugim elemencie tablicy “command”. Pierwszy element przechowuje numer urządzenia, a drugi jego ustawienie w postaci cyfrowej.

Na koniec program wysyła wypełnioną tablicę “command” do odbiornika za pomocą metody “radio.write(&command, sizeof(command));”.

Program odbiornika wygląda tak:

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

RF24 radio(7, 8);

void setup()
{
  radio.begin();
  const byte rxAddr[6] = "leds1";
  radio.openReadingPipe(0, rxAddr);
  
  radio.startListening();
  
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
}

void loop()
{
  if (radio.available())
  {
    byte command[2];
    radio.read(&command, sizeof(command));
    
    if (command[0] < 3)
    {
      digitalWrite(command[0]+2, command[1]);
    }
  }
}

Zasada działania programu jest taka, że do pinów 2, 3, 4 podłączyłem trzy światełka LED (zielone, żółte, czerwone) anodami przez rezystory 220 Ohm. Katody podłączyłem do pinu GND. Urządzenie ma adres “leds1” i numery urządzeń dla światełek to 0 – zielony, 1 – żółty, 2 – czerwony. Zatem jeśli do nadajnika wyślesz polecenie:

leds1 2 1

To w odbiorniku zaświeci się światło czerwone.

Budowa programu przypomina oczywiście program odbiornika z poprzedniego rozdziału.

To co się zmieniło w funkcji “setup”. Adres odbiornika znajduje się z tablicy “rxAddr”. Każdy odbiornik powinien mieć inny adres, by można było sterować nim niezależnie.

Kolejną nowością jest użycie funkcji “pinMode(2, OUTPUT);” [pin ustaw działanie]. Ustawiam nim piny 2, 3, 4 jako wyjście “OUTPUT” [wyjście], żeby sterowały światłami LED.

W funkcji “loop” zaczynamy od znanego sprawdzenia czy modem odebrał dane za pomocą metody “radio.available();”.

Jeśli odebrał, to tworzona jest 2-elementowa tablica “command” [rozkaz/polecenie] typu “byte”, która będzie przechowywać polecenie wysłane do modemu.

Polecenie jest odczytywane za pomocą metody “radio.read”.

Następnie za pomocą “if” [jeśli/gdyby] sprawdzane jest czy pierwszy element tablicy polecenia – przechowujący numer urządzenia jest mniejszy niż 2. Mamy tyko 3 urządzenia numerach 0, 1, 2 więc nie chciałem, żeby błędne polecenie coś napsuło.

Jeśli polecenie ma dobrą wartość to przekazywane jest do funkcji “digitalWrite(command[0]+2, command[1]);” [zapisz do pinu cyfrowego].

Jego pierwszym argumentem jest numer pinu, a drugim ustawienie stanu tego pinu.

Jako pierwszy argument użyłem pierwszego elementu tablicy “command” przechowującego numer urządzenia. Ponieważ numer urządzenia jest od 0 do 2, a piny są od 2 do 4 dodałem do niego “+2”, żeby zamienił się w numer pinu (0+2=2, 1+2=3…).

Drugi argument przekazuje wartość dla pinu. 0 to stan niski – dioda nie świeci, 1 to stan wysoki – dioda świeci.

Na koniec wpisałem w Monitor Portu to:

I 6 metrów dalej zrobiło się to:

Zamiast diod możesz podłączyć przekaźniki i sterować zdalnie urządzeniami na prąd.

Zamiast funkcji możesz użyć “analogWrite” i sterować urządzeniami przez sygnał PWM np. silnikami. Możesz też tam wstawić obsługę serwomechanizmu i mieć zdalnie sterowanego robota.

Jeśli masz pytania lub coś napisałem niezrozumiale, zapytaj w komentarzach.

Modemy radiowe nRf24L01 kupisz w Nettigo.

sprae