matfar 0 Napisano Grudzień 6, 2018 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! Udostępnij ten post Link to post Share on other sites
Gość es2 Grudzień 6, 2018 (edytowany) 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 Grudzień 7, 2018 przez es2 Poprawiłem formatowanie. Udostępnij ten post Link to post Share on other sites
Treker 1111 Grudzień 7, 2018 @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: zamykanie klapy przez 100 ms, sprawdzenie czy czujnik coś wykrył, jeśli wykrył: koniec zamykania, wyjdź z pętli jeśli nie wykrył: wróć do punktu 1, 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ę" Udostępnij ten post Link to post Share on other sites
Gość es2 Grudzień 7, 2018 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: zamykanie klapy przez 100 ms, sprawdzenie czy czujnik coś wykrył, jeśli wykrył: koniec zamykania, wyjdź z pętli jeśli nie wykrył: wróć do punktu 1, 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. Udostępnij ten post Link to post Share on other sites
Treker 1111 Grudzień 7, 2018 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. Udostępnij ten post Link to post Share on other sites
Gość es2 Grudzień 7, 2018 (edytowany) 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 Grudzień 7, 2018 przez es2 Udostępnij ten post Link to post Share on other sites
matfar 0 Grudzień 7, 2018 Bardzo wam dziękuje za radę. Spróbuje poczytać coś więcej na te tematy, które zasugerowaliście. Jeśli będę miał jakiekolwiek pytania na ten temat, odezwę się. Udostępnij ten post Link to post Share on other sites
matfar 0 Grudzień 15, 2018 (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 Grudzień 16, 2018 przez matfar Udostępnij ten post Link to post Share on other sites
matfar 0 Grudzień 16, 2018 Nikt nie jest w stanie pomóc? Udostępnij ten post Link to post Share on other sites
Gość es2 Grudzień 16, 2018 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. Udostępnij ten post Link to post Share on other sites
matfar 0 Grudzień 16, 2018 @es2 A jak do tego dodać czujnik ultradźwiękowy hc-sr04? Chodzi mi o to jaka jest na to komenda, że gdy czujnik wykryje diody się zapalają. Może inaczej można użyć digitalRead? Udostępnij ten post Link to post Share on other sites
Belferek 48 Grudzień 16, 2018 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ć. Udostępnij ten post Link to post Share on other sites
Gość es2 Grudzień 16, 2018 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. Udostępnij ten post Link to post Share on other sites
matfar 0 Grudzień 16, 2018 @Belferek coś takiego. Dodam jeszcze, że chciałbym aby były dwa czujniki Udostępnij ten post Link to post Share on other sites
Belferek 48 Grudzień 16, 2018 (edytowany) 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 Grudzień 16, 2018 przez Belferek 1 Udostępnij ten post Link to post Share on other sites