Skocz do zawartości

Błędne odczyty ultradźwiękowego czujnika odległości gdy działa buzzer pasywny


Łukasz_K

Pomocna odpowiedź

Witam serdecznie.

Niedawno zacząłem interesować się tematyką Arduino. Na początek w ramach ćwiczeń/eksperymentu postanowiłem zbudować prosty układ składający się z Arduino Uno R3 (klon), czujnika odległości HC-SR04 i modułu YL-44 z buzzer pasywnym. Posiłkując się kodem z kursu Arduino na forbot.pl napisałem program, którego zadaniem było załączanie brzęczyka, gdy w odległości 30-150cm od czujnika odległości znajdzie się przeszkoda i wyłączenie buzzera, gdy przeszkoda zniknie z pola widzenia. Niestety układ nie działał jak powinien. W momencie wykrycia przeszkody głośniczek się załączał, ale w momencie gdy przeszkody już nie było buzzer nadal wydawał dźwięk, mimo że nie powinien. By sprawdzić dlaczego tak się dzieje uprościłem maksymalnie kod pozbywając się warunków, a funkcję tone() wrzuciłem do sekcji setup(). Teraz buzzer działa cały czas, gdy płytka podłączona jest do zasilania. Jednocześnie mierzona jest odległość i wyświetlana wartość pomiaru w monitorze portu szeregowego.

Oto kod programu:

#define trigPin 7
#define echoPin 8
#define buzzerPin 5

void setup() {
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 pinMode(buzzerPin, OUTPUT);

 //analogWrite(buzzerPin, 128);
 tone(buzzerPin, 1000);
 Serial.begin(9600);
}

void loop() {
 Serial.print(zmierzOdleglosc());
 Serial.println(" cm");
 delay(200);
}

int zmierzOdleglosc() {
 long czas = 0;
 long dystans = 0;

 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);

 czas = pulseIn(echoPin, HIGH);
 dystans = czas / 58;

 return dystans;
}

oraz opis połączeń modułów z płytką Arduino:

Moduł ultradźwiękowego czujnika odległości HC-SR04:

Vcc -- 5V

Trig -- PIN 7

Echo -- PIN 8

Gnd -- GND

Moduł buzzera pasywnego YL-44 (buzzer pasywny, rezystor: 102, tranzystor: 2TY):

VCC -- 5V

I/O -- PIN 5

GND -- GND

Dodam tylko, że układ stoi nieruchomo naprzeciw ściany w odległości około 153 cm.

Gdy moduł buzzera wpięty jest do układu, otrzymuję następujące wyniki:

65, 107, 89, 107, 89, 90, 90, 90, 107, 106, 89, 141, 89, 107, 123, 106, 106, 106, 89, 107, 73, 90, 152, 94, 152, 78, 107, 89, 90, 90, 124, 123, 72, 90, 107, 106, 89, 124, 89, 90, 90, 90, 90, 90, 90, 90, 107, 89, 90, 90, 107, 89, 73, 90, 107, 89, 90

Gdy odłączę buzzer, wtedy wyniki pomiaru są prawidłowe i wynoszą:

152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 153, 152, 152, 152, 152, 153, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 153, 152, 152, 153, 152, 152, 153, 152

Zastosowanie funkcji analogWrite(), czyli PWM nie rozwiązuje problemu. Zastosowanie 3 parametru w funkcji pulseIn() również nie pomaga. To samo dotyczy 3 parametru funkcji tone(). Gdy buzzer wydaje dźwięk, odczyty odległości są błędne. Gdy buzzer się wyłącza, wyniki są prawidłowe.

Dlaczego tak się dzieje? Czy ktoś spotkał się z podobną anomalią? Próbowałem używać różnych pinów, innych częstotliwości dźwięku w fukncji tone() - nic nie pomaga. Byłbym bardzo wdzięczny za pomoc lub podpowiedź.

Link do komentarza
Share on other sites

Widzę trzy możliwości:

