Skocz do zawartości

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


Komentator

Pomocna odpowiedź


#define redLED 10
#define yellowLED1 9
#define yellowLED2 8
#define greenLED1 7
#define greenLED2 6
#define trigPin 5
#define echoPin 4
#define buzzer 3


void setup() {
  Serial.begin(9600);
  pinMode(redLED, OUTPUT);
  pinMode(yellowLED1, OUTPUT);
  pinMode(yellowLED2, OUTPUT);
  pinMode(greenLED1, OUTPUT);
  pinMode(greenLED2, OUTPUT);
  pinMode(trigPin, OUTPUT); // trig jako wyjście
  pinMode(echoPin, INPUT); // echo jako wejście
  pinMode(buzzer, OUTPUT);
}

int zmierzOdleglosc() {
  long czas, dystans;

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  czas = pulseIn(echoPin, HIGH); // długość impulsu musi się mieścić w przedziale od 10 mikrosekund do 3 minut.
  dystans = czas / 58; // liczba 58 Wynika z czasu przez jaki dźwięk pokonuje odległość 1 cm oraz wzoru na odległość jaką przedstawił producent.

  return dystans;
}


void loop() {
  long zakres1 = 4;
  long zakres2 = 7;
  long zakres3 = 11;
  long zakres4 = 16;
  long zakres5 = 21;
  long zakres6 = 26;
  int time1 = 25 ;
  int time2 = 50 ;
  int time3 = 75 ;
  int time4 = 100 ;
  Serial.println(zmierzOdleglosc());

  if ((zmierzOdleglosc() < zakres1)) {
    analogWrite(buzzer, 255);
    digitalWrite(redLED, HIGH);
    digitalWrite(yellowLED1, HIGH);
    digitalWrite(yellowLED2, HIGH);
    digitalWrite(greenLED1, HIGH);
    digitalWrite(greenLED2, HIGH);
    delay(10);

  } else if ((zmierzOdleglosc() >= zakres1) && (zmierzOdleglosc() <= zakres2)) {
    analogWrite(buzzer, 230);
    digitalWrite(redLED, HIGH);
    digitalWrite(yellowLED1, HIGH);
    digitalWrite(yellowLED2, HIGH);
    digitalWrite(greenLED1, HIGH);
    digitalWrite(greenLED2, HIGH);
    delay(15);
    analogWrite(buzzer, LOW);
    digitalWrite(redLED, LOW);
    delay(15);

  } else if ((zmierzOdleglosc() > zakres2) && (zmierzOdleglosc() <= zakres3)) {
    digitalWrite(redLED, LOW);
    digitalWrite(yellowLED1, HIGH);
    digitalWrite(yellowLED2, HIGH);
    digitalWrite(greenLED1, HIGH);
    digitalWrite(greenLED2, HIGH);
    analogWrite(buzzer, 195);
    delay(time1);
    analogWrite(buzzer, LOW);
    digitalWrite(yellowLED1, LOW);
    delay(time1);

  } else if ((zmierzOdleglosc() > zakres3) && (zmierzOdleglosc() <= zakres4)) {
    digitalWrite(redLED, LOW);
    digitalWrite(yellowLED1, LOW);
    digitalWrite(yellowLED2, HIGH);
    digitalWrite(greenLED1, HIGH);
    digitalWrite(greenLED2, HIGH);
    analogWrite(buzzer, 130);
    delay(time2);
    analogWrite(buzzer, LOW);
    digitalWrite(yellowLED2, LOW);
    delay(time2);

  } else if ((zmierzOdleglosc() > zakres4) && (zmierzOdleglosc() <= zakres5)) {
    digitalWrite(redLED, LOW);
    digitalWrite(yellowLED1, LOW);
    digitalWrite(yellowLED2, LOW);
    digitalWrite(greenLED1, HIGH);
    digitalWrite(greenLED2, HIGH);
    analogWrite(buzzer, 95);
    delay(time3);
    analogWrite(buzzer, LOW);
    digitalWrite(greenLED1, LOW);
    delay(time3);


  } else if ((zmierzOdleglosc() > zakres5) && (zmierzOdleglosc() <= zakres6)) {
    digitalWrite(redLED, LOW);
    digitalWrite(yellowLED1, LOW);
    digitalWrite(yellowLED2, LOW);
    digitalWrite(greenLED1, LOW);
    digitalWrite(greenLED2, HIGH);
    analogWrite(buzzer, 60);
    delay(time4);
    analogWrite(buzzer, LOW);
    digitalWrite(greenLED2, LOW);
    delay(time4);

  } else if ((zmierzOdleglosc() > zakres6)) { // obiket poza zakresami
    // Serial.println("obiekt poza zakresem");
    digitalWrite(redLED, LOW);
    digitalWrite(yellowLED1, LOW);
    digitalWrite(yellowLED2, LOW);
    digitalWrite(greenLED1, LOW);
    digitalWrite(greenLED2, LOW);
    analogWrite(buzzer, LOW); // wyłączamy buzzer, gdy obiket poza zakresem
  }
  delay(10);
}

