Ultrasonic, czyli walka czujników z Seeedstudio, HC-SR04 i MaxBotix
Każdemu komu marzy się budowa robota, wcześniej czy później będzie musiał podjąć decyzje o czujniku do wykrywania przeszkód. W końcu nie chcemy, aby nasz robot odbijał się od ściany do ściany. Na rynku dostępnych jest wiele takich czujników od ultradźwiękowych, podczerwieni, aż po najzwyklejsze mechaniczne. My się natomiast skupiliśmy na tych pierwszych z grupy. Czym są czujniki ultradźwiękowe i jak działają. Otóż takie czujniki składają się z nadajnika i odbiornika. Nadajnik emituje krótkie fale dźwiękowe o wysokiej częstotliwości w regularnych odstępach czasu. Kiedy sygnał natrafi na przeszkodę odbija się od niej i wraca do odbiornika. Odległość od przeszkody mierzona jest na podstawie czasu, po którym sygnał powrócił do czujnika. Tu warto dodać, iż w przypadku czujników ultradźwiękowych tło, kolor, rodzaj czy przejrzystość przeszkody nie mają wpływu na pomiar.

Do testów wykorzystaliśmy popularne czujniki, które bez problemu można zakupić w sieci, są nimi Seeedstudio SEN136B5B, HC-SR04 oraz MaxBotix MaxSonar EZ1 (MB1010). W przypadku Seeedstudio jak i HC-SR04 użyliśmy wspólnej biblioteki NewPing(code.google.com). Dzięki temu nie musieliśmy kombinować z pisaniem oddzielnych kodów. Na poniższym rysunku widać jak podłączyć czujnik SEN136B5B do Arduino.


Przyjrzyjmy się specyfikacji czujnika Seeedstudio
Specyfikacja
Zasilanie |
5V |
Zużycie prądowe |
15 mA |
Częstotliwość ultradźwięków |
40k Hz |
Zasięg max |
400 cm |
Zasięg min |
3 cm |
Rozdzielczość |
1 cm |
Szerokość impulsu Trig |
10 μs |
Wymiary |
43x20x15 mm |
Poniżej przedstawiliśmy przykładowy kod z biblioteki, o której wcześniej wspomnieliśmy. Jak widać, musieliśmy jedynie zadeklarować do jakich pinów Arduino podłączyliśmy nasz czujnik. Potem pozostało nam odczytać odległość w jakiej znajdowała się przeszkoda. W rzeczywistości komenda sonar.ping() odczytuje nam czas jak długo czekaliśmy na odpowiedź. W celu uzyskania odległości w cm musimy nasz czas podzielić przez US_ROUNDTRIP_CM. Nasza biblioteka umożliwiała nam jeszcze zastosowanie filtra, który ustabilizowałby pomiary, jednak my nie używaliśmy go w naszym teście.
#include <NewPing.h> // Dołączenie biblioteki NewPing #definePING_PIN 7 // Deklaracja pinu Arduino do którego podłączony jest //czujnik #define MAX_DISTANCE 400 // Deklaracja maksymalnego zasięgu pomiaru. NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE); // Konfiguracja NewPing, ustawienie pinów oraz zasięgu void setup() { Serial.begin(115200); } void loop() { delay(50); // Przerwa pomiędzy sygnałami 50ms (około 20 sygnałów/sec). //29ms to najkrótsza przerwa pomiędzy sygnałami. unsigned int uS = sonar.ping(); // Wyślij sygnał, odbierz sygnał w microsekundach(uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Konwersja sygnału na odległość i wyświetlenie wartości //(jeśli 0 to po za pomiarem) Serial.println("cm"); }
Drugim czujnikiem wykorzystanym w teście był HC-SR04. Różni się on od czujnika SEN136B5B dwoma wyjściami (TRIG i ECHO).


