Ultrasonic, czyli walka czujników z Seeedstudio, HC-SR04 i MaxBotix

Porównanie czujników ultradźwiękowych w praktyce.

Wstęp

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.

Testowane czujniki

Do testów wykorzystaliśmy popularne czujniki, które bez problemu można zakupić w sieci, są nimi Seeedstudio SEN136B5B, HC-SR04, MaxBotix MB1010.

Jest biblioteka, która obsługuje większośc z nich (Maxbotix ma interfejs szeregowy co znacznie ułatwia odczyt), to New Ping Dzięki temu nie  musieliśmy kombinować z pisaniem oddzielnych kodów.

Jak podłączyć czujnik SEN136B5B do Arduino

SEN136B5B od SeeedStudio

Przyjrzyjmy się specyfikacji czujnika Seeedstudio

Specyfikacja czujnika od Seeedstudio

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

#define PING_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).

HC-SR04

Schemat podłączenia

Specyfikacja HC-SR04

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.

Schemat podłączenia czujnika Maxbotix

Ż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);

}

MaxBotix MB1010

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.

Wyniki pomiarów

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ść.