Trochę rozbudowałem program z zadania 9.3 i zrobiłem kodzik na czujniki parkowania 😄

  • Lubię! 1
Link do komentarza
Share on other sites

Witam, udało mi się zrobić zadanie 8.3 jednak wydaje mi się że kod który napisałem mógłby być trochę krótszy.

#define URECHO  3
#define URTRIG  5

unsigned int DistanceMeasured = 0;

void setup() {
  Serial.begin(9600);
  
  pinMode(URTRIG, OUTPUT);
  digitalWrite(URTRIG, HIGH);

  pinMode(URECHO, INPUT);

  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  delay(500);
  
  Serial.println("Init the sensor");
}

void loop() {
  zakres(6, 15, 6);
  zakres(15, 30, 7);
  zakres(30, 50, 8);
  zakres(50, 80, 9);
  zakres(80, 120, 10);
  
  delay(100);
 
  Serial.println(odleglosc() / 50);

  
  
}

int odleglosc() {
    digitalWrite(URTRIG, LOW);
    digitalWrite(URTRIG, HIGH);
    unsigned long LowLevelTime = pulseIn(URECHO, LOW);

    return LowLevelTime;
  }

void zakres(int a, int b, int pin) {
  int dystans = odleglosc() / 50;
  if ((dystans > a) && (dystans < b)) {
    digitalWrite(pin, HIGH);
    }
    else {
      digitalWrite(pin, LOW);
    }
    if(digitalRead(6) == HIGH){
    for(int i = 7; i < 11; i++) {
      digitalWrite(i, HIGH);
      }
    }
    if(digitalRead(7) == HIGH) {
      for(int i = 8; i < 11; i++){
        digitalWrite(i,HIGH);
      }
    }  
    if(digitalRead(8) == HIGH) {
      for(int i = 9; i < 11; i++){
        digitalWrite(i,HIGH);
      }
    }
    if(digitalRead(9) == HIGH) {
      for(int i = 10; i < 11; i++){
        digitalWrite(i,HIGH);
      }
    } 
}

Chodzi mi dokładnie o te 5 if-ów dla wartości wejść od 6 do 9, jeśli miałby ktoś pomysł jak by to skrócić będę bardzo wdzięczny za poradę.

Link do komentarza
Share on other sites

Bardzo to skomplikowałeś. A można się odnieść bezpośrednio do czasu, np.:

if (czas < 120)
  digitalWrite(11, HIGH);
else
  digitalWrite(11, LOW);

if (czas < 80)
  digitalWrite(10, HIGH);
else
  digitalWrite(10, LOW);
...

W takiej sytuacji jeżeli ten czas będzie mniejszy od 80, to jednocześnie będzie też mniejszy od 120, więc zaświecą się obie diody. Można też użyć operatora warunkowego, by taki ciąg skrócić:

digitalWrite(11, HIGH ? czas < 120 : LOW);
digitalWrite(10, HIGH ? czas < 80 : LOW);
...

A jeżeli się dodatkowo sprawdzi, że HIGH ma wartość 1, a LOW wartość 0 i wie się, że operatory porównania zwracają 0, gdy wynik jest fałszywy, a 1, gdy prawdziwy, to można uprościć:

digitalWrite(11, czas < 120);
digitalWrite(10, czas < 80);
...

I w takiej sytuacji nie ma tych kilku osobnych funkcji dla osobnych zakresów, po prostu taki ciąg warunków "załatwi" to sam.

  • Pomogłeś! 1
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

