Skocz do zawartości

HC-SR04 - Wielofunkcyjność programowa na podstawie czujnika odległości. Modyfikacja programu


Forseti

Pomocna odpowiedź

19 godzin temu, _LM_ napisał:

mimo to w jednej okoliczności działanie będzie niepożądane.

Chodzi Ci o wartosc "0"? jesli tak to zaden problem jesli w jednym obiegu przelaczania w jednym momencie nic sie nie dzieje..

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

Brawo 🙂 chociaż przykład %4 był nietrafiony znacznie lepiej widać gdyby było %5 czyli

254 % 5 = 4
255 % 5 = 0 
0   % 5 = 0  

Więc reszta modulo będzie dawała 0 w dwóch po sobie następujących iteracjach. Można to łatwo naprawić. Ogólnie chciałem pokazać jak łatwo można realizować niektóre obliczenia

Edytowano przez _LM_
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

No bo to się ściśle tyczy twojego projektu pokazałem że zamiast trzech zmiennych, do wyliczania trybu programu wystarczy jedna z zapisem modulo

  int aktualnyStan = digitalRead(Przycisk_1);

  if (ostatniStan == HIGH &&  aktualnyStan == LOW)  {//Jeśli ostatni stan był wyłączony i aktualny stan jest włączony to:
    tryb_program += 1; //Warunek - sprawdzenie stanu - jeśli Przycisk_1 włączony
  }

zamiast tych nadmiarowych zmiennych możesz wpisać tak jak wcześniej pokazałem 

if(!digitalRead(Przycisk_1))tryb_program++;

switch(tryb_program % 4){
  case 0:...
    ....
}

Zadziała to identycznie z tym  że nieco szybciej i zabierze mniej ramu. Zachęcam do prób bo to  nie jest czarna magia. znak % jest operatorem reszty z dzielenia czyli 

tryb_program = 0 % 4 = 0;   
tryb_program = 1 % 4 = 1;  
tryb_program = 2 % 4 = 2;
tryb_program = 3 % 4 = 3;
tryb_program = 4 % 4 = 0;
tryb_program = 5 % 4 = 1;
tryb_program = 6 % 4 = 2;
tryb_program = 7 % 4 = 3;
tryb_program = 8 % 4 = 0;
tryb_program = 9 % 4 = 1;
......
tryb_program = 254 % 4 = 2;
tryb_program = 255 % 4 = 3;
tryb_program =   0 % 4 = 0; // tu zmienna "przekręciła się" i liczenie zaczyna się od zera

 

    

Link do komentarza
Share on other sites

11 minut temu, Forseti napisał:

Brutalna motywacja Panowie. Skoro poświęcacie mi swój czas byłoby iście niedżentelmeńsko nie zabrać się za ww. temat. Postaram się to ogarnąć 🙂

Dzisiejszy swiat jest bez litosci..😉 reszta z dzielenia to rowniez dobra opcja...moze Ci sie przydac rowniez w przyszlosci np. do "rozbiorki" liczby na cyfry...np. masz

int = 57842;

A chcialbys to zamienic na

byte1 = 5
byte2 = 7
byte3 = 8
byte4 = 4
byte5 = 2

(to tak tylko dla przykladu..)

Link do komentarza
Share on other sites

Pobawiłem się z kodem i mam pewne spostrzeżenia. Takie rozwiązanie powoduje, że jak trzymam microswitch wciśnięty to programy latają jeden po drugim w kółko. Zwiększyłem opóźnienie w odczycie stanu przycisku do delay(150) no i jakoś to chodzi (drgania styków?). Jednak trzeba uważać przy przełączaniu. 

//Program symulujący pracę dwóch programów przełączanych za pomocą przełącznika monostabilnego
//Przyciski typu microswitch
//Program_1 - LED 1
//Program_2 - LED 2

#define Przycisk_1 A0 //Microswitch_1
#define LED_1 A4 //LED zielona 1
#define LED_2 A5 //LED zielona 2

uint8_t tryb_program = 0; //Zmienna trybu programu
int ostatniStan = HIGH; //PULLUP

void setup () {
  //Wyprowadzenie przycisków
  pinMode(Przycisk_1, INPUT_PULLUP); //Wejście przycisku 1 w trybie PULLUP

  //Wyprowadzenia LED
  pinMode(LED_1, OUTPUT); //Wyjście na LED zielona 1
  pinMode(LED_2, OUTPUT); //Wyjście na LED zielona 2

  //Ustawienie wyjściowego stanu LED
  digitalWrite(LED_1, LOW); //Stan diody LED1 - wyłączona
  digitalWrite(LED_2, LOW); //Stan diody LED2 - wyłączona
}

void loop () {

  int aktualnyStan = digitalRead(Przycisk_1);

  if (!digitalRead(Przycisk_1)) tryb_program++;  {//Jeśli ostatni stan był wyłączony i aktualny stan jest włączony to:
  }

  switch (tryb_program % 4) {

    case 1:
      digitalWrite(LED_1, HIGH);
      digitalWrite(LED_2, LOW);
      //Włącz LED zielona 1 - PROGRAM 1
      break;
    case 2:
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, HIGH);
      //Włącz LED zielona 2 - PROGRAM 2
      break;
    case 3:
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, LOW);
      //Wyłącz LED - Stan OFF
      break;
  }
  ostatniStan = aktualnyStan;
  delay(120);
}

Na IFach działa to zdecydowanie pewniej. 🙃

Link do komentarza
Share on other sites

while(!digitalRead(Przycisk_1)));

Wstaw przed delay. Wywal te klamerki za 

tryb_program++;

tak samo aktualny stan nie jest już potrzebny 

No i w sumie delay w tym przypadku też może mieć mniejszą wartość

Edytowano przez _LM_
Link do komentarza
Share on other sites

(edytowany)

@_LM_ Wykonałem polecenie:

//Program symulujący pracę dwóch programów przełączanych za pomocą przełącznika monostabilnego
//Przyciski typu microswitch
//Program_1 - LED 1
//Program_2 - LED 2

#define Przycisk_1 A0 //Microswitch_1
#define LED_1 A4 //LED zielona 1
#define LED_2 A5 //LED zielona 2

uint8_t tryb_program = 0; //Zmienna trybu programu

void setup () {
  //Wyprowadzenie przycisków
  pinMode(Przycisk_1, INPUT_PULLUP); //Wejście przycisku 1 w trybie PULLUP

  //Wyprowadzenia LED
  pinMode(LED_1, OUTPUT); //Wyjście na LED zielona 1
  pinMode(LED_2, OUTPUT); //Wyjście na LED zielona 2

  //Ustawienie wyjściowego stanu LED
  digitalWrite(LED_1, LOW); //Stan diody LED1 - wyłączona
  digitalWrite(LED_2, LOW); //Stan diody LED2 - wyłączona
}

void loop () {

  if (!digitalRead(Przycisk_1)) tryb_program++; {} //Jeśli ostatni stan był wyłączony i aktualny stan jest włączony to:

  switch (tryb_program % 4) {

    case 1:
      digitalWrite(LED_1, HIGH);
      digitalWrite(LED_2, LOW);
      //Włącz LED zielona 1 - PROGRAM 1
      break;
    case 2:
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, HIGH);
      //Włącz LED zielona 2 - PROGRAM 2
      break;
    case 3:
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, LOW);
      //Wyłącz LED - Stan OFF
      break;
  }
  while (!digitalRead(Przycisk_1));
  delay(50);
}

 

Czy w takiej sytuacji nie będzie problemu z drganiem styków microswitcha ? 

Muszę się dokształcić z tego co się stało w tym kodzie 🙂 (brak czasu aby tak szybko ogarniać) - 1h dziennie max. Czytałem już wstępnie o modulo ale muszę to przećwiczyć. Doszkolę się ! 

23 godziny temu, _LM_ napisał:

Wstaw przed delay. Wywal te klamerki za 


tryb_program++;

 

Czy nie "dobrą szkołą" jest pozostawianie klamerek?

Edytowano przez Forseti
Link do komentarza
Share on other sites

21 minut temu, Forseti napisał:

Czy nie "dobrą szkołą" jest pozostawianie klamerek?

No w tym miejscu co były to nie. Przypominam 😉

  if (!digitalRead(Przycisk_1)) tryb_program++;  {//Jeśli ostatni stan był wyłączony i aktualny stan jest włączony to:
  }

Jak już to miały one obejmować tryb_program.

21 minut temu, Forseti napisał:

Czy w takiej sytuacji nie będzie problemu z drganiem styków microswitcha ?

W zamyśle program zatrzyma się na 
 

while (!digitalRead(Przycisk_1));

I będzie czekał do czasu zwolnienia przycisku, nawet gdyby switch odbił to i tak po while ma delaya,

więc nie powinno to aż tak przeszkadzać. Poza tym z moich badań wynika że mało które microswitche dzwonią dłużej niż 20ms 

21 minut temu, Forseti napisał:

Czytałem już wstępnie o modulo ale muszę to przećwiczyć

Nic na siłę, ja jeśli widzę taką możliwość to staram się pokazywać co gdzie można usprawnić, program napiszesz tak jak tobie jest wygodnie. Na przyszłość będziesz wiedział że istnieje taki ciekawy operator

 

Edytowano przez _LM_
Link do komentarza
Share on other sites

Przeszedłem płynnie do nauki obsługi silników DC w oparciu o L293D Motor Driver Shield i rozszerzyłem omawiany kod o prosty program sterujący silnikiem DC. Testowany Voltomierzem - bez podpinania silników. 

//Program symulujący pracę jednego silnika DC opartego o L293D Motor Driver Shield.
//Przełączanie trybów microswitch

#include <AFMotor.h> //Wczytanie Biblioteki AFMotor dla Arduino Shield

#define Przycisk_1 A5 //Microswitch_1
#define LED_1 A3 //LED zielona 1
#define LED_2 A4 //LED zielona 2
#define MAX_SPEED 190 //Ustawienie prędkości silników DC - 0-255
#define MAX_SPEED_OFFSET //?? Interwał przyśpieszania ??

AF_DCMotor motor1(4); //Przypisanie silnika 1 na wyjście M1 Shielda

uint8_t tryb_program = 0; //Zmienna trybu programu
int Ustaw_predkosc = 0; //ustawienie prędkości startowej silnika

void setup()
{
  //Wyprowadzenie przycisków
  pinMode(Przycisk_1, INPUT_PULLUP); //Wejście przycisku 1 w trybie PULLUP

  //Wyprowadzenia LED
  pinMode(LED_1, OUTPUT); //Wyjście na LED zielona 1
  pinMode(LED_2, OUTPUT); //Wyjście na LED zielona 2

  //Ustawienie wyjściowego stanu LED
  digitalWrite(LED_1, LOW); //Stan diody LED1 - wyłączona
  digitalWrite(LED_2, LOW); //Stan diody LED2 - wyłączona

  //Ustawienie początkowej wartości silnika DC oraz STOP
  motor1.setSpeed(200);
  motor1.run(RELEASE);
}

