logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[AVR] [C] - Jak obsłużyć przerwania INT0 i timer0 w atMega8?

PiAsKoS 11 Lis 2013 21:02 6300 60
Najlepsze odpowiedzi

Jak zrealizować wybudzanie z INT0 i odliczanie czasu w AVR tak, aby układ pobierał jak najmniej energii?

Nie rób „przerwania w przerwaniu” — przerwanie z INT0 ma tylko uruchomić licznik i wrócić do pętli głównej, a potem Timer zgłasza już własne przerwanie [#12941625] Jeśli chcesz oszczędzać energię, najlepsze jest użycie Timer2 w trybie asynchronicznym z kwarcem 32,768 kHz na TOSC1/TOSC2 i taktowanie ATmegi wewnętrznym 1 MHz [#12941754][#12942099] W takim układzie po zamknięciu drzwi mikrokontroler może spać w Power Down, a podczas odliczania i piszczenia przechodzić do Power Save, bo tylko ten tryb pozwala Timer2 wybudzać MCU [#12942099][#12970532] Power Down nie zadziała z Timer2 do wybudzania, więc jeśli licznik ma pracować podczas snu, trzeba użyć Power Save; INT0 w Power Down wybudza tylko jako niski poziom, nie zbocze [#12941754][#12971988] Jeśli czujnik daje sygnał odwrotny do wymaganego, trzeba odwrócić go sprzętowo, a nie programowo [#12964632] W praktyce użytkownikowi ostatecznie zadziałało dopiero po poprawieniu sprzętu: brakujących kondensatorach przy kwarcu i błędnym rezystorze pull-down [#12972605]
Wygenerowane przez model językowy.
REKLAMA
  • #1 12941598
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    uC zajmuje się hobbystyczne i moja wiedza jest dość ograniczona dlatego poszę o pomoc.

    Dłubie sobie powoli urządzenie które po otwarciu drzwi(czujnik magnetyczny) będzie odliczało daną ilość czasu w zależności od ustawionych dip-switchy i zacznie piszczeć.

    Problem pojawił się z przerwaniami.
    Mam przerwanie z INT0 od czujnika i przerwanie z timer0 z preskalerem do odliczania 0,5 s.

    Myślałem, żeby zrobić tak, że po wykryciu przerwania INT w nim odpala się timer0 i zaczyna liczyć, ale doczytałem, że nie można zrobić przerwania w przerwaniu.

    Bedę wdzięczny za wszelkie sugestie.


    Dodam jeszcze, że atMega8 taktowana jest kwarcem zegarkowym 32768Hz w celu zmniejszenia zużycia energii i zasilana jest bateryjnie.
  • REKLAMA
  • #2 12941625
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    MOżna zrobić jak to określiłeś "przerwania w przerwaniu" tylko należy na początku funkcji obsługi przerwania od INT0 włączyć przerwania globalne. Można do tego celu także wykorzystać ISR_NOBLOCK: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

    Jednak robi się to zupełnie inaczej niż myślisz. Przerwanie INT0 włącza timer i kończy swoje działanie wracając do pętli głównej. Timer odlicza czas i zgłasza swoje przerwanie.

    Ot i cała filozofia :)


    EDIT.
    Ponieważ dodałeś o kwarcu - nie ma to znaczenia.
    Co więcej pomiędzy przerwaniem INT0, a przerwaniem Timer0 możesz uśpić mikrokontroler do odpowiedniego trybu.
    Może pokaż schemat i program.
  • #3 12941696
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Jestem elektronikiem i jest to na tyle prosty układ, że obyło się bez schematu.
    Na ten czas wyglada to tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #4 12941754
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    OK - schemat zbędny :)

    Używasz trybu Power Down, ale w jego przypadku INT wybudza tylko za pomocą:

    Cytat:
    Only level interrupt INT1 and INT0.

    a Ty ustawiasz zbocze narastające.

    Przed pętlą główną powinieneś wykonać ustawienie timer0, ale bez jego włączania czyli preskaler " No clock source".

    Aby włączyć timer0 po wykryciu INT0 powinieneś w funkcji przerwania ISR(INT0_vect) włączyć preskaler, co powoduje start timera. W tym momencie powinieneś zmienić tryb usypiania na IDLE bo timer0 nie obudzi z Power Down, gdyż jest nieczynny w trakcie tego trybu.

    Tak naprawdę powinieneś wykorzystać Timer2 w trybie asynchronicznym z kwarc 32,768kHz na pinach TOSC1 i TOSC2, a mikrokontroler popędzać wewnętrznym 1MHz.
  • #5 12941792
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    dondu napisał:
    Tak naprawdę powinieneś wykorzystać Timer2 i kwarc 32768kHz a mikrokontroler popędzać wewnętrznym 1MHz.


    Ale w tym przypadku nie uda się tak zejść ze zużyciem energii.

    Póki co w ogóle mogę wyrzucić tryb uśpienia i zając sie tym na samym końcu.
  • REKLAMA
  • #6 12941808
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    PiAsKoS napisał:
    Póki co w ogóle mogę wyrzucić tryb uśpienia i zając sie tym na samym końcu.

    To błędna kolejność. W tego typu urządzeniach powinieneś zacząć od ustalenia jak oszczędzać energię, a dopiero później robić resztę. Innymi słowy najpierw bilans czasu pracy i snu, i na tej podstawie decyzja.

    Niestety nie wiem co robisz, więc trudno pisać konkretnie.
  • #7 12941834
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Ale wyjaśniłem co robie, jak potrzeba jeszcze jakiś informacji to śmiało pytać :)

    Założenie co do energii było takie, żeby jak najdłużej żyło na baterii.
    Przełączenie w tryb uśpienia gdy nic nie robi i wszystkie wiszące piny pull-up. Takie informacje znalazłem w sieci.
  • #8 12941851
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    Nie wyraziłem się ściśle :)

    Z Twojego postu nie jestem w stanie ocenić bilansów czasu uśpienia i pracy mikrokontrolera, a jak pisałem to istotne. Pobieżnie wydaje się, że on praktycznie śpi prawie 99,9% czasu. Jeżeli tak, to Timer2 + kwarc 32kHz + ATmega na wewnętrznym generatorze RC 1MHz to jest najlepsza opcja pod względem oszczędzania energii.


    EDIT. Jaki to mikrokontroler?
  • #9 12941973
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    PiAsKoS napisał:

    Dodam jeszcze, że atMega8 taktowana jest kwarcem zegarkowym 32768Hz w celu zmniejszenia zużycia energii i zasilana jest bateryjnie.
    :)
  • REKLAMA
  • #11 12941999
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Zasilanie bateryjne 3,6V - 5200mAh.
    Urządzenie będzie pracować 24h/dobe.

    Otwarcie drzwi nastepuje kilkdziesiąt/set razy dziennie.

    Elementy zuzywające energię ograniczone do minimum czyli atmega8 i w czasie wysterowania buzzera jeden tranzystor.
    Buzzer ma pobór ok 60mA.

    Nie wiem czy coś jeszcze potrzeba?

    Dodano po 1 [minuty]:

    ATmega 8A-PU :)
  • #12 12942015
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    Popraw jeśli źle myślę:
    - uC śpi obserwując INT0 które informuje o otwarciu drzwi,
    - gdy wykrywa otwarcie drzwi ma ustawić timer,
    - timer odlicza czas (jaki?) i piszczy przez czas (jaki?),
    - drzwi zostają zamknięte to wracamy do początku.

    Czy coś pominąłem?
    A co gdy drzwi zostaną zamknięte przed upływem czasu timera?
  • #13 12942058
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Dokładnie,
    1. Śpi i czeka na INT0
    2. Otwarcie drzwi wywołuje przerwanie i odpala timer
    3. Dip-switchami na płytce ustawiamy czas jaki ma czekać zanim zacznie piszczec (powiedzmy 5s, 10s, 20s, 30s i 60s) w zależności od potrzeby
    4. Piszy tak długo dopóki ktos nie zamknie drzwi
    5. Gdy ktoś zamknie drzwi przed upływem określonego czasu to usypia i nic sie nie dzieje.
  • Pomocny post
    #14 12942099
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    No to od razu bez szczegółowego liczenia powinieneś zrobić tak:

    dondu napisał:
    Tak naprawdę powinieneś wykorzystać Timer2 w trybie asynchronicznym z kwarc 32,768kHz na pinach TOSC1 i TOSC2, a mikrokontroler popędzać wewnętrznym 1MHz.

    Innymi słowy Twój mikrokontroler będzie prawie 100% czasu spał:
    - w czasie zamkniętych drzwi w trybie Power Down,
    - w czasie odliczania i czasu w trybie Power Save,
    - w czasie piszczenia - co najmniej Power Save.
    W ten sposób ograniczysz zużycie do minimum.

    Zastanów się także nad użyciem mikrokontrolera z literką V, które pracują nawet przy 1,8V np. ATmega48V zużywa 250μA przy 1MHz dla 1.8V, a kosztuje mniej niż ATmega8A. Być może jakiś ATtiny byłby jeszcze lepszy.
  • #15 12942135
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Przestawić fusy nie problem także wersja z 1MHz i 32kHz da rade :)
    Zwłaszcza że TOSC1 i 2 w atmedze mojej to te same piny co XTAL1 i 2.

    Ze względu na to, że mam już złozone 3 sztuki nie chce wprowadzać modyfikacji w układ.

    No to teraz od nowa wszystko. Cała wizja runeła ;)
  • REKLAMA
  • #17 12942147
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Atmega 48V byłaby fajna ale jest 2xdroższa. Nie byłby to problem ale jezeli to urzadenie uda mi się wykonać to będę musiał złożyć dla siebie więcej sztuk.

    Dodano po 31 [sekundy]:

    Jasne wszystko tylko zobaczymy jak z realizacja ;)
  • #18 12942153
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    PiAsKoS napisał:
    Atmega 48V byłaby fajna ale jest 2xdroższa.

    W TME kosztuje netto 4,16zł przy jednej sztuce, przy 5szt 3.67, a przy 25 szt zaledwie 3.19.

    PiAsKoS napisał:
    Jasne wszystko tylko zobaczymy jak z realizacja ;)

    W razie problemów pytaj w tym temacie :)
  • #19 12942181
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Dziękuje :)
    Od jutra działam z tematem także pewnie jeszcze tu wrócę ;)
  • #21 12963032
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Wracamy do walki :)

    Testowałem czy działa mi asynchroniczny tryb Timer2 i działa, buzzer pika co sekunde, ale przy takim kodzie jak poniżej nie włącza się pikanie w momencie przyjścia przerwania z INT0 tylko zaraz po wsadzeniu baterii.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dodano po 55 [minuty]:

    Ok, znalazłem zapis:

    
    When the asynchronous operation is selected, the 32.768kHZ Oscillator for Timer/Counter2
    is always running, except in Power-down and Standby modes.
    


    To jak zacząć liczyć gdy wystąpi przerwanie?
  • #22 12963496
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    PiAsKoS napisał:
    ... tylko zaraz po wsadzeniu baterii.


    Poniżej, leży bezpośrednia przyczyna takiego zachowania się uC.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    PiAsKoS napisał:
    To jak zacząć liczyć gdy wystąpi przerwanie?

    Uruchomienie oscylatora, nie jest tożsame z uruchomieniem licznika.

    Poza tym, w Twoim programie widać jeden wielki "chaos", co przekłada się na przypadkową kolejność konfiguracji poszczególnych rejestrów uC.

    PS
    A wszystkie Twoje kłopoty, wynikają pośrednio z
    ...
    PiAsKoS napisał:
    ...i moja wiedza jest dość ograniczona...
    :-P

    Poprawiłem, ponieważ autor tematu nie zna się na żartach :cry:
  • #23 12963597
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    Pozmieniałem i już działa, moje niedopatrzenie.

    Po co ten komentarz na końcu?
    Edit:

    zumek Nie chodzi o to że nie znam sie na żartach, przestałem w pewnym momencie korzystać z elektrody ponieważ zaczeły się robić takie akcje, że jak ktoś miał mniejszą wiedze z tematu to tylko po nim jechali i być może dlatego taka moja reakcja ;)


    Program działa tak jak chce, odlicza czas pika itd.
    Teraz kwestia usypiania i oszczedzania energii.

    Chciałem uzywać trybu POWER DOWN ale da się go wybudzić tylko stanem niskim na INT0 lub 1. Pod INT0 mam podpiety czujnik magnetyczny który gdy się rozwiera zdejmuje mase.

    Jakies pomysły jak wybudzac czujnikiem bez zakładania dodatkowych bramek logicznych?
  • #25 12964640
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    gdyby to był sygnał 0 i 1 to nie ma problemu bo jeden tranzystor wystarczy ale czujnik daje mase lub ją przerywa i tyle :|

    ---------------------------------------------------
    Aby nie kombinować z dokładaniem kolejnej elektroniki która sama z siebie także będzie zużywać energię padła decyzja, że będzie używany tryb IDLE ale procek zmienię za radą na np atMege48V :)

    ................
    Jeszcze jedna kwestia bo pojawił sie problem.

    Czujnik magnetyczny jest praktycznie cały czas zwarty do masy. po podłaczeniu amperomierza pokazuje że całośc zużywa w IDLE 40mA o.O

    Gdy go rozepnę jest 1,5mA. Da się jakoś tak skonfigurować pin PD2 (INT0) żeby nie było takiego zużycia?
  • #26 12966733
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    PiAsKoS napisał:
    Czujnik magnetyczny jest praktycznie cały czas zwarty do masy. po podłaczeniu amperomierza pokazuje że całośc zużywa w IDLE 40mA o.O

    Gdy go rozepnę jest 1,5mA. Da się jakoś tak skonfigurować pin PD2 (INT0) żeby nie było takiego zuzycia?

    Nie rozumiem, czego oczekujesz lub co masz na myśli. Z opisu wynika, że to czujnik jest odpowiedzialny za tak duży pobór prądu, a nie pin mikrokontrolera. Wyjaśnij dokładniej w czym rzecz.
  • #27 12966776
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    To jest pasywny czujnik magnetyczny. on mechanicznie zwiera mase i tyle. Przy tym jak jest zwarty czyli drzwi sa zamkniete żre 40mA i nie wiem jak temu zaradzic ;)
  • #29 12966787
    PiAsKoS
    Poziom 15  
    Posty: 223
    Pomógł: 3
    Ocena: 12
    to zwykły magnet chyba firmy Satel do systemów alarmowych. dwa kable i na koncu magnes.

Podsumowanie tematu

✨ Użytkownik pracuje nad urządzeniem opartym na mikrokontrolerze ATmega8, które ma odliczać czas po otwarciu drzwi, wykorzystując przerwania INT0 i timer0. Problemy pojawiły się przy obsłudze przerwań, ponieważ nie można zainicjować przerwania w przerwaniu. Użytkownik otrzymał sugestie dotyczące włączenia timer0 w procedurze obsługi przerwania INT0 oraz przejścia w tryb uśpienia, aby oszczędzać energię. W trakcie dyskusji poruszono również kwestie związane z różnymi trybami uśpienia (Power Down, Power Save) oraz ich wpływem na zużycie energii. Użytkownik zdecydował się na użycie ATmega48V dla lepszej efektywności energetycznej. Ostatecznie, po rozwiązaniu problemów z konfiguracją, urządzenie działa zgodnie z oczekiwaniami, a jego pobór prądu wynosi 300uA.
Wygenerowane przez model językowy.
REKLAMA