Skocz do zawartości
Komentator

Kurs Arduino - #9 - Czujnik odległości HC-SR04, funkcje

Pomocna odpowiedź

Program mierzy odległość i wyświetla ją na LCD w cm oraz przedstawia formie graficznej. Przy pomiarze poniżej 5 cm włącza się buzzer. Co muszę wpisać w miejsce "*" by zamiast gwiazdek na ekranie pojawiały się prostokąty?

#include <LiquidCrystal.h> //Dołączenie bilbioteki
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
#define trigPin 12
#define echoPin 11

void setup() 
{
 pinMode(trigPin, OUTPUT); //Pin, do którego podłączymy trig jako wyjście
 pinMode(echoPin, INPUT); //a echo, jako wejście
 pinMode(13, OUTPUT);
 lcd.begin(16, 2); //Deklaracja typu
}

void loop() 
{
 zakres(0,5);
 lcd.setCursor(0, 0); //Ustawienie kursora
 lcd.print(zmierzOdleglosc()); //Wyświetlenie tekstu
 lcd.print(" cm");
 delay(200);
 lcd.clear();
 int gwiazki = map(zmierzOdleglosc(), 0, 50, 16, 0);
 for (int i = 0; i < gwiazki; i++)
 {
   lcd.setCursor(i, 1); //Ustawienie kursora
   lcd.print("*"); //Wyświetlenie gwiazdek
 }
}
int zmierzOdleglosc()
{
 long czas, dystans;
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW); 
 czas = pulseIn(echoPin, HIGH);
 dystans = czas / 58;
 return dystans;
}
void zakres(int a, int b) {
 int jakDaleko = zmierzOdleglosc();
 if ((jakDaleko > a) && (jakDaleko < b)) {
     digitalWrite(13, HIGH); //Włączamy buzzer
 } else {
     digitalWrite(13, LOW); //Wyłączamy buzzer, gdy obiekt poza zakresem
 }
}

Udostępnij ten post


Link to post
Share on other sites

VVasyl, musisz sprawdzić w dokumentacji sterownika LCD (HD44780) jaki kod odpowiada za zamalowany prostokąt. Znajdziesz to w tabeli obsługiwanych znaków.

Udostępnij ten post


Link to post
Share on other sites

Mam problem. Zaimplementowałem ten kod tuż przed wprowadzeniem buzzera i wyskakują mi w terminalu ładne odległości, ale jak nagle czujnik nie ma nic w polu widzenia przez nawet moment, to wywala 0 cm i niby spoko, ale potem już ciągle wywala 0 cm i nie podaje nic, dopóki nie zresetuję zasilania HC-SR04 (wypinam z niego vcc i podpinam jeszcze raz i jest dobrze). Niby mogę zrobić załączanie zasilania tuż przed pomiarem i wyłączanie tuż po, żeby się resetował, ale to trochę ciulowa opcja. Jakieś pomysły?

Udostępnij ten post


Link to post
Share on other sites

mosi2, z czego zasilasz układ? Czy Arduino jest oryginalne? Spróbuj dodać jakiś kondensator blisko zasilania czujnika (jeśli masz coś pod ręką).

Udostępnij ten post


Link to post
Share on other sites

Oryginalne, zasilam prosto z usb, ale wg noty ten moduł ciągnie 2mA więc nie sądziłem, że to to. Spróbuję dorzucić kondensator, dzięki za radę 🙂

Btw, jak używam dwóch sonarów stojąch koło siebie, to z trigeruję drugi w momencie jak pierwszy kończy podawanie wyniku, czy muszę odczekac? Bo teoretycznie skoro ten pierwszy już skończył robotę to nie powinno być zakłóceń, ale miałem jakieś śmieci na uarcie i zrobiłem opoźnienie 10ms przed odczytem drugiego, co je wyeliminowalo. Tylko, że jak to ma być w minisumo to każde opóźnienie jest średnio mile widziane...

Dodam tylko, że to nie do końca moje minisumo - ja bym tam wrzucił sharpy i gołą atmegę, ale to w ramach zajęć z robotyki dla mojego byłego liceum 🙂

Udostępnij ten post


Link to post
Share on other sites

Moim zdaniem to, że czujnik odebrał echo wcale nie znaczy, że sprawa zakończona. Przecież impuls ultradźwiękowy wciąż jest gdzieś w przestrzeni i w każdej chwili może wrócić ponownie odbity od czegoś innego. Z odpaleniem następnego pomiaru lub czujnika powinieneś poczekać aż upłynie czas dolotu i powrotu od przeszkody oddalonej o maksymalną odległość jaką przewidujesz dla swojego systemu. A najlepiej o maksymalną odległość na jakiej wykrywa cokolwiek ten czujnik. Wtedy na pewno nic nie wróci (tzn. nawet jak wróci to nie zostanie wykryte) i nie zakłóci następnego pomiaru.

Jeżeli w programie nie masz żadnego timeoutu czyli zabezpieczenia przed nieprzyjściem echa (trzeci parametr funkcji PulseIn), to gdy nie ma przeszkody generowany jest trigger, program czeka na echo, ono nie przychodzi więc program czeka na echo, ono nie przychodzi itd.. Odłączenie zasilania czujnika generuje zakłócenie na pinie sygnału zwrotnego i "odmraża" funkcję PulseIn tak, że program może wypisać jakiś bzdurny wynik i wygenerować kolejny trigger.

Udostępnij ten post


Link to post
Share on other sites

Czyli jeśli teoretyczny zasięg to 200cm, to dzielę 4m przez prędkość dźwięku w powietrzu i mam potrzebne opóźnienie, tak? Czy powinienem brać jakieś poprawki na randomowość układu...

Timeout mam aktualnie ustawiony na 4000 mikrosekund (a te bugi wciąż wyskakują)

