eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaAVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu › Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie kodu
  • Path: news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed2.atman.pl!newsfeed.atman.pl!ne
    wsfeed.neostrada.pl!unt-exc-02.news.neostrada.pl!unt-spo-a-02.news.neostrada.pl
    !news.neostrada.pl.POSTED!not-for-mail
    From: "Robbo" <y...@m...com>
    Newsgroups: pl.misc.elektronika
    References: <4d528e6b$0$2436$65785112@news.neostrada.pl>
    <4d52df8e$0$2452$65785112@news.neostrada.pl>
    <4d53ffa7$0$2504$65785112@news.neostrada.pl>
    <4d540151$0$2457$65785112@news.neostrada.pl>
    <4d5403d7$0$2459$65785112@news.neostrada.pl>
    <4d540849$0$2439$65785112@news.neostrada.pl>
    <4d542b3c$0$2443$65785112@news.neostrada.pl>
    <4d5434ea$0$2455$65785112@news.neostrada.pl>
    Subject: Re: AVR ATmega, pomiar częstotliwości przebiegu, prośba o sprawdzenie
    kodu
    Date: Thu, 10 Feb 2011 21:56:55 +0100
    MIME-Version: 1.0
    Content-Type: text/plain; format=flowed; charset="iso-8859-2"; reply-type=response
    Content-Transfer-Encoding: 8bit
    X-Priority: 3
    X-MSMail-Priority: Normal
    X-Newsreader: Microsoft Outlook Express 6.00.2900.5512
    X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5512
    X-Antivirus: avast! (VPS 110210-0, 2011-02-10), Outbound message
    X-Antivirus-Status: Clean
    Lines: 148
    Message-ID: <4d54511b$0$2440$65785112@news.neostrada.pl>
    Organization: Telekomunikacja Polska
    NNTP-Posting-Host: 83.24.142.160
    X-Trace: 1297371419 unt-rea-b-01.news.neostrada.pl 2440 83.24.142.160:1435
    X-Complaints-To: a...@n...neostrada.pl
    Xref: news-archive.icm.edu.pl pl.misc.elektronika:604629
    [ ukryj nagłówki ]

    Dziękuję bardzo za ten kod. Przykład z wykorzystaniem union oraz struct
    również bardzo cenny!

    Twój kod, tak na szybko, bez union i struct (chodzi o samą ideę):

    SIGNAL (SIG_INPUT_CAPTURE3)
    {
    icr = ICR3;

    if (ETIFR & _BV(TOV3)) {
    overflow++;
    ETIFR |= _BV(TOV3);
    ff++; // licznik zdarzeń tego typu
    }

    actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
    pp = (unsigned long)icr + overflow * 65536UL;
    }

    SIGNAL (SIG_OVERFLOW3)
    {
    overflow++;
    }

    Wyświetlam sobie na LCD wartość ff. Na ogół ma wartość "1" i tak już
    zostaje. Wynika z tego, że bardzo rzadko mam sytuację z jednoczesnymi
    przerwaniami.

    Wydaje mi się, że możliwe jest jeszcze pewne uproszczenie -- w praktyce mi
    ono zdaje egzamin (a przynajmniej tak mi się wydaje na podstawie
    obserwacji). Chodzi o to, że u Ciebie "overflow" inkrementowany jest
    nieustannie. To nie jest błąd -- wszystko działa jak należy. Niemniej ja
    chciałem mieć "overflow" zerowany, gdyż zależnie od jego wartości chciałem
    zrobić odcinanie niskich częstotliwości mierzonego sygnału. Oto przeróbka:

    *** KROK 1

    SIGNAL (SIG_INPUT_CAPTURE3)
    {
    icr = ICR3;

    if (ETIFR & _BV(TOV3)) {
    overflow++;
    ETIFR |= _BV(TOV3);
    }

    actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
    pp = (unsigned long)icr + overflow * 65536UL;

    pp -= overflow * 65536UL;
    overflow = 0;
    }

    powyższe można uprościć do takiej postaci:

    *** KROK 2

    SIGNAL (SIG_INPUT_CAPTURE3)
    {
    icr = ICR3;

    if (ETIFR & _BV(TOV3)) {
    overflow++;
    ETIFR |= _BV(TOV3);
    }

    actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
    pp = (unsigned long)icr;

    overflow = 0;
    }

    Zatem wydaje mi się (może się mylę, ale w praktyce działa i wygląda OK), że
    w "pp" nie musimy trzymać wartości licznika software'owego, a wystarczy
    trzymać ICR.
    Co o tym myślisz?

    A oto kompletny kod -- odcinamy poniżej ok. 2Hz (w szczególności, gdy sygnał
    w ogóle jest zerowy).

    SIGNAL (SIG_INPUT_CAPTURE3)
    {
    icr = ICR3;

    if (ETIFR & _BV(TOV3)) {
    overflow++;
    ETIFR |= _BV(TOV3);
    }

    actualDuration = ((unsigned long)icr + overflow * 65536UL) - pp;
    pp = (unsigned long)icr;

    overflow = 0;
    }

    SIGNAL (SIG_OVERFLOW3)
    {
    overflow++;
    }

    int main(void)
    {
    char buf[16];
    unsigned long actualDurationLatch;

    TCCR3A = 0;
    TCCR3B |= _BV(ICES3) | _BV(ICNC3) |
    _BV(CS32) | _BV(30); // prescaler 64
    ETIMSK |= _BV(TICIE3) | _BV(TOIE3);

    sei();

    while (1) {
    cli();
    actualDurationLatch = actualDuration;
    sei();

    if ((overflow >= 5) || (actualDurationLatch > 150000)) {
    LCDwriteString("-------------");
    } else {
    sprintf(s, "%ld ", actualDurationLatch);
    LCDwriteString(s);
    }
    }
    }


    W moim pierwotnym liście podałem kod z wykorzystaniem SIG_OUTPUT_COMPARE2
    oraz SIG_INTERRUPT7. Kod tamten miał (w porównaniu do tego z wykorzystaniem
    input capture) tę wadę, że zwiększanie zmiennej "timer" 100000 razy na
    sekundę obciążąło procesor. Niemniej miał on też pewną zaletę -- chodzi o
    to, że dla niskich częstotliwości "odcinanie" miałem zawsze w określonym
    czasie (np. gdy timer osiągnął wartość 100000; timer był resetowany po
    każdym zboczu narastającym -- zatem wartość 100000 mówiła, że minęło 100000
    ticków zegara od ostatniego zbocza narastającego sygnału mierzonego). Tu
    (chodzi o kod z input capture) niestety jest problem. Gdy sygnał zaniknie
    nagle, to "overflow" musi doliczyć do 5 (taką wartość sobie przyjąłem), ale
    przecież ICR może mieć różną wartość i czas, w którym "overflow" doliczy do
    5 może być różny (gdy ICR było bliskie 0, to będzie to czas prawie pięciu
    przepełnień ICR; gdy ICR było prawie 65000, to będzie to czas nieco ponad
    czterech przepełnień ICR). Aby mieć dokładne odcinanie (po upływie dokładnie
    określonego czasu), musiałbym zrobić dodatkowy timer (np. dający impuls co 1
    sekundę), resetowany w SIG_INPUT_CAPTURE3. Jeśli timer da impuls (czyli nie
    został zresetowany w ciągu ostatniej sekundy), to znaczy, że sygnał jest
    poniżej 1Hz i robimy odcinanie.

    R.

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: