Skocz do zawartości

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


Komentator

Pomocna odpowiedź

Płytka działa poprawinie, jednak martwię się tylko o to wejście 3.3V.

Jest jakiś sposób jak sprawdzić czy działa to wejście(dioda + opornik R=?, czy po prostu miernikiem napięcia)?

[ Dodano: 07-02-2017, 15:52 ]

Tak jak wspomniałem Arduino działa, lecz sprawdziłem tak jak kazaliście pin 3.3v i po dobie przerwy ukazał mi się spadek z 0.5 na 0.0 po ponownym sprawdzenia już było od 0 .1 do 0.0. Następnie sprawdziłem pin 5V idziałał poprawnie bez żadnych spadków itp.

Ostatnie pytanie, jakie ma zastosowania ten pin3.3v, czy jest często używany

Link do komentarza
Share on other sites

Gregory_59, to znaczy, że spaliła Ci się część 3.3V - nie do końca pamiętam jak elektrycznie to rozwiązano w Arduino, ale możliwe, że to jest tylko jeden stabilizator.

Jak często się czegoś takiego używa? Mi trudno powiedzieć, osobiście nie używałem 3.3V ani razu, ale ja też z Arduino nie czaruję za wiele, bo nie mam obecnie czasu sięz tym bawić :/.

Link do komentarza
Share on other sites

Podczas robienia zadania z funkcjami do obliczania pól figur natknęłam się na mały problem. Chciałam do tego wykorzystać dodatkowo funkcję switch, która umożliwi obliczenie pola dla tylko jednej wybranej figury.

int wybierzPole;
float wynik=0;
String odebraneDane_a;
String odebraneDane_b;
String odebraneDane_r;
String odebraneDane_h;

void setup() {
 Serial.begin(9600);
 Serial.println("Czego pole chcesz obliczyc?");
 Serial.println("Wybierz: \n p - prostokat, \n k - kwadrat, \n o - kolo, \n t - trojkat,");
}

void loop() {
 if (Serial.available()>0){
   wybierzPole = Serial.read();

   switch(wybierzPole){
     case 'k':                      
       Serial.println("Podaj dlugosc boku kwadratu:");
       delay(5000);
       odebraneDane_a = Serial.readStringUntil('\n');
       wynik = kwadratPole(odebraneDane_a.toInt());
       Serial.println(wynik);
     break;

     case 'o':
       Serial.println("Podaj dlugosc promienia kola:");
       delay(5000);
       odebraneDane_r = Serial.readStringUntil('\n');
       wynik = koloPole(odebraneDane_r.toFloat());
       Serial.println(wynik);
     break;

     case 't':
       Serial.println("Podaj dlugosc boku trojkata:");
       odebraneDane_a = Serial.readStringUntil('\n');
       delay(5000);
       Serial.println("Podaj dlugosc wysokosci trojkata:");
       delay(5000);
       odebraneDane_h = Serial.readStringUntil('\n');
        wynik = trojkatPole(odebraneDane_a.toInt(),odebraneDane_h.toInt());
        Serial.println(wynik);
     break;

     case 'p':
       Serial.println("Podaj dlugosc pierwszego boku prostokata:");
       odebraneDane_a = Serial.readStringUntil('\n');
       delay(5000);
       Serial.println("Podaj dlugosc drugiego boku prostokata:");
       delay(5000);
       odebraneDane_b = Serial.readStringUntil('\n');
       wynik = prostokatPole(odebraneDane_a.toInt(),odebraneDane_b.toInt());
       Serial.println(wynik);
     break;
   }
   delay(5000);
 }
}

int kwadratPole(int a){
 wynik = a*a;
 return wynik;
}

float koloPole(float r){
 wynik = 3.14*r*r;
 return wynik;
}

int prostokatPole(int a, int b){
 wynik = a*b;
 return wynik;
}

int trojkatPole(int a, int h){
 wynik = 0.5*a*h;
 return wynik;
}

To co mi się zbytnio nie podoba i co chciałabym zmienić to opóźnienia. W tej chwili musiałam je wstawić, bo inaczej nie miałam możliwości wpisania długości boków itp.

Co muszę zrobić, aby program grzecznie czekał na liczby ode mnie i nie podawał mi od razu wyniku = 0?

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

Małe, rozwiązanie z opóźnieniami działa, ale jest złe i raczej bym tak nie robił 🙂 Najlepiej skorzystać tutaj z pętli while(), która będzie wykonywana do czasu, gdy odbierzemy jakieś dane przez UART. Oczywiście pętla może być pusta w środku. Za jej pomocą będzie można "zatrzymać program" na odpowiedni czas.

Link do komentarza
Share on other sites

Dzięki za radę.

Z racji, że z pustą pętlą nie do końca chciało mi wyjść (nie mogłam się potem z niej wydostać), zmodyfikowałam nieco swój program.

Pewnie dalej nie jest idealny, ale działa zdecydowanie lepiej niż z opóźnieniami. 😃

int wybierzPole;
float wynik=0;

void setup() {
 Serial.begin(9600);
 Serial.println("Czego pole chcesz obliczyc?");
 Serial.println("Wybierz: \n p - prostokat, \n k - kwadrat, \n o - kolo, \n t - trojkat,");
}

void loop() {

String odebraneDane_1="";
String odebraneDane_2="";

 if (Serial.available()>0){
   wybierzPole = Serial.read();

   switch(wybierzPole){
     case 'k':                      
       Serial.println("Podaj dlugosc boku kwadratu:");
       while(odebraneDane_1==""){
         odebraneDane_1 = Serial.readStringUntil('\n');
        }
       Serial.println("a= " + odebraneDane_1);
       wynik = kwadratPole(odebraneDane_1.toInt());
       Serial.println(wynik);
     break;

     case 'o':
       Serial.println("Podaj dlugosc promienia kola:");
       while(odebraneDane_1==""){
         odebraneDane_1 = Serial.readStringUntil('\n');
        } 
       Serial.println("r= " + odebraneDane_1);
       wynik = koloPole(odebraneDane_1.toFloat());
       Serial.println(wynik);
     break;

     case 't':
       Serial.println("Podaj dlugosc boku trojkata:");
       while(odebraneDane_1==""){
         odebraneDane_1 = Serial.readStringUntil('\n');
        }
       Serial.println("Podaj dlugosc wysokosci trojkata:");
       while(odebraneDane_2==""){
         odebraneDane_2 = Serial.readStringUntil('\n');
        }  
       Serial.println("a= " + odebraneDane_1 +" h= " + odebraneDane_2);
       wynik = trojkatPole(odebraneDane_1.toInt(),odebraneDane_2.toInt());
       Serial.println(wynik);
     break;

     case 'p':
     Serial.println("Podaj dlugosc pierwszego boku prostokata:");
       while(odebraneDane_1==""){
         odebraneDane_1 = Serial.readStringUntil('\n');
        }
       Serial.println("Podaj dlugosc drugiego boku prostokata:");
       while(odebraneDane_2==""){
         odebraneDane_2 = Serial.readStringUntil('\n');
        }  
       Serial.println("x= " + odebraneDane_1 +" y= " + odebraneDane_2);         
       wynik = prostokatPole(odebraneDane_1.toInt(),odebraneDane_2.toInt());
       Serial.println(wynik);
     break;
   }
   Serial.println();
 }
}

int kwadratPole(int a){
 wynik = a*a;
 return wynik;
}

float koloPole(float r){
 wynik = 3.14*r*r;
 return wynik;
}

int prostokatPole(int a, int b){
 wynik = a*b;
 return wynik;
}

int trojkatPole(int a, int h){
 wynik = 0.5*a*h;
 return wynik;
}
Link do komentarza
Share on other sites

9.3

#define trig 12
#define echo 11

void setup() {
 Serial.begin(9600);
 pinMode(trig, OUTPUT);
 pinMode(echo, INPUT);

 pinMode(5, OUTPUT);
 pinMode(6, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
}

void loop() {
 Serial.print("Dystans od przeszkody: ");
 Serial.print(zmierzonaOdleglosc());
 Serial.println(" cm");

 if (zmierzonaOdleglosc() <= 10) {
   digitalWrite(9, HIGH);
   digitalWrite(8, HIGH);
   digitalWrite(7, HIGH);
   digitalWrite(6, HIGH);
   digitalWrite(5, HIGH);
 }
 else {
   digitalWrite(9, LOW);
   digitalWrite(8, LOW);
   digitalWrite(7, LOW);
   digitalWrite(6, LOW);
   digitalWrite(5, LOW);
   if (zmierzonaOdleglosc() <= 20) {
     digitalWrite(8, HIGH);
     digitalWrite(7, HIGH);
     digitalWrite(6, HIGH);
     digitalWrite(5, HIGH);
   }
   else {
     digitalWrite(9, LOW);
     digitalWrite(8, LOW);
     digitalWrite(7, LOW);
     digitalWrite(6, LOW);
     digitalWrite(5, LOW);
     if (zmierzonaOdleglosc() <= 30) {
       digitalWrite(7, HIGH);
       digitalWrite(6, HIGH);
       digitalWrite(5, HIGH);
     }
     else {
       digitalWrite(9, LOW);
       digitalWrite(8, LOW);
       digitalWrite(7, LOW);
       digitalWrite(6, LOW);
       digitalWrite(5, LOW);
       if (zmierzonaOdleglosc() <= 40) {
         digitalWrite(6, HIGH);
         digitalWrite(5, HIGH);
       }
       else {
         digitalWrite(9, LOW);
         digitalWrite(8, LOW);
         digitalWrite(7, LOW);
         digitalWrite(6, LOW);
         digitalWrite(5, LOW);
         if (zmierzonaOdleglosc() <= 50) {
           digitalWrite(5, HIGH);
         }
         else {
           digitalWrite(9, LOW);
           digitalWrite(8, LOW);
           digitalWrite(7, LOW);
           digitalWrite(6, LOW);
           digitalWrite(5, LOW);
         }
       }
     }

   }
 }
 delay(300);
}

int zmierzonaOdleglosc() {

 long czas, dystans;
 digitalWrite(trig, LOW);
 delayMicroseconds(2);
 digitalWrite(trig, HIGH);
 delayMicroseconds(10);
 digitalWrite(trig, LOW);

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

 return dystans;
}
Link do komentarza
Share on other sites

thequeash, na przyszłość przydałoby się więcej komentarzy w kodzie. Wtedy zawsze łatwiej zrozumieć kod - za jakiś czas sam zapomnisz, co dokładnie chciałeś w nim zrobić 🙂 Powodzenia w dalszej nauce!

Link do komentarza
Share on other sites

Witam,
Mam pytanie:

na podstawie kursu postanowiłem zrobić prosty czujnik parkowania do garażu (żeby pokazać Żonie, że z moich "kabelków" i Ona będzie miała coś pożytecznego;) i zastanawiam się jak zrealizować wyłączenie np. diody czy buzera w momencie jak już zaparkuje i stan pomiarów nie będzie wskazywał zmiany przez określony okres czasu.

O ile włączenie następuje w momencie pojawienia się obiektu w zakresie pomiarowym, o tyle wyłączenie wskazań kiedy obiekt już jest w tym zakresie, jest dla mnie jak na razie niewykonalne.

Koncepcja dwóch pomiarów odległości w określonym odstępie czasowym i porównania ich do siebie wydaje się sensowna, ale nie bardzo wiem jak sformułować kod.

Z góry dzięki za pomoc.

Link do komentarza
Share on other sites

Emilowicz, witam na forum 🙂

Najlepiej będzie w każdym obiegu pętli porównywać aktualny odczyt z poprzednim. Jeśli jest taki sam, to zwiększamy zmienną "licznikową" (stworzoną na tę okazję) o 1. Gdy jej wartość przekroczy np. 100, to wyłączamy diody. Zerowanie zmiennej licznikowej powinno nastąpić, gdy odczyt z czujnika ulegnie zmianie. Oczywiście, aby całość działała poprawnie należy wprowadzić w całej pętli drobne opóźnienie np 50-100 ms (inaczej zmienna licznikowa przekroczy wybraną wartość zbyt szybko). Dodatkowo warto dać margines np. +/- 2 cm. Jak wiadomo czujnik może złapać zawsze zakłócenia. Nie można oczekiwać, że w momencie zaparkowania samochodu odczyty będą cały czas idealnie stabilne 🙂

Link do komentarza
Share on other sites

Cześć!

Odczytujac na monitorze portu szeregowego odleglosc od obiektu moj czujnik czasem pokazuje mi wartosc 0cm, nawet jesli nie ma przed nim zadnych obiektow. moze byc to wina niedolutowanego wyprowadzenia na zdjeciu?

Link do komentarza
Share on other sites

Od dłuższego czasu korzystałem z forum "na gapę" 😉

Wiele podpatrzyłem, niestety brak czasu i zabawa z Arduino z doskoku nie pozwala mi usystematyzować wiedzy i pewnie dlatego wychodzą takie hece:

zmajstrowałem coś tak trochę po omacku... brakuje mi pomysłów jak z tego wybrnąć

generalnie wszystko nawet działa do momentu gdy licznik osiągnie wymaganą wartość i program powinien zgasić diody... gasi ale pierwsza wciąż się świeci... ponadto program nie reaguje na zmianę dystansu po wejściu w tryb naliczania... pewnie coś namieszałem w kodzie i nie do końca wiem jak z tego złożyć coś sensownego.


#define trig 12
#define echo 11



void setup() {
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
pinMode (1, OUTPUT);
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (5, OUTPUT);
pinMode(6, OUTPUT);

Serial.begin(9600);
}

void loop () {

 int czas, dist;      // pierwszy pomiar---- dalej sekwencja  zapalająca odpowiednie diody
 digitalWrite(trig, HIGH);
 delayMicroseconds(1000);
 digitalWrite(trig, LOW);
 czas = pulseIn(echo, HIGH);
 dist = ((czas/2) / 29.1)+2;

Serial.println("pierwszy pomiar:  "); //wrzucam na serial 1. pomiar
Serial.print(dist);

 if (dist <=5) {
   digitalWrite(1, HIGH);
   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);
   digitalWrite(4, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(6, HIGH);
   delay(100);
 }
 else if (dist <=10 ) {
   digitalWrite(1, HIGH);
   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);
   digitalWrite(4, HIGH);
   digitalWrite(5, HIGH);
   digitalWrite(6, LOW);
  delay(100);
 }
 else if (dist <=20) { 
   digitalWrite(1, HIGH);
   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);
   digitalWrite(4, HIGH);
   digitalWrite(5, LOW);
   digitalWrite(6, LOW);
   delay(100);
 }
 else if (dist <=30) { 
   digitalWrite(1, HIGH);
   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);
   digitalWrite(4, LOW);
   digitalWrite(5, LOW);
   digitalWrite(6, LOW);
  delay(100);
 }
else if (dist <=50) { 
   digitalWrite(1, HIGH);
   digitalWrite(2, HIGH);
   digitalWrite(3, LOW);
   digitalWrite(4, LOW);
   digitalWrite(5, LOW);
   digitalWrite(6, LOW);
   delay(100);
 }
 else if (dist <=100) { 
   digitalWrite(1, HIGH);
   digitalWrite(2, LOW);
   digitalWrite(3, LOW);
   digitalWrite(4, LOW);
   digitalWrite(5, LOW);
   digitalWrite(6, LOW);
   delay(100);
 }
  else if (dist >100) { 
   digitalWrite(1, LOW);
   digitalWrite(2, LOW);
   digitalWrite(3, LOW);
   digitalWrite(4, LOW);
   digitalWrite(5, LOW);
   digitalWrite(6, LOW);
   delay(100);
 }
 delay(300);
  int czas2, dist2;           // drugi pomiar odległości
 digitalWrite(trig, HIGH);
 delayMicroseconds(1000);
 digitalWrite(trig, LOW);
 czas2 = pulseIn(echo, HIGH);
 dist2 = ((czas2/2) / 29.1)+2;




Serial.println("drugi pomiar:  ");  //wrzucam na serial 1. pomiar
Serial.print(dist2);
 int licznik =0;                    //deklaruje zmienna licznika
 while (dist==(dist2 + 2)||dist==(dist2-2)) // dopóki 1. i2. pomiar sięrównają z tolerancją
 {
   licznik++;                        // naliczaj   
   delay(1000);  

Serial.println("licznik:  ");     //wrzucam na serial licznik
Serial.print(licznik);  

if (licznik==50)                     // jesli licznik = 50 to zgas diody
 {
   digitalWrite(1, LOW);
   digitalWrite(2, LOW);
   digitalWrite(3, LOW);
   digitalWrite(4, LOW);
   digitalWrite(5, LOW);
   digitalWrite(6, LOW);
 }

 }
   if (dist!=(dist2 + 2)||dist !=(dist2-2))  // jesli 1. i 2. różnią się to licznik=0
 {
   licznik=0;
 }

 }
Link do komentarza
Share on other sites

kiniu14, faktycznie może być tam jakiś problem. Jak masz możliwość dolutowania tej nóżki, to warto ją poprawić. Jeśli nie, to zgłoś sprawę do sprzedawcy 🙂 Upewnij się podczas robienia pomiarów, że przed czujnikiem jest dużo wolnego miejsca (i nie jest przekrzywiony w kierunku stołu) - może coś zakłóca odczyty.

Emilowicz, ogólnie idziesz (chyba) w dobrym kierunku, ale ciężko mi teraz dobrze przeanalizować Twój program (trochę namieszałeś z wcięciami). W ramach podpowiedzi wklejam moje rozwiązanie napisane "pseudokodem". Powinno trochę pomóc 😉

int poprzedni_pomiar = 0;
int licznik = 0;

void loop() {
 aktualny_pomiar = zmierz_odległość;
 int roznica = aktualny_pomiar - poprzedni_pomiar;

 if (abs(roznica) < 3) { //Jeśli wartość bezwzględna z różnicy jest mniejsza od 3
   licznik++; //Zliczamy czas, gdy pojazd stoi w miejscu

   if (licznik > 100) { //Jeśli pojazd stoi w miejscu
     wylacz_diody(); //Wyłączamy diody
   }
 } else {
   licznik = 0; //zerujemy licznik, bo wskazania nie są takie same
   pokaz_wynik_na_diodach();
   poprzedni_pomiar = aktualny_pomiar; //Zapamiętujemy aktualny pomiar jako "poprzedni"
 }

 odczekaj(100ms);
}
Link do komentarza
Share on other sites

Witam,
mam pewien problem w odniesieniu do tego zadania z artykułu

Zadanie domowe 9.1

Napisz funkcję, która sprawia, że dioda będzie pulsować (stopniowe przygaszanie i rozjaśnianie). Skorzystaj oczywiście z wiadomości zdobytych podczas lekcji o sygnale PWM.

chciałem to trochę rozbudować o funkcje stopniowego przygaszania i rozjaśniana po wciśnięci guzika i napisałem program:

int pwm;
int zmiana = 5;


void setup() {
 pinMode(5, INPUT_PULLUP); // przypisanie pinu 5 na guzik  
 pinMode(11, OUTPUT);    //wyście LED
}

void loop() {
 delay(100);
if(digitalRead(5) == LOW){  //jeżeli przycisne guzik zostanie wywołana funkcja
 funkcjaLED();
 }       
}  


void funkcjaLED(){
 analogWrite(11,pwm); //przypisanie wwjscia sygnalu pwm
 pwm += zmiana; 
 delay(10);  
 if(pwm == 255 || pwm ==0){
   zmiana = 0-zmiana; //zmiana znaku na przeciwny jezeli osiagnie próg 0 lub 255

} 
}

kod ten nie działa, bo dioda przygasza się i rozbłyska tylko gdy trzymam guzik, więc go przerobiłem i rozbudowałem o potencjometr który reguluje ilość błyśnięć:

int pwm;
int zmiana = 5;
int q;


void setup() {
 pinMode(5, INPUT_PULLUP); // przypisanie pinu 5 na guzik  
 pinMode(11, OUTPUT);    //wyście LED
}

void loop() {

 int ilosc = analogRead(A0);     //odczytanie wartosci z potencjometru
 int ile =map(ilosc,0,1023,1,10);  //podzielenie wartosc z potencjometru na 10  rozjasnien
 delay(200);
 digitalWrite(11, LOW);  //wylaczenie diody po skonczonym obiegu, bo inaczej by sie ciagle żarzyła
if(digitalRead(5) == LOW){    //po nacisnieciu guzika...
 ulepsz(ile);  //okresla "ile" razy sygnal pwm ma powodowac rozjasnienie z odczytanej i zmapowanej wartosci potencjometru    
 }  
}  

void ulepsz(int ile){
 q= 2*ile;   //okreslenie ilosci blysniec x2 bo za kazdym przejscie przez 0 i 255 daje 1, więc przy 10 byłoby 5 gdyby nie x2
 while(q != 0){  //zatrzymanie w pętli while
   funkcjaLED();
 }
}
void funkcjaLED(){
 analogWrite(11,pwm); //przypisanie wwjscia sygnalu pwm
 pwm += zmiana; 
 delay(10);

 if(pwm == 255 || pwm ==0){
   zmiana = 0-zmiana; //zmiana znaku na przeciwny jezeli osiagnie próg 0 lub 255
   q--;    //odjęcie 
} 
}

Ten kod działa wyśmienicie ale czy da się ten kod uprościć?

Zastanawia mnie fakt dlaczego w pierwszym kodzie dioda mruga tylko wtedy gdy trzymam guzik. Dla "for" kod mi nie działał, dopiero gdy zatrzymałem w while działa.

Moje ostatnie pytanie dlaczego jak pwm jest na 0 dioda ciągle się "żarzy" i nie wygasza, gdy pętla się skończy, muszę ją zawsze po pętli wyłączyć?

Dziękuje z góry za odpowiedzi mnie nękające 🙂

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.