Skocz do zawartości
Komentator

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

Pomocna odpowiedź

Dzień dobry,
mam podobny problem jak kolega mosi2 - czujnik po podłączeniu przez krótki czas prawidłowo mierzy odległość (słuchać delikatne stukanie) jednak po chwili wiesza się i wyskakują same zera (stukanie znika). Pomaga jedynie reset zasilania bądź ruszenie czujnikiem/przewodami. Podłączenie kondensatorów niestety nie pomogło... Kod mam dokładnie ten sam co w kursie tuż przez podłączeniem buzzera.

Arduino oryginalne, zasilanie USB.

Będę wdzięczny za pomoc. 🙂

Udostępnij ten post


Link to post
Share on other sites

MateuszG, jeśli pomaga ruszenie przewodami, to... na pewno coś jest nie tak z przewodami. Może coś się wyrobiło i nie zawsze styka? Najlepiej spróbuj złożyć układ w innej części płytki stykowej i wykorzystać inne przewody. Czasami jakaś blaszka może nie stykać - najpierw należy wyeliminować problemy tego typu 🙂

Udostępnij ten post


Link to post
Share on other sites

Niestety ani wymiana płytki stykowej ani przewodów nie pomogła... dziwna sprawa. Miernik przez chwile działa prawidłowo po czym się "męczy". Jak go pierwszy raz podłączyłem słychać było przez chwile buczenie - być może wtedy się coś uszkodziło. Jest to jednak dziwne, gdyż był on na 100% podłączony prawidłowo.

Udostępnij ten post


Link to post
Share on other sites

MateuszG, jeśli poprzednio poruszanie przewodami coś zmieniało, to na 100% tutaj należy doszukiwać się problemów. Sprawdź inny pin Arduino - może wyrobił się konkretny pin w złączu (mało prawdopodobne, ale możliwe) 🙂

Udostępnij ten post


Link to post
Share on other sites

Ten sam problem co koledzy MateuszG i mosi2. Czujnik działa przez pewien czas (gwoli ścisłości do pewnej odległości - u mnie tak około 50 cm), potem zaczyna oddawać same zera aż do odłączenia i ponownego połączenia.

To raczej nie wina przewodów/pinów/płytki, jutro na świeżym mózgu spróbuję zgłębić posty marka1707, może mi pomoże.

Udostępnij ten post


Link to post
Share on other sites

peku, ok daj znać jakie efekty. Jak nadal będzie problem to zgłoś do sprzedawcy, pewnie sprawdzi i wymieni, jeśli faktycznie coś jest źle 🙂

Udostępnij ten post


Link to post
Share on other sites

Ok, tak jak zasugerował marek1707 spróbowałem napisać kodzik, który sam (bez użycia funkcji pulseIn) będzie mierzył ile czasu upłynęło między wysłaniem a odebraniem impulsu.

#define trigger 9
#define echo 11

void setup()
{
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);
Serial.begin(9600);
digitalWrite(trigger,LOW);
}

void loop()
{
long startTime,stopTime; //zmienne do pomiaru czasu
bool signalReceived=true;
   delayMicroseconds(20); //zainicjowanie impulsu triggerem
digitalWrite(trigger,HIGH);
delayMicroseconds(10);
digitalWrite(trigger,LOW);
startTime=millis(); //początek pomiaru czasu do sprawdzenia warunku z pierwsze pętli while
while(digitalRead(echo)==LOW) 
{
	stopTime=millis();
	if((stopTime-startTime)>24) 
       {break; signalReceived=false; Serial.println("Brak sygnalu");}// jeśli sygnał nie dociera przez 24 milisekundy - odległośc zapewne wieksza od 4 metrów
} 
if (signalReceived==true)
{
	startTime=micros(); //początek pomiaru czasu - wyniku
	while(digitalRead(echo)==HIGH) {} //oczekiwanie na powrót echa
	stopTime=micros(); //koniec pomiaru czasu
	Serial.println(stopTime-startTime);
}
delay(500);

}

Do testowania wykorzystywałem małe pudełko i ścianę oddaloną ode mnie o niecałe 3 metry.

Starałem się doprowadzić do zacięcia się czujnika żeby sprawdzić przyczyny. Okazało się, że czujnik działa poprawnie jeżeli jego sygnał trafia w miarę prostopadle na badaną przeszkodę. Kiedy odchylałem pudełko pod pewnym kątem sygnał odbijał się od niego tak, że czujnik nie zbierał echa ultradźwięku. Podobny efekt wywoływałem stając do ściany pod kątem lub celując czujnikiem od ściany do sufitu i z powrotem.

Co udało mi się zrozumieć:

- od momentu wysłania sygnału triggerem na wyjściu echo NATYCHMIAST jest stan logiczny 1/HIGH (dlatego nigdy nie uzyskałem komunikatu z pierwszej pętli while)

