logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Arduino Leonardo - jak opóźnić silnik bez użycia delay()?

Piooner 27 Lut 2015 08:41 4176 30
REKLAMA
  • #1 14482269
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Witam mój problem polega na tym że
    po naciśnięciu przycisku wszystko działa tak jak chce ale gdy dodam krótki fragment kodu
    Kod: text
    Zaloguj się, aby zobaczyć kod
    w celu opóźnienia silnika żeby zmienić np kierunek obrotu to już nie działa program wiem że przeszkadza mi delay. Ale cokolwiek nie robię (noInterrupts(); ,break czy timery nic nie działa) Podpowie mi ktoś czego użyć żeby to zadziałało?:)


    Kod: text
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 14482324
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Co Ci konkretnie nie działa?
  • #3 14482334
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Odpalę program działa ale przycisk trzeba dłużej przytrzymać zgaśnie wszystko i później koniec nie uruchomię przyciskiem chodź bym nie wiem jak długo go trzymał wydaję mi się że
    long debounceDelay = 50; i zwykły delay
    mieszają tu sprawę i nie wiem jak to obejść.
  • REKLAMA
  • #5 14482379
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Kolega szczywronek mnie uprzedził.
    Zarówno delay() jaki i millis() potrzebują przerwań do działania.
    Oczywiście możesz to obejść samemu programując timery.
    Ale wcześniej czy później i tak będzie potrzebował przerwań.
    Co chciałeś uzyskać wyłączając przerwania?
  • #6 14482408
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Dalej nie rozumiem, najprostszy program do migania diody ma delay i nie ma nigdzie przerwań ?
    więc co muszę zrobić żeby mi to działało?
    noInterrupts
    i Interrupts muszą być w innym miejscu żeby przycisk wszystko włączał i wyłączał?
    bo teraz jest chyba tak że stosując 5 razy delay(1000) program czeka 5 sekund razem z long debounceDelay = 50; i wtedy szaleję wszystko ?
  • #7 14482439
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    W przykładzie Blink są używane przerwania właśnie na potrzeby procedury delay() do odmierzania czasu.
    Domyślnie w Arduino przerwania są włączone.
    Zostaw przerwania w spokoju (nie wyłączaj ich).
    Jak ma działać Twój program, co chcesz uzyskać?
  • #8 14482540
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Mam taki program
    Kod: text
    Zaloguj się, aby zobaczyć kod

    po wciśnięciu przycisku silnik przestaję się kręcić,wciskam kręci się działa.
    po dopisaniu kodu
    Kod: text
    Zaloguj się, aby zobaczyć kod
    w celu zmniejszenia prędkości odpalam program przycisk raz tylko działa wyłącza wszystko i koniec.Nie umiem sobie z tym poradzić.
  • #9 14482567
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    W którym miejscu to wstawiłeś?
    Co to znaczy wszystko wyłącza?
    - silnik zatrzymuje się?
    - wiesza się uC?
    - nie działają przyciski?
    Opisz co się dzieje dokładniej, pokaż schemat połączeń.
  • REKLAMA
  • #10 14482662
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Kod: text
    Zaloguj się, aby zobaczyć kod


    taki jest program,
    wcisnę raz przycisk silnik staję
    i koniec nie włączę go już ponownym wciśnięciem przycisku.
    podłączenie musi być dobre skoro usuwam z programu to
    Kod: text
    Zaloguj się, aby zobaczyć kod
    i wszystko śmiga silnik się kręci przycisk staję przycisk kręci tak jak chce.
    Wiesza się uC o co chodzi?
  • #11 14482963
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    1. Czy masz zewnętrzny rezystor podciągający do GND lub Vcc pin 2?
    Jeśli nie, a sterujesz zwieraniem do masy to zastosuj pinMode( buttonPin, INPUT_PULLUP), u Ciebie jest pinMode( buttonPin, INPUT) i jeśli nie zrobiłeś zewnętrznego podciągania to pin sobie "fruwa w powietrzu" raz dając HIGH a raz LOW w dowolnym momencie kiedy nie jest zwartu do któregoś bieguna. Dlatego prosiłem o schemat...
    2. Zostaw włączone przerwania!!! Wykasuj / nie używaj poleceń: noInterrups() ani interrups();
    3. Zmniejsz te szalone wartości delay() na końcu do jakiś 200-300 ms

    Program ożyje...
  • #12 14499176
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Po zastosowaniu 3 punktów program nadal nie działa tak jak powinien, a co do punktu 3 czemu szalone wartości? nie mogę sobie ustawić delay tak żeby silnik kręcił się 2 sekundy z jedną prędkością a 5 sekund z inną ?
  • #13 14499379
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Twój program po wprowadzeniu wspomnianych zmian działa o tyle że reaguje na przycisk.
    Możesz sobie zmieniać dowolnie prędkość i czas jej trwania ale jeśli użyjesz do tego delay() to blokuje działanie całego programu.
    Tak się nie robi.
    Skoro nie potrafisz na razie użyć przerwań to użyj delay() o małej wartości ale w pętli, gdzie m.in. będziesz sprawdzał stan klawiszy i ew. robił inne rzeczy.
  • #14 14500682
    toomus
    Poziom 12  
    Posty: 34
    Pomógł: 3
    Ocena: 10
    Funkcja delay() to czyste zło! Musisz to przerobić na non-blocking, tak jak masz to zrobione wcześniej w programie - loop() nie może się zatrzymywać.
  • #15 14501711
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Ale jak to zrobić bez delay ? jak kod mogę zastosować?
  • #16 14501769
    toomus
    Poziom 12  
    Posty: 34
    Pomógł: 3
    Ocena: 10
    Poniższe dwa programy robią to samo:

    Wersja z delay()
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Wersja non-blocking
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Chyba rozumiesz teraz dlaczego delay() to zło Jeśli nasłuchujesz czujników, albo masz w programie kod, który musi się wykonywać w innych odstępach czasu i w wielu innych przypadkach, z delay() jest to niewykonalne. Po prostu nie używać.
  • REKLAMA
  • #17 14502020
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Chyba już powoli zaczynam to rozumieć ale dalej nie wiem jak to wykorzystać na swoim przykładzie mam prosty program
    po wciśnięciu przycisku silnik kręci się wciskam nie kręci się
    ale gdy chce dodać komendę żeby po upływie 2 s jego prędkość się zwiększyła to nie działa to tak jak powinno
    Kod: text
    Zaloguj się, aby zobaczyć kod

    gdzie tu błąd ?
  • #18 14502279
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Kolega zapisał Ci symbolicznie wykonanie warunkowe procedury myFunction().
    Głównie chodzi o to że nie ująłeś w nawiasy całego bloku.
    Powinno być tak:
    Kod: text
    Zaloguj się, aby zobaczyć kod
    Ponadto musisz zapamiętać wartość millis() wcześniej (np. w setup() ) aby porównywać;
    Kod: text
    Zaloguj się, aby zobaczyć kod
    Inaczej oczekujesz, że jedno przewinięcie pętli da Ci te 2000 ms
  • #19 14502528
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Program działa wielkie dzięki ale mam jeszcze jedno pytanie ;)
    po upływie tych 2000ms silnik kręci się już z szybszą prędkością nawet gdy wyłączam przyciskiem i włączam dalej kręci się z tą szybszą prędkością
    (rozumiem że to przez millis bo ona nalicza czas od początku włączenia arduino)
    dopiero reset pomaga.
  • #20 14503464
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Nigdzie w programie nie zmieniasz prędkości silnika przyciskiem!
    Prędkość jest tylko zwiększana po upływie określonego czasu.
    Powinieneś użyć zmiennej zawierającej stan przycisku do zmiany prędkości.
  • #21 14504554
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    tak wiem nie oto mi chodziło chcę żeby było tak jak po wykorzystaniu delay
    czyli:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    silnik co 5 sekund zmienia swoją prędkość

    bo gdy jest tak:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    to silnik kręci się (100) tylko przez pierwsze 2 sekundy a później chodzi na 230 do Never Ending Story :)

    Wszystko oczywiście chodzi po wciśnięciu przycisku raz po drugim razie jest stop.
    na delay już dawno bym to zrobił no ale właśnie wtedy nie działa przycisk tak jak należy.
  • #22 14504616
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Cytat:
    to silnik kręci się (100) tylko przez pierwsze 2 sekundy a później chodzi na 230 do Never Ending Story
    Zastanów się...
    Musisz zaingerować w warunki w pętli.
    Podałem Ci zmienną która może na to wpływać.
    Nie musi to być zmienna.
    Może to być właśnie upływający czas.
    Czyli jeśli upłynęło ileś czasu to zmień prędkość na inną...
    Przecież masz już przykład odmierzania czasu w kodzie...
    I na delay() przycisk nie będzie działał...
    Sorry, ale wygląda na to, że nie rozumiesz jak działa Twój dotychczasowy kod.
  • #23 14505349
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Czyli muszę przekształcić tylko ten kod
    Kod: text
    Zaloguj się, aby zobaczyć kod

    żeby timer odliczył 2 sekundy załączył else np.na 5 sekund
    potem wykonał by (np. 5 sekund if) i tak w koło.
    Wtedy by to działało tak jak na dwóch delay-ach.
    Dobrze to rozumiem?
  • #24 14505402
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Jeśli chcesz uzyskać tylko naprzemienną zmianę prędkości, to wystarczy, że dodasz pod kodem warunek:
    Kod: text
    Zaloguj się, aby zobaczyć kod
    gdzie x = czas wykonywania bloku if {} + czas bloku else {}
    Spowoduje to przypisanie do zmiennej timer nowego czasu do porównań i znów będzie wykonywany blok if{}, i tak w kółko
  • #25 14505501
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    działa tylko else (50)
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #26 14505606
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    No i gdzie Ty przypisujesz nowy czas ?!
    Powinno być tak:
    Kod: text
    Zaloguj się, aby zobaczyć kod
    Zwróć uwagę na prawidłowe wstawianie klamerek otaczających blok.
  • #27 14505659
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Kod: text
    Zaloguj się, aby zobaczyć kod


    mam ustawić timer na 7000 tak jak jest
    tu:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    ? bo dalej to nie działa,nie pojmuję tych timerów a chyba nie mam wyjścia bo na boolean też mi nie wychodzi.
  • #28 14505769
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Podałem Ci gotowy kod.
    Nigdzie nie używasz timerów a tylko mierzysz czas jaki upłynął od uruchomienia mikrokontrolera ( funkcja millis() ) i porównujesz z zapamiętanym poprzednio w zmiennej o nazwie timer
  • #29 14505814
    Piooner
    Poziom 10  
    Posty: 38
    Ocena: 2
    Wklejam wysyłam
    silnik 2 sekundy kręci się z małą prędkością później przyśpiesza i tak zostaję więc nie działa
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Myślałem jeszcze o wykorzystaniu blinkwithoutdelay
    Kod: text
    Zaloguj się, aby zobaczyć kod


    tylko w jaki sposób przekształcić kod żeby
    zamiast
    Kod: text
    Zaloguj się, aby zobaczyć kod
    było
    Kod: text
    Zaloguj się, aby zobaczyć kod
    w ten sposób na przemian też mógł bym sterować prędkością.
  • #30 14505895
    EuroGenio
    Poziom 18  
    Posty: 179
    Pomógł: 32
    Ocena: 11
    Sorry pomyłka:
    Zamiast
    Kod: text
    Zaloguj się, aby zobaczyć kod
    powinno być:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    BlinkWithoutDelay miga diodą na tej samej zasadzie.

Podsumowanie tematu

✨ W dyskusji poruszono problem opóźnienia działania silnika w projekcie opartym na Arduino Leonardo bez użycia funkcji delay(). Użytkownik zauważył, że dodanie delay() powoduje zablokowanie programu, co uniemożliwia prawidłowe działanie przycisku. Uczestnicy sugerowali, aby nie wyłączać przerwań, ponieważ zarówno delay(), jak i millis() wymagają ich do działania. Zamiast tego, zaproponowano użycie techniki non-blocking, polegającej na wykorzystaniu millis() do odmierzania czasu, co pozwala na równoczesne wykonywanie innych zadań w pętli. Użytkownik został również poinstruowany, jak zaimplementować zmienną timer do kontrolowania prędkości silnika w zależności od upływu czasu, co pozwala na naprzemienne zmiany prędkości bez blokowania programu.
Wygenerowane przez model językowy.
REKLAMA