#define trig 11
#define echo 12

#define led1 7
#define led2 6
#define led3 5
#define led4 4
#define led5 3
#define led6 2

long current = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(200); //
  howFar(10);
}

long echolocate() {
    digitalWrite(trig, LOW);
    delayMicroseconds(1);

    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    
    digitalWrite(trig, LOW);

    long read = pulseIn(echo, HIGH)/58;
  
    return read;
}

void howFar(int max){
  long x = echolocate();
  if(x > max){
    turnOff();
  }
  else if (current != x)
  {
    current = x;
    x = map(x, 1, max, 6, 1);
    turnOff();
    turnLeds(x);
  }
}

void turnLeds(byte number){
  for(byte i = 2; i <= number+1 ; i++){
    digitalWrite(i, HIGH);
  }
}

void turnOff(){
  for(byte i = 2; i <= 7 ; i++){
    digitalWrite(i, LOW);
  }
}

Mój kod zadania 9.3,

PS. działa ale zapomniałem do komentować. 

Edytowano przez RakietowyKim
Dodany ps
  • Lubię! 1
Link do komentarza
Share on other sites

@RakietowyKim pamiętaj, że komentarze warto robić dla samego siebie. Zdaje sobie sprawę, że przy takich krótkich programach może pozornie nie być takiej potrzeby, ale warto wyrabiać sobie taki nawyk, bo czy za jakiś czas będziesz pamiętał co miała robić funkcja howFar? Dobrze byłoby chociaż wewnątrz funkcji dopisać sobie krótki komentarz co ona właściwie robi.

  • Lubię! 1
Link do komentarza
Share on other sites

No to wpadam z pierwszym pakietem zadań domowych. 😄
Przy ostatnim z dzisiejszych miałem mały zastój umysłowy, ale jakoś ogarnąłem ten koszmarek. 😉

A przy okazji, wydaje mi się, że coś jest nie tak z numeracją zadań - 9.1, 9.2, potem znowu 9.1, następnie 9.3 i już leci po kolei. 😅

Zad. 9.1

void setup() {
  pinMode(3, OUTPUT); //Konfiguracja pinu 3 jako wyjscie-pwm
}

void loop() {
  rozjasnianieLED();
}

void rozjasnianieLED() {
  for (int pwm = 0; pwm <= 255; pwm++) { //Powtarzaj do osiagniecia PWM 255 
    analogWrite(3, pwm); //Stopniowe zwiekszanie jasnosci diody
    delay(25);
  }

  for (int pwm = 255; pwm >= 0; pwm--) { //Powtarzaj do soiagniecia pwm 0
    analogWrite(3, pwm); //Stopniowe zmienjszanie jasnosci diody
    delay(25);
  }
}

 

Zad. 9.2

void setup() {
  pinMode(3, OUTPUT); //Konfiguracja pinu 3 jako wyjscie
  miganieLED(5, 300, 400); //Wywolanie wlasnej funkcji, ustalenie wartosci kolejnych argumentow
}

void loop() {}

void miganieLED(int ile, int czasOn, int czasOff) {
  for (int i=0; i < ile; i++) { //Powtorz tyle razy ile podano w wywoalniu
    digitalWrite(3, HIGH); //Wlaczenie diody
    delay(czasOn); //Odczekaj przez pierwszy czas podany w wywolaniu
    digitalWrite(3, LOW); //Wylaczenie diody
    delay(czasOff); //Odczekaj przez drugi czas podany w wywolaniu
  }
}

 

Zad. 9.1 - obliczanie pól

//Deklaracja zmiennych
boolean startProgramu = 0; //Zmienna pomocnicza
int wybor = 0; //Pusty ciag danych odebranych z UART
float wymiarA = 0; //Pierwszy wymiar - krotszy bok, wysokosc, promien
float wymiarB = 0; //Drugi wymiar - dluzszy bok, podstawa

void setup(){
  Serial.begin(9600); //Uruchomienie komunikacji UART
}

