Skocz do zawartości

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


Pomocna odpowiedź

(edytowany)

Poniżej mój program z linijką, w której diody będą się rozświetlają stopniowo tzn. pierwsza zacznie świecić coraz mocniej od 128 cm, przy 64 będzie świecić pełną mocą, i wtedy kolejna dioda zacznie się rozświetlać itd.

Skorzystałem z tablic (których jeszcze na kursie nie było) - tablice i pętle pozwoliły znacznie skrócić program 🙂.

Funkcja constrain() przy obliczaniu jasności diody użyta bo funkcja analogWrite() nie robi tego sama - zakłada, że wartość drugiego argumentu będzie z przedziału 0 - 255. To dziwne moim zdaniem, że przyjmuje argument value typu int podczas gdy mogłyby być to argument typu byte i wtedy wszystko byłoby jasne 😉.

#define trigger 12
#define echo 13

#define g1 3
#define g2 5
#define g3 6
#define y1 9
#define y2 10
#define r1 11

#define magicNumber 58 //to calculate distance from time

int diodes[] = {g1, g2, g3, y1, y2, r1};
int distances[] = {128, 64, 32, 16, 8, 4, 2};

void setup() {
  //setting pins for HC-SR04
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);
  //setting pins for diodes
  for (int i = 0; i < 6; i++) {
    pinMode(diodes[i], OUTPUT);
  }
}

void loop() {
  int distance = measureDistance();
  for (int i = 0; i < 6; i++) {
    setBrightness(i, distance);
  }
  delay(200);
}

int measureDistance() {
  long time, distance;
  digitalWrite(trigger, LOW);
  delayMicroseconds(2);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  time = pulseIn(echo, HIGH);
  distance = time / magicNumber;
  return distance;
}

void setBrightness(int index, int distance) {
  int mappedDistance = map(distance, distances[index], distances[index + 1], 0, 255);
  int brightness = constrain(mappedDistance, 0, 255);
  analogWrite(diodes[index], brightness);
}

I na dodatek filmik jak to działa

linijka.thumb.gif.2bd60dff1be3f0fbed97fde4ba0bd52b.gif

Edytowano przez Raccoon
dodany film
  • Lubię! 1
Link to post
Share on other sites

@Raccoon fajnie że kombinujesz, funkcja setBrightness wygląda bardzo ładnie 🙂 faktycznie tablice mogą tu znacznie uprościć zadanie.

Dnia 13.02.2021 o 17:28, Raccoon napisał:

tu powinno być nazwę naszej funkcji a nie zmiennej.

Dziękujemy za zwrócenie uwagi, poprawimy niebawem 🙂 Choć nie jest to ogromny błąd, a nawet nieco prawdy - sama nazwa funkcji jest można powiedzieć zmienną, bo nazwa ta to wskaźnik na funkcję.

Link to post
Share on other sites

Ciekawostka !!!!

Po przystawieniu różnych rzeczy jak np: koc lub zeszyt od którego odbija się fala mamy różne odczyty ale najciekawsze  🤔🤔🤔🤔    jest to że przy odpowiednim koncie ustawienia np : książki czujnik pokazuje nam inne wartości (183 cm i więcej  ) a  przy ustawieniu książki w tym samym miejscu tylko pozycji pionowej    mamy np: 10  cm).

A odnośnie kursu to dla mnie rewelacja. Naprawdę świetnie zrobiony. 

Link to post
Share on other sites

@tomekk06 tak zgadza się, różne materiały mają różny współczynnik pochłaniania, pod różnymi katami są też inne odbicia więc te wyniki będą się różnić. Bez kalibracji taki czujnik działa orientacyjnie 🙂 

8 godzin temu, tomekk06 napisał:

A odnośnie kursu to dla mnie rewelacja. Naprawdę świetnie zrobiony. 

To bardzo dziękujemy! 🙂 

Link to post
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

9.3 Chciałem powtórzyć własne zmienne program działa dobrze.

#define trigPin 12
#define echoPin 11

