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

Atmega8 - Przerwania zewnętrzne

Legier 12 Lip 2013 15:56 2736 19
  • #1 12 Lip 2013 15:56
    Legier
    Poziom 11  

    Witam.
    Niedawno zacząłem przygodę z mikrokontrolerami AVR i utknąłem na przerwaniach zewnętrznych. Poczytałem trochę na temat tego jak poustawiać bity w rejestrach, ale gdy dochodzi co do czego to efekt jest zaskakujący.
    Podpiąłem do Atmegi8 enkoder oraz 3 LEDy. Gdy pokręcę enkoderem w jedną stronę jedna z diod ma zmienić swój stan, a gdy w drugą stronę to druga. Ostatnia pętla ma sprawdzać czy sygnał z enkodera nadal jest na pinie (sygnalizuje to miganiem trzeciej diody), aby przy wolno obracanym enkoderze przerwanie nie nastąpiło kilka razy dla tego samego impulsu.
    Problem jaki występuje to to, że bez względu na ustawienie stanu jaki ma wywołać przerwanie, występuje ono cały czas (dioda cały czas miga) nawet gdy od PD2 odłączę wszystko. Enkoder podłączam do Vcc (próbowałem też do PB1 ustawionego na wyjście/wejście ze stanem 1), do PD2 (wejście 0) i PB0 (wejście 0). Przerwania jako tak mi działały jedynie przy takim ustawieniu: PD2 (wyjście 1) PB0 (wejście 0) oraz GND. Proszę o pomoc bo nie mam już pomysłu jak to rozwiązać.
    Poniżej wklejam kod.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 19
  • Arrow Multisolution Day
  • #2 12 Lip 2013 16:00
    2091744
    Użytkownik usunął konto  
  • #3 12 Lip 2013 16:12
    dondu
    Moderator Mikrokontrolery Projektowanie

    1. Nie definiuj F_CPU w kodzie z tych powodów: http://mikrokontrolery.blogspot.com/2011/03/fcpu-gcc-gdzie-definiowac.html

    2. Dlaczego w tym przypadku:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    nie używasz zdefiniowanych nazw pinów, skoro używasz zdefiniowanych nazw bitów konfiguracyjnych? Brak konsekwencji przez co łatwiej popełnić błąd.

    3. Nie używaj starych funkcji przerwań tylko nowe ISR(): http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

    4. Nie stosuj funkcji opóźnienia w przerwaniach: http://mikrokontrolery.blogspot.com/2011/04/problemy-c-przerwania.html
    Rozumiem, że robisz to tylko dla testów eliminując drgania styków, a docelowy zrobisz bez nich w przerwaniach?

    5. Masz zewnętrzne rezystory pull-up? A może enkoder ma własne? Od tego trzeba zacząć, ponieważ nie włączasz pull-up'ów wewnętrznych. Prośba kaamil1984 o schemat jest więc jak najbardziej zasadna.

    EDIT:

    Dodatkowe pytania do pkt 4:
    Czy zastanowiłeś się, co się dzieje z flagą przerwania, gdy występują drgania styków, a mikrokontroler czeka w przerwaniu w funkcji delay?
    Jakie są tego konsekwencje po skończeniu wykonywania przerwania?

    0
  • #4 12 Lip 2013 17:04
    Legier
    Poziom 11  

    Wrzucam schemat.
    Funkcji delay użyłem tylko po to żeby mieć jakiś sygnał że program jest w tamtej pętli. Normalnie bym jej tam nie wrzucił.
    Nie dawałem pull-up'ów a enkoder nie ma własnych.
    Flagami jeszcze się nie zajmowałem. Na razie naukę przerwałem na przerwaniach, bo nie mogłem iść dalej przez nie.
    Co do punktu 2. to ledwo co się cokolwiek nauczyłem w programowaniu AVR'ów, więc mój kod jeszcze nie będzie na wysokim poziomie.
    Atmega8 - Przerwania zewnętrzne

    0
  • #5 12 Lip 2013 17:20
    dondu
    Moderator Mikrokontrolery Projektowanie

    No to już wiemy więcej:

    6. Nie podłączasz prawidłowo mikrokontrolera - zrób to dobrze zarówno filtrowanie zasilania, jak i podciągnij pin Reset:
    http://mikrokontrolery.blogspot.com/2011/04/minimalne-podlaczanie-pinow.html
    Tutaj dodam także uwagę, żebyś AREF nie zwierał z masą.

    Ad. 5 Nie podajesz co ta za typ enkodera, więc pytania dot. tego punktu nadal są aktualne.

    Ad 4. Nie odpowiedziałeś na pytania dodane do pkt 4 na końcu mojego poprzedniego postu.

    Ad 2 OK, w takim układzie przyglądnij się programom np. tutaj:
    http://mikrokontrolery.blogspot.com/2011/03/atmega8-pierwszy-program.html

    7. Z czego zasilasz ten układ?

    0
  • #7 12 Lip 2013 17:35
    dondu
    Moderator Mikrokontrolery Projektowanie

    Ad 5
    Ten enkoder nie ma w sobie rezystorów podciągających piny wyjściowe do Vcc. Należy więc zastosować albo zewnętrzne rezystory, albo włączyć wewnętrzne pull-up mikrokontrolera na wejściach do których podłączasz enkoder. To tak samo jak ze zwykłym przyciskiem. To jest najważniejsza przyczyna Twoich problemów na równi z Resetem. Dlaczego? Bo pin bez wymuszonej polaryzacji jest antenką:
    http://mikrokontrolery.blogspot.com/2011/04/zakocenia-w-pracy-mikrokontrolerow.html
    czyli zbiera zakłócenia co w przypadku pinu Reset kończy się ... sam domyślasz się czym.

    Poza tym musisz zmienić schemat. Pin wspólny enkodera podłącz nie do plusa tylko do masy.
    To powinienem był napisać w poprzednim poście :)

    Ad 4. Co wiesz na temat drgań styków?

    Zrób więc wszystkie poprawki dot filtracji, resetu i enkodera, i pokaż nowy schemat.

    0
  • Arrow Multisolution Day
  • #8 12 Lip 2013 18:10
    Legier
    Poziom 11  

    Wrzucam nowy schemat. Do resetu dałem rezystor tylko 3k, bo większego aktualnie nie mam, tak samo z kondensatorem. Załatwię to w najbliższym czasie. Zmiany w kodzie również zrobiłem i dziwne jest to, że ta dioda z pętli dalej cały czas miga, ale pozostałe reagują na ruchy enkodera. Co do drgań styków to wim, że w momencie przełączania czegoś to na granicy zmiany stanu następuje wiele krótkich przełączeń za nim stan się na nowo ustali. Może kiepsko to opisałem, ale wiem co to drgania styków.
    Atmega8 - Przerwania zewnętrzne

    0
  • #9 12 Lip 2013 18:20
    dondu
    Moderator Mikrokontrolery Projektowanie

    3kΩ może być za mało i możesz mieć problemy z programowaniem. Jeżeli więc wystąpią, to dodaj szeregowo taki, byś przekroczył 4,7k.

    Kondensatora nie widzę na nowym schemacie :)


    Legier napisał:
    Zmiany w kodzie również zrobiłem i dziwne jest to, że ta dioda z pętli dalej cały czas miga, ale pozostałe reagują na ruchy enkodera.

    To czemu od razu go nie pokazujesz?

    Legier napisał:
    Co do drgań styków to wim, że w momencie przełączania czegoś to na granicy zmiany stanu następuje wiele krótkich przełączeń za nim stan się na nowo ustali. Może kiepsko to opisałem, ale wiem co to drgania styków.

    Dobrze opisałeś i teraz należy się nad tym zastanowić jaki to ma wpływ na Twój aktualny program, ale musimy go najpierw zobaczyć.

    0
  • #10 12 Lip 2013 18:28
    Legier
    Poziom 11  

    Ok, dałem 5k. Kondensatora nie ma, bo go nie dałem, bo go nie mam (jeszcze).
    Dioda z pętli cały czas miga. Przy dowolnym obrocie enkodera jedna z pozostałych diod (zawsze ta sama) się zapali i zgaśnie, a druga zmienia swój stan, ale chyba bardziej w losowy sposób niż zależny ode mnie.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #12 12 Lip 2013 18:47
    Legier
    Poziom 11  

    Tak jest ok?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #13 12 Lip 2013 18:58
    dondu
    Moderator Mikrokontrolery Projektowanie

    OK, mam nadzieję, że zegar ustawiłeś w opcjach.

    Ponieważ muszę wyjść, to dam Ci wskazówki, a resztę wymyślisz sam lub koledzy pewnie podpowiedzą.

    Gdy pierwsze zbocze drgania styku ustawi flagę przerwania i mikrokontroler wejdzie w funkcję jego obsługi, to zaraz na początku automatycznie kasuje (w tym mikrokontrolerze) flagę przerwania.

    Ty w swoim programie w funkcji przerwania wykonujesz jakieś czynności (na razie nie istotne), a następnie czekasz w deley. W tym czasie styki drgają i ponownie włączają flagę przerwania.

    Po wyjściu z przerwania, następuje więc ... ponowne przerwanie, pomimo, że styki już nie drgają.


    EDIT:
    Pozostałe także popraw:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #14 12 Lip 2013 20:38
    Legier
    Poziom 11  

    Niby wiem,ale nie wiem co miałbym zrobić. Bo w momencie ruchu enkodera od razu jest zapalana flaga INTF0, więc natychmiast (prawie) przechodzimy do instrukcji przerwania, w której de fakto nie powieniem robić opóźnień oraz pętli, więc w funkcji przerwania nie zapobiegnę drganiom styków. Mogę jedynie wyzerować flagę przerwania jeśli drgania wystąpią gdy wykonywane są instrukcje. Tylko co jeśli drgania występują nadal, gdy już funkcja przerwania zakończyła swoją robotę?

    0
  • #15 12 Lip 2013 22:05
    BlueDraco
    Specjalista - Mikrokontrolery

    Kurczę, przez ponad 20 lat projektowania urządzeń z mikrokontrolerami nigdy nie zdarzyło mi się wpaść na tak dziwaczny pomysł, jak przerwanie od przycisku/styku/impulsatora służące do czegokolwiek innego niż obudzenie urządzenia z głębokiego uśpienia.

    Poczytaj coś o uczciwym ignorowaniu drgań styków przy użyciu przerwania timera, a potem zabieraj się za obsługę guzików i impulsatorów - w przerwaniu timera oczywiście.

    0
  • #16 12 Lip 2013 23:20
    piotrva
    Moderator na urlopie...

    Jak mówi przedmówca - przyciski + przerwania nadają się tylko do obudzenia procesora lub ewentualnie zasygnalizowania jakiejś krytycznej operacji związanej z klawiaturą (itp.). Drgania styków w takim układzie niestety mogą prowadzić do dosyć nieoczekiwanych i niechcianych efektów.

    0
  • #17 12 Lip 2013 23:30
    dondu
    Moderator Mikrokontrolery Projektowanie

    BlueDraco już nakierował Ciebie dość mocno, a ja chciałem byś sam do tego doszedł, i częściowo jesteś na dobrym tropie:

    Legier napisał:
    Bo w momencie ruchu enkodera od razu jest zapalana flaga INTF0, więc natychmiast (prawie) przechodzimy do instrukcji przerwania, w której de fakto nie powieniem robić opóźnień oraz pętli, więc w funkcji przerwania nie zapobiegnę drganiom styków. Mogę jedynie wyzerować flagę przerwania jeśli drgania wystąpią gdy wykonywane są instrukcje. Tylko co jeśli drgania występują nadal, gdy już funkcja przerwania zakończyła swoją robotę?

    Można oczywiście w przerwaniu czekać, ale trzeba być świadomym skutków i ograniczeń jakie to powoduje, a są one baaaardzo konkretne. Gdybyś tuż przed wyjściem z funkcji przerwania programowo gasił flagę przerwania, to drgania styków nie łapały by się w trakcie czekania w przerwaniu. Ty jednak tego nie robiłeś :)

    Można także opóźnienie od pierwszego przerwania liczyć za pomocą delay w pętli głównej, lub tak jak sugeruje BlueDraco przez timer, a przerwanie INT0 ewentualnie wykorzystać do jego wystartowania i zapamiętania aktualnego (w momencie przerwania) stanu pinów enkodera.

    Która opcja dla Ciebie jest lepsza zależy od Twojego projektu. Jeżeli więc jest to tylko w celu poznania przerwań zewnętrznych w oparciu o enkoder, to sugeruję ustawianie w przerwaniu tylko flagi, a resztę w pętli głównej. W następnym kroku edukacji wykorzystanie przerwania INT0 i timera, a następnie jeszcze inaczej, bez przerwania INT0 i tylko z timerem.

    EDIT.
    Ooo, i Piotr się dołączył :)

    0
  • #18 13 Lip 2013 19:38
    Legier
    Poziom 11  

    dondu:Coś tam obiło mi się o timerach, ale póki co tego jeszcze nie zgłębiałem i chciałem poznawać krok po kroku, bo mógłby mi się zrobić mętlik w głowie. Odnośnie ustawienia flagi w przerwaniu, to co jeśli wystąpi taka sytuacja: Po wyjściu z przerwania (flaga ustawiona na 1) drgania styków jeszcze nie ustały, a główny program jeszcze nie zdążył dojść do flagi, wtedy ponownie wskoczy mi w to przerwanie mimo ustawionej flagi. Ponadto widzę też inny problem. Mam enkoder i kręcąc w jedną stronę mam impulsy 1 - 3 - 2, a w drugą 2 - 3 - 1. Jeśli INT0 wykrywa impuls "1" to problem może być w przypadku gdy enkoder wysyła 2 - 3 - 1, pierwszy sygnał (2) zostanie zignorowany), 3 - wywoła przerwanie, ale będą drgania styków i co jeśli (wtedy mamy 2 styki) styki będą drgać różnie? Wtedy może się okazać, że uC wyłapie tylko jeden i niepoprawnie zareaguje.

    0
  • #19 13 Lip 2013 19:48
    BlueDraco
    Specjalista - Mikrokontrolery

    I dlatego właśnie zacznij od przerwania timera, np. coś ok. 100 Hz.

    0
  • #20 13 Lip 2013 19:53
    Legier
    Poziom 11  

    No, ok. Dzięki wielkie. Zamykam temat.

    0