Specyfikacja
Zasilanie |
5V |
Zużycie prądowe |
15 mA |
Częstotliwość ultradźwięków |
40k Hz |
Zasięg max |
400 cm |
Zasięg min Kąt pomiaru |
2 cm 15 stopni |
Szerokość impulsu Trig |
10 μs |
Wymiary |
45x20x15 mm |
Tak jak w przypadku czujnika SEN136B5B tu również skorzystaliśmy z tego samego kodu zmieniając jedynie piny, do których podłączyliśmy czujnik.
#include <NewPing.h> // Dołączenie biblioteki NewPing #define TRIGGER_PIN 12 // Deklaracja pinu Arduino do którego podłączone jest Trig #define ECHO_PIN 11 // Deklaracja pinu Arduino do którego podłączone jest Echo #define MAX_DISTANCE 400 // Deklaracja maksymalnego zasięgu pomiaru. NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // Konfiguracja NewPing, ustawienie pinów oraz zasięgu void setup() { Serial.begin(115200); } void loop() { delay(50); // Przerwa pomiędzy sygnałami 50ms (około 20 sygnałów/sec). //29ms to najkrótsza przerwa pomiędzy sygnałami. unsigned int uS = sonar.ping(); // Wyślij sygnał, odbierz sygnał w microsekundach(uS). Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); // Konwersja sygnału na odległość i wyświetlenie wartości //(jeśli 0 to po za pomiarem) Serial.println("cm"); }
Trzecim i ostatnim czujnikiem był Maxbotix EZ1, który posiada wyjście analogowe, PWM oraz serial out. My skorzystaliśmy z wyjścia analogowego.

Żeby nie zagłębiać się w szczegóły karty katalogowej, naszą odczytaną wartość podzieliliśmy przez 2, a następnie pomnożyliśmy przez 2.54( przejście z cali na cm).
int sensorPin = 0; //analog pin 0 void setup(){ Serial.begin(9600); } void loop(){ float val = analogRead(sensorPin)/2.0; Serial.println(val*2.54); delay(100); }