Udostępnij ten post


Link to post
Share on other sites

Przede wszystkim pokaż kod - będzie wiadomo o czym mówimy. Jeżeli kod jest prosty i czysty (tzn. program nie ma szans zwisnąć w jakichś zagmatwanych obliczeniach lub warunkach) to jest duża szansa, że problemem jest działanie samego czujnika lub funkcji PulseIn. Spróbuj zastąpić ją swoją własną funkcją, która nie musi mierzyć prawdziwego czasu (może oddawać jakiś wynik w spodziewanym zakresie, zawsze ten sam lub losowy), ale za to sama wykrywa początek impulsu i jego koniec. Może też zapalać jakąś diodkę gdy wykryje stan 1 i gasić gdy impuls się skończy. Wtedy pomagluj czujnik i zobacz, czy błędy się powtarzają. Może on sam zwisa w jakimś dziwnym stanie a może reszta programu gdzieś głupieje. We własnej funkcji możesz grzebać do woli więc łatwiej będzie wykryć miejsce kłopotów. Oczywiście naturalną koleją rzeczy będzie rozwinięcie funkcji tak, bu już samodzielnie mierzyła czas 🙂

----------------

EDIT: 4 metry to dla dźwięku ponad 12ms (dla v=330m/s). Teraz doczytałem, że ten czujnik generuje impuls zawsze. Jest on krótszy lub dłuższy, ale dokumentacja nie przewiduje sytuacji, gdy impulsu nie będzie. Nawet dla braku przeszkody impuls będzie miał maks. 38ms. Tak więc, gdyby wszystko szło jak po maśle nie powinna zdarzać się sytuacja zwisu z powodu braku impulsu a timeout powinien funkcję PulseIn wydobywać z oczekiwania. Przed wszystkim musisz dorpowadzić do sytuacji wydarzenia się tego błędu i zacząć wtedy analizować co się dzieje. Jakie są stany na pinach? Czy program stoi w jednym miejscu (w którym?), czy jednak poprawnie pracuje generując kolejne triggery? Jakie są wyniki oddawane wtedy przez PulseIn. Wiadomo, typowe uruchamianie kodu sterownika.

EDIT2: Specyfika działania funkcji PulseIn jest taka, że wywołana z parametrem HIGH najpierw będzie czekała na stan LOW po to, by pewnie wykryć zbocze narastające i od tego momentu liczyć czas. Gdy więc zostanie wywołana za późno (po wygenerowaniu triggera i po rozpoczęciu impulsu odpowiedzi), sygnał zwrotny zostanie niezauważony i.. zwis lub timeout.

Udostępnij ten post


Link to post
Share on other sites

A czy mogę po prostu podłączyc zasilanie z dołączonego pakietu 9v poprzez wejscie arduino?

Udostępnij ten post


Link to post
Share on other sites

RicardoMax, które wejście masz na myśli? W zestaw z baterią jest klips zakończony złączem pasującym do gniazda na płytce Arduino. Oczywiście możesz tak zasilać płytkę. Nie podłączaj jednak 9V w innych miejscach, bo możesz uszkodzić płytkę.

Udostępnij ten post


Link to post
Share on other sites

Zadanko domowe - LED-owe ...

#define trigger 12
#define echo 11

void setup() {
 Serial.begin (9600);
 pinMode(trigger, OUTPUT);
 pinMode(echo, INPUT); 
 int liczbaDiod = 0;
   pinMode(0, OUTPUT);
 digitalWrite(0, LOW);
   pinMode(1, OUTPUT);
 digitalWrite(1, LOW);
   pinMode(2, OUTPUT);
 digitalWrite(2, LOW);
   pinMode(3, OUTPUT);
 digitalWrite(3, LOW);
   pinMode(4, OUTPUT);
 digitalWrite(4, LOW);
   pinMode(5, OUTPUT);
 digitalWrite(5, LOW);
   pinMode(6, OUTPUT);
 digitalWrite(6, LOW);
   pinMode(7, OUTPUT);
 digitalWrite(7, LOW);
   pinMode(8, OUTPUT);
 digitalWrite(8, LOW);
}

void loop() {
 int dystans2 = pomiar(); //wykonaj pomiar, zwróć wartość w cm
 int liczbaDiod = map(dystans2, 0, 50, 9, 1); //przelicz zakres pomiarowy 50cm na liczbę diod
   Serial.print("dystans2 =");
   Serial.println(dystans2);
   for (int a = 0; a < liczbaDiod; a++) { //załącz diody od 1 do liczbaDiod
   digitalWrite(a, HIGH);
   }
 delay(1000); //pauza, dla lepszego efektu
   for (int a = 0; a < 9; a++) { //wyłącz wszystkie diody, same nie zgasną ;-P dla widoczności kolejnego pomiaru
   digitalWrite(a, LOW);
   }
}

int pomiar() {
 long czas, dystans;
 digitalWrite(trigger, LOW);
 delayMicroseconds(2);
 digitalWrite(trigger, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigger, LOW);
 czas = pulseIn(echo, HIGH);
 dystans = czas / 58 + 1; //przeliczenie jednostek na cm
 return dystans;
}

No i teraz tak: wszystkie diody musiałem opisać jak wyżej, czy da się to skrócić?

Udostępnij ten post


Link to post
Share on other sites

Kurojatka, da się to skrócić - będziemy tak robić podczas kontynuacji kursu 🙂

W między czasie polecam uzupełnić kod komentarzami!

Udostępnij ten post


Link to post
Share on other sites

czy mozna przenieś mikro-kontroler z płytki arduino na swoja płytkę stykowa

Udostępnij ten post


Link to post
Share on other sites

Rafi212, można 🙂

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Napisz odpowiedź...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...