Elektroda.pl
Elektroda.pl
X
PCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Zarządzalny sterownik silnika krokowego

18 Sty 2013 22:05 2772 15
  • Poziom 38  
    Witam.

    Jakiś czas temu dla pewnej osoby pisałem sterowanie silnikiem krokowym w C pod atmegę 8, mam prośbę -jeśli ktoś ma jakiś pomysł jak ulepszyć kod to proszę o propozycje.
    No i wiem, że program jest chaotycznie napisany, ale to tylko wynik pracy w wolnych chwilach, więc proszę o wyrozumiałość.

    Aha i wiem, że nie includuje się plików C, ale to puki co wersja prototypowa.


    Podstawowa sprawa to 2 pytania:
    -Jak najłatwiej zrealizować przejście co jeden krok (teraz mam minimum 4) i pamiętanie ostatniej pozycji?
    -W którym miejscu programu wrzucić sekcję od kręcenia silniczkiem, tak by dało się sterować podczas pracy nie przerywając jej?

    Pliki w załączniku, mam tylko prośbę o nie wykorzystywanie komercyjne, swoją drogą program jest zbyt słaby żeby go sprzedać, jednak prośba zostaje.


    Jeszcze raz, proszę tylko o konstruktywne rady, bo wiem że program wymaga jeszcze podstawowych poprawek, jednak mam nadzieję że dzięki udostępnieniu źródeł program będzie miał szansę na jakiś rozwój.
    Wiadomo że gdybym miał to robić zarobkowo, to musiałoby to inaczej wyglądać, natomiast robię to hobbystycznie i traktuję to jako naukę języka C.
  • PCBway
  • Poziom 43  
    Cytat:
    -Jak najłatwiej zrealizować przejście co jeden krok (teraz mam minimum 4) i pamiętanie ostatniej pozycji?
    Zdefiniować sobie zmienną określającą położenie silnika, z której będzie można w dowolnej chwili określić stan, który trzeba ustawić na portach. Jeśli robisz to żeby się uczyć to dlaczego co jeden krok, a nie np co 1/8, nawet na prostym hardware'rze da się zrobić stosując PWM, nawet programowy.(dokładność silników przy pracy mikrokrokowej nie jest powalająca, ale redukcja drgań bardzo skuteczna) Przydało zrobić automatyczne hamowanie i rozpędzanie czyli ciągłą zmianę prędkości podczas obracania wirnika (nie rozpędzisz silnika do maksymalnej prędkości w jednym kroku).

    Cytat:
    -W którym miejscu programu wrzucić sekcję od kręcenia silniczkiem, tak by dało się sterować podczas pracy nie przerywając jej?
    Użyć przerwań.

    Cytat:
    mam nadzieję że dzięki udostępnieniu źródeł program będzie miał szansę na jakiś rozwój.
    Musiał by być bardziej czytelny, oddzielając obsługę wyświetlacza i klawiatury, właściwy sterownik silnika to tylko 1/5 twojego programu ok 100 linii kodu, dokładniej fragment skopiowany 6 razy w różnych wersjach - w ramach nauki warto przemyśleć jak to skrócić, myślę że nie będzie trudno skrócić 6 krotnie ;), zamiast analizować jak to działa, zastanawiam się od którego if'a jest ten else - krótka ocena czytelności kodu.

    Wybrałeś zły dział forum, przez to programiści mikrokontrolerów twojego postu nawet nie oglądają.
  • Poziom 38  
    Powiem tak, dziękuję za odzew, no i jak wiadomo najwięcej programu to menu użytkownika, bo sam sterownik w moim wykonaniu to banał.


    Puki co zastanawiam się jak to najlepiej z przerwaniem rozwiązać, w tej chwili na przerwaniu przycisku mam "mini menu" do zmiany prędkości, ale nie jestem z tego rozwiązania zadowolony, wykombinowałem za to tak, by część sterująca siedziała w przerwaniu timera, a część użytkownika w głównej pętli, będzie tylko trzeba wykombinować jak będzie to wyglądać w praktyce.

    No i dziękuję za pomysł z zmienną od położenia, jak znajdę jakiś dłuższy kawałek wolnego czasu to będę kombinował z tym.
  • Poziom 38  
    Odświeżam.

    Zrobiłem już tak, że silnik pamięta pozycję i dzięki temu mogę sterować co krok, a nie co 4, jak w poprzedniej wersji, dorobiłem też funkcję delay2, bo zmienna w funkcji _delay_ms() zabierała dużo flasha.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zastanawiam się teraz jak przerobić kręcenie na timer, bo chciałbym żeby kręciło sobie na przerwaniu timera, a menu działało swoją drogą, wtedy nie mogę używać oczywiście funkcji delay.

    Coś tam kombinowałem, ale mi nie wyszło, no i stosując timer nie wiem jak zrobić regulację wypełnienia, w normalnym sterowaniu dodałbym pomiędzy pozycjami, jedną która ma wszystkie uzwojenia niezałączone i ustawiał czas przerwy proporcjonalnie do czasu impulsu (w menu byłoby wprowadzanie procentów), no ale chcę to zrobić na timerze i sprawa się komplikuje, bo tam delay-ów nie mogę dać.


    Co do timera, to 8 bitowy dzieli taktowanie przez 256, do tego można też ustawić preskaler, prawda czy coś źle doczytałem?

    8MHz/256=31.25KHz, czyli po osiągnięciu 31 przepełnień mam prawie 1ms, dobrze kombinuję?
  • Moderator na urlopie...
    Co do timera to na wejście podajesz sygnał podzielony przez prescaler, czyli: 1, 8, 64, 256 lub 1024. Potem możesz za pomocą trybu CTC osiągać dodatkowy podział przez wartość regulowaną z zakresu 1-256 dla wersji 8-bit lub 1-65536 dla 16-bit.
    A co do uruchomienia na timerze - wrzucasz ten kod do timera i wywalasz ręczne delaye - kod wykona się jednorazowo co przerwanie timera a czas między przerwaniami będzie odpowiadał opóźnieniu.
  • PCBway
  • Poziom 38  
    Okazało się, że źle ustawiłem wcześniej timer, na takim ustawieniu jak teraz, będzie choć trochę zgodne z prawdziwym czasem? (Wrzuciłem 12ms na razie do testu).
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Teraz jest podział przez 250 jeśli dobrze rozumuję?
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Specjalista - Mikrokontrolery
    1. Ustaw timer tak, by bez pomocy oprogramowania generował przerwania w stałych odstępach czasu.

    2. Użyj tablicy zamast instrukcji switch, która w każdym case robi to samo, tylko z inną wartością stałej. Switch zdecydowanie nie do tego służy.

    pozycja ++;
    pozycja &= 3;

    PORTC = tab[pozycja];
  • Poziom 38  
    W timerze miało być TCCR0|=(1<<CS00);, teraz timer działa ok.

    Puki co kombinuję dalej z samą obsługą silniczka (dzięki za powyższą radę, tablica to lepszy pomysł) i największą zagwozdką dla mnie jest wypełnienie.
  • Moderator na urlopie...
    1. Stosuj ISR() i nazwy wektorów przerwań z _VECT lub _VECTOR w nazwie - taka kosmetyczna drobnostka
    2. Nie stosuj do nastawiania częstotliwości trybu prostego, ale zastosuj tryb CTC. Wtedy podłączając / odłaczając zegar (lub lepiej blokując przerwanie) masz kontrolę nad praca silnika, a za pomocą rejestru OCR w trybie CTC będziesz mógł szybko i prosto regulować prędkość pracy.
  • Poziom 38  
    No dzięki za radę, bo na normalnym timerze jakoś ciężko było przechodzić w menu i mrugało też, taki timerek ustawiłem teraz:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Kod "kręcący":
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Coś tam jeszcze pewnie jest do poprawienia, ale cieszy mnie, to że już coś działa i to nie aż tak dziko jak w poprzednim programie, no i zajmuje 36,1% flasha, jak zrobię porządek, to powinno być jeszcze mniej.
  • Specjalista - Mikrokontrolery
    To jeszcze parę uwag nt. stylu:

    Po co używasz kodowania szesnastkowego przy zapisie wartości do timera? Żeby trudniej było zgadnąć, o jaką wartość chodzi? (Zresztą wartość jest o 1 za duża).

    If-then-else służy do zróżnicowania akcji. U Ciebie część akcji pod then jest taka sama, jak pod else - one powinny być wyłączone spod konstrukcji warunkowych.

    Zastosowanie maskowania (pokazałem wyżej) "pozycja &= 3" eliminuje konieczność badania wartości zmiennej pozycja i rozejścia warunkowego. Akcja te jest taka sama, niezależnie od tego, czy inkrementujesz, czy dekrementujesz tę zmienną, więC można to zrobić niezależnie od kierunku.
  • Poziom 38  
    Taki wynik podał mi kalkulator (nie chciało się przekształcać wzoru), więc wpisałem, ale widocznie będzie trzeba zweryfikować, skoro o 1 za duża.

    No to będzie trzeba if-y przerobić.

    Krótko mówiąc pozycja &= 3; dopuści tylko liczby z przedziału <0,3>?

    EDIT:

    Maska akurat działa bez problemu, ale mam inny problem, jeśli ustawię z poziomu przycisków czas 100ms lub większy, to silniczek dopiero po kilkudziesięciu sekundach startuje, jeśli natomiast wrzucę tą wartość od razu do programu, to działa normalnie (zmienna czasy).

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Coś nie tak? Jakoś nie potrafię odszukać źródła tego dziwnego problemu.

    EDIT:
    Zmieniłem zmienne volatile na volatile uint_8t, te które miały jakieś duże liczby dostały rozmiar większy niż 8bit i wygląda na to, że działa.
  • Poziom 38  
    Po czasie wracam z innym problemem, sterownik miał jeszcze mieć opcję ustawiania czasu trwania impulsu i przerwy po nim, udało mi się to zrealizować, ale zaniepokoiła mnie pewna rzecz.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Podczas kończenia poprzedniego kroku następny już chce się robić i dopiero potem następuje przerwa, także załączają się 2 uzwojenia w jednym czasie.
    Zarządzalny sterownik silnika krokowego
    Patrzyłem kilka razy na kod, ale jakoś nie umiem wypatrzeć czemu się tak dzieje, nawet gdy czas przerw po impulsie ustawię na 0 coś takiego się dzieje.
    Zarządzalny sterownik silnika krokowego
  • Specjalista - Mikrokontrolery
    Co prawda ani trochę nie rozumiem, co ma kod, który pokazałeś do przebiegów, które oglądasz. ale na wszelki wypadek zmień tryb pracy dwukanałowej w oscyloskopie z Alt na Chop. ;)
  • Poziom 38  
    Kod ma generować przerwę przed impulsem (bo przy wolnych obrotach silnik nie zniesie za długich impulsów), w tej chwili wygląda to tak, że najpierw pojawia się ten pik, potem przerwa i dopiero impuls, a ma być przerwa-->impuls. Prawdopodobnie pik następuje jednak po poprzednim impulsie, no ale denerwuje mnie to, że coś takiego się pojawia i raczej dobrze nie wpływa na pracę silnika (dodatkowe generowanie przepięć i w efekcie znaczne grzanie diod zabezpieczających).

    Oscyloskop niestety z karty dźwiękowej, ale na diodach LED również widać ten niepożądany efekt.
  • Poziom 38  
    Opcja przerwa/impuls przy długiej przerwie sprawia, że moment obrotowy jest dość słaby, ale wpadłem na inny pomysł, tzn w jednym ze schematów na forum CNC było coś podobnego, zaaplikowałem to do swojego schematu i teraz na każdym kroku da zmieniać się PWM, docelowo planuję jeszcze dołożyć hamowanie, które po prostu zmniejszy wypełnienie na postoju.
    Jak Wam się "widzi" takie coś?
    Zarządzalny sterownik silnika krokowego
    Mam już zaprojektowaną płytkę, teraz tylko dopieścić, poskładać i przerobić nieco program, dodam że na złącze 3pin wpina się po prostu potencjometr. Dobry pomysł, czy może raczej programowo też by się dało? Bo jeśli zrobienie tego w programie byłoby trudniejsze, to nic nie stoi na przeszkodzie, by te kilka zł do przeróbki dopłacić, tym bardziej że projekt PCB jest.