void setup(){
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(8, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(9, OUTPUT);
  
  
}
void loop(){
  zakres(5, 10);
  zakres2(11, 15);
  zakres3(16, 20);
  zakres4(21, 25);
  zakres5(26, 30);
  zakres6(31, 40);
  
  digitalWrite(8, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(9, LOW);

  
}

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(8, HIGH);
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(9, HIGH);
      delay(10);
    }else{
      digitalWrite(8, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
    }
  }
   void zakres2(int a, int b){
    int jakDaleko = zmierzOdleglosc();
    if((jakDaleko > a) && (jakDaleko < b)){
      digitalWrite(8, HIGH);
      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(9, HIGH);
      delay(10);
    }else{
      digitalWrite(8, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
    }
  }

void zakres3(int a, int b){
    int jakDaleko = zmierzOdleglosc();
    if((jakDaleko > a) && (jakDaleko < b)){
      digitalWrite(8, HIGH);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(9, HIGH);
      delay(10);
    }else{
      digitalWrite(8, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
    }
  }
  void zakres4(int a, int b){
    int jakDaleko = zmierzOdleglosc();
    if((jakDaleko > a) && (jakDaleko < b)){
      digitalWrite(8, HIGH);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, HIGH);
      digitalWrite(9, HIGH);
      delay(10);
    }else{
      digitalWrite(8, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
    }
  }
  void zakres5(int a, int b){
    int jakDaleko = zmierzOdleglosc();
    if((jakDaleko > a) && (jakDaleko < b)){
      digitalWrite(8, HIGH);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, HIGH);
      delay(10);
    }else{
      digitalWrite(8, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
    }
  }
 void zakres6(int a, int b){
    int jakDaleko = zmierzOdleglosc();
    if((jakDaleko > a) && (jakDaleko < b)){
      digitalWrite(8, HIGH);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
      delay(10);
    }else{
      digitalWrite(8, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(9, LOW);
    }
  }
  

 

  • Lubię! 1
Link to post
Share on other sites

@Anthony Super, że robisz zadania domowe 🙂 Mam tylko drobną uwagę, która akurat może wynikać z tego, że w kursie nie ma jeszcze na tym etapie zbyt wiele o tablicach więc potraktuj to jako dodatek i zadanie z gwiazdką 🌟 poczytaj o tablicach i spróbuj tak zamienić kod żeby wyznaczana była liczba zapalonych diod. Przyda ci się do tego funkcja map która przeskaluje Ci pomierzoną odległość na liczbę zapalonych diod, a liczba ta bezpośrednio przełoży się na tak zwany indeks w tablicy.

Spróbuj własnych sił, jakby było ciężko to postaramy się razem nieco pomóc 😉 

Link to post
Share on other sites

Cześć,

Piszę z następującym problemem: otóż chciałam trochę rozbudować zadanie domowe 9.1 (to o obliczaniu pola figur) tak aby po wpisaniu do UART dało się wybrać figurę, której pole chcemy obliczyć a następnie również przez UART wpisać dane (np. długości boków). Niestety program działa poprawnie tylko do pewnego momentu (co jest zaznaczone w kodzie). Podejrzewam, że problem tkwi w wielokrotnym odczytywaniu wysyłanych danych. Jeśli się mylę proszę o poprawienie mnie. Oczywiście program nie jest jeszcze skończony ale wolałabym najpierw rozwiązać trapiący mnie problem.

String odebraneDane="";
String odebraneA="";
int wybor=0;
boolean tekst=false, tekst1=false;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
 while(tekst==false)
   {
  Serial.println("Podaj pole jakiej figury chcesz obliczyć");
  Serial.println("Prostokat - wpisz 1, trojkat - wpisz 2 ");
   tekst=true;
   }
 if(Serial.available()>0) //jesli odebrano dane
  {
   odebraneDane=Serial.readStringUntil('\n'); //odczytaj je do konca linii
   wybor=odebraneDane.toInt();

   if(wybor==1) //jesli wybrano prostokat
    {
     while(tekst1==false)
      {  
       Serial.println("Podaj długosc boku a");
       tekst1=true;
      } //do tego momentu program dziala wedlug planu
       if(Serial.available()>0)
        {
         odebraneA=Serial.readStringUntil('\n');
         odebraneA.toInt();
         Serial.println(odebraneA); //wstawilam ta linijke aby sprawdzic czy faktycznie do zmiennej odebraneA zostala przypisana wartosc
        }
    }
  }
}


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

  return wynik;
}

int trojkatPole(int a, int h)
{
  int wynik1=0;
  wynik1 = 0.5*a*h;

  return wynik1;
}

Pytanie moje brzmi: gdzie leży błąd, i co mogę zrobić (który fragment zmienić lub może dowiedzieć się o jakiś nowych funkcjach) aby program działał poprawnie?

Swoją drogą świetny kurs 😀

Pozdrawiam

Link to post
Share on other sites

@emiemi8

Cześć. Nie analizowałem bardzo wnikliwie Twojego kodu, ale zauważyłem, że miałem podobny problem. Odniosę się tylko do fragmentu kodu który "nie działa według planu" 😄 Oczywiście ciężko jest pomóc jeśli tego planu się nie zna ale domyślam się w czym tkwi problem. Fragment:

if(Serial.available()>0)
{
	odebraneA=Serial.readStringUntil('\n');
	odebraneA.toInt();
	Serial.println(odebraneA); //wstawilam ta linijke aby sprawdzic czy faktycznie do zmiennej odebraneA zostala przypisana wartosc
}

można zamienić na

while(Serial.available() == 0) {} ; //pętla nieskończona która zostanie przerwana przy odebraniu danych (czekanie do podania wartosci)
odebraneA=Serial.readStringUntil('\n');
odebraneA.toInt();
Serial.println(odebraneA); //wstawilam ta linijke aby sprawdzic czy faktycznie do zmiennej odebraneA zostala przypisana wartosc

W tym przypadku program czeka w pustej pętli nieskończonej z której wychodzi w momencie odbioru danych. Jest to o tyle wygodniejsze rozwiązanie, że wymuszamy zatrzymanie programu do czasu aż prześlemy dane. Mam nadzieję, że pomogłem. Pozdrawiam 😄

  • Lubię! 1
  • Pomogłeś! 1
Link to post
Share on other sites
Cytat
Dnia 10.03.2021 o 00:32, szymon812 napisał:

Oczywiście ciężko jest pomóc jeśli tego planu się nie zna

 

Plan był taki żeby dane dało się wpisywać za pomocą UART. Zresztą nie ma to specjalnego znaczenia bo teraz program działa - dzięki @szymon812!

Natomiast ciekawi mnie, czy istnieją sposoby, żeby zrobić to tak aby program nie zatrzymywał się w nieskończonej pustej pętli (zastanawiałam się nad przypadkiem programu, który z racji powiedzmy swojego przeznaczenia nie mógłby być wstrzymywany w takiej pustej pętli)?

Pozdrawiam

Link to post
Share on other sites

Na pewno istnieją jakieś inne sposoby rozwiązania tego problemu ale to już wszystko zależy od specyfiki programu. W tym przypadku możemy sobie pozwolić na to, żeby program tkwił w pętli nieskończonej bo nie ma nic innego do realizacji. W przypadkach, gdyby jednak miał coś do roboty wtedy trzeba by zmodyfikować program. Pomocna mogłaby być zmienna typu bool, która odpowiednio ustawiana mogłaby przez instrukcje warunkową pozwalać na oczekiwanie lub nie. W zależności od tego, co program miałby robić równolegle można też wykorzystać przerwania ale to pojawia się trochę dalej w kursie :D. To są takie dość ogólne rzuty myślowe, bo ciężko znaleźć konkretne rozwiązanie na dosyć ogólny problem :D

Link to post
Share on other sites

Mam pytanie odnośnie domyślnego trybu pinów.
W tej części kursu jest napisane, że ten program (użyłem wewnętrznej dioday 13 i podłaczonej z rezystorem do pin 12)

void setup() {
  zamigajLED(150, 8, 13);
  zamigajLED(150, 8, 12);
}

void loop() {
}

void zamigajLED(int czas, int ile, int pin){

  for (int i=0; i < ile; i++) {
    digitalWrite(pin, HIGH); //Włączenie diody
    delay(czas); //Odczekanie jakiegoś czasu
    digitalWrite(pin, LOW); //Wyłączenie diody
    delay(czas); //Odczekanie jakiegoś czasu
  }
}

powinien dać efekt "Miga tylko dioda podłączona do pinu 13, a ta pod 8 nie chce dać znaku życia."


U mnie jest na inaczej. Dioda pin 13 (wewnętrzna) zapala się zamiast mrugać, a dioda podłaczona do pin 12 przez rezystor mruga - ale wyraźnie słabiej niż gdy piny są ustawione na Output.

Wg dokumentacji https://www.arduino.cc/en/Tutorial/Foundations/DigitalPins
 

Cytat

Arduino (Atmega) pins default to inputs

Dlaczego dioda na pin 12 mimo to mruga?

Link to post
Share on other sites

i jeszcze drobna uwaga do ostatniego programu w tej części kursu, tego z czujnikiem odległości i buzzerem: dla czystości formy (i łatwości zrozumienia później, użyty w programie trzy razy numer pinu 2 też lepiej byłoby ustawić w define, czyli początek powinien być:

#define trigPin 12
#define echoPin 11
#define buzzerPIN 2

a dalej "2" zastąpione "buzzerPIN".

 

Szybko ten kurs minął, jeszcze tylko ostatnia część i trzeba myśleć co dalej. Świetny kurs!

Link to post
Share on other sites

@pawelmb Chyba coś namieszałeś. Funkcja zamigaj powinna być w pętli loop(), a w setup() brakuje ustawienie używanych pinów jako wyjścia. Dlatego działa słabo bo pin jest domyślnie wejściem.

Link to post
Share on other sites
(edytowany)

Zadanie 9.3

Popełniłem taki oto kod: 

#define trigPin 12
#define echoPin 11

void setup() {
 Serial.begin (9600);
 pinMode(trigPin, OUTPUT); //Trig jako wyjście - pomiar odległości
 pinMode(echoPin, INPUT); //ECHO jako wejście - odczyt zmierzonej odległości
 pinMode(2, OUTPUT); //Wyjście na LED zielona 1
 pinMode(3, OUTPUT); //Wyjście na LED zielona 2
 pinMode(4, OUTPUT); //Wyjście na LED czerwona 1
 pinMode(5, OUTPUT); //Wyjście na LED czerwona 2
 }

void loop() {
zakres(10, 15, 20, 25, 30 ); //Włącz LEDY jeśli odległość 10,15,20,30 - poniżej 10 migaj 2x LED czerwony
  delay(100);
}
    
  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 c, int d, int e) {
  int jakDaleko = zmierzOdleglosc();
  if ((jakDaleko >e) ){
    digitalWrite(3,LOW); //Odpal LED zielona 1
  }else{
    digitalWrite(3,HIGH);//Wyłączamy LED zielona 1 gdy obiekt poza zakresem
  }
  if ((jakDaleko >d) ){
    digitalWrite(2,LOW); //Odpal LED zielona 2
    
  }else{
    digitalWrite(2,HIGH); //Wyłącz LED zielona 2
  }
  if ((jakDaleko >c) ){
    digitalWrite(4,LOW); //Odpal LED czerwona 1
  }else{
    digitalWrite(4,HIGH); //Wyłącz LED czerwona 1
  }
   if ((jakDaleko >b)){
    digitalWrite(5,LOW); //Odpal LED czerwona 2
  }else{
    digitalWrite(5,HIGH); //Wyłącz LED czerwona 2
  }
 if ((jakDaleko <a)){
    digitalWrite(4,LOW);
    digitalWrite(3,LOW);  
    digitalWrite(2,LOW);      
    digitalWrite(5,HIGH); //Miganie LED czerwona 2
    digitalWrite(4,HIGH); //Miganie LED czerwona 1
    delay(100);
    digitalWrite(5,LOW); //Miganie LED czerwona 2
    digitalWrite(4,LOW); //Miganie LED czerwona 1
    delay(100);
    }
}

 

Linijka wskazuje odległość za pomocą 4 LED (2x zielona, 2x czerwona). Modyfikacja polega na tym, że poniżej 10cm włącza się ostrzeżenie (alarm) poprzez miganie dwóch czerwonych LEDów. 

Kod mam wrażenie, ze jest przaśny ale własny 😛

 

 

Czujnik odległości.jpg

Edytowano przez Forseti
Dodane zdjęcie
  • Lubię! 1
Link to post
Share on other sites

@Forseti super, fajnie że robisz zadania samemu, ale mam radę 😉 nie używaj zmiennych a,b,c,d,e itp. bo jest to bardzo niejasny zapis. 

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

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.