1. Funkcja buzzera z jakiegoś powodu "gryzie" się z funkcją pomiaru odległości. Nie znam arduino i trudno mi określić dlaczego tak będzie ( mogę zgadywać... 🙂 ). Najłatwiej to sprawdzisz jak zostawisz kod bez zmian, ale odłączysz buzzer od pinu mikrokontrolera...

2. Buzzer w czasie pracy pobiera cyklicznie "spory" prąd co może doprowadzać do spadków napięcia na zasilaniu, a nawet niewielkie spadki wystarczają do wprowadzenia dodatkowego szumu w pracę czujnika ultradźwiękowego ( a dokładniej wzmacniaczy tam się znajdujących ) i "ogłupienie" systemu.

3. Buzzer zakłóca pracę czujnika ultradźwiękowego ( wysyła trochę śmieci w jego częstotliwości? )

Najprościej to sprawdzisz jak zbudujesz drugi układ z oddzielnym zasilaniem i jeden będzie miał włączony buzzer, a drugi ultradźwięki. Jak buzzer jest blisko czujnika ultradźwiękowym i go zakłóca to wina buzzera, natomiast jak buzzer nie zakłóca czujnika ultradźwiękowego samą bliskością to "śmieci" idą po zasilaniu - które w tym przypadku rozdzieliliśmy.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Nie jestem ekspertem, powoli poznaję Arduino. Jeśli w funkcjach analogWrite() i tone() są użyte przerwania to prawdopodobnie zakłócają one czas trwania pętli w funkcji pulseIn() i rozjeżdżają się obliczenia w tej funkcji. Funkcja pulseIn() podaje czas trwania impulsu w przybliżeniu, na podstawie liczby wykonań odpowiedniej pętli, przynajmniej tak mi się wydaje po obejrzeniu kodu.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Też początkowo sądziłem, że funkcje tone() i pulseIn() zastosowane jednocześnie powodują jakiś konflikt. Gdzieś wyczytałem, że Arduino Uno posiada 3 timery: Timer0, Timer1 i Timer2. Funkcja tone() korzysta z tego ostatniego, ale nie znalazłem informacji, żeby funkcja pulseIn() wykorzystywała jakiś timer, więc nie sądzę, żeby przerwania i kwestia odwołań do tego samego timera były przyczyną problemów. Gdybym zamiast funkcji pulseIn() korzystał z biblioteki NewPing, to taki problem mógłby się pojawić, ponieważ ww. biblioteka wykorzystuje Timer2. Ale ja z tej biblioteki nie korzystam. Poza tym kompilator prawdopodobnie zgłosiłby w takiej sytuacji błąd.

Wydaje mi się, że problem tkwi w zasilaniu, jak zasugerował MirekCz. Możliwe, że buzzer powoduje jakieś wahania napięcia, co wydaje mi się trochę dziwne, bo z tego co pamiętam buzzer nie pobiera dużego prądu, maks 40mA. Postaram się sprawdzić co mogę.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Witam.

Ja bym stawiał na zakłócenia dźwiękiem. Buzer piezoelektryczny nie emituje sinusoidy, bardziej prostokąt, więc pewnie te 40kHz leż ma w widmie. Nie zdziwiłbym się więc, gdyby to była przyczyna. Zwłaszcza jeżeli buzer i czujnik są blisko siebie.

Pozdrawiam.

Link do komentarza
Share on other sites

@Jamik

Przyczyną problemów na pewno nie są zakłócenia dźwiękiem. Posiadam dwie płytki: Arduino Uno i Arduino Mega 2560. Na jednej zamontowałem czujnik odległości, a na drugiej buzzer. Położyłem działające płytki obok siebie i dokonałem odczytu wartości z czujnika HC-SR04 w monitorze portu szeregowego. Wyniki były poprawne. Tak więc buzzer nie zakłóca pracy czujnika odległości generowaną falą dźwiękową.

Swoją drogą płytka Arduino Mega 2560 w połączeniu z czujnikiem odległości i buzzerem dawała podobne, błędne wyniki jak Arduino Uno.

@MirekCz

