Elkészült a kód első változata. Röviden menjünk végig rajta!
void setup() {
pinMode(ECHO_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(BUZZ_PIN, OUTPUT);
motor.attach(SERVO_PIN);
digitalWrite(TRIG_PIN, LOW);
digitalWrite(BUZZ_PIN, LOW);
Serial.begin(9600);
motor.write(90); // set to middle position
prevangleindex = 1;
prefetch(); // waiting ~5 sec to leave the area
initialize_distances(); // collecting initial distances
}
Inicializálom a pineket, hogy melyiken fogadom, illetve küldöm az adatokat. A motort középre állítom. A prefetch() csak egy időhúzó lépés, hogy az eszköz telepítése után legyen idő elhagyni a védendő területet. Ez idő alatt másodpercenként annyit csipog, amennyi másodperc eltelt a bekapcsolás után. Öt után elhalgat, a rendszer megkezdi a működését.
Az initialize_distances függyvényben ezután jobbra fordul a riasztó, 20-szor távolságot mér, majd kiszámolja a t-próba konfidencia intervallumait. A műveletet megismétli a középső és a bal oldalra való fordulás után. Ezt a függvényt collect_baseline-nak neveztem el, háromszor hívom meg az initialize_distances-en belül.
void collect_baseline(int orientation){
float avg;
float sd;
collect_dists();
avg = calc_avg();
sd = calc_sd(avg);
base[orientation].low = avg - T * (sd / sqrt(20.0));
base[orientation].high = avg + T * (sd / sqrt(20.0));
}
A T a kritikus érték 19-es szabadsági fokra, mert 20 mintánk van, és 99.5% konfidencia intervallumra. (Először 95%-ra állítottam be, de az nem volt jó, később részletezem, miért.) Az érték a statisztikai könyvekben és a Wikipédián is megtalálható.
A kód loop része a következő:
void loop() {
actualangleindex = random(3);
smooth_step(angles[prevangleindex], angles[actualangleindex]);
if(is_extreme_dist(actualangleindex) == true){
tone(BUZZ_PIN, 300);
} else {
noTone(BUZZ_PIN);
}
prevangleindex = actualangleindex;
}
Választunk véletlenszerűen egy irányt, a motort szép lassan odaforgatjuk, végzünk újabb 20 mérést, majd egy t-próbával megnézzük, hogy eltér-e az átlag attól, amit a collect_baseline esetén rögzítettünk. (Beleesik-e a konfidencia intervallumba) Ha eltér, veszettül riasztunk. Ha nem tér el, kikapcsoljuk a hangot.
Nos, a próbák során elég gyatrán teljesít a riasztó. Bármit is csináltam, kb 2-3 perc működési idő után elkezdett folyamatosan sípolni. A hiba oka nagyon meglepett. A riasztó a motor folyamatos mozgásának hatására szép lassan vándorolni kezdett a sima felületű asztalon, ezért egy idő után úgy érzékelte, hogy minden megváltozott körülötte.
Ekkor kivettem a szervó mozgatását a kódból. A fals riasztások mégsem szűntek meg. Elkezdtem kiíratni milyen értékeket mér a szerkezet, illetve milyen átlagokat rögzített. A konfidencia intervallumok közelében jöttek a találatok. Igaz is, a 95% azt jelenti, hogy a mért értékek legfeljebb 95%-a ebbe a tartományba esik. De nem minden. Ekkor tértem át a 99,5%-ra. A fals találatok száma valóban lecsökkent, de nem szűnt meg!
A felület, amire a riasztót irányítottam, merőleges volt a szenzorra, és kb. 1,4 méterre volt. Valami ismeretlen okból viszont néha a húsz mérés átlaga 90 cm lett. Tehát hiába állt mozdulatlanuk a szerkezet, akkor is beriasztott. Több helyen is írták, hogy a levegő hőmérséklete befolyásolja a szenzor mérési pontosságát, illetve felléphet interferencia is. Jelen pillanatban egyikre sincs ötletem, hogyan küszöbölhetném ki.
Ha ez még nem lenne elég néha ki tudtam cselezni a készüléket. Az irányváltások között, amikor forgatja a motort, akkor nem rögzíti a távolságokat. Tehát ha ebben a pillanatban gyorsan átugrottam a riasztó előtt, akkor nem adott hangjelzést.
A fejlesztés következő lépése, hogy kipróbálom több mérési pont alkalmazását, illetve beiktatok még egy kis szünetet a mérések között, hátha csökken az interferencia. Valamint kellene némi csúszásgátló a riasztó talpa alá. Hihetetlen, hogy egy egyszerű projekt során mennyi probléma előjön!