void loop()
{
  if (!digitalRead(Przycisk_1)) tryb_program++;  //Jeśli ostatni stan był wyłączony i aktualny stan jest włączony to:

  switch (tryb_program % 4) {

    case 1:
      //Jeśli przycisk wciśnięty x1 to włącz PROGRAM 1

      digitalWrite(LED_1, HIGH);
      digitalWrite(LED_2, HIGH);
      delay(200);
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, LOW);
      delay(200); //Włączenie LED- sygnalizacja włączenia Programu 1 - zbędne

      //Włącz silnik
      motor1.run(FORWARD);

      //Przyśpiesz od 0 do max
      for (Ustaw_predkosc = 0; Ustaw_predkosc < MAX_SPEED; Ustaw_predkosc += 2)
      {
        motor1.setSpeed(Ustaw_predkosc);
        delay(10);
      }

      //Zwolnij od max do 0
      for (Ustaw_predkosc = MAX_SPEED; Ustaw_predkosc != 0; Ustaw_predkosc--)
      {
        motor1.setSpeed(Ustaw_predkosc);
        delay(10);
      }

      //Zmiana kierunku obrotów silnika DC
      motor1.run(BACKWARD);

      //Przyśpiesz od 0 do max
      for (Ustaw_predkosc = 0; Ustaw_predkosc < MAX_SPEED; Ustaw_predkosc += 2)
      {
        motor1.setSpeed(Ustaw_predkosc);
        delay(10);
      }
      //Zwolnij od max do 0
      for (Ustaw_predkosc = MAX_SPEED; Ustaw_predkosc != 0; Ustaw_predkosc -= 2)
      {
        motor1.setSpeed(Ustaw_predkosc);
        delay(10);
      }
      //Wyłacz silnik
      motor1.run(RELEASE);
      delay(50);
      break;

    case 2:   //Jeśli przycisk wciśnięty x2 to włącz PROGRAM 2
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, HIGH);
      //Wyłacz silnik
      motor1.run(RELEASE);
      delay(50);
      break;

    case 3: //Jeśli przycisk wciśnięty x3 to włącz wszystko
      digitalWrite(LED_1, LOW);
      digitalWrite(LED_2, LOW);
      //Wyłacz silnik
      motor1.run(RELEASE);
      delay(50);
      //Wyłącz LED - Stan OFF
      break;
  }
  while (!digitalRead(Przycisk_1));
  delay(50);
}

 

Program startuje pod naciśnięciu microswitcha (Przycisk_1) jednak na ponowne kliknięcia nie ma żadnej reakcji. Kod biega w kółko pętli w poleceniu switch - case 1. Brak przeskoku na case2 oraz case3. Udało się czasem "wstrzelić" w zmianę case ale to wygląda jak drganie styków microswitcha 😕

Link do komentarza
Share on other sites

for (Ustaw_predkosc = 0; Ustaw_predkosc < MAX_SPEED; Ustaw_predkosc += 2)
      {
        motor1.setSpeed(Ustaw_predkosc);
        delay(10);
      }

     

Wykonujac taka petle jestes w niej dopuki zmienna "Ustaw_predkosc" jest mniejsza niz "MAX_SPEED"...w kazdym obiegu dodajesz 2 i uzywasz delay() o dlugosci 10ms. Czyli 95*10=950ms...tyle czasu siedzisz w jednym "for" zakladajac nawet ze reszta nie pochlania czasu..takich "for" masz kolejno 4, czyli 4*950=3800ms(strasznie dlugo!). Wiec po wejsciu w "case 1" bedziesz mogl sprawdzic swoj guzik dopiero po okolo 4 sekundach..tragedia🤕

Wyjsciem jest sprawdzanie stanu guzika w kazdym obiegu "for"...a jesli takowy zaobserwowano to trzeba tak zmodyfikowac zmienna "Ustaw_predkosc" zeby juz wszystkie warunki w reszcie "for" nie zostaly spelnione...poprostu omijamy reszte zawartosci "case 1" po to zeby mozna bylo wejsc w inny "case"...

Link do komentarza
Share on other sites

@farmaceuta W sensie w każdą pętlę for wpisać warunek if (!digitalRead(Przycisk_1)) ?

Zastanawiam się czy ten sposób przełączania (przycisk) programów dla bardziej rozbudowanego kodu ma sens i czy nie będę musiał pobawić się (nauczyć) w przerwania. 😕 . Wtedy jednak musiałbym wlutowywać się w piny 2,3 (przerwania) czego nie chcę robić.  Przepraszam, że odpisuję po tak długim czasie ale walczyłem z zasilaniem do robota- mam już platformę do testów i programowania. 

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.