- czujnik zwiesza się jeżeli nie "usłyszy" swojego echa

- zwiecha objawia się tym, że cały czas na wyjściu echo mam logiczną 1; sprawdzałem też multimetrem, podczas normalnego działania (kiedy czujnik odległości dostaje impuls zwrotny) miernik pokazuje ok. 0.1V (rozumiem że to uśredniony wynik, pewnie dlatego jest tak niski, że na końcu pętli loop jest delay 500 ms) a podczas błędu niecałe ale stałe 5V.

- mogłem "odwiesić" czujnik stukając palcem w obudowę - chyba dostarczałem wyczekiwanej częstotliwości dźwięku - w wyniku otrzymywałem czas od wysłania triggera do stuknięcia, który był rzędu kilku sekund i oczywiście nijak przydatny do pomiaru odległości.

Czego nie rozumiem: po wklejeniu do drugiej pętli while fragmentu kodu, który miałby przerywać tę pętlę po pewnym czasie (24ms - czas potrzebny dźwiękowi do przebycia 8m) czujnik dalej nie reaguje (na pinie echo nie dostaję stanu LOW), mimo że ustawiam go w takiej pozycji, w której normalnie daje poprawne wyniki. A przecież w każdym wykonaniu pętli loop powinien być wysyłany sygnał ultradźwięku przez trigger i w końcu coś powinienem dostać (nawet choćby wynik 2,3 czy nawet 10-krotnie większy).

Chyba że... jeżeli na wyjściu echo jest 1/HIGH, to trigger nie może nadać sygnału?

Jak teraz temu zaradzić?

Moja biedawiedza podsuwa mi tylko pomysł na zabawę z tranzystorem i sterowanie z jego pomocą zasilaniem czujnika (szybkie wył/wł jeżeli czas oczekiwania na echo będzie zbyt duży).

Udostępnij ten post


Link to post
Share on other sites

peku, w tym fragmencie używasz break;

 break; signalReceived=false; Serial.println("Brak sygnalu");}// jeśli sygnał nie dociera przez 24 milisekundy - odległośc 

Tylko, że jeśli masz break, to rzeczy, które są po nim już się nie wykonują, czyli:

signalReceived=false; Serial.println("Brak sygnalu");

Nigdy nie zostaje wywołane. Tak miało być 🙂?

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Tak rzeczywiście błąd ale w zasadzie nieistotny jeżeli moje rozumowanie jest poprawne, bo czujnik od razu po wysłaniu impulsu ultradźwięku podaje na wyjściu echo stan wysoki i z jego wyłączeniem czeka na czoło fali powracającej, więc czas w którym na wyjściu echo jest stan LOW powinien być równy 0.

Udostępnij ten post


Link to post
Share on other sites

Powrót po pewnym czasie do Arduino okazał się być bolesny, aczkolwiek wszystkiego chyba nie zapomniałem 😋.

Zadanie 9.1

float jasnosc = 0;
float zmiana = 2.5;
#define LED 9

void setup() {
pinMode(LED, OUTPUT);
}
void LaunchLed(){
 while(jasnosc!=255){
   analogWrite(LED, jasnosc);
   jasnosc+=zmiana;
   delay(20);
 }
}
void DelaunchLed(){
 while(jasnosc!=0){
   analogWrite(LED, jasnosc);
   jasnosc-=zmiana;
   delay(20);
 }
}
void loop() {
 LaunchLed();
 DelaunchLed();
}

Zadanie 9.2

int i, tablica[4], j, liczby = 0;
String zmienne;

void setup() {
 Serial.begin(9600);
 while (!Serial) {};
 wpisanie_zmiennych();
 LED(tablica[0], tablica[1], tablica[2], tablica[3]);
}
void LED(int on, int off, int count, int pin) {
 pinMode(pin, OUTPUT);
 for(i=1; i<=count; i++) {
   digitalWrite(pin, HIGH);
   delay(on);
   digitalWrite(pin, LOW);
   delay(off);
 }
}
void wpisanie_zmiennych() {
 for (j=1; j<=4; j++) {
   switch(j) {
     case 1: Serial.println("Wyslij czas, jaki ma swiecic dioda(w msek)");
     break;
     case 2: Serial.println("Wyslij czas, jaki ma byc zgaszona dioda(w msek)");
     break;
     case 3: Serial.println("Wyslij liczbe, ile razy ma mrugnac dioda");
     break;
     case 4: Serial.println("Do ktorego pinu podlaczyles diode");
     break;
   }
   while (Serial.available()<=0) {};
   zmienne=Serial.readStringUntil('\n');
   liczby = zmienne.toInt();
   tablica[j-1]=liczby;
 }
}
void loop() {

}

