Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 14 mar 2026, o 12:10


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 5 ] 
Autor Wiadomość
PostNapisane: 20 sty 2015, o 21:50 
Offline
Użytkownik

Dołączył(a): 18 paź 2012
Posty: 42
Pomógł: 0

W akcie desperacji zwracam się do Was z problemem, nad którym siedzę już dosyć długo.

Muszę zmierzyć prędkości obrotową obracającego się koła. Koło może obracać się w dwóch kierunkach. Jednocześnie muszę zmierzyć drogę, jaką pokonało - coś w stylu "jojo".
Całość zbudowana jest na Atmega32, kwarc 16000000, uart i parę innych bzdetów takich jak LCD 16x2. Do obsługi enkodera (rozdzielczość 1600 imp na obrót) wykorzystuje przerwanie INT0.

Obsługa enkodera:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


i to działa bez problemu - nie myli się nawet przy dużej prędkości koła.

Do odmierzania czasu wykorzystuję Timer1 (prescaler 64, i ICR1 = 249 tryb CTC). "Próbkuję" co 100ms - do takich założeń muszę się dostosować... (timer programowy z kodów Kolegi Mirka - kurcze jak prawie 90% innych kodów których używam).
Problem jest w monecie pomiaru prędkości obrotowej koła.
Niby proste - w przerwaniu enkodera inkrementujemy zmienną i resetujemy ja co 100ms, ale niestety nie jest tak słodko.
W momencie, w którym pojawia się przerwanie od enkodera, wstrzymywane jest przerwanie od Timera1 i wyniki sypia się...
Próbowałem kodów do obsługi enkodera z Forum i umieszczałem je w jednym przerwaniu "globalnym" (sprawdzałem stan enkodera nawet z częstotliwością ok 50kHz - wtedy uart poszedł w krzaki), ale niestety gubił kroki. Próbowałem też, liczyć czas, między jednym przerwaniem enkodera a drugim i też lipa. W kodzie nie ma ani jednego "delay..."

Czy jest jakiś inny sposób na obliczanie prędkości ew. obsługę w jednym przerwaniu?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 24 sty 2015, o 21:22 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

grzesiekk napisał(a):
Niby proste - w przerwaniu enkodera inkrementujemy zmienną i resetujemy ja co 100ms, ale niestety nie jest tak słodko.
W momencie, w którym pojawia się przerwanie od enkodera, wstrzymywane jest przerwanie od Timera1 i wyniki sypia się...

Ta zmienna powinna mieć specyfikator volatile, a tam, gdzie ją zerujesz, porównujesz w pętli głównej programu to należy ją otoczyć ATOMIC_BLOCK.

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 26 sty 2015, o 15:35 
Offline
Użytkownik

Dołączył(a): 18 paź 2012
Posty: 42
Pomógł: 0

Dziękuję za odzew. Czyli najlepiej użyć w tym wypadku, w przerwaniu - tam zeruję i wykonuję proste obliczenia, ATOMIC_BLOCK(ATOMIC_RESTORESTATE) i w nim umieścić te operacje? Dobrze rozumiem?


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 26 sty 2015, o 17:16 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

grzesiekk napisał(a):
Czyli najlepiej użyć w tym wypadku, w przerwaniu - tam zeruję i wykonuję proste obliczenia, ATOMIC_BLOCK(ATOMIC_RESTORESTATE) i w nim umieścić te operacje? Dobrze rozumiem?

W przerwaniu ta zmienna nie zostanie zmieniona przez inną funkcję przerwania. Tak jest domyślnie dla mikrokontrolerów AVR i kompilatora avr-gcc. Tutaj nie musisz tego wstawiać. Ten blok ATOMIC_BLOCK to chwilowe wyłączenie przerwań, a domyślnie jak procesor wykonuje operacje w przerwaniu to drugie przerwanie czeka w kolejce.

Myślę, że problemem w tym przypadku jest użycie liczb zmiennoprzecinkowych i działania na nich w przerwaniu. Takie obliczenia zajmują dużo czasu. Przerwania powinny trwać możliwie krótko. Jeśli tak nie jest to inne przerwanie (w tym przypadku od zmiany stanu INT1) musi czekać. Jeśli okaże się, że w czasie tych obliczeń przerwanie INT1 wystąpi 2 razy, ale nie może zostać obsłużone to jedna zmiana zostanie zgubiona, bo procesor po zakończeniu obsługi przerwania od timera2 ma informację, że jakaś część sprzętu coś chciała, ale nie wie ile razy. Spróbuj może tak to poprawić:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Autor postu otrzymał pochwałę

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 27 sty 2015, o 14:21 
Offline
Użytkownik

Dołączył(a): 18 paź 2012
Posty: 42
Pomógł: 0

Poprawiłem i zdecydowanie szybciej chodzi i mniej miejsca zajmuje. Nie wiem co mnie przyćmiło bo już kiedyś to robiłem. Niestety jest tylko trochę lepiej ale to juz najpewniej problem z mechaniką.
Dzięki wielkie za pomoc.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 5 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO