Skocz do zawartości

Jak w programie używać dokładnych enkoderów ?


klonyyy

Pomocna odpowiedź

Witam !

Ostatnio przesiadłem się z avr'ów na stm'y, żeby poznać ich możliwości, i zainteresował mnie tryb "enkodera" timerów mojego stm'a. Zdobyłem silnik z enkoderem 512 imp/obr i zastanawiam się jak wysterować taki silnik - jako że ma on jeszcze przekładnie na jeden obrót osi wyjścia przypada duża liczba impulsów - ok 1100. Zliczoną przez timer wartość odczytuję z rejestru, ale nie mam pojęcia jak to zamienić na dany ruch osi - czy zrobić to w pętli while ( while (timx->cnt<=y) jedź) czy jakoś inaczej ? Jak przy tak dokładnym enkoderze liczyć dłuższe dystanse ?

Może ktoś się juz bawił takimi enkodrami i jest w stanie powiedzieć kilka słów na temat sterowania?

pozdrawiam,
Piotrek

Link do komentarza
Share on other sites

Czym więcej impulsów na obrót tym prościej.

Optymalna metoda to dokładnie zmierzyć czas ostatniego impulsu (lub jak są niedokładności to uśrednić ostatnich kilku impulsów). W ten sposób znasz ostatnią prędkość. Krótkie przerwanie z kilkoma linijkami kodu wystarczy.

Inna metoda to mierzyć ilość impulsów przez jakiś czas (np 10 czy 100ms), ale tutaj masz problem przy wolnych prędkościach, bo różnica pomiedzy 4 impulsami w 10ms a 5 impulsami to już 25% i wynik będzie mocno skakał, a uśrednianie zbyt długich odcinków czasowych nie ma sensu, bo przy dużej prędkości za wolno dostajesz odpowiedź o zmianie szybkości silnika.

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

Dzięki za odpoweiedź !

Ok, ale jak już mam coś takiego, to żeby przełożyć to na dany ruch silnika musze stosować jakieś algorytmy, jak pid itp ? Chodzi mi o to że póki co to jest tylko taka kontrola, ale jak tą kontrolą wpłynąć na ruch silnika, o załóżmy dokładnie 2 obroty wału na wyjściu ?

Chętnie bym coś na ten temat poczytał ale nie mogę znaleźć jakiejś fajnej konkretniej publikacji.

pozdrawiam

Link do komentarza
Share on other sites

Docelowo przyda Ci się regulator PI lub PID. Implementacja zależy od tego, co chcesz uzyskać kontrolę prędkości czy ilości obrotów. Zacznij sobie od czegoś łatwego, z czasem sam zrozumiesz temat. Mam w planach artykuł na ten temat, ale ostatnio brakuje mi czasu...

Na początek zobacz jak silnik będzie się zachowywał przy prostym sterowaniu. Typu kręć do momentu, gdy wartość z enkoderów jest mniejsza od 2 obrotów wału, następnie hamowanie itd.

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

W sumie to zależy mi na kontroli prędkości, bo ostatecznie wykorzystam to prawdopodobnie w minisumo. Dobra zrobię tak jak mówisz - poczytam o pid'zie, pooglądam kody i spróbuję coś sam sklecić, a jak coś będę się pytał.

pozdrawiam

Aha jeszcze jedno

Na początek zobacz jak silnik będzie się zachowywał przy prostym sterowaniu. Typu kręć do momentu, gdy wartość z enkoderów jest mniejsza od 2 obrotów wału, następnie hamowanie itd.

Czyli coś takiego jak wczesniej pisałem w while'u ? tzn while(timx->cnt <=y)kręć a poza whilem dać stop ?

Link do komentarza
Share on other sites

Jak zależy Ci na kontroli prędkości, to lepiej zacznij inaczej. Generuj sobie przerwanie np.: SysTickiem, co kilka milisekund i sprawdzaj ile impulsów naliczył interfejs enkoderów. Staraj się napisać sam człon proporcjonalny, aby dążyć do pewnej zadanej prędkości niezależnie od obciążenia wału. Efekty powinny być wyczuwalne, gdy będziesz palcem próbował zatrzymywać ośkę.

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

Ooo o to mi chodziło - konkretna odpowiedź. Dzięki tak też zrobię i pokażę rezultaty.

Niestety ferie się kończą i kurcze coraz mniej czasu jest na dłubanie...

EDIT: Po przeczytaniu Twojej publikacji udało mi się napisać człon proporcjonalny - na pewno wymaga jeszcze dostrojenia i jest bardzo prymitywny, ale działa tak jak mówiłeś - gdy chcę zatrzymać silnik zaczyna on mocniej napierać 😉

Czyli teraz jak wszystko już będzie ładnie chodziło, to jak steruję silnikiem zadaję mu po prostu docelową prędkość ? A co jak chcę mu zadadać dany dystans ? Wtedy daję mu prędkość i czas ?

Link do komentarza
Share on other sites

1. Jak masz tylko człon proporcjonalny to lepiej najpierw przejdź na PD. To pozwala Tobie kontrolować poprawne dochodzenie do zadanej wartości (bez przesterowania lub z minimalnym, czego nie zrobisz z samym członem P - chyba, że strasznie wydłużysz czas dochodzenia do wartości).

2. Z fizyki prędkość * czas = droga... ok... ale tutaj silnik się rozpędza, potem zwalnia i niekoniecznie to się pokryje. Powinieneś mieć kolejny algorytm który to odpowiednio wysteruje. Na sam dystans w najprostszym wykonaniu wystarczy kolejny PID. Podajesz dystans (i ew. maksymalną prędkość) a on będzie zliczał impulsy i napierał tak długo aż nie zbliży się do celu i wtedy zacznie hamować.

Trudniej będzie jak jeszcze chcesz w to wmieszać czas, bo będziesz potrzebował kolejny regulator mierzący czas (i np. sterujący maksymalną prędkością), albo jeden dużo bardziej skomplikowany regulator.

Link do komentarza
Share on other sites

Dzięki za odpowiedź !

1. Ok poczytam trochę i spróbuję go dodać.

2. Ale jak sterować silnikiem na dystans, gdy przesunięcie o jeden stopień to pokaźna liczba implsów ? Jak ma być to większy dystans ( rozumiem wartość docelowa w pid) to chyba nie pomieści się to w zmiennych ?

Czasu ja nie chcę tutaj mieszać, chcę to zrobić najprostszym sposobem, ale zarazem spodsobem który daje całkiem dobre efekty.

Link do komentarza
Share on other sites

klonyyy, ja się nigdy nie bawiłem w sterowanie silnikiem wykorzystując enkodery, tym bardziej w algorytm PID i generalnie algorytmicznie nie czuję się zbyt pewnie, ale odnośnie drugiego problemu, to ja bym go rozwiązał dość prosto (przynajmniej tak mi się wydaje 😋 ). Rozbijaj wielkie liczby na wielokrotności dziesiątki i zapisuj je do tablicy o takiej strukturze: int odl[4] = {tysiące, setki, dziesiątki, jedności}. Do tego dodajesz drabinkę if'ów, aby po zliczeniu 10 jedności/dziesiątek/setek/tysięcy przechodził do następnej wielokrotności i gotowe. Cała ta operacja nie powinna być aż tak wymagająca, więc ja umieściłbym ją w obsłudze przerwania 🙂 Niech się wypowie, ktoś mocniejszy, bo moje rozwiązanie jest czysto teoretyczne 😋

Link do komentarza
Share on other sites

@piotreks-89 wlaśnei mi też to rozwiązanie z po prostu dużymi liczbami wydaje się prymitywne, no ale poczekamy na odpowiedź jakiegoś praktyka 😋

A ja mam jeszcze takie pytanie - co jeśli największa liczba impulsów na 10ms to 1200 a z kolei pwm mam w granicach 0-1500, to jak mam przełożyć ilość impulsów na wypełnienie ? Myślałem żeby stworzyć sobie zmienną która przyjmuje wartości od 0 do 100 (%) i liczyć sobie ile ma impulsów na ile możliwych i takim samym współczynnikiem wypełniać rejestry od timera pwm.

Link do komentarza
Share on other sites

klonyyy, te wartości nie musza być takie same. Ty powinieneś w tej chwili zadawać prędkość w impulsach na przykładowe 10ms. To regulator PID powinien dążyć do utrzymania tej prędkości - Ciebie nie powinno dużo interesować jakimi wartościami PWM on to uzyska.

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

Czyli teraz ustawiam sobie tylko współczynnik Kp i patrzę na to ile ma wartość impulsów przeczywista do docelowej ? Ogólnie Kp powinno być zmiennoprzecinkowe, czy bez tego da się osiągnąć wystarczjącą precyzję ?

Link do komentarza
Share on other sites

Masz dwie możliwości:

1. Liczby zmiennoprzecinkowe

2. Fixed-point math ( czyli liczby całkowite z "przecinkiem" gdzie np. 8 najniższych bitów to wartość po przecinku)

Generalnie algorytm oparty na liczbach całkowitych będzie szybszy.

Do tego pamiętaj, że masz typy typu long, czyli 32 bitowe... pozwala to na zrobienie wielu obliczeń. Ew. masz też long long itd...

Na początek prościej, chociaż wolniej, będzie używać float. Jak będziesz chciał to zoptymalizować to najwyżej pójdziesz w stronę fixed-point math

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.