Professional Documents
Culture Documents
Inteligentny Dom Automatyzacja Mieszkania Za Pomoca Platformy Arduino Systemu Android I Zwyklego K Mike Riley Ebookpoint - PL
Inteligentny Dom Automatyzacja Mieszkania Za Pomoca Platformy Arduino Systemu Android I Zwyklego K Mike Riley Ebookpoint - PL
com G0105202497
Tytuł oryginału: Programming Your Home: Automate with Arduino, Android, and Your Computer
ISBN: 978-83-246-5678-3
© Helion 2013.
All rights reserved.
Many of the designations used by manufacturers and sellers to distinguish their products
are claimed as trademarks. Where those designations appear in this book, and The Pragmatic
Programmers, LLC was aware of a trademark claim, the designations have been printed in initial
capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic
Programming, Pragmatic Bookshelf, PragProg and the linking g device are trademarks of The
Pragmatic Programmers, LLC.
Wydawnictwo HELION dołożyło wszelkich starań, by zawarte w tej książce informacje były
kompletne i rzetelne. Nie bierze jednak żadnej odpowiedzialności ani za ich wykorzystanie,
ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Wydawnictwo
HELION nie ponosi również żadnej odpowiedzialności za ewentualne szkody wynikłe
z wykorzystania informacji zawartych w książce.
Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (księgarnia internetowa, katalog książek)
Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/intdom_ebook
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.
Printed in Poland.
Podziękowania .................................................................................... 13
Dodatki ....................................................................275
Dodatek A. Instalacja bibliotek platformy Arduino .................... 277
A.1.1. System Apple OS X ......................................................................... 277
A.1.2. System Linux ..................................................................................... 278
A.1.3. System Windows ................................................................................ 278
O
dkąd pamiętam, uwielbiam majsterkować. Doskonale pamiętam, jak
rozłożyłem na najdrobniejsze elementy zepsuty magnetofon mojego
ojca — te pierwsze doświadczenia nauczyły mnie szacunku dla
technologii stosowanej do produkcji tego i podobnych urządzeń. Od tamtego
czasu zestawy małego konstruktora, kolejki elektryczne i programowalne
kalkulatory zostały zastąpione przez komputery osobiste, urządzenia mobilne
i mikrokontrolery. Przez lata z pasją poznawałem nie tylko zasady działa-
nia części elektronicznych, ale także techniki ich łączenia w celu budowy
zaskakujących rozwiązań, które nierzadko dawały mi mnóstwo satysfakcji
i napawały mnie dumą. Właśnie dlatego pisanie tej książki sprawiło mi
tyle radości.
Jednym z najważniejszych celów tej książki (obok świetnej zabawy) jest
pomaganie innym w dostrzeganiu potencjału drzemiącego w pozornie po-
spolitych konstrukcjach i mechanizmach — rzeczach, które po zastosowa-
niu przemyślanej technologii mogą ułatwić nam życie. Mimo to powstanie
tej książki nie byłoby możliwe bez wsparcia osób, które pomogły mi wy-
brać i właściwie zaprezentować najciekawsze pomysły. Jestem winien tym
osobom ogromną wdzięczność za wsparcie podczas prac nad tą książką.
Wielkie podziękowania należą się redaktor tej książki, Jackie Carter, która
spędziła długie godziny na poprawianiu mojego tekstu, aby cały materiał
był dostatecznie jasny i precyzyjny. Korektorka językowa, Molly McBeath,
dokonywała cudów, znajdując dobrze ukryte (przynajmniej z mojej per-
spektywy) literówki i błędy gramatyczne. Jestem też winien podziękowania
Mike Riley
Adres e-mail: mike@mikeriley.com
Naperville, grudzień 2011
W
itam we wspaniałym świecie automatyzacji domu, w którym wszyst-
ko jest możliwe! Każdy, kto kiedykolwiek marzył o domu, który
będzie oferował coś więcej niż schronienie przed zjawiskami
pogodowymi i który udostępni domownikom nowoczesne rozwiązania cyfro-
we, znajdzie w tej książce wskazówki, jak stworzyć odpowiednie mechanizmy.
Dzięki opisanym tutaj łatwym w budowie projektom czytelnik opanuje umie-
jętności potrzebne do planowania i realizacji własnych niepowtarzalnych
projektów automatyzacji domu.
Głównym celem tej książki jest zainteresowanie czytelnika metodami auto-
matyzacji domu i wskazanie ogromnego potencjału drzemiącego w prostych
i niedrogich urządzeniach. Chciałbym też, aby każdy nabrał pewności siebie
i wiary we własne umiejętności, aby w przyszłości realizować własne pomysły.
Opisane projekty mogą też być doskonałym sposobem spędzania czasu
z dziećmi, a gotowe rozwiązania z pewnością będą powodem do dumy dla
naszych małych konstruktorów. Kto wie? Być może nasze dzieła automa-
tyzujące funkcjonowanie domu zmienią świat i będą zaczątkiem jakiegoś
wielkiego biznesu (jeśli na przykład ludzie zainteresują się naszym oszczę-
dzającym czas i pieniądze rozwiązaniem).
1
Patrz odpowiednio http://www.pachube.com, http://www.exosite.com i http://
www.yaler.org.
2
Patrz odpowiednio http://www.makezine.com i http://www.instructables.com.
3
http://groups.google.com/group/comp.home.automation/topics
Z
anim przystąpimy do łączenia sprzętu i pisania kodu, warto przy-
najmniej na chwilę pochylić się nad podstawami i zastanowić się, co
właściwie rozumiemy przez automatyzację domu, jakie rozwiązania
były dostępne na rynku w przeszłości i dlaczego konstruowanie własnych
rozwiązań ma sens (teraz i w przyszłości).
Przeanalizujemy też kilka zalecanych praktyk projektowych i konstruktor-
skich, które będziemy konsekwentnie stosowali podczas realizacji projek-
tów opisanych w tej książce.
Zaczniemy od zdefiniowania, co rozumiemy przez automatyzację domu.
W dalszej części rozdziału omówimy kilka gotowych rozwiązań dostęp-
nych na rynku, po czym dokonamy krótkiego przeglądu wybranych, naj-
bardziej popularnych urządzeń i programów. Na końcu tego rozdziału
zaprezentuję kilka narzędzi i praktyk, które ułatwiły mi budowę projektów
na potrzeby tej książki oraz wielu innych projektów, które trudno zaliczyć
do kategorii automatyzacji domu.
1
http://freemind.sourceforge.net
2
http://fritzing.org/
3
http://inkscape.org
4
http://www.creating-your-app.de/electronic_toolbox_features.html?&L=1
5
http://icircuitapp.com/
6
http://ithoughts.co.uk
7
http://minidraw.net/
8
http://www.pragprog.com/magazines/2011-04/testing-arduino-code
9
http://developer.android.com/guide/topics/testing/testing_android.html
Z
anim przystąpimy do właściwej realizacji projektów opisanych w tej
książce, musimy przeanalizować materiały i zalecane metodyki, które
będziemy stosowali podczas budowy tych rozwiązań.
Najważniejszą zasadą, którą stosowałem podczas przygotowywania tej
książki, było zachowanie prostoty i możliwie niewielkich kosztów w przy-
padku wszystkich prezentowanych projektów. Konstruowanie rozwiązań
podobnych do konstrukcji Rube’a Goldberga, kosztujących tysiące złotych
i używanych do otwierania puszek z zupą, oczywiście może sprawić twór-
cy mnóstwo radości, jednak nieporównanie bardziej praktycznym wyjściem
będzie kupienie otwieracza za zaledwie kilka złotych. Robiłem, co w mojej
mocy, aby najlepiej wykorzystać pieniądze i czas poświęcany każdemu pro-
jektowi. Zaledwie kilka spośród tych projektów wymaga nakładów prze-
kraczających dwieście złotych i zajmuje więcej niż godzinę.
Dobrym rozwiązaniem jest wielokrotne wykorzystywanie tych samych
elementów. Wielokrotne stosowanie gotowych rozwiązań jest oczywiście
prostsze w przypadku oprogramowania, ale także wiele elementów sprzę-
towych stwarza taką możliwość. Właśnie dlatego tak dużą popularnością
cieszą się niedrogie płytki mikrokontrolerów (na przykład Arduino), które
stanowią serce wielu takich projektów1. Aby jak najskuteczniej oszczędzać
pieniądze i ograniczać inwestycje w sprzęt, warto podjąć próbę rozpoczę-
cia dwóch projektów równocześnie, aby po pierwszych próbach (ale przed
1
http://arduino.cc/
2
Patrz odpowiednio http://www.adafruit.com i http://www.sparkfun.com.
3
http://developer.android.com/guide/topics/usb/adk.html
4
http://jquerymobile.com/
5
http://developer.android.com/sdk
Jaś pyta...
Czy środowisko Arduino IDE zawiera wirtualny
emulator?
Inaczej niż w przypadku większości środowisk wytwarzania aplikacji
dla komputerów i urządzeń mobilnych, nie istnieje oficjalny emulator
platformy Arduino. Symulowanie działania wielu różnych fizycznych
czujników i silników obsługiwanych przez platformę Arduino byłoby
bardzo trudne. Wielu niezależnych producentów i programistów
próbowało stworzyć takie narzędzie, jednak wszystkie te rozwiązania
albo działają w wybranych systemach operacyjnych, albo emulują
układ ATMega zamiast całej platformy Arduino. Użytkownicy sys-
temu operacyjnego Windows mają do wyboru emulatory Virtual
Breadboard i Emulare6 — polecam zwłaszcza program Virtual Bread-
board z uwagi na jego wirtualną reprezentację sprzętowej platformy
Arduino. Środowisko Virtual Breadboard dodatkowo udostępnia
ograniczony zbiór emulowanych czujników i innych urządzeń, które
można łączyć na ekranie z wirtualną reprezentacją płytki Arduino.
Zważywszy na dość niski koszt samej platformy Arduino, niewielu
konstruktorów używa emulatora do innych zadań niż testy jednost-
kowe lub jako wygodnej, przenośnej reprezentacji platformy sprzę-
towej. Zamiast tracić czas na eksperymenty z emulatorami lepiej wy-
dać pieniądze na właściwą platformę sprzętową. Szkice są krótkie,
a okno danych szeregowych środowiska Arduino IDE jest na tyle wy-
godne i pomocne, że można na tej podstawie bez trudu diagnozo-
wać i doskonalić kod wykonywany na prawdziwym sprzęcie.
6
Patrz odpowiednio http://www.virtualbreadboard.net i http://emulare.sourceforge.
net/.
7
http://www.digi.com/xbeewifi
K
ażdy mieszkaniec Środkowego Zachodu Stanów Zjednoczonych
(w tym ja) był świadkiem wielu ulewnych deszczów i doskonale wie,
jak po takiej nawałnicy wygląda piwnica domu. Dramatyczne relacje
o zalaniach i awariach pomp w czasie najbardziej ulewnych deszczów często
kończą się stwierdzeniem: „gdybym wiedział, jak szybko podnosi się poziom
wody w osadniku, miałbym więcej czasu na wyniesienie najcenniejszych rze-
czy z piwnicy”.
Wyobraźmy sobie jeszcze inny scenariusz, w którym do usuwania wilgoci
z piwnicy jest używany osuszacz. Niedrogie osuszacze często przestają działać
w momencie, w którym poziom wody w zbiorniku osiąga określony poziom.
Niektóre modele emitują wtedy sygnał dźwiękowy lub włączają migającą
diodę, jednak ten sposób komunikowania wypełnienia zbiornika jest o tyle
nieefektywny, że osuszacze z reguły są instalowane w rzadko odwiedzanych
pomieszczeniach.
Czyż nie lepszym i bardziej wygodnym rozwiązaniem byłoby otrzymywa-
nie wiadomości poczty elektronicznej w momencie przekroczenia określonego
progu w zbiorniku, tak aby właściciel mógł podjąć stosowne działania?
(Patrz rysunek 3.1 zatytułowany „Niech dom wysyła do swojego właściciela
1
http://www.adafruit.com/index.php?main_page=product_info&cPath=
17_21&products_id=201
2
http://www.sparkfun.com/products/8606
3
http://www.makershed.com/ProductDetails.asp?ProductCode=JM691104
4
http://www.adafruit.com/products/418
5
https://www.adafruit.com/products/70
3.3. Łączenie
Zacznijmy od sprawdzenia, czy czujnik ugięcia działa zgodnie z naszymi
oczekiwaniami. Końcówkę dodatnią czujnika należy połączyć z 5-woltowym
wtykiem na płytce Arduino za pomocą przewodu. Końcówka dodatnia to
ta połączona z paskiem ciągnącym się wzdłuż całej długości czujnika. Koń-
cówka ujemna to ta połączona z częścią czujnika przypominającą drabinę.
Końcówkę ujemną należy podłączyć do analogowego wtyku 0 za pomocą
drugiego przewodu. Na końcu należy zmostkować analogowy wtyk 0 z wty-
kiem uziemienia przy użyciu rezystora 10 kΩ, aby obniżyć natężenie prądu
w układzie. Warto przeanalizować rysunek 3.3 zatytułowany „Diagram
połączeń systemu powiadamiania o poziomie wody”, aby upewnić się, że
przewody i rezystor zostały połączone z właściwymi wtykami.
Plik WaterLevelNotifier/WaterLevelSensor.pde
int bend_value = 0;
byte bend_state = 0;
void setup()
{
// na potrzeby komunikatów diagnostycznych w oknie portu szeregowego
Serial.begin(9600);
// ustawia wtyk dla wbudowanej diody LED
pinMode(ONBOARD_LED, OUTPUT);
}
Plik WaterLevelNotifier/WaterLevelSensor.pde
void loop()
{
// czeka sekundę w każdej iteracji pętli
delay(1000);
// sprawdza napięcie na wtyku FLEX_SENSOR
bend_value = analogRead(FLEX_SENSOR);
switch (bend_state)
{
case 0: // wartość zmiennej bend_value nie przekracza górnego ani dolnego progu
if (bend_value >= FLEX_TOO_HI || bend_value <= FLEX_TOO_LOW)
{
bend_state = 1;
SendWaterAlert(bend_value, bend_state);
}
break;
case 1: // wartość zmiennej bend_value przekracza górny lub dolny próg
if (bend_value < FLEX_TOO_HI && bend_value > FLEX_TOO_LOW)
{
bend_state = 0;
SendWaterAlert(bend_value, bend_state);
}
break;
}
}
6
http://git-scm.com/
rozwiązań, warto sprawdzić, czy nasz test przekroczenia progów działa pra-
widłowo — w tym celu przeanalizujemy komunikaty wyświetlane w oknie
portu szeregowego środowiska Arduino IDE.
Uruchamianie szkicu
Po zapisaniu szkicu należy kliknąć przycisk Verify na pasku narzędzi środo-
wiska Arduino IDE. Kliknięcie tego przycisku spowoduje skompilowanie
szkicu i sprawdzenie ewentualnych błędów składowych. Po potwierdzeniu
braku błędów należy wysłać szkic na platformę Arduino, klikając przycisk
Upload dostępny na pasku narzędzi. Wbudowana dioda LED na płytce
Arduino powinna przez pewien czas migać, aby zasygnalizować otrzymywa-
nie szkicu. Kiedy dioda przestanie migać, wysłany szkic powinien działać.
Warto teraz otworzyć okno Serial Monitor środowiska Arduino IDE. Jeśli
wyrażenie Serial.print("bend_value="); w głównej pętli szkicu do tej pory
nie zostało umieszczone w komentarzu, możemy obserwować liczby stale
wyświetlane w oknie monitora portu szeregowego (z częstotliwością około
jednej nowej wartości na sekundę). Jeśli znaki wyświetlane w tym oknie są
nieczytelne, należy sprawdzić, czy zastosowano prawidłową szybkość transmisji
(w tym przypadku należy zastosować wartość 9600). Bieżące ustawienia moż-
na sprawdzić na liście rozwijanej widocznej w prawym dolnym rogu okna
tego monitora portu szeregowego. Należy zanotować wskazania czujnika
ugięcia w czasie, gdy jest wyprostowany, wygięty w jedną stronę i wygięty
w drugą stronę.
W zależności od parametrów opornika i rodzaju zastosowanych urządzeń
należy zaktualizować wartości stałych FLEX_TOO_HIGH i FLEX_TOO_LOW zgodnie
z odczytami widocznymi w oknie monitora portu szeregowego. Po zapisa-
niu odpowiednich wartości progowych należy zapisać program i ponownie
wysłać go na platformę Arduino, stosując taką samą procedurę jak poprzed-
nio. Zdefiniowanie górnego i dolnego progu potrzebnych do prawidłowego
wykrywania stanu wygięcia czujnika może wymagać dwóch lub trzech prób.
Po zmodyfikowaniu górnego i dolnego progu tak, aby najlepiej pasowały do
danej konfiguracji, należy obserwować wbudowaną diodę LED na płytce
Arduino, aby mieć pewność, że dioda zapala się w momencie odpowiednio
mocnego wygięcia czujnika w jedną lub drugą stronę oraz gaśnie w momen-
cie przywrócenia oryginalnego położenia (po wyprostowaniu czujnika).
Testowanie szkicu
Po dopracowaniu konfiguracji sprzętowej i sprawdzeniu, czy wysłany szkic
platformy Arduino działa prawidłowo, możemy wreszcie przeprowadzić
prosty test wody — wystarczy nalać wodę do miski i jednocześnie zanurzyć
spławik w wodzie, trzymając kciukiem i palcem wskazującym drugi koniec
czujnika ugięcia. Łączenia obu przewodów z czujnikiem ugięcia należy oczy-
wiście zabezpieczyć za pomocą wodoodpornej taśmy izolacyjnej. Sugeruję
zastosowanie wielu warstw taśmy, aby nie tylko dysponować solidnym uchwy-
tem czujnika, ale też ochronić go przed przypadkowymi kroplami wody.
Po prawidłowym i bezpiecznym przygotowaniu testu należy sprawdzić, czy
wypieranie przez wodę spławika przymocowanego do czujnika ugięcia spo-
woduje na tyle duże wygięcie w jednym z kierunków, że będzie powodo-
wało zapalanie diody LED.
Należy uważać, aby nie zalać odsłoniętego czujnika ugięcia. Mimo że
natężenie prądu przepływającego przez płytkę Arduino jest stosunkowo
niewielkie, połączenie wody i elektryczności może mieć fatalne skutki.
Wszystkie elektroniczne elementy, w tym czujnik ugięcia i dołączony spławik,
należy umieścić w szczelnej torbie foliowej (oczywiście w sposób umożli-
wiający zginanie czujnika). Należy zachować daleko idącą ostrożność, aby
wykluczyć ryzyko zamoczenia odkrytych przewodów lub połączeń elek-
trycznych. Woda może nie tylko uszkodzić sprzęt, ale także doprowadzić
do niebezpiecznego porażenia prądem.
Podstawowe elementy systemu powiadamiania o poziomie wody są już kom-
pletne. Na tym etapie sygnalizacja przekroczenia alarmowego poziomu
wody ogranicza się jednak do zapalenia miniaturowej diody LED na płytce
Arduino. Takie rozwiązanie być może wystarczy w przypadku projektów
akademickich lub konstruktorów pracujących w bezpośrednim sąsiedztwie
platformy Arduino monitorującej zbiornik wodny, jednak w naszym przypad-
ku konieczne będzie znalezienie innego sposobu powiadamiania o rosnącym
poziomie wody.
Dużo lepszym rozwiązaniem będzie otrzymywanie powiadomień w formie
wiadomości poczty elektronicznej, szczególnie jeśli system mierzący poziom
wody znajduje się w rzadko odwiedzanym pomieszczeniu. System może na-
wet działać w zupełnie innym miejscu — może na przykład monitorować
poziom wody w osadniku w domku letniskowym w trakcie ulewnych deszczy.
Realizacja tego zadania będzie wymagała dołączenia do platformy Ar-
duino modułu sieciowego i napisania kodu, który po przekroczeniu progu
Plik WaterLevelNotifier/wateralert.php
<?php
// Uzyskuje rodzaj powiadomienia do wysłania
// oraz bieżącą wartość czujnika ugięcia.
$alertvalue = $_GET["alert"];
$flexvalue = $_GET["flex"];
$contact = 'your@emailaddress.com';
if ($alertvalue == "1") {
$subject = "Alarm czujnika poziomu wody";
$message = "Rosnący poziom wody spowodował, że czujnik ugięcia
osiągnął wartość " . $flexvalue . ".";
mail($contact, $subject, $message);
echo("<p>Ostrzeżenie o poziomie wody zostało wysłane.</p>");
} elseif ($alertvalue == "0") {
$subject = "Poziom wody mieści się w normie";
$message = "Poziom wody nie przekracza progów alarmowych.
Czujnik ugięcia ma wartość " . $flexvalue . ".";
mail($contact, $subject, $message);
echo("<p>Informacja o bezpiecznym poziomie wody została wysłana.</p>");
}
?>
Zabezpieczanie powiadomień
Jeśli opisany skrypt ma na stałe pełnić funkcję usługi przekazywania
wiadomości generowanych przez platformę Arduino, warto rozważyć
dodanie warstwy zabezpieczeń sygnału transmisyjnego, tak aby tylko
nasz system sprawdzania poziomu wody mógł wysyłać ostrzeżenia.
Usługę można zabezpieczyć albo za pomocą tak prostego (ale też
słabego) mechanizmu jak przekazywanie hasła w ramach parame-
trów GET protokołu HTTP, albo stosując bezpieczny token transak-
cyjny wymieniany pomiędzy serwerem WWW a platformą Arduino
podczas uwierzytelniania. Mimo że analiza dobrych mechanizmów
zabezpieczeń wykraczałaby poza zakres tematyczny tej książki, warto
rozważyć takie rozwiązanie, aby uniknąć sytuacji, w której publicznie
dostępny skrypt przekazujący PHP pocztę elektroniczną zostanie wyko-
rzystany przez nieproszonych gości.
7
Patrz odpowiednio strony http://arduino.cc/en/Reference/Ethernet i http://www.
arduino.cc/playground/Code/Spi.
Plik WaterLevelNotifier/WaterLevelNotifier.pde
#include <SPI.h>
#include <Ethernet.h>
Plik WaterLevelNotifier/WaterLevelNotifier.pde
void setup()
{
// na potrzeby komunikatów diagnostycznych w oknie portu szeregowego
Serial.begin(9600);
8
http://code.google.com/p/tinkerit/source/browse/trunk/Ethernet2+library/Ethernet2/
Wysyłanie komunikatu
Do tej pory używaliśmy platformy Arduino do odczytywania wartości
analogowych generowanych przez czujnik ugięcia. Zainicjalizowaliśmy też
moduł sieciowy w celu połączenia tej platformy z lokalną siecią komputerową.
W kodzie naszego szkicu wyznaczyliśmy także miejsce dla funkcji niezbędnej
do wywołania skryptu PHP na serwerze WWW. Możemy teraz przystąpić
do implementacji tej funkcji. Funkcja zostanie nazwana ContactWebServer.
Funkcja ContactWebServer otrzyma na wejściu te same dwa parametry, które
przekazywaliśmy na wejściu funkcji SendWaterAlert, czyli band_value i bend_
state. Na końcu funkcji SendWaterAlert należy dodać wiersz ContactWebServer
(bend_value, bend_state);, ponieważ nasz program będzie nawiązywał komu-
nikację z wyznaczonym serwerem PHP za każdym razem, gdy czujnik ugięcia
zmieni swój stan.
Nasz system jest prawie gotowy. Pozostaje nam już tylko napisanie ciała
funkcji ContactWebServer. Kod tej funkcji będzie odpowiadał za nawiązanie
połączenia ze skryptem PHP na serwerze WWW i za wysłanie na ten ser-
wer odpowiednio sformatowanego żądania GET protokołu HTTP. Wysyłany
łańcuch musi zawierać wartości zmiennych bend_state i bend_value. Łańcuch
przygotowany na poziomie szkicu zostanie następnie przetworzony po stronie
serwera przez odpowiednią funkcję języka PHP.
9
http://gkaindl.com/software/arduino-ethernet
Plik WaterLevelNotifier/WaterLevelNotifier.pde
if (client.connect())
{
Serial.println("Połączono z serwerem PHP");
// generuje żądanie protokołu HTTP
client.print("GET /wateralert.php?alert=");
client.print(bend_state);
client.print("&flex=");
client.print(bend_value);
client.println(" HTTP/1.0");
client.println();
client.stop();
}
else
{
Serial.println("Próba połączenia z serwerem WWW zakończyła się niepowodzeniem");
}
}
Jeśli zamontowałeś drzwiczki dla swojego psa lub kota, możesz za-
montować czujnik ugięcia ponad drzwiczkami i tak skierować drugi
koniec czujnika, aby swobodnie ślizgał się po powierzchni drzwiczek
i jednocześnie wychylał się wraz z tymi drzwiczkami. Tak zamontowa-
ny czujnik można połączyć z kamerą internetową, aby sprawdzić,
czy rzeczywiście nasze zwierzę korzysta z dodatkowego wejścia, czy
raczej nasz dom jest odwiedzany przez nieproszonych gości.
P
amiętasz, jak ostatni raz odwiedziłeś znajomych, którzy mają wielkie-
go psa? Czy donośne szczekanie niskim tonem, które rozległo się
zaraz po naciśnięciu dzwonka, nie wywołało u Ciebie niepokoju przed
wejściem do mieszkania? Większość właścicieli psów docenia czujność
swoich czworonożnych przyjaciół. Psy potrafią błyskawicznie reagować na
ruch i natychmiast przystępować do działania, które najczęściej polega na
szczekaniu, wychylaniu pysków zza zasłon w oknach i innych czynnościach
niezbędnych do sprawdzenia, co dzieje się na zewnątrz.
Elektryczny pies stróżujący oferuje bardzo podobne korzyści w sferze bezpie-
czeństwa i jednocześnie nie ma wad prawdziwych psów, choćby w postaci
wszechobecnej sierści (patrz rysunek 4.1 zatytułowany „Odstraszanie nie-
chcianych gości za pomocą elektrycznego psa stróżującego”).
Projekt wymaga połączenia platformy Arduino, modułu dźwiękowego, pa-
sywnego czujnika ruchu na podczerwień (ang. Passive InfraRed — PIR)
oraz silnika wykonawczego. Po zaprogramowaniu i aktywowaniu system
będzie naśladował wściekłego psa, który tylko czeka na okazję, żeby rzucić się
na niepożądanego gościa. Niewielki pręt przymocowany do ramion silnika
wykonawczego będzie naśladował ruchy zdenerwowanego, skaczącego psa.
1
http://www.adafruit.com/products/175
2
http://www.adafruit.com/products/155
3
http://www.ladyada.net/make/waveshield/
Jaś pyta...
Czy istnieje jakiś moduł platformy Arduino
odtwarzający pliki MP3?
Tak! W sklepie internetowym Sparkfun można znaleźć rozszerzenie
platformy Arduino nazwane modułem MP3 i przypominające stan-
dardowy moduł dźwiękowy firmy Adafruit4. Z uwagi na różnice
dzielące niezbędne biblioteki w tym rozdziale skoncentruję się na
implementacji modułu dźwiękowego. Zainteresowanych czytelników
zachęcam do samodzielnych eksperymentów z alternatywnym mo-
dułem MP3 firmy Sparkfun. Czytelników, którzy potrzebują modułu
dźwiękowego zdolnego do odtwarzania plików w dodatkowych
formatach, jak Windows Media Audio, MIDI czy Ogg Vorbis, z pew-
nością zainteresuje moduł Seeed Music Shield dostępny w sklepie
Maker Shed — Seeed Music Shield jest przykładem doskonałej in-
tegracji funkcji odtwarzania plików audio ze świetnie zaprojekto-
wanym modułem platformy Arduino5.
4
http://www.sparkfun.com/products/9736
5
http://www.makershed.com/ProductDetails.asp?ProductCode=MKSEEED14
6
http://www.freesound.org
Jaś pyta...
Jak działa czujnik ruchu PIR?
Czujnik PIR wykrywa ruch, porównując dwie próbki promieniowania
podczerwonego emitowanego przez poruszające się ciało, które
jest cieplejsze od środowiska za nim. W momencie, w którym jed-
na strona czujnika odczyta wyższą wartość od drugiej strony, czujnik
wysyła do cyfrowego wtyku sygnał o wykryciu ruchu. Czujnik pod-
czerwony będący sercem czujnika ruchu PIR jest zwykle pokryty sfe-
ryczną soczewką, która ułatwia koncentrowanie światła i tym samym
wykrywanie zmian w obrazie podczerwonym (a więc także ruchu).
Szczegółowe wyjaśnienie zasad działania czujników ruchu PIR wraz
z niezbędnymi podstawami teoretycznymi można naleźć na odpo-
wiedniej stronie internetowej serwisu Ladyady7.
7
http://www.ladyada.net/learn/sensors/pir.html
8
http://www.ladyada.net/make/waveshield/convert.html
9
http://audacity.sourceforge.net/
10
http://www.ladyada.net/make/waveshield/libraryhc.html
11
http://www.arduino.cc/playground/Main/Mediaplayer
12
http://www.ladyada.net/media/wavshield/AFWave_18-02-09.zip
13
http://www.arduino.cc/playground/Main/Mediaplayer
AF_Wave/wave.cpp.o:/Applications/Arduino.app/
Contents/Resources/Java/libraries/AF_Wave/wave.cpp:33: first defined here
#include <avr/pgmspace.h>
#include "util.h"
#include "MediaPlayer.h"
#include <ServoTimer2.h>
14
http://www.arduino.cc/playground/uploads/Main/ServoTimer2.zip
void setup() {
pinMode(ledPin, OUTPUT); // ustawia tryb pinMode OUTPUT dla wbudowanej diody LED
pinMode(inputPin, INPUT); // ustawia tryb INPUT dla wtyku inputPin
// (czujnika ruchu PIR)
theservo.attach(7); // łączy cyfrowe wyjście serwomotoru z wtykiem nr 7
randomSeed(analogRead(0)); // przekazuje wartość początkową dla generatora liczb
// losowych platformy Arduino
Serial.begin(9600);
}
runku nasz szkic powinien zapalić wbudowaną diodę LED i wysłać komuni-
kat o wykryciu ruchu do okna portu szeregowego środowiska Arduino IDE.
Możemy teraz wygenerować liczbę losową z przedziału od 1 do 5 na pod-
stawie utworzonej wcześniej wartości początkowej generatora. Uzyskaną
w ten sposób wartość wykorzystujemy do odtworzenia jednego z plików
dźwiękowych i wymuszenia na serwomotorze określonej liczby obrotów.
Po wykonaniu tej operacji nasz program czeka jedną sekundę, przywraca
ustawienie początkowe serwomotoru i wykonuje całą pętlę od początku. Jeśli
czujnik PIR nie wykryje ruchu (jeśli sygnał na wtyku nr 12 jest równy LOW),
wyłączamy wbudowaną diodę LED, wysyłamy do okna monitorowania portu
szeregowego komunikat Brak ruchu, zatrzymujemy odtwarzanie dźwięku
i przywracamy wartość LOW we fladze pirStatus.
Plik ElectricGuardDog/ElectricGuardDog.pde
void loop(){
pirValue = digitalRead(inputPin); // sprawdza wartość czujnika PIR
if (pirValue == HIGH) { // jeśli wykryto ruch
digitalWrite(ledPin, HIGH); // włącza wbudowaną diodę LED
if (pirStatus == LOW) { // wymusza ruch serwomotoru
Serial.println("Wykryto ruch");
// generuje liczbę losową z przedziału od 1 do 5, aby wybrać przypadkowy
// plik dźwiękowy,
// po czym odtwarza ten plik i wymusza obrót serwomotoru o liczbę stopni
// zależną od wylosowanej wartości
switch (random(1,6)) {
case 1:
Serial.println("Odtwarzanie pliku 1.WAV");
theservo.write(1250);
mediaPlayer.play("1.WAV");
break;
case 2:
Serial.println("Odtwarzanie pliku 2.WAV");
theservo.write(1400);
mediaPlayer.play("2.WAV");
break;
case 3:
Serial.println("Odtwarzanie pliku 3.WAV");
theservo.write(1600);
mediaPlayer.play("3.WAV");
break;
case 4:
Serial.println("Odtwarzanie pliku 4.WAV");
theservo.write(1850);
mediaPlayer.play("4.WAV");
break;
case 5:
Serial.println("Odtwarzanie pliku 5.WAV");
theservo.write(2100);
mediaPlayer.play("5.WAV");
break;
}
4.5. Testowanie
Czujnik ruchu PIR należy umieścić w miejscu, które umożliwi wygodne te-
stowanie wykrywania ruchu. Po zainstalowaniu czujnika warto pobrać gotowy
szkic i otworzyć okno portu szeregowego środowiska Arduino IDE.
Aby wyzwolić sygnał czujnika ruchu, wystarczy pomachać przed nim ręką.
Nasz elektryczny pies stróżujący powinien zareagować na ten ruch odtworze-
niem pliku dźwiękowego i ruchem serwomotoru. Jeśli uznamy, że obrót
M
am dwójkę dzieci, które wprost uwielbiają ptaki. Już jako małe dzie-
ci miały swoje pierwsze papużki. Lubiły też obserwować dzikie
ptaki konstruujące gniazda i posilające się w karmniku zamontowa-
nym przy oknie sypialni. Dokarmianie ptaków wiąże się jednak z pewnym
problemem — dzieci ciągle zapominają o uzupełnianiu nasion dla ptaków
w karmnikach. Zdarzało się, że z rozmaitych powodów w karmniku brako-
wało nasion przez całe dnie, a nawet tygodnie. Czyż nie byłoby prościej,
gdyby sam karmnik informował nas o konieczności uzupełnienia karmy?
Historia pustego karmnika była inspiracją dla tego projektu. Czy można sobie
wyobrazić lepszą formę powiadamiania o konieczności dosypania nasion niż
„ćwierkanie” na Twitterze? Zainteresowani znajomi i krewni mogą śledzić
konto karmnika, aby wiedzieć, kiedy karmnik jest odwiedzany przez ptaki,
kiedy wymaga uzupełnienia karmy i czy nasiona zostały dosypane. (Patrz
rysunek 5.1 zatytułowany „Wysyłanie powiadomień przez karmnik dla
ptaków za pośrednictwem Twittera”).
1
http://www.makershed.com/ProductDetails.asp?ProductCode=MKGR1
2
http://www.adafruit.com
3
http://www.solio.com/chargers/
Budowa czujnika
Budowa i testowanie czujnika grzędy to najprostszy element tego projektu.
Wystarczy użyć kawałka folii aluminiowej wielkości połowy opakowania
od listka gumy do żucia i owinąć grzędę. Należy następnie połączyć jeden
koniec rezystora 10 MΩ z wtykiem cyfrowym nr 7 na płytce Arduino oraz
drugi koniec z wtykiem nr 10. Przewód połączony z folią aluminiową należy
połączyć z końcówką rezystora podłączoną do wtyku cyfrowego nr 7. Od-
powiedni schemat połączeń pokazano na rysunku 5.4 zatytułowanym „Spo-
sób podłączenia czujnika pojemnościowego”.
Programowanie czujnika
Należy teraz połączyć platformę Arduino z komputerem, po czym uruchomić
środowisko Arduino IDE w celu napisania kodu obsługującego czujnik.
4
http://www.arduino.cc/playground/Main/CapSense
#include <CapSense.h>
void setup()
{
// na potrzeby komunikatów diagnostycznych w oknie portu szeregowego
Serial.begin(9600);
void loop() {
// czeka sekundę w każdej iteracji pętli
delay(1000);
switch (perch_state)
{
case 0: // żaden ptak nie siedzi obecnie na grzędzie
if (perch_value >= ON_PERCH)
{
perch_state = 1;
SendPerchAlert(perch_value, perch_state);
}
break;
case 1: // jakiś ptak siedzi teraz na grzędzie
if (perch_value < ON_PERCH)
{
perch_state = 0;
SendPerchAlert(perch_value, perch_state);
}
break;
}
}
Warto zwrócić uwagę na wartość stałej ON_PERCH (równą 1500), którą porów-
nujemy z zarejestrowaną wartością zmiennej perch_value. Z uwagi na róż-
nice dotyczące przewodnictwa elektrycznego zastosowanej folii i samej po-
wierzchni czujnika każdy powinien dostosować wartość progową reprezento-
waną przez stałą ON_PERCH (tak jak dostosowywaliśmy odpowiednie progi
w projekcie systemu powiadamiania o poziomie wody). Należy też zwrócić
uwagę na wartość 30 przypisaną stałej CAP_SENSE. Ta wartość określa licz-
bę pobrań próbnych wartości w jednym cyklu mierzenia pojemności.
Skoro dysponujemy już działającym czujnikiem grzędy dla ptaków, czas opra-
cować mechanizm wykrywający niski poziom ziarna. Jak to zrobić? Warto
zastosować fotokomórkę.
5
http://www.ladyada.net/learn/sensors/cds.html
void loop() {
// czeka sekundę w każdej iteracji pętli
delay(1000);
switch (seed_state)
{
case 0: // pojemnik na ziarno został napełniony
if (seed_value >= SEED)
{
seed_state = 1;
SendSeedAlert(seed_value, seed_state);
}
break;
case 1: // pojemnik na ziarno jest pusty
if (seed_value < SEED)
{
seed_state = 0;
SendSeedAlert(seed_value, seed_state);
}
break;
}
}
6
http://www.ladyada.net/make/xbee/
7
http://ladyada.net/make/xbee/point2point.html
8
http://alioth.debian.org/projects/minicom/
Jeśli w oknie odbieranych danych nie widać żadnych znaków, należy jeszcze
raz sprawdzić przewody łączące moduł XBee z odpowiednimi wtykami na
płytce Arduino. Warto też zamienić te moduły miejscami, aby sprawdzić, czy
oba urządzenia są rozpoznawane po połączeniu z komputerem za pomocą
przewodu FTDI USB. W oknie terminala aplikacji portu szeregowego
należy wpisać polecenie AT i sprawdzić, czy w odpowiedzi otrzymamy po-
twierdzenie OK.
Jeśli moduły XBee wciąż nie mogą nawiązać połączenia, warto poprosić
o pomoc sprzedawcę, u którego zakupiono ten sprzęt.
Po udanej próbie nawiązania komunikacji przez parę modułów XBee mo-
żemy ponownie podłączyć fotokomórkę i czujnik pojemnościowy do płytki
Arduino i połączyć kod obsługujący ten moduł z kodem analizującym warunki
progowe obu czujników. Kompletny schemat połączeń tego systemu pokaza-
no na rysunku 5.6 zatytułowanym „Ćwierkający karmnik dla ptaków z czuj-
nikami i modułem XBee podłączonymi do platformy Arduino”.
Kończenie szkicu
Musimy odczytywać wartości obu czujników — czujnika pojemnościowe-
go z folii aluminiowej oraz fotokomórki. Początkowo odczytywane warto-
ści będą trafiały do okna monitora portu szeregowego środowiska Arduino
IDE, a docelowo (po wprowadzeniu drobnej zmiany w kodzie) będą wy-
syłane przez moduł XBee. Na tym etapie naszym celem jest połączenie
kodu sprawdzającego wyznaczone wcześniej wartości progowe dla czujni-
ka pojemnościowego i fotokomórki z kodem wysyłającym do modułu
XBee ostrzeżenia o przekroczeniu tych wartości. Po dodaniu tej logiki do
napisanego wcześniej kodu testującego stan grzędy i pojemnika na nasiona
możemy zakończyć pracę nad szkicem dla tego projektu.
Plik TweetingBirdFeeder/TweetingBirdFeeder.pde
#include <CapSense.h>;
#include <NewSoftSerial.h>
void setup()
{
// na potrzeby komunikatów diagnostycznych w oknie portu szeregowego
Serial.begin(9600);
void loop() {
// czeka sekundę w każdej iteracji pętli
delay(1000);
switch (perch_state)
{
case 0: // żaden ptak nie siedzi na grzędzie
if (perch_value >= ON_PERCH)
{
perch_state = 1;
SendPerchAlert(perch_value, perch_state);
}
break;
case 1: // jakiś ptak siedzi teraz na grzędzie
if (perch_value < ON_PERCH)
{
perch_state = 0;
SendPerchAlert(perch_value, perch_state);
}
break;
}
switch (seed_state)
{
case 0: // pojemnik na ziarno został napełniony
if (seed_value >= SEED)
{
seed_state = 1;
SendSeedAlert(seed_value, seed_state);
}
break;
case 1: // pojemnik na ziarno jest pusty
if (seed_value < SEED)
{
seed_state = 0;
SendSeedAlert(seed_value, seed_state);
}
break;
}
}
9
http://www.sqlite.org/download.html
10
https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/
11
http://oauth.net/
Type. Można też wskazać niestandardową ikonę aplikacji, jednak ten krok
nie jest wymagany. Po wpisaniu tekstu zabezpieczenia CAPTCHA na-
leży kliknąć przycisk Create your Twitter application na dole strony. Przed
przejściem do następnego kroku należy jeszcze zapoznać się z warunkami
korzystania z interfejsu Twitter API i zaakceptować proponowane zapisy.
Po zaakceptowaniu żądania wygenerowany zostanie unikatowy klucz API,
klucz konsumenta standardu OAuth oraz klucz tajny konsumenta. Aby
uzyskać dostęp do tokenu dostępu (oauth_token) i klucza tajnego tokenu
dostępu (oauth_token_secret), należy kliknąć opcję My Access Token wi-
doczną po lewej stronie. Obie wartości należy skopiować i zapisać w bez-
piecznym, odpowiednio chronionym pliku. Obie wartości będą potrzebne
do komunikacji z nowym kontem na Twitterze z poziomu kodu programu.
Oczywiście należy zadbać o zachowanie tych wartości w ścisłej tajemnicy!
Nie chcemy przecież, aby jakiś złośliwy, pozbawiony skrupułów użytkownik
przejął nasz tajny token, wykorzystywał go do wysyłania spamu do naszych
przyjaciół i doprowadzał do pasji całą społeczność użytkowników Twittera.
Skoro dysponujemy już kontem na Twitterze i poprawnym kluczem interfejsu
API tego serwisu, możemy wykorzystać uzyskane dane uwierzytelniające
w kodzie aplikacji języka Python napisanej dla naszego ćwierkającego karm-
nika dla ptaków.
Biblioteka Python-Twitter
Mimo że mamy dostęp do Twittera za pośrednictwem interfejsu API, wciąż
nie dysponujemy mechanizmem komunikacji z Twitterem z poziomu skryp-
tów języka Python. Warto wykorzystać do tego celu rozwiązania dostępne
w bibliotece Python-Twitter12. Aby zainstalować obie biblioteki potrzebne
do realizacji tego projektu, czyli Pyserial i Python-Twitter, należy pobrać
najnowsze wersje tych bibliotek i użyć standardowego polecenia sudo python
setup.py install. W przypadku instalowania tych bibliotek w systemie Mac
OS X 10.6 (Snow Leopard) lub nowszym można skorzystać z już zainsta-
lowanego narzędzia instalacyjnego Pythona nazwanego easy_install. Aby
jednak uniknąć problemów związanych z 64-bitowymi wersjami bibliotek,
odpowiednie polecenie należy poprzedzić flagą architektury i386, aby zain-
stalować bibliotekę Python-Twitter bez żadnych błędów. Kompletne polece-
nie dla tej biblioteki powinno mieć następującą postać: sudo env ARCHFLAGS="-
arch i386" easy_install python-twitter.
12
http://code.google.com/p/python-twitter/
if sys.platform == "win32":
os.system("cls")
else:
os.system("clear")
def transmit(msg):
# uzyskuje i odpowiednio formatuje bieżącą datę i godzinę
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
table = "seedstatus"
if msg == "ziarnoWNormie":
tweet = "Ziarno w karmniku zostało uzupełnione."
table = "seedstatus"
except KeyboardInterrupt:
# przerywa program w momencie wykrycia naciśnięcia kombinacji klawiszy Ctrl+C
print("\nProgram nasłuchujący komunikatów ćwierkającego karmnika dla ptaków kończy pracę.\n")
sqlcursor.close()
pass
13
http://www.solio.com/chargers/
14
http://www.sunforceproducts.com/results.php?CAT_ID=1
W ramach tego projektu udało nam się osiągnąć całkiem sporo zupełnie no-
wych celów — od zastosowania fotokomórki i własnoręcznie zbudowanego
czujnika pojemnościowego, przez opanowanie sztuki łączenia w pary modu-
łów XBee i nawiązywania komunikacji bezprzewodowej między nimi, po
napisanie skryptu rejestrującego dane w ustrukturyzowanej bazie danych,
reagującego na zdarzenia i publikującego posty na Twitterze za pośrednic-
twem interfejsu API tego serwisu. Zastosowaliśmy także autonomiczny sys-
tem zasilania płytki Arduino i modułu XBee oraz zabezpieczyliśmy te wraż-
liwe komponenty elektroniczne przed szkodliwym działaniem warunków
atmosferycznych.
Te cenne lekcje z pewnością wykorzystamy przynajmniej w projektach
realizowanych w części pozostałych rozdziałów.
15
http://cairoplot.sourceforge.net/
K
ażdy, kto po całym dniu pracy wraca do domu i odkrywa, że czeka na
niego jakaś ważna przesyłka kurierska, wie, jakie to przyjemne uczu-
cie. Nawet jeśli uważnie śledziliśmy paczkę w internecie i spodzie-
waliśmy się jej tego dnia, po stwierdzeniu, że przesyłka bezpiecznie do-
tarła do naszego domu, czujemy się trochę jak po otrzymaniu prezentu uro-
dzinowego.
Jeszcze lepszym rozwiązaniem byłoby informowanie adresata o dostarcze-
niu przesyłki nie tyle w momencie jej pozostawienia w domu odbiorcy, co
w chwili potwierdzenia tego zdarzenia przez kuriera. (Patrz rysunek 6.1
zatytułowany „Otrzymywanie wiadomości poczty elektronicznej po dostar-
czeniu przesyłki”). Co będzie, jeśli kurier zostawi przesyłkę pod niewłaści-
wym adresem? Bez obaw. System wykrywania dostarczania paczek wyśle
wiadomość poczty elektronicznej w momencie pozostawienia paczki przed
drzwiami. Takie powiadomienia można bez trudu filtrować, tak aby od-
powiednie wiadomości pozostawały aktywne do momentu potwierdzenia
odbioru przesyłki na stronie internetowej.
1
http://www.adafruit.com/products/166
2
Firma Sparkfun ma w ofercie kwadratowy czujnik o jeszcze większej powierzchni:
http://www.sparkfun.com/products/9376.
Moduł XBee należy podłączyć do płytki Arduino w taki sam sposób jak
w projekcie ćwierkającego karmnika dla ptaków. Końcówkę zasilania mo-
dułu XBee należy połączyć z wtykiem zasilania 5,5 na płytce Arduino.
Końcówkę uziemienia modułu XBee należy połączyć z drugim dostępnym
wtykiem uziemienia na płytce Arduino. Końcówkę danych przychodzą-
cych tego modułu należy połączyć z wtykiem cyfrowym nr 2, a końcówkę
danych wychodzących — z wtykiem cyfrowym nr 3. Po połączeniu wszyst-
kich elementów nasz system powinien wyglądać tak jak rozwiązanie poka-
zane na rysunku 6.5 zatytułowanym „Wykrywacz dostarczonych paczek”.
Musimy jeszcze połączyć komputer z portem URL platformy Arduino,
aby nie tylko zapewnić zasilanie całego układu, ale też umożliwić napisa-
nie, uruchomienie i przetestowanie szkicu utworzonego dla tego projektu.
#include <NewSoftSerial.h>
void setup()
{
// na potrzeby komunikatów diagnostycznych w oknie portu szeregowego
Serial.begin(9600);
if (force_state)
Serial.print("Dostarczono przesyłkę, force_value=");
else
Serial.print("Zabrano przesyłkę, force_value=");
Serial.println(force_value);
XBeeSerial.println(force_value);
}
void loop()
{
// czeka sekundę w każdej iteracji pętli
delay(1000);
switch (force_state)
{
case 0: // sprawdza, czy dostarczono paczkę
if (force_value >= FORCE_THRESHOLD)
{
force_state = 1;
SendDeliveryAlert(force_value, force_state);
}
break;
case 1: // sprawdza, czy zabrano paczkę
if (force_value < FORCE_THRESHOLD)
{
force_state = 0;
SendDeliveryAlert(force_value, force_state);
}
break;
}
}
szeregowego. Należy teraz puścić czujnik siły nacisku i odczekać kilka se-
kund. W oknie monitora portu szeregowego powinna zostać wyświetlona
wartość mniejsza niż 400 wraz z komunikatem o braku paczki. W razie bra-
ku odpowiednich komunikatów warto raz jeszcze sprawdzić wszystkie połą-
czenia. Być może będziemy musieli zwiększyć lub zmniejszyć wartość pro-
gową force_sensor_value, aby wyeliminować wpływ przypadkowych od-
czytów analogowych czujnika wskutek drgań lub nieoczekiwanych wahań.
Należy również sprawdzić, czy moduły radiowe XBee są prawidłowo połą-
czone i czy komunikują się ze sobą. Warto też użyć polecenia screen (opi-
sanego już w rozdziale 5. zatytułowanym „Ćwierkający karmnik dla pta-
ków”) do obserwacji komunikatów wysyłanych przez czujnik siły nacisku
w reakcji na jego ściskanie palcami. Przesyłane w ten sposób informacje po-
winny być takie same jak te wyświetlane w oknie monitora portu szeregowego
w ramach środowiska Arduino IDE. Po sprawdzeniu wszystkich elementów
możemy przystąpić do pisania skryptu języka Python, który będzie odpo-
wiadał za nasłuchiwanie komunikatów przychodzących do docelowego
modułu XBee (połączonego z komputerem za pomocą przewodu FTDI)
i na tej podstawie podejmował odpowiednie działania.
3
https://github.com/alertedsnake/packagetrack
4
https://github.com/alertedsnake/python-fedex
# Formatuje wiadomość
mail_header = 'To:' + recipient + '\n' + 'From: ' + gmail_sender + '\n' \
+ 'Subject: ' + subject + '\n'
message_body = message
mail_message = mail_header + '\n ' + message_body + ' \n\n'
# Zamyka połączenie
gmail_smtp.close()
def process_message(mg):
try:
# Należy pamiętać o konieczności użycia prawidłowej ścieżki do pliku
# packagedelivery.sqlite
connection = sqlite3.connect("packagedelivery.sqlite")
cursor = connection.cursor()
if (msg == "Delivery"):
try:
connection = sqlite3.connect("packagedelivery.sqlite")
cursor = connection.cursor()
cursor.execute('SELECT * FROM tracking WHERE '\
+ 'delivery_status=0')
results = cursor.fetchall()
message = ""
for x in results:
tracking_number = str(x[1])
description = str(x[2])
print tracking_number
package = Package(tracking_number)
info = package.track()
delivery_status = info.status
delivery_date = str(info.delivery_date)
if (delivery_status.lower() == 'delivered'):
sql_statement = 'UPDATE tracking SET \
delivery_status = "1", delivery_date = \
"' + delivery_date + \
'" WHERE tracking_number = "' \
+ tracking_number + '";'
cursor.execute(sql_statement)
connection.commit()
message = message + description \
+ ' paczka oznaczona numerem ' \
+ tracking_number \
+ ' została dostarczona dnia ' \
+ delivery_date +'\n\n'
# Zamyka kursor
cursor.close()
except:
print("Wystąpił problem podczas próby dostępu do tabeli tracking " \
+ "w bazie danych packagedelivery")
else:
send_email('Zabrano paczkę', 'Wykryto zdarzenie zabrania paczki.')
if sys.platform == "win32":
os.system("cls")
else:
os.system("clear")
if "Empty" in XBee_message:
# Uzyskuje i odpowiednio formatuje bieżącą datę i godzinę
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print("Wykryto zdarzenie zabrania paczki - " + timestamp)
process_message("Empty")
except KeyboardInterrupt:
print("\nWykrywacz dostarczonych paczek kończy działanie.\n")
pass
W razie błędu podczas działania tego skryptu lub w razie braku odpowiednich
wartości w bazie danych należy przywrócić oryginalny stan tabeli tracking
i zastosować dostępne metody diagnozowania tego skryptu (najprostszą
z nich jest umieszczenie w odpowiednich miejscach kodu wywołań funkcji
print()), aby sprawdzić, które miejsca kodu powodują problemy.
W
yobraźmy sobie, że po długim dniu w pracy wracamy do domu
i włączamy światła, telewizję i wszystkie urządzenia jednocze-
śnie, korzystając z aplikacji zainstalowanej na naszym telefonie
komórkowym. System może obejmować wszystkie urządzenia elektryczne
zasilane przez standardowe gniazdka.
W tym rozdziale spróbujemy urzeczywistnić to marzenie przy użyciu kompu-
tera podłączonego do internetu, aplikacji internetowej na bazie frameworku
Ruby on Rails, aplikacji zainstalowanej na smartfonie z systemem Android
oraz dużo starszej technologii znanej jako X10. Zbudujemy aplikację
zdalnego włącznika światła dla systemu Android, która umożliwi nam włą-
czanie i wyłączanie światła za pośrednictwem ekranu dotykowego smartfonu
(patrz rysunek 7.1 zatytułowany „Łatwe sterowanie oświetleniem domu
i urządzeniami elektrycznymi”). Po zakończeniu tego projektu będziemy
mogli sterować urządzeniami domowymi nie tylko z dowolnego miejsca
w domu, ale także z każdego miejsca, w którym będziemy mieli dostęp do
internetu (o ile serwer z aplikacją na bazie frameworku Rails będzie pu-
blicznie dostępny).
1
https://www.virtualbox.org/
2
http://www.x10.com
3
http://www.heyu.org/heyu_faq.html
4
http://heyu.org
5
http://www.rubyonrails.com
6
http://eclipse.org
7
http://developer.android.com/sdk
8
http://developer.android.com/sdk/eclipse-adt.html
9
http://www.heyu.org/docs/protocol.txt
7.3. Łączenie
Interfejs X10 CM11A należy podłączyć do gniazdka elektrycznego nie-
daleko komputera, tak aby przewód tego interfejsu sięgał komputera. Po-
nieważ interfejs CM11A używa 9-wtykowego złącza szeregowego i wymaga
zastosowania adaptera USB – port szeregowy wraz z odpowiednim ste-
rownikiem (patrz rysunek 7.3 zatytułowany „Interfejs X10 CM11A ste-
rujący internetowym włącznikiem światła”). Użytkownicy komputerów
z systemem operacyjnym Mac OS X 10.6 lub nowszym mogą pobrać ste-
rownik PL-2303 z witryny internetowej Prolific10. Komputery z najnowszymi
dystrybucjami systemu Linux nie powinny mieć najmniejszych problemów
z identyfikacją interfejsu PL-2303 i nawiązywaniem połączenia z tym in-
terfejsem.
Należy teraz podłączyć adapter USB – port szeregowy do komputera i do
interfejsu CM11A (podłączonego wcześniej do prądu). Musimy jeszcze
określić urządzenie reprezentujące port szeregowy (urządzenie przypisane
do tego interfejsu przez system operacyjny). W tym celu należy znaleźć od-
powiednie urządzenie tty w katalogu /dev za pomocą polecenia ls /dev/tty*
wpisanego w oknie terminala. Jeszcze prostszym rozwiązaniem jest uru-
chomienie środowiska Arduino IDE i wybranie opcji Tools/Serial Port.
10
http://www.prolific.com.tw/eng/downloads.asp?ID=31l
11
http://developer.apple.com/technologies/tools/
Jeśli wymienione polecenia nie włączą ani nie wyłączą światła, warto spraw-
dzić inny moduł X10, na przykład AM486 Appliance. Jeśli także ten
moduł nie zadziała prawidłowo, należy spróbować umieścić interfejs kom-
puterowy X10 bliżej włącznika ściennego (najlepiej w taki sposób, aby oba
elementy były podłączone do przewodów w tym samym pomieszczeniu).
Zdecydowana większość problemów, które napotykałem podczas realizacji
projektów na bazie technologii X10, miała bezpośredni związek z charakte-
rem samego protokołu X10, gdzie obowiązuje zasada „odpal i zapomnij”.
Jeśli podejrzewamy, że źródłem problemu może być niewłaściwe działanie
urządzeń X10, warto wymienić wybrane urządzenia i sprawdzić, czy nowe
elementy cokolwiek zmieniły. Być może warto poprosić o pomoc elektryka,
który sprawdzi ewentualne zakłócenia i inne problemy z instalacją elek-
tryczną mogące utrudniać przekazywanie impulsów protokołu X10 po-
między interfejsem CM11A a stosowanymi modułami X10.
Po sprawdzeniu, czy komputer komunikuje się z interfejsem CM11A za
pośrednictwem wiersza poleceń narzędzia Heyu, możemy zaimplementować
dostępne rozkazy w ramach aplikacji internetowej. Odpowiednio zapro-
jektowana aplikacja internetowa zapewni łatwy dostęp do punktów koń-
cowych technologii X10 z poziomu przeglądarki internetowej (a docelowo
także z poziomu aplikacji dla systemu Android).
create app/controllers/command_controller.rb
route get "command/cmd"
invoke erb
create app/views/command
create app/views/command/cmd.html.erb
invoke test_unit
create test/functional/command_controller_test.rb
invoke helper
create app/helpers/command_helper.rb
invoke test_unit
create test/unit/helpers/command_helper_test.rb
if @result == "on"
%x[/usr/local/bin/heyu on h3]
end
if @result == "off"
%x[/usr/local/bin/heyu off h3]
end
end
end
12
http://developer.android.com/sdk
13
http://developer.android.com/guide/developing/devices/managing-avds.html
package com.mysampleapp.lightswitch;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ToggleButton;
import android.view.View;
import java.net.URL;
import java.io.InputStream;
14
http://developer.android.com/guide/publishing/app-signing.html
15
http://developer.android.com/guide/developing/building/building-eclipse.html
16
http://www.sinatrarb.com/
J
ednym z najbardziej popularnych efektów w filmach science fiction jest
automatyczne otwieranie i zamykanie rozmaitych przegród, a także
podnoszenie i opuszczanie zasłon w oknach. Okazuje się, że to, co
kiedyś było wyobrażeniem o przyszłości, nie jest dzisiaj niczym szczególnym
i stale zyskuje na popularności. W tym projekcie skonstruujemy system,
który będzie podnosił i opuszczał zasłony w zależności od natężenia świa-
tła i temperatury. Zasłony są podnoszone w reakcji na rosnącą temperatu-
rę, a opuszczane po wykryciu światła słonecznego (patrz rysunek 8.1 za-
tytułowany „Automatyczne zasłony okienne”).
Podstawowym elementem sprzętowym potrzebnym do realizacji tego pro-
jektu będzie silnik krokowy — to sterowane przez płytkę Arduino urzą-
dzenie będzie wykonywało określoną liczbę obrotów w kierunku zgodnym
z ruchem wskazówek zegara i w kierunku przeciwnym do tego ruchu. Od-
powiednie połączenie wału silnika krokowego do linki systemu podnosze-
nia i opuszczania zasłon umożliwi sterowanie zasłonami zależnie od sy-
gnałów wysyłanych przez płytkę Arduino.
Przeanalizujmy teraz pozostałe elementy składowe niezbędne do budowy
tego projektu.
1
https://www.adafruit.com/products/324
2
http://www.adafruit.com/products/81
3
https://www.adafruit.com/products/352
4
https://www.adafruit.com/products/165
5
http://www.ladyada.net/make/mshield/make.html
6
https://github.com/adafruit/Adafruit-Motor-Shield-library
#include <AFMotor.h>
void setup() {
Serial.begin(9600);
Serial.println("Początek testu silnika krokowego...");
// Za pomocą funkcji setSpeed można ustawić szybkość obracania wału silnika
motor.setSpeed(20);
}
void loop() {
// funkcja step()
motor.step(100, FORWARD, DOUBLE);
motor.step(100, BACKWARD, DOUBLE);
}
7
http://www.ladyada.net/make/mshield/use.html
nie obraca się, należy najpierw sprawdzić przewody łączące silnik z modułem
silnika. Warto też sprawdzić, czy płytka Arduino na pewno jest podłą-
czona do zasilacza 12-woltowego, ponieważ warunkiem działania silnika
jest dostarczenie odpowiedniego napięcia. W razie problemów z określeniem
kierunku obrotów silnika wystarczy przymocować do wału kawałek wstążki.
Obracająca się wstążka powinna ułatwić jednoznaczne stwierdzenie, czy
wał rzeczywiście obraca się w obu kierunkach.
Dysponujemy już działającym silnikiem krokowym, zatem możemy przystąpić
do uzupełnienia systemu o czujniki temperatury i światła, tak aby ten sil-
nik mógł działać w reakcji na zmieniającą się sytuację.
Plik CurtainAutomation/CurtainAutomation.pde
#include <AFMotor.h>
#define LIGHT_PIN 0
#define LIGHT_THRESHOLD 800
#define TEMP_PIN 5
#define TEMP_THRESHOLD 72
#define TEMP_VOLTAGE 5.0
#define ONBOARD_LED 13
int curtain_state = 1;
int light_status = 0;
double temp_status = 0;
void setup() {
Serial.begin(9600);
Serial.println("Konfigurowanie systemu automatycznej zasłony...");
// ustawia szybkość obrotów wału silnika krokowego na poziomie 100 obrotów na minutę
motor.setSpeed(100);
// inicjalizacja silnika
// motor.step(100, FORWARD, SINGLE);
// motor.release();
delay(1000);
}
void loop() {
// sprawdza temperaturę
int temp_reading = analogRead(TEMP_PIN);
delay(500);
switch (curtain_state)
{
case 0:
if (daylight && !warm)
// podnosi zasłonę
{
curtain_state = 1;
Curtain(curtain_state);
}
break;
case 1:
if (!daylight || warm)
// opuszcza zasłonę
{
curtain_state = 0;
Curtain(curtain_state);
}
break;
}
}
zasłony. Jeśli system jest zbyt czuły i na przykład podnosi zasłonę w reakcji na
wewnętrzne światło odbijane od szyby, być może trzeba będzie umieścić
fotokomórkę w innym miejscu. Sam zamontowałem ten czujnik w rogu okna
za pomocą czarnej taśmy izolacyjnej. W ten sposób ograniczyłem ryzyko
interpretowania światła zapalanego wewnątrz pomieszczenia jako coraz
jaśniej świecącego słońca.
Warto pozwolić temu systemowi swobodnie działać przez kilka dni, obser-
wując reakcje zasłony na światło słoneczne i temperaturę w pomieszczeniu.
Na tej podstawie będzie można dostosować wartości progowe czujników
temperatury i natężenia światła. Po prawidłowym skonfigurowaniu wszystkich
ustawień będziemy mogli się ograniczyć do sprawdzania co kilka tygodni
położenia linki sterującej i ewentualnej ponownej kalibracji systemu. Po
pewnym czasie automatyczne zasłony nie będą już wymagały żadnych
interwencji. Kiedy goście po raz pierwszy zobaczą automatycznie podnoszone
i opuszczane zasłony, z pewnością będą pod ogromnym wrażeniem.
M
asz dosyć noszenia przy sobie tradycyjnych metalowych kluczy
do swojego domu? Zapewne nie rozstajesz się ze swoim smartfo-
nem. Czyż nie byłoby wygodniej, gdyby drzwi wejściowe do domu
można było otwierać za pośrednictwem aplikacji działającej na tym smartfo-
nie? Czy nie warto pomyśleć o dodatkowym zabezpieczeniu polegającym
na fotografowaniu (za pomocą tej samej aplikacji) osób otwierających drzwi
i wysyłaniu tych zdjęć do właściciela domu w formie załączników poczty
elektronicznej? (Patrz rysunek 9.1 zatytułowany „Bezprzewodowe otwie-
ranie drzwi wejściowych za pomocą smartfonu”).
W tym projekcie użyjemy niedrogiego telefonu z systemem Android pierwszej
generacji. Smartfon zostanie połączony z płytką IOIO (czyt. jo-jo) firmy
Sparkfun i przełącznikiem przekaźnikowym sterującym ryglem elektrycznym.
Telefon z systemem Android pierwszej generacji będzie pełnił funkcję
serwera reagującego na żądania odblokowania drzwi wysyłane za pośrednic-
twem drugiego telefonu z systemem Android, na którym będzie działała od-
powiednia aplikacja kliencka. Po otrzymaniu żądania odblokowania zam-
ka telefon występujący w roli serwera robi zdjęcie za pomocą wbudowanego
aparatu i wysyła fotografię jako załącznik wiadomości poczty elektronicznej.
Do dzieła!
1
http://accessories.android.com
2
http://www.sparkfun.com/products/10747
3
http://www.adafruit.com/products/327
3. Zasilacz DC 5 V, 1 A4.
4. Zasilacz impulsowy 12 V, 5 A do zasilania elektrycznego rygla5.
5. Trzy przewody.
6. Smartfon z systemem operacyjnym Android i wbudowanym apa-
ratem fotograficznym (najlepiej oryginalny telefon Android G1).
Odpowiednie urządzenie można bez trudu znaleźć na aukcjach
internetowych w cenie poniżej 300 zł. Warto przy tym pamiętać, że
nie wszystkie telefony z systemem Android są zgodne z płytką IOIO.
Szczegółowe informacje można znaleźć na grupach dyskusyjnych
poświęconych płytce IOIO6.
7. Przewód barrel jack-JST (2-pin), który zostanie podłączony do złącza
kątowego JST na płytce IOIO7.
4
http://www.sparkfun.com/products/8269
5
http://www.adafruit.com/products/352
6
https://groups.google.com/group/ioio-users?pli=1
7
http://www.sparkfun.com/products/8734
8
Patrz odpowiednio http://www.sparkfun.com/products/10748 i http://www.
sparkfun.com/products/8612.
9
http://www.smarthome.com/5192/Electric-Door-Strike-Mortise-Type/p.aspx
10
http://www.sparkfun.com/products/10745
11
http://handbagdevices.com/
12
https://github.com/ytai/ioio/wiki
13
http://www.sparkfun.com/tutorials/280
Plik AndroidDoorLock/HelloIOIO-PTS/src/ioio/examples/hello/pts/MainActivity.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button_ = (ToggleButton) findViewById(R.id.button);
powertailbutton_ = (ToggleButton) findViewById(R.id.powertailbutton);
}
powertail_.write(!powertailbutton_.isChecked());
try {
sleep(10);
} catch (InterruptedException e) {
}
}
}
Jaś pyta...
Czym jest intencja systemu Android?
Zgodnie z dokumentacją systemu Android dla programistów intencja
to „abstrakcyjny opis operacji do wykonania”14. W największym skró-
cie intencje służą do wysyłania i odbierania komunikatów przekazy-
wanych pomiędzy działaniami i usługami systemu Android. Inten-
cje umożliwiają także wysyłanie komunikatów do tej samej aplika-
cji, która je generuje, jednak zdecydowanie częściej służą do wy-
syłania komunikatów z jednej aplikacji (na przykład przeglądarki
internetowej, która pobrała plik audio) do innej aplikacji (na przykład
odtwarzacza muzycznego).
Jeśli zarejestrowano wiele aplikacji otrzymujących określone komuni-
katy, na ekranie może być wyświetlane okno dialogowe z prośbą
o wybór właściwej aplikacji, do której ma być adresowany dany
komunikat. Każdy doświadczony użytkownik urządzenia z systemem
Android wielokrotnie miał do czynienia ze wspomnianym oknem
dialogowym. System operacyjny Android umożliwia użytkowni-
kom zaznaczenie w tym oknie dialogowym pola wyboru aplikacji
domyślnej, tak aby podobne pytania nie były ponownie wyświe-
tlane i nie denerwowały właściciela telefonu.
Konieczność proszenia użytkownika o wskazanie docelowej apli-
kacji powoduje, że w przypadku w pełni autonomicznych operacji
(na przykład wysyłania wiadomości poczty elektronicznej) mecha-
nizm intencji jest dalece nieoptymalny. Problem w tym, że aplikacja
wysyłająca tego rodzaju komunikaty (w tym przypadku aplikacja
poczty elektronicznej) może wymagać od użytkownika wykonania
dodatkowych czynności (na przykład kliknięcia przycisku Wyślij w pro-
gramie poczty elektronicznej, aby ostatecznie wysłać wiadomość
poczty elektronicznej wygenerowaną przez program źródłowy).
14
http://developer.android.com/reference/android/content/Intent.html
15
http://code.google.com/p/android-webserver/
16
http://www.jondev.net/articles/Sending_Emails_without_User_Intervention_
%28no_Intents%29_in_Android
17
http://code.google.com/p/krvarma-android-samples/
Plik AndroidDoorLock/DoorLockServer/src/com/mysampleapp/
androiddoorlockserver/AndroidDoorLockServerActivity.java
@Override
protected void loop() throws ConnectionLostException {
if (mToggleButton.isChecked()) {
if (LockStatus.getInstance().getLockStatus()) {
try {
powertail_.write(false);
// wstrzymuje działanie na 5 sekund
// (przez ten czas zamek jest otwarty)
sleep(5000);
powertail_.write(true);
LockStatus.getInstance().setMyVar(false);
// Robi zdjęcie i wysyła je w formie załącznika
// do wiadomości e-mail
camerasurface.startTakePicture();
} catch (InterruptedException e) {
}
}else {
try {
sleep(10);
} catch (InterruptedException e) {
}
}
} else {
powertail_.write(true);
}
}
elektronicznej. Dzięki temu będziemy wiedzieć nie tylko, kiedy miało miejsce
żądanie otwarcia drzwi wejściowych, ale też kto wszedł do domu po automa-
tycznym odblokowaniu zamka.
Robienie zdjęcia
Na potrzeby tego aspektu projektu należy przeanalizować zawartość pliku
CameraSurface.java w rozpakowanym katalogu DoorLockServer. Najważ-
niejsze funkcje potrzebne do utworzenia obiektu powierzchni aparatu i uzy-
skania obrazu zostały dość dobrze udokumentowane w zestawie narzędzi
Android SDK. Co więcej, w internecie istnieją dosłownie setki przykła-
dów kodu i poradników dotyczących uzyskiwania plików graficznych ze
zdjęciami w systemie Android18. Mechanizm pobierania obrazów w ramach
aplikacji serwera WWW opracowałem na bazie przykładowego kodu pro-
gramisty aplikacji systemu Android Krishnaraja Varmy.
Konfiguracja aparatu używanego w kodzie aplikacji systemu Android wymaga
zaimportowania wielu przestrzeni nazw tego systemu. W tym celu musimy
wykonać kilka dodatkowych kroków przygotowujących powierzchnię wy-
świetlania. Oto najważniejsze biblioteki używane w części programu od-
powiedzialnej za uzyskanie obrazu (w ramach pliku DoorLockServer.zip):
Plik AndroidDoorLock/DoorLockServer/src/com/mysampleapp/androiddoorlockserver/
CameraSurface.java
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.GestureDetector.OnGestureListener;
18
http://developer.android.com/reference/android/hardware/Camera.html
outStream.write(data);
outStream.close();
Czytelnicy, którzy wolą, aby każde kolejne zdjęcie było trwale zapisywane
na karcie SD (zamiast nadpisywać tak samo nazwany plik z poprzednim
zdjęciem), mogą dopisywać do nazwy pliku graficznego przyrostek znacznika
czasowego — oto rozwiązanie zastosowane w oryginalnym kodzie Krish-
naraja:
FileOutputStream outStream = ne FileOutputStream(String.format(
"/sdcard/%d.jpg", System.currentTimeMillis()));
Takie rozwiązanie nie jest jednak zalecane, jeśli na karcie SD nie ma dosta-
tecznie dużo przestrzeni i jeśli nie planujemy przechowywać tych samych
obrazów w telefonie i w skrzynce odbiorczej poczty elektronicznej. Czytel-
nicy, którzy zdecydują się na stosowanie tego schematu nazewnictwa, mu-
szą pamiętać o konieczności rejestrowania nazw plików z odpowiednimi
znacznikami czasowymi, aby na tej podstawie wybierać właściwe załączniki
do wysyłanych wiadomości. Przeanalizujmy teraz sposób dołączania obra-
zów do wiadomości poczty elektronicznej i wysyłania tych wiadomości.
Wysyłanie wiadomości
Skoro już pobraliśmy i zapisaliśmy na karcie SD tymczasowy plik obrazu
ze zdjęciem (zrobionym za pomocą wbudowanego aparatu), musimy jesz-
cze użyć autonomicznego mechanizmu dołączania tego zdjęcia do tworzo-
nej wiadomości (bez konieczności angażowania użytkownika). Na szczęście
możemy użyć do tego celu kodu JavaMail for Android autorstwa Jona Simo-
na. Projekt obejmuje między innymi funkcję wysyłania wiadomości poczty
elektronicznej w systemie Android. W tym celu musimy pobrać i dodać
do projektu zależności (pliki jar) potrzebne do działania JavaMail for
Android i kodu Jona obsługującego wiadomości poczty elektronicznej19.
Odpowiedni kod możemy zmodyfikować z myślą o wysyłaniu załączników
z plikami graficznymi. Musimy najpierw zaimportować wiele bibliotek
Javy używanych przez klasę JavaMail:
19
http://code.google.com/p/javamail-android/
import java.util.Date;
import java.util.Properties;
import javax.activation.CommandMap;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.MailcapCommandMap;
import javax.mail.BodyPart;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
Testowanie serwera
Serwer tego projektu można przetestować, uzyskując dostęp do jego adresu
URL z poziomu przeglądarki internetowej. Warto sprawdzić, czy elek-
tryczny zamek rzeczywiście został otwarty, czy aparat zrobił zdjęcie i czy
to zdjęcie zostało wysłane do wybranego adresata w formie załącznika
wiadomości poczty elektronicznej. Jeśli wszystko działa zgodnie z oczekiwa-
niami, możemy sobie pogratulować dobrze wykonanej pracy. Zważywszy
na liczę zależności występujących w tym projekcie, prawidłowe połączenie
wszystkich tych elementów już za pierwszym razem można potraktować
jako dobry powód do świętowania. Jeśli coś nie działa prawidłowo, warto
uważnie przeanalizować każdą funkcję z osobna. Czy serwer WWW od-
powiada na żądania? Czy przełącznik PowerSwitch Tail włącza zasilanie
elektrycznego rygla? Czy migawka aparatu fotograficznego zamyka się?
Warto pamiętać, że w zależności od szybkości połączenia sieciowego i mo-
dułu komunikacji bezprzewodowej Wi-Fi wbudowanego w telefon z syste-
mem Android wysłanie zdjęcia za pośrednictwem poczty elektronicznej
może zająć nawet minutę.
Podczas realizacji tego projektu udało nam się osiągnąć całkiem sporo —
już teraz moglibyśmy używać systemu zdalnie otwieranego zamka poprzez
wpisywanie odpowiedniego adresu URL w przeglądarce internetowej.
Warto jednak poświęcić jeszcze dosłownie chwilę na opracowanie własnej
aplikacji klienckiej, która będzie uzyskiwała dostęp do wspomnianego adresu
URL (podobnie jak w przypadku projektu internetowego włącznika światła).
Dzięki temu będziemy mogli otworzyć drzwi za pomocą zaledwie jednego
kliknięcia. Docelowo moglibyśmy zgromadzić więcej funkcji automatyzacji
domu w jednym programie mobilnym, który umożliwi dostęp do różnych
projektów za pośrednictwem jednego zbiorczego interfejsu.
Kwestie bezpieczeństwa
Jedną z zalet własnej, niestandardowej aplikacji klienckiej dla systemu
Android jest możliwość zabezpieczenia (choć trzeba przyznać, że
niezbyt skutecznego) dostępu do zdalnie sterowanego zamka. Po-
nieważ adres URL serwera WWW, na który wysyłamy żądanie otwarcia
drzwi, nie jest wyświetlany na ekranie smartfonu, adres ten pozostanie
ukryty przynajmniej dla użytkowników, którzy nie potrafią odnaleźć
odpowiednich zapisów w kodzie źródłowym. Opisane zabezpieczenie
nie gwarantuje jednak skuteczności, ponieważ sam adres URL jest wy-
syłany na serwer w formie zwykłego tekstu. Jedno z rozszerzeń tego
projektu, które zaproponuję w dalszej części tego rozdziału (w pod-
rozdziale „Następne kroki”), będzie dotyczyło właśnie dodania lepszych
mechanizmów zabezpieczeń. Dodanie hasła lub (co byłoby jeszcze
lepsze) jakiegoś wyszukanego schematu uwierzytelniania według
wielu czynników znacznie podniosłoby wartość tego systemu.
Plik AndroidDoorLock/DoorLockClient/src/com/mysampleapp/doorlockclient/
DoorLockClient.java
package com.mysampleapp.doorlockclient;
import java.io.InputStream;
import java.net.URL;
import android.net.wifi.WifiManager;
import android.widget.Button;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
findViewById(R.id.unlockbutton).setOnClickListener(mClickListenerUnlockButton);
try {
WifiManager wm =
(WifiManager) getSystemService(WIFI_SERVICE);
if (!wm.isWifiEnabled()) {
unlockbutton.setEnabled(false);
wm.setWifiEnabled(true);
// Czeka 17 sekund na aktywację modułu Wi-Fi
// i nawiązanie połączenia
Thread.sleep(17000);
unlockbutton.setEnabled(true);
}
} catch (Exception e) {
Log.e("LightSwitchClient", "Error: " + e.getMessage(), e);
}
}
View.OnClickListener mClickListenerUnlockButton =
new View.OnClickListener() {
public void onClick(View v) {
try {
final InputStream is =
new URL("http://192.168.1.230:8000").openStream();
}
catch (Exception e) {
}
}
};
}
20
https://www.grc.com/ppp.htm
C
zyż nie byłoby wspaniale, gdybyśmy podczas zbliżania się do drzwi
wejściowych byli pozdrawiani przez nasz dom i informowani o waż-
nych zdarzeniach, które miały miejsce podczas naszej nieobecności?
A może nasz dom powinien odpowiadać na pytania o stan skrzynki odbior-
czej poczty elektronicznej, polecenia sprawdzenia prognozy pogody lub żąda-
nia odtworzenia ulubionej kolejki plików muzycznych? Dom mógłby też gło-
śno powiadamiać domowników o zdarzeniach wykrywanych przez czujniki,
na przykład o przekroczeniu poziomu wody w zbiorniku lub o konieczności
dosypania nasion dla ptaków w karmniku (odpowiednio z pierwszego i dru-
giego projektu). (Patrz rysunek 10.1 zatytułowany „Powiadamianie o zda-
rzeniach”).
Ten projekt tchnie nowe życie w te z pozoru dziwaczne projekty. Utworzymy
centralny węzeł odpowiedzialny za obsługę komunikacji pomiędzy wszyst-
kimi systemami zbudowanymi w tej książce i za głosowe porozumiewanie
się z użytkownikiem.
Otrzymywanie wiadomości poczty elektronicznej i wpisów na Twitterze
oczywiście ma swoje zalety, jednak możliwość prowadzenia konwersacji
z własnym domem byłaby jeszcze ciekawsza. Byłoby wspaniale, gdybyśmy
mogli głośno zadać pytanie „która godzina?” bądź wypowiedzieć jakieś
polecenie, na przykład „włącz światła” lub „puść muzykę”, i gdyby nasz dom
reagował, generując odpowiednią odpowiedź lub wykonując nasze polecenie.
Właśnie opisane mechanizmy zrealizujemy w ramach projektu opisanego
w tym rozdziale. Projekt połączy opracowane wcześniej projekty internetowe-
go włącznika światła i drzwi sterowanych przez Androida oraz umożliwi
sterowanie tymi rozwiązaniami za pomocą poleceń głosowych.
Przy okazji realizacji tego projektu przeanalizujemy możliwości implementacji
dodatkowych poleceń głosowych, jak wybór wykonawcy i albumu do od-
tworzenia przez zestaw stereo, zwiększanie i zmniejszanie głośności itp.
1
http://www.supertooth.net/AU/produitmusique.htm
2
http://www.radioshack.com/product/index.jsp?productId=2131022
3
http://store.griffintechnology.com/imic
rozwiązaniem. Jeśli jednak jakość dźwięku ma dla nas większe znaczenie niż
wygoda transmisji bezprzewodowej, tylko przewodowe połączenie komputera
ze wzmacniaczem stereo zapewni oczekiwany efekt. Jeśli mamy szczęście
i instalujemy system w pomieszczeniach, w których zainstalowano już
okablowanie dla systemu nagłośnienia, połączenie komputera z tym sys-
temem jest oczywistym rozwiązaniem.
4
Użytkownicy polskiej wersji systemu OS X Lion mogą wybrać syntezator mowy
Agata — przyp. tłum.
5
http://developer.apple.com/library/mac/#documentation/AppleScript/
Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html
6
http://developer.apple.com/library/mac/#documentation/Darwin/Reference/
ManPages/man1/osascript.1.html
7
Patrz odpowiednio http://developer.android.com/resources/articles/speech-input.html
lub http://msdn.microsoft.com/en-us/library/ee125663%28VS.85%29.aspx.
Z
decydowana większość tej książki była poświęcona rzeczywistym
projektom automatyzacji domu, które już teraz można zrealizować
stosunkowo niewielkim kosztem. W tym rozdziale przeanalizujemy
wyjątkowo ciekawą, błyskawiczną ewolucję w dziedzinie mikrokontrolerów,
smartfonów i komputerów, aby na tej podstawie spróbować przepowiedzieć
przyszłość tych technologii.
Zaczniemy od omówienia potencjalnych scenariuszy rozwoju technologii
Arduino, systemu Android i innych systemów operacyjnych w niedalekiej
przyszłości. W dalszej części rozdziału podejmiemy próbę rozszerzenia
naszych prognoz jeszcze o dekadę, aby wyobrazić sobie technologie auto-
matyzacji domu, które będą nam towarzyszyć w 2025 roku. Zważywszy na
niesamowity postęp technologii mobilnych w ostatnich dziesięciu latach,
nasze pomysły dotyczące przyszłego rozwoju tych technologii szybko mogą
się okazać zupełnie pospolite. W rzeczywistości większość proponowanych
scenariuszy można by zrealizować już teraz (podczas implementacji tych
rozwiązań bardzo pomocne byłyby doświadczenia zebrane w trakcie pro-
jektów opisanych w tej książce). Zanim wybiegniemy dalej w przyszłość,
warto przyjrzeć się rozwiązaniom, które powinny zagościć na sklepowych
półkach już w ciągu roku.
Arduino 1.0
Dokładnie w czasie, gdy pisałem ostatnie strony tej książki, zespół odpo-
wiedzialny za rozwój technologii Arduino zapowiedział nadchodzące wyda-
nie wersji 1.0. W nowej wersji wprowadzono wiele daleko idących zmian,
które z pewnością wymuszą odpowiednie dostosowanie istniejącego kodu.
Decyzja zespołu rozwijającego technologię Arduino była o tyle ryzykow-
na, że istnieje mnóstwo bibliotek, przykładów kodu, dokumentów, książek
i zapisów wideo przygotowanych przez samych użytkowników dla wcze-
śniejszych wersji tej technologii. Nie inaczej jest w przypadku tej książki.
Po spopularyzowaniu standardu Arduino 1.0 opisane projekty i ich za-
leżności (w formie bibliotek) z pewnością będą wymagały modyfikacji pod
kątem zmian wprowadzonych w tym standardzie. Najważniejsze spośród
wprowadzonych zmian opisano poniżej:
Rozszerzenia plików szkiców zmieniono z .pde na .ino. Zdecydo-
wano się na tę zmianę, aby uniknąć mylenia tych szkiców ze szkica-
mi języka Processing, które także są zapisywane w plikach z roz-
szerzeniem .pde.
Biblioteka Ethernet platformy Arduino będzie oferowała rdzenną
obsługę systemu DNS i protokołu DHCP. Takie rozwiązanie
znacznie ułatwi przypisywanie adresów IP.
Klasa String została zoptymalizowana, dzięki czemu wymaga
mniejszej ilości zasobów i może realizować więcej zadań, gene-
rując mniejsze obciążenie.
Klasa Serial oferuje teraz więcej funkcji do analizy składniowej,
dzięki którym możemy łatwiej przeszukiwać dane i ładować wiele
bajtów do bufora. Opisana zmiana może powodować pewne
Android@Home
Na konferencji Google IO w 2011 roku oficjalnie ogłoszono powstanie
interfejsu Android Open Accessory API i zestawu narzędzi Android
Development Kit (ADK). Celem obu projektów było zapewnienie dostępu
1
http://arduino.cc/blog/2011/10/04/arduino-1-0/
2
http://www.adafruit.com/products/191
S
koro dysponujemy już niezbędnymi podstawami, możemy wykorzystać
zebrane doświadczenia w zakresie projektowania i konstruowania sys-
temów automatyzacji domu do tworzenia własnych projektów. W tym
niedługim ostatnim rozdziale krótko przeanalizujemy pomysły na alterna-
tywne wykorzystanie elementów i urządzeń, których używaliśmy w projektach
opisanych w tej książce.
Czytelnicy, którzy zbudowali wszystkie projekty opisane w tej książce, już
teraz dysponują większością sprzętu potrzebnego do realizacji pomysłów
prezentowanych w tym rozdziale. Możemy także wykorzystać kod źródło-
wy tych projektów — w wielu przypadkach wystarczy wprowadzenie kilku
drobnych zmian. Przeanalizujmy teraz kilka dodatkowych sposobów na
zaprogramowanie domu.
1
http://www.adafruit.com/products/164
2
http://www.adafruit.com/products/143
3
http://www.adafruit.com/products/387
4
https://www.adafruit.com/products/385
5
http://www.sparkfun.com/products/9964
6
http://revision3.com/tbhs/homeauto
się sposób prezentacji projektu przez Bena, ponieważ nie zanudza widzów
szczegółami budowy samego termostatu. Co więcej, w projekcie zastosowa-
no części, których sami używaliśmy w rozdziale 8. zatytułowanym „Auto-
matyzacja działania zasłony”, zatem budowa i implementacja tego pro-
jektu nie powinny nam sprawić żadnego problemu.
J
edną z największych zalet rodziny produktów Arduino jest zastosowa-
nie otwartej platformy sprzętowej. Oznacza to, że każdy może uczestni-
czyć w procesie tworzenia i rozwijania bibliotek sprzętowych i pro-
gramowych dla tej platformy. Takie biblioteki można następnie łatwo dołą-
czać do szkiców platformy Arduino, aby albo rozszerzyć oferowane przez
nią funkcje i mechanizmy, albo (tak jest w większości przypadków) ułatwić
samemu sobie pisanie szkiców.
Rozwiązania opracowane przez społeczność użytkowników tej platformy
zostały wykorzystane w wielu projektach opisanych w tej książce. Okazuje
się jednak, że instalacja nowych bibliotek platformy Arduino nie jest auto-
matyczna i nie sprowadza się do uruchomienia skryptu instalacyjnego.
Pliki bibliotek, które często są udostępniane w formie skompresowanych
archiwów .zip, należy rozpakować i umieścić w folderze libraries środowiska
programowania Arduino IDE. Położenie tego folderu zależy od systemu
operacyjnego, w którym uruchamiamy środowisko Arduino IDE.
#include <CapSense.h>;
void setup() {}
void loop() {}
I czujnik pojemnościowy, 98
budowa, 99
iCircuit, 32 programowanie, 99
IDE, 42, 57, 69, 257 fotokomórka, 102
Inkscape, 31 konfiguracja bazy danych, 114
internetowy włącznik światła, 149 lista komponentów, 95
Android, 162 nasłuchiwanie komunikatów, 119
testowanie, 167 publikowanie wpisów, 113
bieżący stan światła, 162 schemat połączeń, 108
budowa rozwiązania, 153 szkic, 109
kod klienta, 158, 162 Twitter, 94
testowanie, 161, 167 XBee, 95
lista komponentów, 151 zabezpieczenie urządzeń, 121
łączenie, 154 zasilanie, 122
rozbudowa, 170 fotowoltaniczne, 122
Ruby on Rails, 158 klucz
X10, 150 API, 118
CM11A, 155 konsumenta standardu OAuth,
IOIO, 195, 199 118
ADK, 41 tajnego tokenu dostępu, 118
IOIOLib, 202 tajny konsumenta, 118
schemat połączeń, 201 kompilator, 156
serwer WWW, 212 komunikacja bezprzewodowa, 106
IP, 68, 209 Bluetooth, 234
przypisanie stałego adresu, 68 Wi-Fi, 106
iPad, 32 XBee, 43, 106
Elektor Electronic Toolbox, 32 krok, 178
iCircuit, 32
iThoughts HD, 32 M
miniDraw, 32
MAC, 68
K metodyka wytwarzania sterowanego
testami, Patrz TTD
karmnik dla ptaków, 93 Minicom, 107
Arduino Nano, 95, 97 miniDraw, 32
budowa rozwiązania, 98
części systemu, 96
moduł monitorowanie, 85
dźwiękowy, 78 zasada działania, 84
AF_Wave, 85 płytki mikrokontrolerów, 37
Arduino, 82 Arduino, 37
łączenie, 82 pojemność elektryczna, 99
próbki dźwięków, 83 PowerSwitch Tail II, 194
szkic demonstracyjny, 85 powiadamianie o zdarzeniach, 230
zarządzanie odtwarzaniem, 86 konfiguracja głośników, 231
parowanie, 44 Bluetooth, 232
sieciowy, 67, 70 nawiązywanie połączenia, 233
Arduino, 67 lista komponentów, 231
kodowanie, 67 mechanizm rozpoznawania mowy,
przypisanie adresu, 68 234
stały adres IP, 68 konfiguracja, 234
multimetr, 34 włączanie mówionych
komunikatów, 235
O wybór głosu, 237
rozbudowa, 250
open source, 31 syntezator mowy, 237, 240
Freemind, 31 kod, 242
Fritzing, 31 testowanie, 249
Heyu, 150 TTS, 230
Inkscape, 31 wewnętrzny mikrofon, 238
kalibracja, 239
P protokół komunikacji, 26
parowanie modułów, 44 SOAP, 138
pasywny czujnik ruchu na standaryzacja, 26
podczerwień, Patrz PIR TCP/IP, 27
Perfect Paper Passwords, 227 wysyłania impulsów, 26
PHP, 64, 65 przełącznik przekaźnikowy, 194
hosting, 64 Python, 33, 45
mail, 66 easy_install, 118
wiadomości e-mail, 65 identyfikacja XBee, 143
pin, Patrz wtyk implementacja dostarczania paczek,
PIR, 77 139
instalacja, 90 testowanie skryptu, 144
łączenie, 82