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 - silnik krokowy i praca ciągła w funkcji

Belialek 07 Kwi 2019 19:34 1176 15
REKLAMA
  • #1 17891830
    Belialek
    Poziom 22  
    Posty: 977
    Pomógł: 19
    Ocena: 124
    Witam,

    Mam następujący kod, który w pętli loop sprawdza jaka jest wartość zmiennej "flag_menu" i w zależności o tego wywołuje odpowiedni funkcje. Wszystko w programie szło fajnie, aż do momentu chęci dodania funkcji, której działanie mogło by być przerwane przez interwencję użytkownika:

    REKLAMA


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Ta funkcja ma wykonać 4*2592 kroków silnika krokowego i to działa idealnie - nie mam za to pojęcia, jak przerwać działanie tej funkcji poprzez np naciśniecie przycisku. Przykład, który analizowałem (Link) poruszał co prawda ten temat, ale on był wrzucony bezpośrednio w funkcję loop() a ja potrzebuję to realizować wewnątrz własnej. Linijka stepper.rotate(4*2592); musi się najpierw wykonać, a dopiero potem wykonuje się kolejna, tak więc sprawdzanie przycisku w tym miejscu ni ma najmniejszego sensu, a jak próbowałem to sprawdzać w loop() przez
    if (buttonState == HIGH && flag==1) ...{
    to również nie dawało żadnego efektu, instrukcja w funkcji musiała się wykonać "do końca".

    Jak powinno się rozwiązywać tego typu zagadnienia? Bo zapewne taki problem będę miał w każdej sytuacji, w której program będzie "w tle" oczekiwał na reakcję użytkownika.

    Korzystam ze sterownika (i biblioteki) DRV8825
  • REKLAMA
  • #2 17892041
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 17892063
    Ture11
    Poziom 39  
    Posty: 5420
    Pomógł: 573
    Ocena: 1130
    Musisz albo zedytować bibliotekę obsługi silnika, albo stworzyć ją samodzielnie. No, chyba, że można rozdzielić funkcję (nie wiem, jaka to funkcja i jak działa, więc podaję przykład):

    zamiast: "stepper.rotate(4*2592); "
    wykonać pętle FOR z powtrórzeniem 2592 razy "stepper.rotate(4*1); " i sprawdzeniem stanu przycisku (wtedy czas reakcji będzie bardziej przyjazny dla człowieka, choć też nie natychmiastowy).

    Samo dodanie przerwań, bez edycji biblioteki, nic Ci nie da.
  • REKLAMA
  • #4 17892143
    Belialek
    Poziom 22  
    Posty: 977
    Pomógł: 19
    Ocena: 124
    @khoam: chcę zrobić dokładnie tak jak piszesz - płytka akurat jest własnej produkcji, ale wrzucony bootloader Arduino, z konfiguracją pinu nie będę miał problemu.

    @Ture11: próbowałem zrobić coś podobnego, ale były wyraźnie zauważalne opóźnienia (tak jakby między krokami był jakiś niewielki delay, przez co praca silnika była "szarpana" i obrót był znacząco wolniejszy) - być może coś namieszałem, jutro sprawdzę krótkim programem z pominięciem LCD, menu ustawień itd... Ogólnie pętla FOR była by dla mnie lepsza (dlatego testowałem wcześniej), bo mógłbym zrobić nieskończoną pętlę z której wyjść można tylko naciskając przycisk, no ale wspomniany wcześniej delay zniechęcił mnie do tego.

    Kolejne pytanie - w konfiguracji programu (jeszcze przed setup() )mam taką stałą:
    #define RPM 220
    (przykładowy program biblioteki) - mogę to przenieść do funkcji i zmienić na zmienną? Chciałbym ten parametr również ustawiać z poziomu menu a nie mieć na sztywno przypisaną wartość.
  • #5 17892158
    Konto nie istnieje
    Poziom 1  
  • #6 17892523
    Belialek
    Poziom 22  
    Posty: 977
    Pomógł: 19
    Ocena: 124
    Hmm czyli - o ile dobrze rozumiem - po naciśnięciu przycisku silnik się zatrzyma, ale zanim wywołam kolejna funkcję, program poczeka aż rotate() dobiegnie końca?
  • #7 17892820
    LChucki
    Poziom 31  
    Posty: 1940
    Pomógł: 104
    Ocena: 379
    Belialek napisał:
    Hmm czyli - o ile dobrze rozumiem - po naciśnięciu przycisku silnik się zatrzyma, ale zanim wywołam kolejna funkcję, program poczeka aż rotate() dobiegnie końca?

    Zamiast robić protezy zrób jak napisał @Ture11 w #3.
  • #8 17892896
    Konto nie istnieje
    Poziom 1  
  • #9 17893410
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    Pętle można przerwać break, funkcje wstawiając return. Nie musisz zmieniać dostępnych funkcji, wystarczy wybrać odpowiednią. Można też zmienić bibliotekę bazową, polecam accelstepper. Zamiast używać funkcji, która ma wykonać 5000 kroków wystarczy zaraz po wejściu w funkcje wywołać pętlę while(1), tu wrzucić całą zawartość tego przykładu nonblock, kazać silnikowi kręcić się w prawo i sprawdzać czy (minęło np. 5000 kroków lub został wciśnięty przycisk) i dać return.
    W accelstepper to jest o tyle lepsze, że używając przyspieszania i hamowania funkcja nie blokuje się w jednym punkcie tylko umieszczasz ją w loop (lub swoim while1) zamiast od razu ją wyhamować możesz zmienić jej miejsce gdzie ma się zatrzymać:
    targetPosition (currentPosition +5000)
    while(1)
    {run()
    if (przycisk) targetPosition (currentPosition ()+100) break;- łagodne zahamowanie i opuszczenie pętli, ilość 100 można zamienić, tak by zdążył wyhamować zgodnie z ustawionymi parametrami
    }
    Jest też funkcja "stop()", która robi dokładnie to samo - ustawia nowy punkt docelowy tak by zatrzymać silnik najszybciej jak to możliwe z aktualnej prędkości i ustawionego przyspieszenia.
    Ewentualnie jak już chcesz modyfikować używaną bibliotekę to lepiej od razu skopiuj funkcję i daj zmodyfikowanej swoją nazwę, nie będziesz zdziwiony jak po jakiejś aktualizacji program zacznie zachowywać się zupełnie inaczej. Z Twoją nazwą wywali błąd przy kompilacji (bo jej nie znajdzie), wtedy zaświeci się żarówa, przekopiujesz swoją funkcję do zaktualizowanej biblioteki i wszystko wróci do normy.
    Pomogłem? Kup mi kawę.
  • REKLAMA
  • #10 17893425
    Konto nie istnieje
    Poziom 1  
  • #11 17893431
    LChucki
    Poziom 31  
    Posty: 1940
    Pomógł: 104
    Ocena: 379
    khoam napisał:
    kaczakat napisał:
    Ewentualnie jak już chcesz modyfikować używaną bibliotekę to lepiej od razu skopiuj funkcję i daj zmodyfikowanej swoją nazwę

    No to jest genialna porada. Zmiana nazwy jednej funkcji bibliotecznej pociągnie za sobą konieczność zmian w innych miejscach kodu, gdzie ta funkcja jest wywoływana, czyli jeszcze większy bałagan.

    A ja zgadzam się z @kaczakat. Wadą (wcześniej to była zaleta ale padli ofiarą swojego sukcesu) instaluje bibliotekę X a tych X jest kilkanaście, każda żyje "swoim życiem"! Nie ma standardu Arduino! X != X, takie realia!
  • #12 17893470
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    khoam napisał:
    No to jest genialna porada. Zmiana nazwy jednej funkcji bibliotecznej pociągnie za sobą konieczność zmian w innych miejscach kodu, gdzie ta funkcja jest wywoływana, czyli jeszcze większy bałagan.
    No ale ja właśnie odradzam (w przeciwieństwie do Ciebie) modyfikacje istniejących funkcji, tylko dodanie swojej - SKOPIOWANIE istniejącej i modyfikacje kopii ze swoją nazwą, potem używanie kopii ze swoja nazwą.
    Pomogłem? Kup mi kawę.
  • #13 17893494
    Konto nie istnieje
    Poziom 1  
  • #14 17895407
    Belialek
    Poziom 22  
    Posty: 977
    Pomógł: 19
    Ocena: 124
    Dzięki za pomoc - wieczorem powalczę, i na początek spróbuję z ta zmianą w BasicStepperDriver::nextAction()
  • #15 17897240
    Belialek
    Poziom 22  
    Posty: 977
    Pomógł: 19
    Ocena: 124
    Czy po zmianie w pliku BasicStepperDriver.cpp trzeba ten plik jakoś skompilować osobno, czy to wszystko robi sam kompilator Arduino?
  • #16 17897244
    Konto nie istnieje
    Poziom 1  

Podsumowanie tematu

✨ W dyskusji poruszono problem przerwania działania funkcji silnika krokowego w Arduino w odpowiedzi na naciśnięcie przycisku. Użytkownik zaproponował funkcję, która wykonuje 4*2592 kroki, ale nie wiedział, jak umożliwić przerwanie jej działania. Uczestnicy sugerowali różne podejścia, w tym użycie przerwań oraz modyfikację biblioteki obsługi silnika. Zasugerowano również implementację pętli FOR z kontrolą stanu przycisku, co mogłoby poprawić responsywność. Wskazano na możliwość modyfikacji funkcji nextAction() w bibliotece BasicStepperDriver, aby umożliwić natychmiastowe zatrzymanie silnika po wywołaniu disable(). Użytkownik planuje przetestować te zmiany oraz zapytał o konieczność ponownej kompilacji zmodyfikowanego pliku, na co uzyskał potwierdzenie, że kompilator Arduino zajmie się tym automatycznie.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA