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

[atmega8L][c] - Regulacja prędkości obrotowej silnika.

dawid.barracuda 13 Gru 2015 19:11 2544 37
  • #1 13 Gru 2015 19:11
    dawid.barracuda
    Poziom 13  

    Szanowni Forumowicze,
    mam problem z regulacją prędkości obrotowej silnika DC wyposażonego w enkoder za pomocą przerwań INT. Enkoder to czujnik Halla i odbiera impulsy z magnesu neodymowego na wale silnika (magnes 8-polowy). Prędkość kontroluję za pomocą generowanego PWM na atmedze podawanego na mostek L293DNE. Atmega pracuje na 1MHz, a licznik to Timer/Counter0 z preskalerem 1024, czyli czas między impulsami timera to ok. 1ms.
    Z pomocą oscyloskopu doświadczalnie sprawdziłem, że silnik powinien pracować z prędkością 4 zmian stanu enkodera / 240ms.
    Wg mnie algorytm powinien wyglądać tak:
    1) licznik kręci aż do przepełnienia i w tym czasie odbieram impulsy z enkodera za pomocą przerwania INT0;
    2) w momencie przepełnienia obsługuję przerwanie i reguluję zawartość OCR1B, czyli inaczej dostosowuję PWM:
    - jeśli było więcej niż 4 impulsy podczas kręcenia licznika tzn., że kręci się za szybko więc zmniejszam OCR1B;
    - jeśli było mniej niż 4 impulsy podczas kręcenia licznika tzn., że kręci się za wolno więc zwiększam OCR1B;
    - jeśli miałem dokładnie 4 impulsy podczas kręcenia licznika tzn., że mam to co chcę i zostawiam OCR1B bez zmian;
    3) na końcu obsługi przerwania od przepełnienia zeruję licznik impulsów z enkodera i procedura trwa od początku.

    Problem polega na tym, że co bym nie zrobił to OCR1B ustala się na 400 i nie ważne czy dam w kodzie 4 impulsy czy 10 impulsów to ciągle jest to samo.
    Oto kod do obsługi przerwań:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Ta regulacja jednak w ogóle nie działa i nie mam już pomysłów, siedzę nad tym dwa dni bez przerwy, a powyższy kod to i tak najlepsze co udało mi się osiągnąć... W poprzednich OCR1B ciągle leciał do 500, tutaj 'tylko' do 400...
    Gdzie robię błąd? Proszę uprzejmie o wskazówki i pozdrawiam.[/code]

    0 29
  • Pomocny post
    #2 13 Gru 2015 19:21
    BlueDraco
    Specjalista - Mikrokontrolery

    Po pierwsze, masz błędne założenia. Przy czterech impulsach na okres pomiarowy stabilizacja obrotów będzie miała dokładność rzędu 25% - ciut bez sensu.

    Po drugie, kolejne błędy masz zapewne w tych częściach kodu, których nie pokazałeś.

    0
  • #3 13 Gru 2015 19:36
    dawid.barracuda
    Poziom 13  

    Oto reszta kodu.
    Jak policzyłeś dokładność? Tzn. jak uzasadnić to, że dla 4 impulsów mam 25% dokładności? Rozumiem, że 4 impulsy to w sumie 100%, ale nie rozumiem źródła tej niepewności.

    Gwoli wyjaśnienia - kilku zmiennych nie używam, to pozostałości po starych kodach (wiem, że powinienem je skasować :) ) a przetwornik ADC jest po to, że uruchamiam odpowiednią akcję w zależności od napięcia podanego na pin PC5 - stan wysoki wyzwalam za pomocą pilota, którego wyjścia są podpięte pod odpowiednie węzły drabinki rezystorowej. 4 przyciski to i 4 węzły i w zależności od tego jak podzieli się napięcie uruchamiam odpowiednią akcję.

    Najchętniej wykorzystałbym regulator PI jednak nie potrafię go zaimplementować w kodzie.

    Jako, że to próby to na początku walczę tylko z jednym silnikiem dla jednego przycisku.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #4 13 Gru 2015 19:55
    2675900
    Użytkownik usunął konto  
  • Pomocny post
    #5 13 Gru 2015 20:08
    BlueDraco
    Specjalista - Mikrokontrolery

    Program działa prawidłowo - ustawia co chwila w pętli OCR na 400, bo tak został napisany.

    0
  • #6 13 Gru 2015 20:13
    dawid.barracuda
    Poziom 13  

    Próbowałem - stan wysoki powinien trwać 60ms czyli 60 impulsów timera. Efekt ten sam - program jakby nie zwracał uwagi na warunki jakie zadałem i OCR1B leci do tej samej wartości, zawsze za dużej.

    Dodano po 2 [minuty]:

    BlueDraco napisał:
    Program działa prawidłowo - ustawia co chwila w pętli OCR na 400, bo tak został napisany.


    Mówisz o pętli dla przycisku C? Bo dla przycisku A to wiem, że tak jest, na razie próbuję wyregulować tylko dla przycisku C czyli tam gdzie włączam timer.

    0
  • Pomocny post
    #7 13 Gru 2015 20:28
    BlueDraco
    Specjalista - Mikrokontrolery

    Przecież wartości obu OCR są wymuszane co chwila w pętli. Przerwanie timera zmienia je tylko na krótką chwilę, do przejścia przez pętlę.

    0
  • #8 13 Gru 2015 20:40
    dawid.barracuda
    Poziom 13  

    Początkowa wartość obu OCR to zero. Rozważmy tylko akcję dla przycisku C, czyli pierwszy blok intrukcji if. Skoro początkowo mam tam 0 i zaczynam dodawać do tego zera coraz więcej w przerwaniu to skąd nagle pojawia się tam 400?

    Dodano po 4 [minuty]:

    Piotrus_999 napisał:
    Mierz ilosc ticków timera pomiędzi imulsami z czujnika - bedzie dokładniej

    A jaki to silnik? szczotkowy czy bez - ile masz kabelkow do zasilania? Bo jak bez to tak trywialnie go nie wysterujesz.

    Ale kodu Twojego nie rozumiem.

    Nie wiem o co chodzi ze prawdzaniem warunków > lub < 500 dla OCR

    po co jest if w else bez zadnej instrukcji po nim?

    Silnik to Dagu DG01, jedna para przewodów.
    Warunki sprawdzam po to żeby w OCR nie było więcej niż 500 gdyż w rejestrze porównania ICR mam 500 i nie moge przekroczyc5tej wartości w OCR.

    O który fragment else if pytasz?

    0
  • Pomocny post
    #9 13 Gru 2015 20:44
    2675900
    Użytkownik usunął konto  
  • #10 13 Gru 2015 20:49
    dawid.barracuda
    Poziom 13  

    Ale przecież ustawia mi 400 tylko gdy ADC >= 190 && ADC < 260 , więc o co chodzi? :) a przerwania włączam dla przycisku C czyli gdy ADC >= 100 && ADC < 190. Jakim cudem więc dostaje się tu OCR z innego bloku instrukcji?

    0
  • Pomocny post
    #11 13 Gru 2015 20:58
    2675900
    Użytkownik usunął konto  
  • #12 13 Gru 2015 21:52
    dawid.barracuda
    Poziom 13  

    Za moment sprawdzę z diodami, ale zauważyłem pewną rzecz - wywaliłem na chwilę instrukcje dotyczące przycisków innych niż C więc zostawiłem tylko pierwszy blok instrukcji - tam gdzie włączam timer - oraz blok ostatni, gdzie zeruję wartości obu OCRów. Teraz z kolei nic się nie dzieje, na oscyloskopie na wyjściu OC1B widzę tylko piki co jakiś czas. Czyżby to ADC nie działał tak jakbym chciał?

    Dodano po 8 [minuty]:

    Teraz rzecz jeszcze ciekawsza - zostawiłem w pętli głównej tylko to:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    I przerwania te co wyżej. Teraz regulacja działa tak jak założyłem, OCR1B rośnie po naciśnięciu przycisku C i przestaje rosnąć gdy są 4 impulsy na okres licznika. Czy mam rozumieć, że zrobiłem źle zawierzając ślepo ADC? Dlaczego to nie działało tak jak mi się wydawało?

    Dodano po 20 [minuty]:

    Dodam jeszcze czemu wybrałem ADC do obsługi pilota - po prostu nie chciałem zapychać kilku portów skoro nie musiałem. Teraz mam wątpliwości co do tego... Czy lepiej zrobiłbym po prostu podłączając każde z wyjść pilota do portów atmegi pisząc kod do wykrywania stanów każdego portu?

    Dodano po 15 [minuty]:

    Spytam jeszcze - czy poprawne byłoby podejście: zatrzymania w jakiś sposób wykonywania pętli głównej programu (przerwania wykonywane normalnie) po wykryciu wciśnięcia przycisku po to aby te przerwaniela wyregulowały prędkość? Po puszczeniu przycisku puszczamy pętlę główną programu dalej. Czy tak jest poprawnie? Pytam bo jestem amatorem i chcę się tego poprawnie nauczyć :)

    0
  • #13 13 Gru 2015 23:51
    BlueDraco
    Specjalista - Mikrokontrolery

    Poprawnie to by było bez "pętli głównej" (a dokładnie - z pętlą zawierającą jedną instrukcję - uśpienia procesora), tylko z samym przerwaniem timera, w których rozpoznajesz i zmieniasz tryb pracy i regulujesz prędkość silnika.

    0
  • #14 14 Gru 2015 08:32
    dawid.barracuda
    Poziom 13  

    No rozumiem, ale dlaczego ADC nie działa tak jak założyłem?

    1
  • #15 14 Gru 2015 11:17
    BlueDraco
    Specjalista - Mikrokontrolery

    Pewnie dlatego, że dzaiłanie ADC, jak i dowolnego innego sprzętu, zależy nie od założeń, a od schematu (którego nie pokazałeś) i oprogramowania.

    0
  • #16 14 Gru 2015 16:38
    dawid.barracuda
    Poziom 13  

    Oto schematy:
    Podłączenie i zasilanie enkoderów:
    [atmega8L][c] - Regulacja prędkości obrotowej silnika.

    Podłączenie mostka H i silnika do niego + podłączenie go do mikroprocesora:
    [atmega8L][c] - Regulacja prędkości obrotowej silnika.

    Podłączenie odbiornika pilota na rezystorowy dzielnik napięcia i jego wyprowadzenie na ADC:
    [atmega8L][c] - Regulacja prędkości obrotowej silnika.

    Zasilanie całego układu:
    [atmega8L][c] - Regulacja prędkości obrotowej silnika.

    Mikroprocesor mam podłączony tak jak na schemacie ze strony mikrokontrolery.blogspot.com (podaję ze względu na źródło poniższego schematu):
    [atmega8L][c] - Regulacja prędkości obrotowej silnika.


    Dzielnik napięcia wydaje mi się prostą sprawą więc dlaczego ADC nie robi tego, co bym chciał?

    Dodano po 12 [minuty]:

    Dodam jeszcze, że do wyjść PWM z atmegi (PB1 i PB2) podłączyłem przed mostkiem H rezystory 330 kom. To samo zrobiłem z wyjściami OUT z enkoderów - do PD2 i PD3 też podłączyłem rezystory 330 kom. Zrobiłem tak, gdyż na oscyloskopie zauważyłem, że bez tych rezystorów sygnały są bardziej zaśmiecone. Zwiększenie rezsytorów do 1 Mom nie zmniejszało już zaśmiecenia sygnału.

    Do ADC używam pinu PC5.

    0
  • #17 14 Gru 2015 16:41
    2675900
    Użytkownik usunął konto  
  • #18 14 Gru 2015 16:47
    dawid.barracuda
    Poziom 13  

    330k po to, że bez niego na oscyloskopie widać, że jakieś śmieci latają :)
    Odnośnie stanów na pilocie - po to dałem diody żeby działało. Napięcie sprawdzałem i zgadzają się z tym co napisałeś. Nie ma tam właśnie stanu wysokiej impedancji jeśli port jest nieaktywny i wszystkie nieaktywne wyjścia są na potencjale masy bez żadnego oporu i bez diod potencjał spływał częściowo z powrotem do odbiornika, z diodami wszystko się zgadza (kosztem obniżenia 5V do 4.3V)

    Dodano po 1 [minuty]:

    A nie, przepraszam: na dzielniku mam rezystory po 10kom!

    0
  • #19 14 Gru 2015 16:52
    2675900
    Użytkownik usunął konto  
  • #20 14 Gru 2015 17:19
    dawid.barracuda
    Poziom 13  

    Czyli - patrząc po tym fragmencie DS - dobrze by było jakbym zmienił oporniki na ok. 2.5 kom? Do tego np. 50 pomiarów, wywalić kilkanaście skrajnych i obliczyć średnią środkowych?

    Dodano po 6 [minuty]:

    Czy może jednak w tym przypadku lepiej byłoby podpiąć każdy z portów odbiornika pod osobny pin atmegi?

    Dodano po 10 [minuty]:

    Odnośnie jeszcze samego sposobu regulacji - lepiej przejść na taki, w którym mierzę odległość między impulsami, tak?

    0
  • #21 14 Gru 2015 17:20
    2675900
    Użytkownik usunął konto  
  • #22 14 Gru 2015 17:33
    dawid.barracuda
    Poziom 13  

    W sumie się nie zastanawiałem nad tym, bo szczerze się przyznam, że nie wiem jaka to różnica poza tą, że napięcie pomiaru nie może przekroczyć napięcia odniesienia. Jeśli to może pomóc to mam w szufladzie wzorcowe źródło napięcia odniesienia 2.5V.

    0
  • #23 14 Gru 2015 17:50
    2675900
    Użytkownik usunął konto  
  • #24 14 Gru 2015 17:53
    dawid.barracuda
    Poziom 13  

    Piotrus_999 napisał:
    To jest taki pomiar co 4 bitów dokładnosci potrzebuje - daj mu czas (pomin z 8 pomiarów) i licz srednia z 4 to ci ustabilizuje odczyt.


    Jak mam rozumieć, że pomiar potrzebuje 4 bitów dokładności?

    0
  • #25 14 Gru 2015 20:15
    2675900
    Użytkownik usunął konto  
  • #26 14 Gru 2015 22:24
    dawid.barracuda
    Poziom 13  

    Gwoli formalności - rozumiem, że na dzielniku napięcia (Twoje 4 rezystory 50k ) nie musi być po 10k, może być więcej. Wazne, żeby do wejścia ADC z węzła nie wchodziło wiecej niż 10k, czy tak?

    Dodano po 37 [minuty]:

    Jeszcze pytanie - czy timer0 i timer2 mogą pracować jednoczesśnie i niezależnie względem siebie?

    0
  • #27 14 Gru 2015 23:32
    BlueDraco
    Specjalista - Mikrokontrolery

    A co mówi datasheet na temat zależności pomiędzy timerami 0 i 2?

    Cały dzielnik powinien mieć nie za dużą rezystancję. Jeśli ma więcej niż 10 k, to wypadałoby na wejściu ADC wrzucić kondensator 10..100n. Dodatkowy rezystor pomiędzy dzielnikiem i wejściem ADC kompletnie nie ma sensu - on wyłącznie psuje pomiar.

    0
  • #28 14 Gru 2015 23:53
    dawid.barracuda
    Poziom 13  

    Odnośnie rezystora na wejściu ADC to tak jak mówiłem - sugerowałem się śmieciami i jego odfiltrowaniem, ale skoro lepiej to obejść uśrednianiem pomiarów to tak zrobię.

    BlueDraco napisał:
    Jeśli ma więcej niż 10 k, to wypadałoby na wejściu ADC wrzucić kondensator 10..100n.


    Mówisz o kondensatorze pomiędzy węzłem wyjściowym dzielnika a wejściem ADC, czy tak? Jeśli tak, to jakie ma to uzasadnienie? Czy chodzi tu o prawa komutacji dla kondensatora, czyli, że napięcie na kondensatorze nie może zmienić się skokiem? Ma to za zadanie ustabilizować pomiar?

    No i na temat jednoczesnej pracy timer/counter 0/2 nic nie mogę znaleźć w DS.

    0
  • #29 15 Gru 2015 00:31
    2675900
    Użytkownik usunął konto  
  • #30 15 Gru 2015 00:33
    dawid.barracuda
    Poziom 13  

    Ok, rozumiem.
    Jeszcze pytanie - czy timer0 i timer2 mogą pracować jednoczesśnie i niezależnie względem siebie? W datasheet nic nie znalazłem na ten temat.

    0