Rzeczywiście problemy mogą wynikać ze spadków napięcia. Wpiąłem dwa kondensatory do zasilania modułu HC-SR04: elektrolityczny 47uF i ceramiczny 100nF (Czy to są prawidłowe wartości? Jak się dobiera pojemności w takich przypadkach?) i to praktycznie wyeliminowało problem. Zniknął rozrzut w odczytach odległości, a same wartości można uznać za poprawne. Niestety nie mam multimetru, żeby coś więcej sprawdzić.

Mimo wszystko istnieje jednak jakiś wpływ funkcji tone() na wyniki działania czujnika HC-SR04. Do płytki Arduino Uno podpiąłem jedynie czujnik HC-SR04 i zwiększałem iteracyjnie częstotliwość funkcji tone() dla pinu 5 od 500Hz do 5000Hz (pin 5 wolny, nic do niego nie podłączałem). Wyniki podawane przez czujnik odległości były stabilne, jednak wraz ze wzrostem częstotliwości malała odczytana odległość. Przy 500Hz miałem około 152-153 cm (czyli o około 1cm mniej od prawidłowej odległości), a przy 5000 Hz odległość wynosiła już tylko 142-143 cm. Z podłączonym buzzerem i kondensatorami też tak się dzieje. Korzystając z płytki Arduino Mega 2560 również otrzymuję identyczne rezultaty. Z czego to może wynikać?

Link do komentarza
Share on other sites

W poprzednim poście pisałem, że wraz ze wzrostem częstotliwości dźwięku generowanego za pomocą funkcji tone(), maleje wartość zwracana przez funkcję pulseIn(). Najprawdopodobniej winne są przerwania występujące w funkcji tone(), jak zasugerował grg0. Owe przerwania powodują opóźnienia w działaniu funkcji pulseIn() i stąd błędne wyniki zwracane przez tę funkcję. Każda zmiana stanu fali generowanej przez funkcję tone() to pojedyncze przerwanie. Tak więc przy częstotliwości, np. 2500 Hz tych przerwań będzie 5000/sek - całkiem sporo. Im wyższa częstotliwość, tym dłuższy czas obsługi przerwań i tym samym mniejsze wartości czasu zwracane przez funkcję pulseIn(). Znalazłem kilka rozwiązań tego problemu (może komuś się przydadzą):

1. Można wyliczyć czas obsługi przerwań funkcji tone(), przyjmując, że pojedyncze przerwanie trwa około 8 mikrosekund (wielkość dobrana eksperymentalnie), a uzyskaną wartość dodać do wyniku funkcji pulseIn(). Takie rozwiązanie pozwala na uzyskanie akceptowalnych rezultatów, choć nie jest może zbyt eleganckie.

2. Inny sposób polega na wykorzystaniu funkcji pulseInLong() zamiast zwykłej pulseIn(). Funkcja ta znajduje się w standardowych bibliotekach Arduino i pozwala uzyskać prawidłowe rezultaty bez względu na to, czy funkcja tone() została użyta w programie, czy też nie.

3. Warto także rozpatrzyć użycie zewnętrznej biblioteki o nazwie NewPing, której twórcą jest Tim Eckel. Funkcje wchodzące w skład tej biblioteki są "odporne" na skutki działania funkcji tone(). Należy jednak pamiętać, aby w pliku NewPing.h ustawić wartość parametru TIMER_ENABLED na false i nie używać funkcji ping_timer(), która korzysta z tego samego licznika co funkcja tone(). Zmiana parametru TIMER_ENABLED pozwala uniknąć konfliktów. Poza tym jeśli piny ECHO oraz TRIG modułu HC-SR04 nie są podłączone do płytki Arduino za pomocą jednego przewodu, to należy ustawić parametr ONE_PIN_ENABLED na false.

4. Podczas pomiaru odległości za pomocą funkcji pulseIn() można chwilowo wyłączyć obsługę przerwań. Służą do tego komendy noInterrupts() oraz interrupts(). To rozwiązanie pozwala uzyskać prawidłowe wyniki dla funkcji pulseIn(), jednak zaburzone zostaje działanie funkcji tone(). Mimo wszystko w pewnych zastosowaniach może być pomocne, dlatego o nim wspominam.

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.