Skocz do zawartości

Zatrzymanie silnika, gdy czujnik coś wykryje


matfar

Pomocna odpowiedź

Witam, 
robię projekt na Arduino uno, który będzie sterować silnikiem. Do tego projektu zamierzam użyć dwa czujniki odległości. Mój silnik mam za zadanie otworzyć i zamknąć klape. Gdy czujnik coś wyłapie na danej odległości kapa ma się otwierać przez jakiś czas, później chwila pauzy no i po pauzie ma się zamknąć. Mój problem polega na tym, że nie wiem jak napisać kod, który zatrzyma silnik przy zamykaniu klapy wtedy, gdy czujnik odległości coś wykryje. Chciałbym, żeby to działało na takiej samej zasadzie jak brama wjazdowa. Czyli jak fotokomórka coś wykryje przy zamykaniu bramy to wtedy brama się zatrzyma i po chwili zacznie się na nowo otwierać. 


Kod który mam już napisany 

#define trigPin 3
  #define echoPin 2
  
  #define trigPin2 7
  #define echoPin2 6
  
  
  int OTWIERANIE = 8;
  int ZAMYKANIE = 9; 
  
  int czas1 = 8000;
  int czas2 = 8000;
  int pauza = 10000;
  
  void setup() {
    Serial.begin (9600);
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);
    pinMode(trigPin2, OUTPUT);
    pinMode(echoPin2, INPUT);
    pinMode(OTWIERANIE, OUTPUT);
    pinMode(ZAMYKANIE, OUTPUT);   
   
  }
  
  void loop() {  
  
   
  {
  
    long duration, distance;
    digitalWrite(trigPin, LOW);  
    delayMicroseconds(2); 
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10); 
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);
    distance = (duration/2) / 29.1;
    if (distance < 50) {
   CZUJNIK1();
    
  }
    else {
    }
    if (distance >= 200|| distance <= 0){
    Serial.println("Out of range");
    }
    else {
      Serial.print(distance);
      Serial.println(" cm");
    }
  
  
    long duration2, distance2;
    digitalWrite(trigPin2, LOW); 
    delayMicroseconds(2); 
    digitalWrite(trigPin2, HIGH);
    delayMicroseconds(10); 
    digitalWrite(trigPin2, LOW);
    duration2 = pulseIn(echoPin2, HIGH);
    distance2 = (duration2/2) / 29.1;
    if (distance2 < 50) {  
    CZUJNIK2();   
     }
     
    else {  }
    
    if (distance2 >= 200 || distance2 <= 0){
      Serial.println("Out of range");
    }
    else {
      Serial.print(distance2);
      Serial.println(" cm");
    }
  
  }
  {
    
  }
  }
  
  void CZUJNIK1(){
  
  digitalWrite(OTWIERANIE, HIGH);  
     delay(czas2);
     digitalWrite(OTWIERANIE, LOW);   
     delay(pauza);    
    digitalWrite(ZAMYKANIE, HIGH);
    delay(czas1);
  digitalWrite(ZAMYKANIE, LOW);
    
  }
  
  void CZUJNIK2(){
  
    digitalWrite(OTWIERANIE, HIGH);  
     delay(czas2);
     digitalWrite(OTWIERANIE, LOW);   
     delay(pauza);    
    digitalWrite(ZAMYKANIE, HIGH);
    delay(czas1);
  digitalWrite(ZAMYKANIE, LOW);  
    
   
  } 

Z góry dziękuję za pomoc!

Link do komentarza
Share on other sites

Gość es2

Użyj przerwań od czujnika do zatrzymania silnika - nawet się ładnie rymuje ale najpierw poczytaj o millis. Delay-em zawieszasz program nie zobaczy on zmiany stanu czujnika. Przerwania nic nie dadzą, bo co z tego, że przerwanie zatrzyma silnik, jak za chwile, po jakimś tam Delay wykona się digitalWrite(OTWIERANIE, HIGH);
Musisz:
- Zapoznać się z podstawowym kursem Arduino.
- Zapoznać się z z wielowątkowością (choćby z użyciem millis).
- Zapoznać się z przerwaniami zewnętrznymi.
Na szczęście nie musisz zapoznać się z RTOS-em.

Dlaczego OTWIERANIE  i ZAMYKANIE  to zmienne? Jeśli już, to czemu int? Podobnie inne deklaracje GPIO.

Co do

	int czas1 = 8000;
	int czas2 = 8000;
	int pauza = 10000;
	

Podobnie, czemu zmienne? Nigdzie w kodzie nie modyfikujesz ich wartości. Za dużo RAM masz?

Edytowano przez es2
Poprawiłem formatowanie.
Link do komentarza
Share on other sites

@matfar, witam na forum 😉 Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start:

  • Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników.
  • Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć?
  • Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości.
18 godzin temu, matfar napisał:

Mój problem polega na tym, że nie wiem jak napisać kod, który zatrzyma silnik przy zamykaniu klapy wtedy, gdy czujnik odległości coś wykryje.

Możesz to rozwiązać na dwa sposoby. Najlepiej tak jak napisał @es2 z przerwaniami i wielowątkowością. Jest też druga skuteczna metoda, prostsza, ale niezbyt dobra. Mógłbyś zrobić to tak, że zamykanie klapy nie będzie złożone tylko z dwóch instrukcji (włączenie silnika i czekania, aż klapa się zamknie), a zostanie rozbite na więcej operacji:

  1. zamykanie klapy przez 100 ms,
  2. sprawdzenie czy czujnik coś wykrył,
  3. jeśli wykrył: koniec zamykania, wyjdź z pętli
  4. jeśli nie wykrył: wróć do punktu 1,
  5. powtarzaj, aż czujnik coś wykryje lub pętla wykona się tyle razy, że te krótkie zamykanie doprowadzi do właściwego zamknięcia klapy.

Jeśli taki program napiszesz dobrze, to będzie działał płynnie i nie będzie widać skoków przy zamykaniu. Rozwiązanie to jednak ma sporo wad i traktowałbym je racze jako "prowizorkę" 😉

Link do komentarza
Share on other sites

Gość es2
13 minut temu, Treker napisał:

Mógłbyś zrobić to tak, że zamykanie klapy nie będzie złożone tylko z dwóch instrukcji (włączenie silnika i czekania, aż klapa się zamknie), a zostanie rozbite na więcej operacji:

  1. zamykanie klapy przez 100 ms,
  2. sprawdzenie czy czujnik coś wykrył,
  3. jeśli wykrył: koniec zamykania, wyjdź z pętli
  4. jeśli nie wykrył: wróć do punktu 1,
  5. powtarzaj, aż czujnik coś wykryje lub pętla wykona się tyle razy, że te krótkie zamykanie doprowadzi do właściwego zamknięcia klapy.

To też jest pewna forma wielowątkowości tyle, że takiej wybiórczej, realizującej tylko określone zadania w danym przypadku. Czas 100ms jest raczej zbyt długi. Dałbym10ms a może mniej. Taka kombinacja ma pewną wadę (w tym przypadku raczej nieistotną) im delay (zamykanie klapy 100ms pewnie przez delay będzie zrobione) będzie krótszy, tym odchyłka czasu będzie większa. Wynika to z samej zasady działania delay i wpływu czasu wykonania pozostałych kroków.

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

28 minut temu, es2 napisał:

Czas 100ms jest raczej zbyt długi. Dałbym10ms a może mniej.

Niewiele wiadomo tutaj o samym mechanizmie zamykania, więc podałem tylko przykładową wartość. Nie chciałem podać za małej, bo przy słabo napisanym programie przy 10 ms silnik mógłby wcale nie ruszać (jeśli przerwy między kolejnymi wywołaniami funkcji będą zbyt długie). Jednak oczywiście masz rację - ten czas trzeba dokładniej wyregulować obserwując działanie mechanizmu w praktyce.

Link do komentarza
Share on other sites

Gość es2

Wystarczy trochę zmienić algorytm

1. uruchom zamykanie klapy - włącz silnik

2. sprawdzenie czy czujnik coś wykrył,

3. jeśli wykrył: wyłącz zamykanie (wyłącz silnik), wyjdź z pętli

4. jeśli nie wykrył: wróć do punktu 2,

Należałoby dodać timeout. Nie chcę mieszać w głowie autorowi więc użyję millis

1. uruchom zamykanie klapy - włącz silnik, zapamiętaj w zmiennej  systick

2. sprawdzenie czy czujnik coś wykrył,

3. jeśli wykrył: wyłącz zamykanie (wyłącz silnik), wyjdź z pętli

4. jeśli nie wykrył: czy sysytick > wartsc_zapamietana? Jeśli nie wróć do punktu 2,

5. Przekroczony timeout, wyłącz silnik, poinformuj o błedzie

No i doszlismy do najważniejszego, praktycznie wszystkie programy na Arduino, zakładają, że wszystko działa bezbłednie, nie informują o błędach i nie obsługują ich.

Auotor coś zamilkł :-)

 

Edytowano przez es2
Link do komentarza
Share on other sites

(edytowany)

Panowie, poddaje się. Nie mam bladego pojęcia jak to napisać. Przeczytałem cały kurs m.in. o millis, while itp. ale dalej nie wiem jak do tego podejść. Moglibyście mi pomóc 

#define trigPin 3
#define echoPin 2

#define trigPin2 7
#define echoPin2 6


#define OTWIERANIE 8
#define ZAMYKANIE 9

int czas = 8000;

unsigned long aktualnyczas = 0;
unsigned long zapamietanyczassilnika = 0;




void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(trigPin2, OUTPUT);
  pinMode(echoPin2, INPUT);
  pinMode(OTWIERANIE, OUTPUT);
  pinMode(ZAMYKANIE, OUTPUT);   
}

void loop () {
aktualnyczas = millis();
} 
 
int czyjnik1() {
  long czas, dystans;
 
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
 
  czas = pulseIn(echoPin, HIGH);
  dystans = czas / 58;
 
}
int czujnik2() {
  long czas, dystans;
 
  digitalWrite(trigPin2, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin2, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin2, LOW);
 
  czas = pulseIn(echoPin2, HIGH);
  dystans = czas / 58;
 
}

Taki mam początek. Pytanie tylko czy to jest dobrze?

Kładzie mnie na łopatki te millis z tymi warunkami 

 digitalWrite(OTWIERANIE, HIGH);  
     delay(czas);
     digitalWrite(OTWIERANIE, LOW);   
     delay(czas);    
    digitalWrite(ZAMYKANIE, HIGH);
    delay(czas);
  digitalWrite(ZAMYKANIE, LOW);

Chciałbym, żeby to się tam znalazło, ale warunek ma być taki, że przy zamykaniu czujnik nie może nic wykryć jeśli wykryje, klapa ma się otworzyć i po jakimś czasie znowu zamknąć.

Prosiłbym jeszcze raz o pomoc, ale bardziej szczegółowo. Pomimo czytania dalej nie wiem jak to napisać.

Edytowano przez matfar
Link do komentarza
Share on other sites

Gość es2

Miałeś napisane jak rozwiązać problem kilkoma sposobami. Jeśli nie potrafisz użyć millis() zacznij od najprostszego, napisz program migający dioda z użyciem millis.  Następnie to samo, z dwiema diodami, każda migająca z inną częstotliwością. Jak zrozumiesz jak to działa będziesz mógł wrócić do swojego projektu.

Link do komentarza
Share on other sites

No to biorąc pod uwagę problemy autora, to może warto zacząć od pracy koncepcyjnej - algorytmu. Weź ołówek kartkę papieru i narysuj jak ten program ma działać. Zrób zdjęcie i pokaż swoją koncepcję. Tu masz przykład algorytmu na ... "parzenie kawy" - zobacz. Wtedy spróbujemy razem popracować.

Link do komentarza
Share on other sites

Gość es2
8 minut temu, matfar napisał:

Chodzi mi o to jaka jest na to komenda, że gdy czujnik wykryje diody się zapalają.

Nie ma takiej komendy! Gdyby były tego rodzaju komendy, to byłyby ich miliardy. Komenda gdy wykryje, włącz silnik, włącz buzzer, uruchom serwo, wyślij pakiet UDP. Kto by się w tym wszystkim połapał? Musisz sam napisać program, który po wykryciu obiektu przez czujnik zaświeci diody.

Link do komentarza
Share on other sites

A gdzie jest ten drugi czujnik w tym algorytmie? Jeśli mają być dwa czujniki to je ponumeruj np. CZUJNIK1, CZUJNIK2 i uwzględnij w algorytmie. Widzę, że chcesz odmierzać czas. Masz problem z ogarnięciem millis() to może Ci pomoże biblioteka Timers.h - zobacz.

Ludzie już popracowali nad czujnikiem HC-SR-04 więc nie ma co odkrywać Ameryki i może warto spróbować skorzystać z gotowej boblioteki np. NewPing, którą bezpośrednio można zainstalować z poziomu menadżera bibliotek. Tu jest WIKI autora - zobacz

Zainstaluj, przeanalizuj przykłady - coś z tego złożymy 🙂

Przykładowe wykorzystanie:

#include <Timers.h>         //do pomiaru czasu
#include <NewPing.h>        //do obsługi czujników

Timer timer50;              //timer odliczający 50 ms 

//tu zdefiniowane stałe można sobie dostosować do własnych potrzeb

#define TRIGGER_PIN_1  12  // aktywacja czujnika nr 1
#define ECHO_PIN_1     11  // odbiór danych z czujnika nr 1
#define MAX_DISTANCE_1 200 // Max. odległość jaką będzie mierzył czujnik nr 1 w cm.

NewPing czujnik_1(TRIGGER_PIN_1, ECHO_PIN_1, MAX_DISTANCE_1); //definicja czujnika nr 1

void setup()
{
  timer50.begin(50);    //start timera, który będzie odmierzał 50 ms
  Serial.begin(115200); //port szeregowy dla diagnostyki
}

void loop()
{
  if(timer50.available())        //jeśli minęło 50ms
    {
      Serial.print("Ping: ");
      Serial.print(czujnik_1.ping_cm()); //aktywacja czujnika (0 = poza zasięgiem, zakłócenia)
      Serial.println("cm");
      timer50.restart();  //restart timera50 by znowu odliczał 50 ms
    }
  //a tu reszta programu, nie korzystamy z delay!
}

Podłącz czujnik i sprawdź jak działa.

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

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

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.