W ramach naszego testu zrobiliśmy kilka pomiarów w różnej odległości od ściany betonowej i ściany wykonanej z pudeł kartonowych. Chwilowe spadki odczytanych wartości należy pominąć, ponieważ jest to zakłócenie od Maxbotixa (wszystkie 3 czujniki były blisko siebie; HC-SR04 oraz SEN136B5B wysyłają i odbierają impuls co kilka ms, natomiast MaxBotix działa cały czas. Te błędy to odbieranie sygnałów MaxBotixa przez pozostałe dwa czujniki i ich złe zinterpretowanie- częstotliwość MB1010 to 42KHz).
Zdecydowaliśmy się również na obliczenie odchylenia standardowego, które pokazało nam dokładność naszych czujników, a wyniki zawarliśmy w tabelce poniżej.
Przejdźmy teraz do najważniejszego, czyli wyłonienia zwycięzcy. Generalnie, wszystkie trzy czujniki sprawowały się znakomicie w przypadku pomiaru odległości od ściany betonowej. Pomiar był w miarę stabilny i zgodny z naszym przyrządem laboratoryjnym, czyli najzwyklejszą miarką.
Ciekawsze rzeczy zaobserwowaliśmy w drugim teście wykorzystując ścianę z pudeł kartonowych. Tu wygrał MaxBotix, ze swoim stabilnym pomiarem, a na drugim miejscu uplasował się czujnik od Seeedstudio. W przypadku HC-SR04 pomiar lubił “popłynąć” zwracając często wartość niezgodną z rzeczywistą odległością.
Powyższe dwa testy wykonaliśmy po kilka razy w różnych odległościach od naszych przeszkód.
Najciekawszy jednak okazał się ostatni pomiar z pojemnikiem tubowym na układy scalone. Tu również wygrał Maxbotix, ale nie było ani drugiego ani trzeciego miejsca. Dlaczego? Odpowiedź znajdziecie w filmie poniżej. Okazało się, że w zależności od kręcenia pojemnikiem HC-SR04 i czujnik od SeeedStudio potrafiły nie wykryć przeszkody. Miało to miejsce, gdy róg pojemnika był wycelowany w czujniki. Żeby to potwierdzić, sprawdziliśmy jak oba czujniki poradzą sobie z rogiem ściany. Niestety nasze obawy się potwierdziły, ściana nie została wykryta. W poniższym filmie, w celu wyeliminowania nałożenia się sygnałów, o których wspomnieliśmy wyżej, zasłoniliśmy Maxbotixa. MB1010 został w następnej kolejności przetestowany i ku naszemu zdziwieniu, kręcenie pojemnikiem nie zrobiło na nim większego wrażenia. Pomiar był poprawny, a wycelowanie rogiem pojemnika w czujnik nie spowodowało żadnej odchyłki w wynikach.
Podsumowanie testu czujników ultrasonic
Podsumowując nasz krótki test, z całą pewnością możemy polecić czujniki MaxBotixa. Oczywiście są one droższe od dwóch pozostałych, jednak wyniki mówią same za siebie. Budując robota, nie możemy sobie pozwolić, aby nie wykrył on przeszkody. Jeśli przeszkody mają być małe lub z ostrymi krawędziami to MaxBotix będzie idealny. Najtańszy z testowanych czujników – HC-SR04 – nadaje się do wykrywania przeszkód, takich jak ściany, bądź innych dużych przedmiotów bez ostrych rogów, lecz należy pamiętać, iż czasem lubi zwrócić dziwną wartość. Dla naszego robota może to oznaczać błędne nie wykrycie przeszkody prowadzące w rezultacie do zderzenia z nią, dlatego ten czujnik proponujemy użyć jako ostateczność. Oczywiście dziwne wartości, mogą być winą biblioteki, lecz przeglądając filmy na popularnym Youtubie, można się spotkać z podobnymi testami, które to potwierdzają. Jeśli chodzi, o czujnik od SeeedStudio, to gdyby nie fakt, że nie wykrył on rogu pojemnika na scalaki, to jemu również nic nie można zarzucić. Wyniki były w miarę stabilne i układ nie podawał dziwnych odległości od przeszkody, dlatego SEN136B5B zajmuje drugie miejsce w naszym teście.
Na zakończenie, możemy śmiało powiedzieć, iż na każdy czujnik możemy znaleźć taki obiekt, który nie zostanie wykryty. Ma to związek z odbiciem sygnału, który po natrafieniu na taki obiekt (mały i cienki) i odbiciu się od niego, nie będzie na tyle mocny, aby zwrócić odległość.
Mam pytanie. Jak Seedstudio wypada na tle SDM-IO? Według tego porównania HC-S04 jest mało ciekawy: http://www.jarzebski.pl/arduino/czujniki-i-sensory/ultradzwiekowy-czujnik-odleglosci-sdm-io.html?
Seedstudio wypadnie podobnie SDM-IO z tego względu, że oba czujniki mają inne zakresy pomiarowe. SDM jest dokładniejszy, przynajmniej tak wynika ze specyfikacji technicznej (potrafi mierzyć od 0-1.5m), natomiast Seeedstudio mierzy od 3cm, ale ma większy zasięg. W przypadku SDM-IO nie wiem jak będzie wyglądać sprawa wykrywania np. laski lub pojemnika na scalaki. W podanym przez Pana linku test pokrywa tylko wykrywanie sporych powierzchni (blat stołu, monitor, ewentualnie ściana). Dobrze by było zobaczyć jak się SDM zachowa przy zbliżaniu jakiejś cienkiej przeszkody oraz jak reaguje na ostre krawędzie. Wtedy można będzie stwierdzić, który jest lepszy czy Seeedstudio czy SDM. Jeśli chodzi o HC-SR04 to nasz test i test w linku potwierdza, że ten czujnik należy traktować jako ostateczność.
Cześć, spoko artykuł, przydałoby się jednak więcej przypadków testowych i może lepiej kontrolowane warunki.
Tak na przyszłość, publikowanie danych numerycznych w pdf’ie to fatalny pomysł. Znacznie lepiej jest takie dane opublikować jako CSV lub choćby arkusz kalkulacyjny.
Hej. Dzięki za opinię. Nie ja pisałem ten wpis, ale jestem współautorem tego bloga i akademii. Lubię robić lepsze wpisy i chciałbym wykorzystać twoje odczucia. Oto pierwsze:
– Jakie miałaś oczekiwania trafiając do tego wpisu? Co konkretnie chciałaś znaleźć?
Jeśli dobrze zrozumiałem ostatni post ( autora ) to z chęcią bym przeczytał test opisujący działanie czujników odległości w polarnym układzie współrzędnych. Bardziej obrazowo – jak czujniki sprawdziłyby się jako el obrotowego „radaru”?
Jaka jest ich rozdzielczość i czułość kątowa? Jaki fragment przeszkody musi zostać objęty wiązką (w stosunku do 360 st) ,żeby był widoczny?