void loop() {

  if (startProgramu == 0){ //Jezeli zmienna jest 0, zacznij tutaj
    Serial.println("Wybierz pole której figury chcesz obliczyć");
    Serial.println("Pole kwadratu   - wpisz K");
    Serial.println("Pole prostokąta - wpisz P");
    Serial.println("Pole koła       - wpisz O");
    Serial.println("Pole trójkąta   - wpisz T \n\n");
    startProgramu = 1; //Przelacz stan zmiennej
  }

  if (Serial.available() > 0) { //Jezeli odebarano jakies dane
    wybor = Serial.read(); //To odczytaj 1 znak
  }
    switch (wybor) { //Wykonaj taki case, jaki odebrano znak
      
      case 'K': //Pole kwadratu
      Serial.println("Wybrano obliczenie pola kwadratu");
      Serial.println("Podaj wymiar boku (a): ");
      while (Serial.available() == 0) {} //Wstrzymaj program do momentu odebrania danych
      if (Serial.available() > 0) { //Jezeli odebrano dane
        String odebranyWymiarA = Serial.readStringUntil('\n'); //Odczytaj dane do znaku konca linii
        float wymiarA = odebranyWymiarA.toFloat(); //Przekonwertuj odebrane dane na zmienna float
        delay(200);
        Serial.println("Podany wymiar boku: " + String(wymiarA) + "\n");
        float wynik = poleKwadratu(wymiarA); //Odwolaj sie do funkcji poleKwadratu
        Serial.println("Pole kwadratu wynosi: " + String(wynik) + "\n\n");
      }
      startProgramu = 0; //Zresetuj zmienna pomocnicza
      wybor = 0; //Zresetuj zmienna wyboru
      wymiarA = 0; //Zresetuj zmienna wymiaru A
    break; //Zakoncz case K

      case 'P': //Pola prostokata
      Serial.println("Wybrano obliczenie pola porstokąta");
      Serial.println("Podaj wymiar krótszego boku (a):");
      while (Serial.available() == 0) {} //Wstrzymaj program do momentu odebrania danych
      if (Serial.available() > 0) { //Jezeli odebrano dane
        String odebranyWymiarA = Serial.readStringUntil('\n'); //Odczytaj dane do konca linii
        float wymiarA = odebranyWymiarA.toFloat(); //Przekonwertuj odebrane dane na zmienna float
        Serial.println("Podaj wymiar dłuższego boku (b):");
        while (Serial.available() == 0) {} //Wstrzymaj do odebrania koeljnych danych
        if (Serial.available() > 0) { //Jezeli odebrano dane
          String odebranyWymiarB = Serial.readStringUntil('\n'); //Odczytaj dane do końca linii
          float wymiarB = odebranyWymiarB.toFloat(); //Przekonwertuj odebrane dane na zmienna float
          delay(200);
          Serial.println("Podany wymiar krótszego boku (a): " + String(wymiarA) + "\n");
          Serial.println("Podany wymiar dłuższego boku (b): " + String(wymiarB) + "\n");
          float wynik = poleProstokata(wymiarA, wymiarB);
          Serial.println("Pole powierzchni prostokata wynosi " + String(wynik) + "\n\n");
        }
      }
      startProgramu = 0; //Zresetuj zmienne
      wybor = 0; 
      wymiarA = 0;
      wymiarB = 0;
    break; //Zakoncz case P

      case 'O': //Pole kola
      Serial.println("Wybrano obliczenie pola koła");
      Serial.println("Podaj promień koła (r): ");
      while (Serial.available() == 0) {} //Wstrzymaj program do momentu odebrania danych
      if (Serial.available() > 0) { //Jezeli odebrano dane
        String odebranyWymiarA = Serial.readStringUntil('\n'); //Odczytaj dane do konca linii
        float wymiarA = odebranyWymiarA.toFloat(); //Przekonwertuj odebrane dane na zmienna float
        delay(200);
        Serial.println("Podany promien: " + String(wymiarA) + "\n");
        float wynik = poleKola(wymiarA); //Odwolaj sie do funkcji pole kola
        Serial.println("Pole koła wynosi: " + String(wynik) + "\n\n");
      }
      startProgramu = 0; //Zresetuj zmeinne
      wybor = 0;
      wymiarA = 0;
    break; //Zakoncz case O

      case 'T': //Pole trojkata
      Serial.println("Wybrano obliczenie pola porstokąta");
      Serial.println("Podaj wysokość trójkąta (h):");
      while (Serial.available() == 0) {} //Wstrzymaj program do momentu odebrania danych
      if (Serial.available() > 0) { //Jezeli odebrano dane
        String odebranyWymiarA = Serial.readStringUntil('\n'); //Odczytaj dane do konca linii
        float wymiarA = odebranyWymiarA.toFloat(); //Przekonwertuj odebrane dane na zmienna float
        Serial.println("Podaj wymiar podstawy (a):");
        while (Serial.available() == 0) {} //Wstrzymaj do odebrania koeljnych danych
        if (Serial.available() > 0) { //Jezeli odebrano dane
          String odebranyWymiarB = Serial.readStringUntil('\n'); //Odczytaj dane do końca linii
          float wymiarB = odebranyWymiarB.toFloat(); //Przekonwertuj odebrane dane na zmienna float
          delay(200);
          Serial.println("Podana wysokość trójkąta (h): " + String(wymiarA) + "\n");
          Serial.println("Podany wymiar podstawy (a): " + String(wymiarB) + "\n");
          float wynik = poleProstokata(wymiarA, wymiarB);
          Serial.println("Pole powierzchni trójkąta wynosi " + String(wynik) + "\n\n");
        }
      }
      startProgramu = 0; //Zresetuj zmienne
      wybor = 0; 
      wymiarA = 0;
      wymiarB = 0;
    break; //Zakoncz case T
    
    } //Zakonczenie switch-case
} //Zakonczenie petli loop

//Funkcje obliczeniowe
float poleKwadratu (float wymiarA) {
  float wynik = wymiarA * wymiarA;
  return wynik;
}

float poleProstokata (float wymiarA, float wymiarB) {
  float wynik = wymiarA * wymiarB;
  return wynik;
}

float poleKola (float wymiarA) {
  float wynik = PI * wymiarA * wymiarA;
  return wynik;
}

float poleTrojkata (float wymiarA, float wymiarB) {
  float wynik = 0.5 * wymiarA * wymiarB;
  return wynik;
}

 

No i skoro poznaliśmy już funkcję to.Int(), to stwierdziłem, że dla innych typów zmiennych pewnie też istnieją, więc spróbowałem z to.Float(). 😄

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Kod z lekcji.
 

#define trigPin 12
#define echoPin 11

void setup() {
  Serial.begin (9600); //Start UART
  pinMode(trigPin, OUTPUT); //Pin, do ktorego podlaczymy trig jako wyjscie
  pinMode(echoPin, OUTPUT); //Pin echo jako wyjscie
}

void loop() {
  Serial.print(zmierzOdleglosc());
  Serial.println(" cm");

  delay(500);
}

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

 

1666014342103.jpg

1666014342119.jpg

Screenshot_1.png

Link do komentarza
Share on other sites

Hej, utknąłem na pierwszym programie z dalmierzem. Wciąż dostaję odpowiedź w postaci 1021 cm, niezależnie od tego, czy macham czymś przed czujnikiem czy nie.

Wydaje mi się, że złożyłem wg opisu i schematu:
IMG-0956.thumb.jpg.1b6080d8272c0c98efc96640bd1ea3e6.jpg

Program też wydaje się ok:

#define TRIG_PIN 12
#define ECHO_PIN 11

long czas, dystans;

void setup() {
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}

void loop() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  czas = pulseIn(ECHO_PIN, HIGH);
  dystans = czas / 58;
  Serial.print("Czas: ");
  Serial.print(czas);
  Serial.print(", dystans: ");
  Serial.print(dystans);
  Serial.println(" cm");

  delay(1000);
}

Mimo to dostaję wyniki z takimi, dziwnymi wartościami:

Cytat

13:58:51.769 -> Czas: 69690, dystans: 1201 cm
13:58:52.835 -> Czas: 69675, dystans: 1201 cm
13:58:53.901 -> Czas: 69670, dystans: 1201 cm
13:58:54.967 -> Czas: 69677, dystans: 1201 cm
13:58:56.066 -> Czas: 69681, dystans: 1201 cm
 

Ktoś wie, o co może chodzić? Czujnik uszkodzony? Oczywiście pochodzi z zestawu dedykowanego dla kursu.

Edytowano przez kaminski-tomek
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.