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

[Atmega32] Program w C - dioda miga co 2s zamiast co 60s, dlaczego?

Komar91 26 Maj 2012 12:45 4081 32
REKLAMA
  • #1 10935465
    Komar91
    Poziom 18  
    Witam,
    Napisałem taki program według założeń miał on migać diodą co 1min. Układ pracuję na wewnętrznym oscylatorze i nie wiem co jest nie tak bo zamiast migać ci 60s miga co 2s. A oto kod.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Czym może to być spowodowane?
  • REKLAMA
  • #2 10935506
    opamp
    Użytkownik obserwowany
    Jak ustawiłeś częstotliwość kwarcu w programie (konfiguracji) ?
  • #3 10935507
    gaskoin
    Poziom 38  
    A jak wpiszesz opóźnienie 2 sekundy/1 sekundę to działa dobrze ?
  • REKLAMA
  • #4 10935530
    Komar91
    Poziom 18  
    W okienku frequency nic nie miałem wpisane ale jak wpisywałem zarówno 1MHz jak i 8MHz to nic nie dawało może inna częstotliwość. Jak ustawie opóźnienie 1s to działa poprawnie a jak opóźnienie 2s to jest tak 2,5s może to kwestia taktowania ale jaką podać i czy da radę na wewnętrznym kwarcie
  • REKLAMA
  • #5 10935555
    mirekk36
    Poziom 42  
    Nie uda ci się z tak dużą wartością opóźnienia jak 60 tys w Delay_ms .... będzie działało właśnie tylko do ok 2,5s (tzn w zależności od częstotliwości taktowania ten max czas może być różny - nie pamiętam teraz dokładnie tej zależności ale.....)

    musisz więc napisać jakąś własną funkcyjkę np:

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


    i wtedy będzie ci ładnie śmigać jak wpiszesz w kodzie

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 10935570
    Komar91
    Poziom 18  
    Mirekk36 a jaką dać częstotliwość taktowania bo dla twojej funkcji mi dioda miga co około 72s
  • REKLAMA
  • #7 10935630
    mickpr
    Poziom 39  
    Niedokładności, które otrzymujesz wynikają (najprawdopodobniej) z opóźnienia związanego z wywoływaniem funkcji i narzutu jaki zapewnia sama pętla while.

    Proponuję użyć timera - twoje rozwiązanie jest bardzo nieoptymalne.
  • Pomocny post
    #8 10935712
    mirekk36
    Poziom 42  
    Komar91 napisał:
    Mirekk36 a jaką dać częstotliwość taktowania bo dla twojej funkcji mi dioda miga co około 72s


    Najpierw sprawdź czy jak dasz _delay_ms(1000) to czy miga ci co sekundę - jeśli nie to napisz/powiedz/sprawdź czy masz dobrze przede wszystkim Fusebity ustawione ?

    Na pewno sama funkcja i while nie robi takiego narzutu żeby zamiast 60s było 72s ;) - jak już to raczej jak myślę coś z fuskami nie tak.

    Poza tym przy odmierzaniu tak długich czasów _delayem ;) zwróć uwagę na to co się jeszcze dzieje w programie - bo ten narzut może wprost wynikać z czasu wykonywania jakichś procedur przerwań jeśli je masz. A jeśli masz - to zapomnij o wykorzystaniu w taki sposób delya'a bo nigdy się nie uda dobrze tego zrobić - wtedy trzeba timer sprzętowy albo programowy zaprząc do roboty.
  • #9 10935727
    Komar91
    Poziom 18  
    I tak ta funkcja bardzo pomogła. Ja w ustawieniach fusebitów nic nie mieszałem. Cykl 5 mignięć z wyłączeniem trwa ok.12s a powinien 10s. fusebity są tak odczytane hFuse 99; IFuse E1; Mi to nic nie mówi ale Tobie coś może to powie. Dobrze by było gdyby to działało poprawnie i nic nie było trzeba by przeliczać przy dobieraniu przełączeń
  • #10 10935830
    mickpr
    Poziom 39  
    mirekk36 napisał:
    Na pewno sama funkcja i while nie robi takiego narzutu żeby zamiast 60s było 72s :wink: - jak już to raczej jak myślę coś z fuskami nie tak.

    Czy chodzi o kalibrację wewnętrznego oscylatora RC?
    A może jest inny powód - może słynne źle zdefiniowane "F_CPU"?
  • #11 10935867
    mirekk36
    Poziom 42  
    mickpr napisał:
    mirekk36 napisał:
    Na pewno sama funkcja i while nie robi takiego narzutu żeby zamiast 60s było 72s :wink: - jak już to raczej jak myślę coś z fuskami nie tak.


    Czy chodzi o kalibrację wewnętrznego oscylatora RC?

    A może jest inny powód - może słynne źle zdefiniowane "F_CPU"?


    Dwie cenne uwagi ;) .... (chociaż też wewn. oscylator nie mógłby być aż tak mocno rozkalibrowany - no chyba że autor zasilałby procka 3,3V a podejrzewam że działa na 5V

    do autora:

    Musisz ustawić w ustawieniach projektu - no właśnie tylko w czym piszesz program ?? czy przypadkiem nie w super kocim AVR Studio 5/6 ???

    Jeśli weźmiesz coś normalnego jak np: ECLIPSE a w najgorszym wypadku AVR Studio stare 4.xx to będziesz tam miał wyraźne pole do wpisania częstotliwości taktowania.

    Wartości fusów które podałeś oznaczają że działasz na fabrycznym ustawieniu - czyli wewn. oscylator 1MHz dlatego też taką wartość musisz wpisać w ustawieniach projektu - wiesz gdzie to zrobić w Eclipse ??? jak nie to daj znać podpowiem ;)
  • #12 10935887
    Komar91
    Poziom 18  
    Ja piszę w AVR studio4. Zasilanie z usb 5V. Mam taką zakładkę jak na zdjęciu poniżej i tam mam coś wpisać bądź zaznaczyć? [Atmega32] Program w C - dioda miga co 2s zamiast co 60s, dlaczego?

    Dodano po 17 [minuty]:

    Problem się chyba rozwiązał w polu frequency dałem 1000000 oraz w polu optimization dałem zamiast -O0 dałem -Os i teraz już jest prawie poprawnie ale to myślę kwestia kwarcu bo pewnie zaj bym dał zegarowy to by była dokładnie 60s a ja mam teraz 62s czyli 2s spóźnienia. Tragedii nie ma chyba że da się to poprawić jeszcze
  • #13 10936003
    mickpr
    Poziom 39  
    Komar91 napisał:
    dał zegarowy to by była dokładnie 60s a ja mam teraz 62s czyli 2s spóźnienia. Tragedii nie ma chyba że da się to poprawić jeszcze

    Skorygować ustawienia możesz (najlepiej) kalibrując wewnętrzny oscylator RC.
    Ewentualnie zmniejsz licznik pętli o 1, czy 2 i wstaw puste instrukcje
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    (dodatkowo) poza pętlą while.
  • #14 10936032
    25737
    Poziom 10  
    Jak się zajrzy do delay.h to w komentarzu pisze:

    /**
    \ingroup util_delay

    Perform a delay of \c __ms milliseconds, using _delay_loop_2().

    The macro F_CPU is supposed to be defined to a
    constant defining the CPU clock frequency (in Hertz).

    The maximal possible delay is 262.14 ms / F_CPU in MHz.

    When the user request delay which exceed the maximum possible one,
    _delay_ms() provides a decreased resolution functionality. In this
    mode _delay_ms() will work with a resolution of 1/10 ms, providing
    delays up to 6.5535 seconds (independent from CPU frequency). The
    user will not be informed about decreased resolution.
    */



    Dodatkowo chyba juz łatwiej odpalić jakiś Timer... Przecież to 3-4 linijki kodu więcej.
  • #15 10936092
    Komar91
    Poziom 18  
    Teraz to ma być proste urządzenie aby co określony czas załączało i wyłączało pompę. W przyszłości jak podszkolę się w C to ten sterownik będzie można podpiąć do pc za pomocą USB i zmieniać cykle w specjalnym programie. Ale to na razie plany które może kiedyś zrealizuje. :) Aktualnie dziękuje wszystkim za zaangażowanie i pomoc w rozwiązaniu problemu.
  • #16 10941328
    dondu
    Moderator na urlopie...
    25737 napisał:
    Jak się zajrzy do delay.h to w komentarzu pisze:
    Cytat:
    The macro F_CPU is supposed to be defined to a
    constant defining the CPU clock frequency (in Hertz).

    The maximal possible delay is 262.14 ms / F_CPU in MHz.

    When the user request delay which exceed the maximum possible one,
    _delay_ms() provides a decreased resolution functionality. In this
    mode _delay_ms() will work with a resolution of 1/10 ms, providing
    delays up to 6.5535 seconds (independent from CPU frequency). The
    user will not be informed about decreased resolution.

    Skoro już zacytowałeś, to doczytajmy dokładnie całość i wytłuśćmy:

    Cytat:
    When the user request delay which exceed the maximum possible one,
    _delay_ms() provides a decreased resolution functionality. In this
    mode _delay_ms() will work with a resolution of 1/10 ms, providing
    delays up to 6.5535 seconds
    (independent from CPU frequency).
  • #17 10941339
    Komar91
    Poziom 18  
    Czyli jak rozumiem niezależnie od częstotliwości taktowania wykorzystując funkcję _delay_ms() jest błąd rzędu 10%?
  • #18 10941362
    dondu
    Moderator na urlopie...
    Komar91 napisał:
    Czyli jak rozumiem niezależnie od częstotliwości taktowania wykorzystując funkcję _delay_ms() jest błąd rzędu 10%?

    1/10ms to rozdzielczość dla opóźnień większych od 262.14ms osiągana za pomocą funkcji _delay_ms() w delay.h.
    Ten tryb pozwala osiągnąć opóźnienie aż do nieco ponad 6,5s.

    Ponieważ pytasz o błąd, to przy okazji: Czas odmierzanie
  • #19 10941609
    Komar91
    Poziom 18  
    Czyli jak dobrze rozumiem to muszę dać kwarc zegarowy i obsłużyć to timerem aby odmierzał dokładnie 1s teraz dobrze rozumiem?
  • #20 10941621
    dondu
    Moderator na urlopie...
    Komar91 napisał:
    Czyli jak dobrze rozumiem to muszę dać kwarc zegarowy ...

    Nie, nie musisz. Wszystko zależy do czego ma służyć ten projekt i jak dokładnie ma odmierzać czas. Napisz coś więcej o docelowym projekcie.

    EDIT:
    nie doczytałem:
    Komar91 napisał:
    Teraz to ma być proste urządzenie aby co określony czas załączało i wyłączało pompę.

    Tak - zastosuj kwarc 32,768kHz i timer w trybie asynchronicznym + kalibrację programową. A mikrokontroler niech chodzi na wewnętrznym RC.
  • #21 10941633
    Komar91
    Poziom 18  
    Generalnie to projekt dla brata do badań do Doktoratu. W domu ma on taki włącznik czasowy mniej więcej taki
    [Atmega32] Program w C - dioda miga co 2s zamiast co 60s, dlaczego?.
    Lecz tam można włączać lub wyłączać co 15 min a on na razie potrzebuje zmieniać co 1min a później co inny okres czasu więc chciałem to zrobić na najmniejszym AVR i zmieniać czas programowo

    Dodano po 1 [minuty]:

    Co do dokładności to mówił że 2s opóźnienia nie robi mu różnicy ale jak by działało dokładnie to było by lepiej.
  • #23 10941672
    Komar91
    Poziom 18  
    Na razie 2s na minute ale to na funkcji _delay_ms() + funkcja jak napisał Mirekk. W weekend spróbuję zrobić tak jak pisałeś i zobaczę efekty.
  • Pomocny post
    #24 10941683
    dondu
    Moderator na urlopie...
    Komar91 napisał:
    na razie 2s na minute ... W weekend spróbuję zrobić tak jak pisałeś i zobaczę efekty.

    Wzoruj się na kodach z jakichś zegarków jest ich na forum sporo w dziale DIY.
    Na początek możesz zaglądnąć tutaj: LED sterowany przez Timer (przykład bez kwarcu 32,768kHz).
  • #25 10941703
    Komar91
    Poziom 18  
    Dziękuję ale i tak do pisania programu wrócę w piątek bo zbliża się sesja a w tym tygodniu 5 zaliczeń więc grafik napięty.
  • #26 11023333
    Komar91
    Poziom 18  
    Witam ponownie,

    Znajdując chwilę czasu chciałem trochę poprawić kod jaki napisałem, a w zasadzie napisać go od nowa. W obecnej chwili jestem wstanie odmierzyć dokładnie taki czas jaki jest mi potrzebny za pomocą timera. Lecz niestety pojawił się problem. Poniższy kod mruga diodą co określony czas tylko czas załączenia jak i wyłączenia są jednakowe a ja bym chciał zrobić tak że można je definiować oddzielnie niezależnie od siebie czyli np Tzal = 10s Twyl= 20s. Próbowałem to rozwiązać na różne sposoby ale każdy legł w gruzach. Proszę znowu o pomoc.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Pragnę dodać że F_CPU jest ustawiony na 1Mhz wewnętrzny wbudowany w AVR
  • #27 11023488
    mickpr
    Poziom 39  
    Traktuj cyknięcie Timer'a jako kwant czasu. Potem licz oddzielnymi licznikami (programowymi) te kwanty jako czas trwania i czas przerwy.
    Możesz w ten sposób zrobić, co dusza zapragnie.
    Przykładowo - gdy timer "cyka" co 1 sek. Możesz ustawić sobie, że masz 20 sekund (kwantów timera) czas trwania - potem (drugi licznik) 30 sekund (kwantów timera) czas przerwy. Po tych sekundach wracasz do pierwszego licznika.
  • #28 11023608
    Komar91
    Poziom 18  
    A czy mógł bym prosić o fragment kodu abym mógł to jakoś załapać bo nie wiem jak to za bardzo to napisać?
  • #30 11024130
    Komar91
    Poziom 18  
    dondu napisał:
    Komar91 napisał:
    A czy mógł bym prosić o fragment kodu abym mógł to jakoś załapać bo nie wiem jak to za bardzo to napisać?

    Dostałeś przecież ode mnie link, a w nim dokładnie opisany przykład:
    https://www.elektroda.pl/rtvforum/topic2303175.html#10941683


    Czytam to co jest tam napisane, analizuje i kombinuje na kodzie ale nie mam pojęcia jak za pomocą Timera zdefiniować dwa czasy. Dodatkowo próbuje uruchomić drugi timer ale i z tego nici. Czy mógłbyś mi to przedstawić bardziej klarownie jak za pomocą timera dać dwa oddzielne czasy na załączanie i wyłączanie?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA