Skocz do zawartości

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


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

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ć :/.

  • 1 miesiąc później...

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?

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.

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;
}
  • 2 tygodnie później...

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;
}

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!

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.

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 🙂

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?

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;
 }

 }

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);
}

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 🙂

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