Dnešní „chytré“ telefony a tablety mají v sobě obvykle několik různých senzorů, například GPS, akcelerometr, magnetometr, teplotní a světelné čidlo a podobně. Specifickým senzorem je i mikrofon, který používáme k hovoru. Jak tato čidla využít ve vlastní konstrukci aniž bychom museli „rozpárat“ telefon a učit se jednotlivé senzory obsluhovat mikrokontrolérem? Jde to nepoměrně jednodušším způsobem.
Program SensoDuino vytvořený Hazimem Bitarem pro zařízení s OS Android (v aktuální verzi 0,160 pro Android 2.3.3. – 4.4) umí propojit senzory obsažené v telefonu s naším zapojením prostřednictvím BlueTooth a třeba běžného komunikačního modulu HC-05.
Program zjistí, které senzory jsou v telefonu fyzicky přítomné, a nabídne pro ně tři zaškrtávací pole. Prvním se volí, že daný senzor bude čten a hodnoty z něj zobrazeny na displeji, druhým se posílají tyto hodnoty přes BT z telefonu a třetím povolujeme, aby byly stejné hodnoty zapisovány do textového logu. Log je ve formátu CSV, soubor se vytvoří v telefonu v kořenovém adresáři paměťové karty. V menu jde nastavit, v jakém intervalu se budou data z čidel zapisovat (od 10 ms do 10 minut), nicméně musíme sami ohlídat, zda zvolený interval má smysl. Například údaj z GPS, který se typicky mění každou sekundu, nemá význam zapisovat do logu 100x častěji.
Program SensoDuino lze stáhnout a naistalovat z Google play. Je schopen pracovat s následujícími senzory (v závorce jsou uvedeny jednotky a složky údaje, ty uvedené ale nemusí být jediné, které se předávají):
1- ACCELEROMETER (m/s² – X,Y,Z)
2- MAGNETIC_FIELD (uT – X,Y,Z)
3- ORIENTATION (yaw, pitch, roll)
4- GYROSCOPE (rad/s – X,Y,Z)
5- LIGHT (SI lux)
6- PRESSURE (hPa millibar)
7- DEVICE TEMPERATURE (C)
8- PROXIMITY (cm nebo 1,0)
9- GRAVITY (m/s² – X,Y,Z)
10- LINEAR_ACCELERATION (m/s² – X,Y,Z)
11- ROTATION_VECTOR ( X,Y,Z)
12- RELATIVE_HUMIDITY (%)
13- AMBIENT_TEMPERATURE (c)
14- MAGNETIC_FIELD_UNCALIBRATED (uT – X,Y,Z)
15- GAME_ROTATION_VECTOR ( X,Y,Z)
16- GYROSCOPE_UNCALIBRATED (rad/s – X,Y,Z)
17- SIGNIFICANT_MOTION (1,0)
97- AUDIO (Volume in generic units)
98- GPS1 (Lat., Long., Alt.)
99- GPS2 (Bearing, Speed, Date/Time)
Senzory přítomné v zařízení se vypíší do detailního přehledu, v něm jsou důležité především meze hodnot, jakých může výstup ze senzoru nabývat.
Pokud se rozhodneme hodnoty logovat, může výsledek vypadat nějak takto:
Zkusme program prakticky využít k dálkovému ovládání podvozku robrouka pomocí BlueTooth a tříosého akcelerometru. Při naklopení telefonu vpřed (od sebe) se podvozek rozjede vpřed, při naklopení do strany bude přiměřeně zatáčet a při srovnání do roviny nebo naklopení vzad (k sobě) se zastaví. Pro zjednodušení nebudeme vyžadovat couvání ani otáčení na místě, nejvýš „jedno kolo oběhne druhé“, ale rychlost pohybu budeme řídit od nuly. Využijeme modul HC-05 a k řízení modul Arduino Pro Mini nebo Uno.
Doporučené obousměrné připojení modulu HC-05 k Arduinu Uno je na obrázku, pro naše účely stačí jednosměrná komunikace (bez signálu RxD na HC-05). Program SensoDuino je nastaven tak, že vysílá aktuální údaje z akcelerometrů 4x za sekundu.
Oba motory budeme plynule ovládat pomocí PWM, jako výkonový stupeň stačí pro jeden motor jediný tranzistor BC337 s rezistorem 1k5 v bázi. Motory jsou napájené přímo ze zdroje, kterým je jeden Li-pol článek, Arduino je napájené stabilizovaným napětím 5 V ze spínaného měniče.To podstatné je program. Začneme výpisem, poznámky budou následovat.
// Ovladani podvozku pomoci programu SensoDuino // a akcelerometru v mobilnim telefonu // Arduino Pro Mini nebo UNO #include <SoftwareSerial.h> SoftwareSerial BT(2, 3); // RX | TX char c; int counter; char buff[256]; int cas, x, y, z, levy, pravy; void setup() { pinMode (10, OUTPUT); //vystup pravy motor pinMode (11, OUTPUT); //vystup levy motor // Serial.begin(115200); // monitorovani BT.begin(38400); } void loop() { // synchronizace na zacatek dat - znak ">" do { c = cti(); } while (c != '>'); // nacteni vety do bufferu counter = 0; do { c = cti(); buff[counter++] = c; } while (c != '\n'); buff[counter] = ''; // vybrat jen data z akcelerometru - typ 1 int type = atoi(strtok (buff, ",")); if (type == 1) { // udaje do promennych + korekce polohy cidla cas = atoi(strtok (NULL, ",")); x = int(atof(strtok (NULL, ",")) * 1000) - 300; y = int(atof(strtok (NULL, ",")) * 1000) + 300; z = int(atof(strtok (NULL, ",")) * 1000); /* Serial.println(x); Serial.println(y); Serial.println(z); Serial.println(); */ levy = 0; pravy = 0; if (x > 500) { pravy += map(x, 500, 6000, 0, 200); } if (x < -500) { levy += map(x, -500, -6000, 0, 200); } if (y < -500) { levy += map(y, -500, -6000, 0, 200); pravy += map(y, -500, -6000, 0, 200); } analogWrite(10, min(pravy, 255)); analogWrite(11, min(levy, 255)); } } // ceka na znak na vstupu a nacte ho char cti() { while (!BT.available()) {} return BT.read(); }
SenzoDuino posílá svoje výstupy jako text. My budeme zpracovávat jen výstup z akcelerometru a pravděpodobně si také jen akcelerometr zapnene na vysílání, ale program musí být schopen jiná čidla odfiltrovat.
Věta z akcelerometru má podobu: >kk,cc,xx.xx,yy.yy,zz.zz
První znak je vždy „>“, na ten se dá čtení synchronizovat. Pak následuje identifikace čidla (kk), nejvýše dvoumístné přirozené číslo (0 – 99), pak čas (cc) respektive pořadí dat (přirozené číslo), a dál tři reálná čísla se složkami v osách x, y a z. Jednotlivé údaje jsou oddělené znakem „,“, na konci věty je znak ukončení řádku. Ve větě nejsou mezery nebo jiné znaky, jako desetinný oddělovač se používá tečka.
Pro zjednodušení si připravíme metodu „cti“ (úplně na konci), která čeká, dokud není k dispozici znak na vstupu, a pak jej přečte a vrátí se. V době přenosu věty do bufferu se nic jiného nedělá, jen čeká na znaky, rozdekódování věty a řízení přijde na řadu po přijetí celé věty. Případné věty z jiného čidla program přečte do bufferu, ale nijak na ně nereaguje.
Výsledkem jsou složky x, y a z typu integer (s tím se dále snadněji pracuje) překonvertované tak, že původní reálné číslo je před převodem vynásobené 1000. Ve vztahu si můžete všimnout ještě korekce (jednou -300, podruhé +300), která je vázaná na konkrétní telefon a kompenzuje mírné vybočení čidla akcelerometru vzhledem k vodorovné poloze těla telefonu. V určitém rozsahu kolem nuly (+500 až -500 bez korekce) motory stojí.
Jakmile máme složky x a y v proměnných (z se v tomto případě nevyužívá, ale je k dispozici ve své proměnné také), je další postup jednoduchý. Interval výchylky 500 až 6000 (respektive -500 až -6000) převedeme na rozsah řízení PWM, ale nevyužijeme celý interval do 255, necháme si rezervu. Do jednotlivých motorů se pak mixuje jak příspěvek z osy x (zatáčení) tak z osy y (jízda vpřed). Ta rezerva je dobrá na to, aby třeba při plné jízdě vpřed (příspěvek osy je jen 200, ne 255) bylo ještě možné mírně zatáčet (+/- 55). Metody mixování jsou různé, tato zajišťuje jednoduchý kompromis mezi plnou dosažitelnou rychlostí (dopředného pohybu i otáčení) a možnostmi manévrování.
Takto ovládané vozítko jde jemně a citlivě řídit co do rychlosti i zatáčení. Na pohyby telefonem reaguje ovšem s určitým zpožděním, to je dané zejména tím, že data se vysílají jen 4x za sekundu. Je třeba si zvyknout i na to, že do ovládání se promítnou i bezděčné pohyby rukou, nejen naklopení telefonu, protože akcelerometr nerozliší zrychlení ve vodorovném směru od (tíhové) složky gravitace při nakloněném telefonu.
Řízení na dálku je pouze jednou z možností využití programu SensoDuino, jinou je třeba umístit celý telefon na podvozek a pomocí akcelerometrů snímat naklonění terénu, jet podle GPS do daného místa nebo logovat pohyb robota, vázat pohyb na přesný čas (od operátora mobilu) nebo dokonce efektně ovládat robota hlasem nebo jiným zvukem. To poslední jde jen velmi zjednodušeně, protože telefon poskytuje pouze informaci o intenzitě zvuku (hluku) v okolí bez dalšího rozlišení (třeba frekvencí), ale k tomu, aby se robot rozjel nebo zastavil na tlesknutí (nebo povel „stůj!“ hlasitější než jiné okolní zvuky) to stačí.