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

[atmega8][c] Prosty miernik częstotliwości

PSow 01 Gru 2008 01:12 4368 3
  • #1 01 Gru 2008 01:12
    PSow
    Poziom 9  

    Witam, próbuję zrobić prosty miernik częstotliwości przy użyciu ATMega8 i jego wbudowanego komparatora analogowego. O ile pomiar dla sygnałów prostokątnych działa bez zarzutu, to już dla sinusoidy pokazuje bzdury - np. dla sinusa 110 Hz, wychodzi 3,5 kHz i nie mogę rozgryźć dlaczego tak jest.

    W swoim testowym obwodzie, sinusoidę generuję za pomocą PWM, innym ATMega8. Jeden okres składa się tylko z 64 próbek, ale obwód RC bardzo ładnie wszystko wygładza (zaobserwowane na oscyloskopie). Sądziłem, że mogę rozwiązać problem zmieniając sinusoidę na sygnał prostokątny i tym samym doszedłem do poniższego układu (wiem, tranzystor może nie najbardziej sensowny do zadania, ale taki miałem pod ręką - zamierzam go później wymienić). Bramkę dodałem żeby zmniejszyć czas narastania (być może potem nie będzie potrzebna?) i mieć absolutną pewność co do poziomów napięcia, za nią sygnał jest przyzwoitym prostokątem (również zaobserwowane na oscyloskopie), niestety efekt jest identyczny, jak przy pomiarze częstotliwości zaraz za obwodem RC. Dodam, że to co na schemacie zaznaczyłem jako 2V podłączone do AIN1, to w rzeczywistości potencjometr. Przy jego pomocy sprawdziłem działanie układu przy różnych napięciach z przedziału 0-5V na AIN1 i generalnie jakie by ono nie było, nie widać poprawy.

    Co do kodu, próbowałem również wariant z przerwaniem zewnętrznym zamiast użycia komparatora analogowego - efekt ten sam.

    Czy ktoś ma jakiś pomysł i mógłby mnie naprowadzić na właściwy trop?

    Kod miernika:

    Code:
    #define F_CPU 4000000L
    

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "lcd.c"

    volatile char bufor[10];
    volatile uint16_t liczba=0;

    ISR(ANA_COMP_vect)
    {
       liczba++;
    }

    ISR(TIMER1_COMPA_vect)
    {
       lcd_clrscr();
       lcd_gotoxy(0, 0);
       itoa(liczba,bufor,10);
       lcd_puts(bufor);
       lcd_puts(" Hz");
       liczba = 0;
    }

    int main()
    {
       ACSR = _BV(ACIE)|_BV(ACIS1)|_BV(ACIS0);    // komparator: włącza przerwania przy narastających zboczach
       
       OCR1A = 15625;
       TCCR1B = _BV(CS12)|_BV(WGM12);;
       TIMSK |= _BV(OCIE1A);                   // timer1: tryb CTC, odmierza dokładnie 1sec i generuje przerwanie
       
       lcd_init(LCD_DISP_ON);
       
       sei();
       
       for(;;);
       return 0;
    }


    Układ testowy:
    [atmega8][c] Prosty miernik częstotliwości

    0 3
  • #2 01 Gru 2008 07:06
    snow
    Poziom 28  

    Nie lepiej podpiąć się pod wejście INT i zliczać impulsy? Timerem zrób sobie podstawę czasu a później wylicz z tego częstotliwość na podstawie liczby zliczonych impulsów w czasie.

    0
  • Pomocny post
    #3 01 Gru 2008 08:43
    rfhzcx
    Poziom 13  

    Przede wszystkim zastosuj bramkę z wejściem Shmidta - np. 74132. Tu prawdopodobnie tkwi problem w pojawianiu się oscylacji przy sygnale sinusoidalnym.
    AK

    0
  • #4 01 Gru 2008 11:13
    PSow
    Poziom 9  

    Snow, napisałem, że próbowałem też z przerwaniem zewnętrznym - dokładniej zostawiłem wewn. komparator w spokoju i wyjście z bramki AND ze schematu podłączyłem pod INT0. W kodzie wyglądało to tak:

    Code:
    ISR(INT0_vect)
    
    {
       liczba++;
    }

    ISR(TIMER1_COMPA_vect)
    {
       // tak samo jak poprzednio
    }

    int main()
    {
       DDRD &= ~_BV(2);                          // INT0 - input
       GICR = _BV(INT0);                         // włączenie przerwania
       MCUCR = _BV(ISC01)|_BV(ISC00);      // reaguje na narastające zbocze
       
       // reszta tak samo jak poprzednio
    }

    Ogółem wiem też, że można to zrobić znacznie dokładniej, m.in. zliczać wyłącznie całe okresy sygnału. Porządnym przepisaniem kodu zajmę się później, na razie próbuję zrozumieć dlaczego to, co jest działa dla sygnałów prostokątnych, a dla sinusoidalnych już nie.

    Rfhzcx, świetny pomysł, wart zastosowania w ostatecznej wersji. Niestety nie mam w tym momencie niczego z przerzutnikiem Schmitta, żeby sprawdzić. Sprawdziłem za to coś innego - testowo wrzuciłem za bramką ze schematu (równolegle do masy) kondensator (próbowałem z coraz większymi pojemnościami) i przy 6,6uF wynik jest już bardzo bliski dobrego (~120Hz), ale dalej nie jest zbyt stabilny (+/- 15Hz). Nie mniej jednak, chyba udało się potwierdzić, że przyczyną są oscylacje - spróbuje z przerzutnikiem Schmitta zamiast tego kondensatora.

    0
  Szukaj w 5mln produktów