niedziela, 9 sierpnia 2015

[4] Arduino - Ultradzwiękowy czujnik odległości HC-SR04

Opis teoretyczny.


Czujniki ultradźwiękowe emitują fale dźwiękowe o bardzo wysokiej częstotliwości. Są one wysyłane i odbijane od przeszkody. Przez co powstaje zjawisko nazywane powszechnie Echem.
Czujniki ultradźwiękowe charakteryzują się min. [1]:
  • Dużą rozdzielczością,
  • Szerokim zakresem pomiarowym,
  • Wysoką częstotliwością ultradźwięków,
  • Małą wartością dopuszczalnej odległości minimalnej,
  
     Niezależnością pomiarów od typu materiału, światła, koloru oraz środowiska.
Tego typu czujniki są wykorzystywane np. jako czujniki parkowania, w automatyce bądź robotyce. Dzięki swoim właściwością pozwalają one na [1]:
  • Wykrycie obiektów w trudnych warunkach,
  • Detekcje poziomu cieczy o różnych właściwościach,
  • Wykrywanie przedmiotów o różnych fakturach,

Czujnik HC–SR04


Czujnik HC-SR04 pozwala na przeprowadzenie pomiarów w zakresie od 2cm do 2 metrów. Kąt pracy wynosi 30 stopni.

Rys. 1.1. Czujnik HC-SR04 - wygląd zewnętrzny

Aby rozpocząć wykonywanie pomiarów należy podać stan wysoki na pin Trigger o długości 10µs. Po inicjalizacji następuje wysłanie 8 krótkich impulsów o częstotliwości 40KHz. Odbiornik po wysłaniu sygnału pomiarowego oczekuje na sygnał powracający od przeszkody tzw. Echo. Po odebraniu danych na pin Echo podawany jest stan wysoki, którego długość jest proporcjonalna do zmierzonej odległości. Czas trwania impulsu wynosi od 150µs do 25ms. Maksymalny czas oczekiwania na odbiór wiadomości wynosi 38ms.

Przeliczenie odległości następuje na podstawie wzoru zawartego w dokumentacji czujnika:


Gdzie: O – odległość, t- czas trwania impulsu.
Podstawowa część wzoru została wyprowadzona na podstawie prędkości rozchodzenia się dźwięku w powietrzu. Dźwięk przebywa odległość do i od czujnika. Jego prędkość w powietrzu wynosi 340m/s.

Poprawka do wzoru głównego została oszacowana na podstawie rozdzielczości czujnika i noty katalogowej podobnego czujnika US-015, ponieważ są one tego samego typu i działają na takiej samej zasadzie. W nocie katalogowej czujnika HC-SR04 są umieszczone dane tylko dotyczące jego rozdzielczości (czyli 0,3 cm), są to za małe dane aby poprawnie ocenić jego dokładność.
Rys. 1.2. Schemat blokowy działania czujnika HC-SR04

Przykład


W przykładzie zaprezentuje sposób tworzenia oprogramowania z prezentacją danych w monitorze portu szeregowego.

Opóźnienie musi być odpowiednio długie aby nie następowało wyłapywanie ECHA z poprzednich pomiarów ustawienie 2000ms powinno wystarczyć (nawet z dużym nadkładem czasowym).
W programie na podstawie danych obliczone są wartości maksymalne oraz minimalne pozwalające na ocenienie dokładności przeprowadzonych pomiarów. Odległość referencyjna powinna znajdować się w podanym przedziale.

Jedną z najważniejszych funkcji w programie jest pulseIn(). Mierzy ona czas występowania impulsu wysokiego bądź niskiego na wybranym pinie. Od inicjalizacji program czeka na wystąpienie wybranego stanu na zdeklarowanym pinie. W tym przypadku jest to stan wysoki na pinie Echo. 
Funkcja będzie działała poprawnie dla długości impulsu z zakresu od 10 mikrosekund do 3 minut. 
Możliwe jest jeszcze podanie trzeciej wartości tzw. timeout czyli czas jaki minie zanim funkcja rozpocznie swoje działanie. Podaje się go w mikrosekundach (typ unsigned long) [2].

#define ECHO 12
#define TRIGGER 13
float ODLEGLOSC = 0;     //odległość w cm
long CZAS = 0;         //długość impuslu na pinie echo
float MAX = 0;
float MIN = 0;
 
void pomiar_odleglosci(void);
void setup()
{
  Serial.begin(9600);  //Inicjalizacja parametrów portu szeregowego
  pinMode(TRIGGER, OUTPUT);  //Ustawienie pinu Trigger jako wyjście
  pinMode(ECHO, INPUT);      //Ustawienie pinu Echo jako wejście
  Serial.println("HC-SR04 pomiar odleglosci:");  
}
 
void loop()
{
  pomiar_odleglosci();    //Wywołanie funkcji zewnętrznej
  Serial.print("Czas:  ");
  Serial.print(CZAS);
  ODLEGLOSC = (CZAS / 58.0);  //Obliczenie czasu
  Serial.print("  Cm:  ");
  Serial.print(ODLEGLOSC);
  Serial.print("  MAX:  ");
  MAX = ODLEGLOSC + (0.3 + 0.01*ODLEGLOSC); 
  Serial.print(MAX);
  Serial.print("  MIN:  ");
  MIN = ODLEGLOSC - (0.3 + 0.01*ODLEGLOSC);
  Serial.println(MAX);
 
  delay(2100);              //Opóźnienie
}
 
void pomiar_odleglosci()
{
  // impuls 10 uS inicjalizujacy
  digitalWrite(TRIGGER, HIGH);  //Ustawienie stanu wysokiego pin Trigger
  delayMicroseconds(10);        //Opóźnienie 10us
  digitalWrite(TRIGGER, LOW);   //Stan niski na pin Trigger
  CZAS = pulseIn(ECHO, HIGH);   //Obliczenie długości trwania impulsu
}

Na podstawie przeprowadzonych doświadczeń z tym czujnikiem mogę stwierdzić, że przy odległości do 2m, czyli tej zdefiniowanej przez producenta, otrzymane dane mieszczą się w przedziale. Problem dopiero zaczyna się po przekroczeniu wartości maksymalnej.

Bibliografia:

[1]      http://teleinfo.pb.edu.pl/lab/uklady_elektroniki_prof_2/cwiczenie5.pdf
[2]      https://www.arduino.cc/en/Reference/pulseIn