Skocz do zawartości

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


Komentator

Pomocna odpowiedź

(edytowany)

Cześć,

Usiłuję wyrzeźbić prosty prędkościomierz na bazie HC-SR04 ale nie mogę zmusić go do działania. 

Algorytm jest oczywisty:

  1. wywołanie funkcji mierzącej odległość
  2. odczekanie krótkiej chwili
  3. ponowny pomiar
  4. Obliczenie różnicy obydwu wartości
  5. Przeliczenie na prędkość (m/s).

Problem polega na tym, że nie udaje mi dokonać dwóch pomiarów w jednej pętli. Zawsze jeden z pomiarów jest prawidłowy a drugi wynosi niezmiennie 0 (zazwyczaj ten drugi ale po wydłużeniu czasu odstępu czasowego drugi jest ok a pierwszy pokazuje 0). Próbowałem kombinować z odstępem czasowym pomiędzy obydwoma pomiarami, tworzyłem również bliźniaczą funkcję 

measure()

(tyle że inaczej nazwaną) sterującą czujnikiem aby każdy pomiar miał "swoją" ale i to nie pomogło. Pomożecie?

 

[code]
#define trig 5
#define echo 6
#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 4, 7, 8, 12, 13, 9);

void setup() {
  //UART
  Serial.begin(9600);
  //Ustawienie trig i echo
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  //Ustawienie LCD
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Velocity:");
}

void loop() {
  //Odczyt 2 + ograniczenie wartosci 1
  float cm1 = measure();
  if (cm1 > 400) {
    cm1 = 400;
  }
  delay(1);
  //Odczyt 2 + ograniczenie wartosci
  float cm2 = measure();
  if (cm2 > 400) {
    cm2 = 400;
  }
  //Obliczenie prędkości
  float substract = (cm2 - cm1);
  float velocity = abs((substract * 1000) / 100);
  Serial.println(cm1);
  Serial.println(cm2);
  //Wyswietlenie predkosci na LCD
  lcd.setCursor(0, 1);
  lcd.print(velocity, 2);
  lcd.print(" m/s");
  lcd.print("    ");
}

float measure() {
  float echoread;
  // Start nadawanie
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  // Koniec nadawania

  //Odczyt
  echoread = pulseIn(echo, HIGH);
  // Przeliczenie na cm 
  float odo = echoread / 58; 
  return odo;
}


[/code]

 

Edytowano przez Wloczykij555
Link do komentarza
Share on other sites

Spróbuj dać na koniec sekcji setup delay(30). Mnie czasem czujnik nie zalapywal od razu po włączeniu zasilania. Masz też dużo zmiennych typu float. Operacje na nich są dość długotrwałe. Może dla testu spróbuj cześć z nich zamienić na int. Wynik z funkcji pulseIn nie musi być float, nie dostaniesz tam przecież ułamków

Link do komentarza
Share on other sites

(edytowany)

Niestety delay(30) nie pomógł. 

Co do zmiennych, to pierwotnie wszystkie były typu int i działo się dokładnie to samo. Chciałem uzyskać pomiar z dokładnością do 2 miejsc po przecinku więc przemianowałem wszystko na float. Co ciekawe, również wynik z pulsein też musi być float bo inaczej po podzieleniu przez 58 zaokrągla mi końcowy wynik funkcji ("odo") do liczby całkowitej (nawet jeśli tą ostatnią zmienną zadeklarowałem jako float).

 

Ogólnie wszystko wydaje się być ok, wartości na LCD są wyświetlane w oczekiwanym formacie, tyle że są nieprawidłowe.

 

EDIT

Zmodyfikowałem program tak, żeby pierwszy pomiar odbywał się z wywołania funkcji, a drugi był zintegrowany z loop() i dalej lipa. Poniżej wyniki odczytu obu wartości (na górze pierwsza, na dole druga).

 

#define trig 5
#define echo 6
#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 4, 7, 8, 12, 13, 9);

void setup() {
  //UART
  Serial.begin(9600);
  //Ustawienie trig i echo
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  //Ustawienie LCD
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Velocity:");
  delay(30);
}

void loop() {
  //Odczyt 1 + ograniczenie wartosci 1
  float cm1 = measure();
  if (cm1 > 400) {
    cm1 = 400;
  }
  delay(1);
  
  //Odczyt 2 + ograniczenie wartosci 2

float echoread1;
  // Start nadawanie
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  // Koniec nadawania

  //Odczyt
  echoread1 = pulseIn(echo, HIGH);
  // Przeliczenie na cm 
  float cm2 = echoread1 / 58; 
  
//  float cm2 = measure();
  if (cm2 > 400) {
    cm2 = 400;
  }
  //Sprawdzenie odczytów przez UART
  Serial.println(cm1);
  Serial.println(cm2);
  Serial.println("");
  //Obliczenie prędkości
  float substract = (cm2 - cm1);
  float velocity = abs((substract * 1000) / 100);
  //Wyswietlenie predkosci na LCD
  lcd.setCursor(0, 1);
  lcd.print(velocity, 2);
  lcd.print(" m/s");
  lcd.print("    ");
}

float measure() {
  float echoread;
  // Start nadawanie
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  // Koniec nadawania

  //Odczyt
  echoread = pulseIn(echo, HIGH);
  // Przeliczenie na cm 
  float odo = echoread / 58; 
  return odo;
}

Przechwytywanie.thumb.PNG.3bcf25e49156480366cbae630f5c8abb.PNG

Edytowano przez Wloczykij555
Link do komentarza
Share on other sites

1 godzinę temu, Wloczykij555 napisał:

Co ciekawe, również wynik z pulsein też musi być float bo inaczej po podzieleniu przez 58 zaokrągla mi końcowy wynik 

 

Poczytaj o "jawne rzutowanie"...bardzo przydatny temat jesli sa jakies "bledy" podczas dzielenia, mnozenia itp roznych typow i zapisywania wyniku do roznych typow...ogolnie chodzi o to ze wynik jest automatycznie rzutowany do najwiekszego typu lub do typu int...

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

W twoim pierwszym kodzie spróbuj dać opóźnienie po 2 pomiarze, bo po pierwszym dajesz 1ms a po drugim już nie. Kurcze tak na 1 rzut oka powinno działać, ale coś widać nie gra. Jak sobie nie poradzisz to jutro podłącze wieczorem ardu i wrzucę to co Ty masz. 

Link do komentarza
Share on other sites

46 minut temu, farmaceuta napisał:

Poczytaj o "jawne rzutowanie"...bardzo przydatny temat jesli sa jakies "bledy" podczas dzielenia, mnozenia itp roznych typow i zapisywania wyniku do roznych typow...ogolnie chodzi o to ze wynik jest automatycznie rzutowany do najwiekszego typu lub do typu int...

Dzięki! Nowa wiedza wpadła 🙂

 

10 minut temu, Krawi92 napisał:

W twoim pierwszym kodzie spróbuj dać opóźnienie po 2 pomiarze, bo po pierwszym dajesz 1ms a po drugim już nie. Kurcze tak na 1 rzut oka powinno działać, ale coś widać nie gra. Jak sobie nie poradzisz to jutro podłącze wieczorem ardu i wrzucę to co Ty masz. 

Ok, chyba mam odpowiedź a brzmi ona - ten czujnik po prostu ssie 🙃 Dodałem delay() na końcu programu oraz wydłużyłem odstęp czasowy pomiędzy pomiarami i zaczęło trybić. Wygląda na to, że przy tak krótkich czasach załączania i wyłączania ten czujnik się po prostu nie wyrabiał. Na marginesie, LCD też do takich pomiarów się nie nadaje, bo przy szybkich zmianach wartości robi się nieczytelny (zbyt duża bezwładność pikseli). Poniżej finalny kod. Dziękuję za odzew 🙂

 

#define trig 5
#define echo 6
#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 4, 7, 8, 12, 13, 9);

void setup() {
  //UART
  Serial.begin(9600);
  //Ustawienie trig i echo
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  //Ustawienie LCD
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Velocity:");
  delay(30);
}

void loop() {
  //Odczyt 1 + ograniczenie wartosci 1
  float cm1 = measure();
  if (cm1 > 400) {
    cm1 = 400;
  }
  delay(80);
  
  //Odczyt 2 + ograniczenie wartosci 2

  float cm2 = measure();
  if (cm2 > 400) {
    cm2 = 400;
  }
  //Obliczenie różnicy pomiarów
  float substract = (cm2 - cm1);
  
  // Odflitrowanie szumów
  if (substract < 0.15 && substract > -0.15){
    substract = 0;
  }
  
  //Obliczenie prędkosci
  float velocity = abs((substract * 12.5) / 100);

  //Wyswietlenie predkosci na LCD
  Serial.println(velocity, 2);
  lcd.setCursor(0, 1);
  lcd.print(velocity, 2);
  lcd.print(" m/s");
  lcd.print("    ");
  delay(80);
}

float measure() {
  int echoread;
  // Start nadawanie
  digitalWrite(trig, LOW);
  delayMicroseconds(2);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  // Koniec nadawania

  //Odczyt
  echoread = pulseIn(echo, HIGH);
  // Przeliczenie na cm 
  float odo = (float) echoread / 58; 
  return odo;
}

 

Link do komentarza
Share on other sites

Problem tez troche polega na tym że to typowe programowanie liniowe oparte na delayach. Ja bym to postaral się zrobić na timerach programowych, aby nic nie blokowało programu. Te delaye też blokują wyświetlanie na lcd, które też wbrew pozorom nie jest bardzo szybkie i ma swoje ograniczenia. 

Link do komentarza
Share on other sites

Chciałem napisać funkcję w której wpisywanym argumentem było by wejście analogowe np. A0. Jaką zmienną jest A0? Int lub String nie dają rady. Proszę o pomoc.

Link do komentarza
Share on other sites

@Macej98 A0 jest symbolem preprocesora. Nie możesz odwołać się do A0 jak do zmiennej, możesz tylko wpisać. Ale do argumentu funkcji przyjmującej int zadziała.

Link do komentarza
Share on other sites

void loop() {
  temperatura(A5);
}
void temperatura (int pin){
    float pomiar_t = analogRead(pin);
    float temperatura= (pomiar_t* 0.12218964)- 20;
    Serial.println(temperatura);
    delay(1000);
}

Napisałem taką funkcję. Niestety nie działa. 

Link do komentarza
Share on other sites

Nie pokazuje wyniku z czujnika temperatury podpiętego do pinu A5. Natomiast przy identycznym połączeniu, poniższy kod normalnie pokazuje wynik z czujnika temperatury podpiętego do pinu 5.

void loop() {
  float pomiar_t = analogRead(A5);
  float temperatura= (pomiar_t* 0.12218964)- 20;
  Serial.println(temperatura);
  delay(1000);
}

 

Link do komentarza
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...

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.