logo elektroda
logo elektroda
X
logo elektroda
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 6003 60
  • #1 12941598
    PiAsKoS
    Poziom 15  
    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.
  • #2 12941625
    dondu
    Moderator na urlopie...
    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  
    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
    Moderator na urlopie...
    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  
    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.
  • #6 12941808
    dondu
    Moderator na urlopie...
    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  
    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
    Moderator na urlopie...
    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  
    PiAsKoS napisał:

    Dodam jeszcze, że atMega8 taktowana jest kwarcem zegarkowym 32768Hz w celu zmniejszenia zużycia energii i zasilana jest bateryjnie.
    :)
  • #11 12941999
    PiAsKoS
    Poziom 15  
    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
    Moderator na urlopie...
    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  
    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
    Moderator na urlopie...
    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  
    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 ;)
  • #17 12942147
    PiAsKoS
    Poziom 15  
    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
    Moderator na urlopie...
    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  
    Dziękuje :)
    Od jutra działam z tematem także pewnie jeszcze tu wrócę ;)
  • #21 12963032
    PiAsKoS
    Poziom 15  
    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  
    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  
    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  
    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
    Moderator na urlopie...
    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  
    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  
    to zwykły magnet chyba firmy Satel do systemów alarmowych. dwa kable i na koncu magnes.
REKLAMA