Zadanie 9.1

#include <math.h>
String dane;
int tablica [ 3 ];
String figura;
void setup() {
 Serial.begin(9600);
 while(!Serial) {};

}
int prostokat(int a, int b) {
 int wynik = 0;
 wynik = a*b;
 return wynik;
}
float kolo (int r) {
 float wynik = 0;
 wynik = 3.14 * r * r;
 return wynik;
}
float trojkat (int a, int b, int c) {
 float wynik = 0;
 float p = (a+b+c)/2;
 wynik = sqrt(p*(p-a)*(p-b)*(p-c));
 return wynik;
}
void loop() {
 int wynik = 0;
 Serial.println("Podaj nazwe figury, jakiej pole chcesz otrzymac");
 while(Serial.available()<=0) {};
 figura=Serial.readStringUntil('\n');
 if(figura=="prostokat"){
   Serial.println("Podaj dlugosc pierwszego boku");
   while(Serial.available()<=0) {};
   dane=Serial.readStringUntil('\n');
   tablica[0]=dane.toInt();
   Serial.println("Podaj dlugosc drugiego boku");
   while(Serial.available()<=0) {};
   dane=Serial.readStringUntil('\n');
   tablica[1]=dane.toInt();
   Serial.print("Pole wynosi: ");
   Serial.println(prostokat(tablica[0], tablica[1]));
 }
 else if (figura=="kolo") {
   Serial.println("Podaj dlugosc promienia kola");
   while (Serial.available()<=0) {};
   dane=Serial.readStringUntil('\n');
   Serial.print("Pole wynosi: ");
   Serial.println(kolo(dane.toInt()));
 }
 else if (figura=="trojkat") {
   Serial.println("Podaj dlugosc pierwszego boku");
   while (Serial.available()<=0) {};
   dane=Serial.readStringUntil('\n');
   tablica[0]=dane.toInt();
   Serial.println("Podaj dlugosc drugiego boku");
   while (Serial.available()<=0) {};
   dane=Serial.readStringUntil('\n');
   tablica[1]=dane.toInt();
   Serial.println("Podaj dlugosc trzeciego boku");
   while (Serial.available()<=0) {};
   dane=Serial.readStringUntil('\n');
   tablica[2]=dane.toInt();
   Serial.print("Pole wynosi: ");
   Serial.println(trojkat(tablica[0], tablica[1], tablica[2]));
 }
 else {
 Serial.println("Bledna nazwa figury. Podaj ja jeszcze raz");
 loop();}

 while(1) {};
}

EDIT: Dodanie rozw.

Zadanie 9.3 - drobna edycja - pozwoliłem sobie dodać parę funkcji; tak skonstruowane i zaprogramowane urządzenie mogłoby pełnić funkcję czujnika parkowania w samochodzie 🙂

Budowa to oczywiście linijka led, czujnik + buzzer równolegle do ostatniej diody ostrzegawczej. Niestety nie udało mi się wykonać w pełni iteracyjnej wersji programu dla dowolnej liczby diod, brak mi umiejętność dotyczących działania na tablicach 🙁.

#define trig 12
#define echo 13
int number = 0, i = 0, order = 0, security = 0, distance = 0;
int table [9]; // there's only 9 free output pins in Arduino
void setup() { // except pin RX, TX, trig and echo
 clearingtable(); // table reset
 Serial.begin(9600);
 pinMode(trig, OUTPUT);
 pinMode(echo, INPUT);
 digitalWrite(trig, LOW);
 number = Led_number(); // counting of connected diodes
 for (i=1;i<=number;i++) { // ascribing numbers to diodes
   Serial.print("Write pin of diode number "); // question
   Serial.println(i); // number of led
   while(Serial.available()<=0) {}; // waiting for an answer
   order = converseString(); // converting string to integer
   pinMode(order, OUTPUT); 
   table[i-1]=order; // writing data about led to table
 }
 Serial.println("Announce security distance (cm)");
 while(Serial.available()<=0) {}; // value security distance
 security = converseString(); 
}
void clearingtable() { // table reset function
 i = 1;
 for (i=1;i<=9;i++) {
   table [i-1] = 0;
 }
}
int converseString() { // converting string to integer function
 int x = 0;
 String info;
 info = Serial.readStringUntil('\n');
 x = info.toInt();
 return x;
}

int Led_number() { // counting leds function
 int y = 0;
 while(!Serial) {};
 Serial.println("How many diodes have you connected?");
 while(Serial.available()<=0) {};
 y = converseString();
 return y;
}

int determine_distance(int x, int y) { // function, which measures
 int measurment = 0; // actual value of distance
 delayMicroseconds(2);
 digitalWrite(trig, HIGH);
 delayMicroseconds(10);
 digitalWrite(trig, LOW);
 measurment = (pulseIn(echo, HIGH))/58;
 Serial.print("Measurment amounts ");
 Serial.println(measurment);
 measurment = 450 - measurment; // data conversions
 measurment = map(measurment, 0, 450-y, 1, x); 
 return measurment;
}

void show(int x) { // switching on leds with buzzer function
 int j = 1;
 for(j=1;j<=x;j++) {
   digitalWrite(table[j-1], HIGH);
 }
}

void negateshow(int x) { // switching off leds with buzzer function
 int j=1;
 for(j=1;j<=x;j++) {
   digitalWrite(table[j-1], LOW);
 }
}

void loop() {
 distance = determine_distance(number, security); // measurment
 show(distance); // leds on
 delay(500); // waiting
 negateshow(distance); // led off
}

Next edit: Program wzbogaciłem jeszcze o zabezpieczenie przy "szalejącym" czujniku, gdy odległość większa niż 4,5m za pomocą funkcji if, czego nie uwzględniłem jeszcze w powyższym kodzie.

Udostępnij ten post


Link to post
Share on other sites

PrimeSoul, super powodzenia w dalszych pracach - warto eksperymentować.

Co do tablic, to będę omówione w kontynuacji kursu Arduino, może wtedy rozwieją się Twoje wątpliwości 🙂

Udostępnij ten post


Link to post
Share on other sites
Co do tablic, to będę omówione w kontynuacji kursu Arduino, może wtedy rozwieją się Twoje wątpliwości

Żeby stworzyć w pełni iteracyjną jeśli chodzi o liczbę diod wersję programu potrzebowałbym tablicy o bliżej nieokreślonej pojemności. O ile dobrze gdzieś doczytałem chodzi o tablicę dynamiczną. Ale niestety to już wyższa sztuka jazdy w porównaniu ze zwykłymi statycznymi jednowymiarowymi, które dość łatwo jest mi stosować już.

Cóż, przerabiam kursy dalej i po cichu gdzieś tam liczę, że tablice dynamiczne pokażą się prędzej lub później 🙂

Udostępnij ten post


Link to post
Share on other sites

Mam problem, ponieważ zdarzyło mi się eksperymentować 🙂 i podpiąłem diode LED do GND przy pinach zwykłych i plus do zasilania 3.3v, dioda się spaliła. Gdy teraz sprawdzam to miernikiem napięcia(analog) to wskazówka podnosi się max do 0.5V i zaraz spada. Ktoś wie o co chodzi?

Udostępnij ten post


Link to post
Share on other sites

Gregory_59, nigdy nie podłączamy diod bez rezystorów - teraz już chyba zapamiętasz 🙂

Dla formalności polecam kurs podstaw elektroniki: Kurs elektroniki – #1 – napięcie, prąd, opór, zasilanie

Jeśli podłączyłeś diodę między GND i 3,3V (czyli bez udziału mikrokontrolera), to oprócz diody nie powinno się nic spalić. Jeśli miałeś pecha, to mogłeś jednak uszkodzić stabilizator napięcia wbudowany w Arduino, więcej na ten temat znajdziesz w tej serii artykułów: Arduino, co w środku piszczy – #1 – schemat. Jak rozumiem płytka już nie działa i nie możesz jej zaprogramować, tak?

Udostępnij ten post


Link to post
Share on other sites
Gdy teraz sprawdzam to miernikiem napięcia(analog) to wskazówka podnosi się max do 0.5V i zaraz spada. Ktoś wie o co chodzi?

Podepnij pomiędzy 3.3V i GND jakiś duży rezystor, najlepiej min. 100 kiloomów i zmierz na nim spadek. Jeśli nie ma ok. 3V DC, to spaliłeś zasilanie. Możesz jeszcze sprawdzić w taki sam sposób czy 5V jest obecne. Jeśli nie, to niestety czeka Cię lutowanie SMD, tak jak wspomniał Treker stablizatora (to na pewno, możliwe, że czegoś jeszcze). Ale i tak nie ma wtedy gwarancji, że po przywróceniu zasilania będzie wszystko znowu hulać - mikroprocki to bardzo wrażliwe na fluktuacje zasilania ustrojstwa i z nimi nigdy nic nie wiadomo.

P.S. A tak na przyszłość - zanim podepniesz komponent, warto by poczytać chociaż o nim jaką ma zasadę działania... Wtedy wiedziałbyś, że diody mają bardzo małą rezystancję w stanie przewodzenia (w praktyce zakłada się, że nawet zerową) i może przez nie popłynąć wtedy tzw. prąd zwarciowy. Tam, gdzie pracuję, prądy zwarciowe w urządzeniach klientów nie raz powodowały nawet spalenie się ścieżek na PCB, przez co nie nadawały się nawet do naprawy.

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!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   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...