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

pomiar częstotliwości atmega16

bubu2606 22 Gru 2011 12:43 4589 38
REKLAMA
  • #1 10291313
    bubu2606
    Poziom 15  
    Witam:) mam pytanie do forumowiczów w sprawie pomiaru częstotliwości, sprawa przedstawia się następująco:
    chciałbym zrealizować pomiar częstotliwości przy użyciu timera0 (zliczanie impulsów) oraz ustalić czas bramkowania na 1s za pomocą timera1, problem w tym, ze uzyskany wynik strasznie skacze mi po częstotliwościach ;/ i nie wiem jak sobie z tym poradzic.. czy ktoś realizował już podobny projekt i jest chętny podzielić się swoimi spostrzeżeniami i doradzić w jaki sposób należy to wykonac??

    wiem ze należy postąpić w poniższy sposób:
    1. zatrzymanie zliczania impulsow z T0
    2. zatrzymanie odmierzania czasu bramkowania T1
    3. przepisanie zliczonych impulsów do rejestru głównego
    4. wyzerowanie rejestrow zliczania z T0
    5. wznowienie zliczania impulsów z T0
    6. wznowienie odmierzania czasu bramkowania

    Dodano po 35 [minuty]:

    dysponuję następującym programem
    Kod: text
    Zaloguj się, aby zobaczyć kod
    [/code][/quote]
  • REKLAMA
  • Pomocny post
    #2 10292201
    janbernat
    Poziom 38  
    Masz chyba jakiś błąd w założeniach.
    Przy takich ustawieniach licznik będzie liczył zdarzenia- to jest external clock source.
    Zdarzenia- a nie częstotliwość.
    Gdy liczba tych zdarzeń osiągnie wartość wpisaną w OCR1A to wystąpi przewanie.
    To jest tryb dobry do liczenia przedmiotów z jakiejś fotokomórki.
    Żeby wiedzieć ile sztuk wpadło do pudełka i podstawić następne.
    Nie ma w tym żadnego czasu bramkowania.
  • #3 10292969
    SylwekK
    Poziom 32  
    Nie wiem czy kod w Bascom na coś Ci się przyda ale właśnie na takiej zasadzie jak w tym programie zrobiony mam pomiar prędkości wiatru w moim pozycjonerze. Troszkę inaczej wykorzystuję tu timery niż założyłeś ale... Zostawiłem Ci tylko fragment odpowiedzialny za liczenie impulsów i dodałem obsługę wyświetlacza. Program jest na tyle prosty, że z interpretacją nie będziesz miał problemów. Może Ci się to przyda. Jest to w sumie miernik stosunkowo niskich częstotliwości. Wykorzystuje tam jeszcze małe opóźnienie 2ms dla eliminacji drgań, które można spokojnie wywalić z programu. Liczone jest zbocze opadające i co 1s podawany wynik. W moim projekcie działa idealnie. Program ma tą zaletę, że możesz wybrać dowolny port jako wejście taktujące. Pozdrawiam.


    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #4 10293321
    bubu2606
    Poziom 15  
    no własnie chodzi mi o zliczanie impulsów za pomocą odbiornika IR i zamianę ich na częstotliwość, czy da się to zrobić w sposób inny niż jest w tym moim programie?? i w jaki sposób mogę zrealizować swoje ząłożenia zeby pomiar był dokładny??
  • Pomocny post
    #5 10294239
    Konto nie istnieje
    Poziom 1  
  • #6 10294356
    bubu2606
    Poziom 15  
    jeżeli zrobię tak jak powiedział emarcus to wynik będzie skakał po częstotliwości
    obecnie w przerwaniu od przepełnienia

    ISR(TIMER1_COMPA_vect)
    {
    TCCR0=0;//zatrzymanie licznika T0
    zmienna=licznik;
    licznik=0;
    tcnt=TCNT0;
    TCNT0=0; //zerowanie rejestru
    TCCR0 |=(1<<CS00)|(1<<CS01)|(1<<CS02); //ponowny start zliczania timera
    }
    co znacznie poprawiło mi działanie licznika
    jednakże dla częstotliwości np 488 Hz mam wynik 485/4 Hz, dla 3903 Hz mam wynik 3886 Hz więc gdzieś jeszcze mogę to poprawić żeby uzyskać lepszy wynik z mniejszym błędem i dokładnością do 1 Hz
  • #7 10294965
    Konto nie istnieje
    Poziom 1  
  • #8 10295001
    bubu2606
    Poziom 15  
    nie bardzo rozumiem:/
  • #9 10298120
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #10 10299474
    bubu2606
    Poziom 15  
    nie bardzo rozumiem jak z tą flagą sobie poradzić (o jaką flagę chodzi??):/ czy mógłbyś podać jakiś przykład?? sprawdzałem pomiar częstotliwości i za każdym razem błąd wynosi 0,64% czyli chodzi o to co napisałes ze gubi kilka impulsów
  • #11 10299872
    Konto nie istnieje
    Poziom 1  
  • #12 10300201
    bubu2606
    Poziom 15  
    czyli jeżeli w ISR(TIMER1_COMPA_vect) ustawię sobie jakąś flagę i odwołam się do niej w prog głównym to wówczas zostanie wykonane polecenie z nią związane np if(flaga=1); czyli w przerwaniu od przepełnienia licznika 1 musze ustawić tylko wpisanie do zmiennnej wartości TCNT0 i w kolejnym kroku jej wyzerowanie oraz ustawienie flagi (flaga=1);
    wówczas w programie głównym w if(flaga=1) następuje wyswietl=(zmienna)+TCNT0; i wyrzucenie danej na wyswietlacz i wyzerowanie zmiennej wyswietl i flagi

    po swiętach sprawdzę Twoją koncepcję e marcus :) a mam jeszcze pytanie bo ten pomiar jest częścią większego projektu związanego z pomiarem prądu za pomocą przetwornika ADC (wejścia PA1) oraz komunikacją 2 avr poprzez SPI (full duplex) oraz mastera z przetwornikiem ADC 24bitowym, dodatkowo planuję obsługę UARTU i komunikację mastera z PC, czy da się to zrealizować bez większych problemów wykorzystując przerwanie od UART, ADC i ewentualnie SPI?? oczywiście wszystko chcę wyrzucać na wyświetlacz. i czy nie będzie konfliktów związanych z przerwaniami??
  • #13 10303798
    Konto nie istnieje
    Poziom 1  
  • #14 10310145
    bubu2606
    Poziom 15  
    juz się pogubiłem..
    w
    Kod: text
    Zaloguj się, aby zobaczyć kod


    zliczam impusly na wejsciu timera0
    a w przerwaniu od przepełnienia po 1 sekundzie
    Kod: text
    Zaloguj się, aby zobaczyć kod


    natomiast w pętli głównej
    Kod: text
    Zaloguj się, aby zobaczyć kod


    i dalej mam niedokładność
    dla 6428 Hz na oscyloskopie w programie mam 6385 Hz - rónica 33 impulsów
    dla 3907 Hz osc na wyśw 3881 Hz - różnica 26 impulsów
    dla 1965 Hz na wyśw 1952 Hz - różnica 13 impulsów
    dla 1566 Hz na wyśw 1556 Hz - różnica 10 impulsów

    gdzie mogę to poprawić??

    Dodano po 1 [godziny] 56 [minuty]:

    może da się to ulepszyć poprzez wstawki assemblerowe??
  • #15 10311623
    janbernat
    Poziom 38  
    Nie przez wstawki asemblerowe- ale przez założenia.
    No może potem- przez wstawki.
    Jak byś uważnie przeczytał co napisał emarcus- to może byłoby bliżej.
    Jest tak- mamy bramkę AND i oba liczniki są podłączone do wejść.
    Jeden z nich otwiera jedno z wejść bramki na czas 1s a a na drugie wejście bramki w tym czasie podajemy impulsy.
    Potem pierwszy licznik- timer- zamyka bramkę a program oblicza ile impulsów zostało zliczone i przelicza to na częstotliwość.
    Problem jest taki że ten licznik co liczy jest "za krótki"- zliczy do 256 i się przepełnia.
    No ale mamy to szczęście że w momencie przepełnienia generuje przerwanie- a ilość przerwań można policzyć i zapisać.
    Zamiast licznik nazwij tę zmięnną- licznik_ile_razy_policzyl_256.
    Ale on nie liczy tylko przepełnień- jak się przepełni to liczy od nowa.
    To jest nam potrzebna jeszcze jedna zmienna- ile_policzyl-od_ostatniego_przepelnienia.
    Wtedy tę pierwszą zmienną- ilość przepełnień mnożysz przez 256 i dodajesz drugą zmienną.
    I dopiero wtedy wiesz ile masz zliczonych impulsów w czasie 1s.
    O tym że prolog i epilog wejścia w przerwanie zajmuje też jakiś czas- to potem.
    O tym że licznik może liczyć impulsy albo czas trwania impulsu- czyli bramkujący zmienia się rolami z liczącym- to też potem.
  • #16 10312171
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #17 10312177
    bubu2606
    Poziom 15  
    taktuję go wewnętrznym kwarcem stąd błąd??
  • #18 10312183
    Konto nie istnieje
    Poziom 1  
  • #19 10312212
    bubu2606
    Poziom 15  
    odp dla janbernat
    licznik się przepełnia ale w przerwaniu dalej zlicza impulsy więc przepełnienie na nic nie wpływa, chyba że się mylę
  • #20 10314102
    bubu2606
    Poziom 15  
    displ=((imp_prev<<8)|tcnt)*100665/100000;
    i sprawa rozwiązana :D
    różnica 1 Hz dla wskazań oscyloskopu 9825 Hz
  • REKLAMA
  • #22 10322144
    Konto nie istnieje
    Poziom 1  
  • #23 10322226
    bubu2606
    Poziom 15  
    z tym pomiarem częstotliwości to muszę go sprawdzić na kwarcu zewnętrznym ale to jak płytkę wykonam bo faktycznie to może być powód niedokładności, wczoraj jak sprawdzałem to częstotliwość była inna niż dzień wcześniej a więc jest coś na rzeczy
    wydaje mi się że jeżeli będę dysponował kwarcem 8MHz lub 16MHz to nie powinno być większych poprawek w kodzie :) dodatkowo zakładam że pomiar przetwornikiem będę wykonywał też co sekundę i tu moje pytanie czy da się uzależnić pomiar z przetwornika od przepełnienia timera1?? i czy to nie wpłynie na wynik pomiaru częstotliwości
  • #24 10323202
    janbernat
    Poziom 38  
    Rejestr SFIOR str.218

    No jestem już w domu- to mogę więcej napisać.
    W tym rejestrze możesz wpisać jakie zdarzenie uruchomi przetwarzanie ADC.
    Jak przetwarzanie się zakończy to wystawi flagę.
    Teraz są dwie możliwości:
    Zezwalamy na przerwanie od ADC- odczytujemy rejestry ADC i flaga jest automatycznie kasowana.
    Albo:
    W petli głównej sprawdzamy czy flaga przerwania jest ustawiona- jeśli tak to odczytujemy rejestry ADC i kasujemy flagę wpisując na odpowiednią pozycję rejestru przerwań 1.
    Nie 0 ale 1- ten typ tak ma.
  • #25 10327593
    bubu2606
    Poziom 15  
    ustawiam w main SFIOR|=(1<<ADTS2|1<<ADTS1) od przepełnienia licznika TC1


    i w tym momencie mam na wyświetlaczu daną z pomiaru częstotliwości oraz z wejścia przetwornika
    pojawia się dodatkowy problem
    w zależności od tego co jest na wejściu ADC mam różną wartość częstotliwości..
    dla wskazania 4,97 na ADC dla częstotliwości mam 1977
    dla wskazania 1,9 mam częstotliwość 1963
  • #26 10327772
    janbernat
    Poziom 38  
    Pokaż aktualny kod- jeśli obsługa przerwania ADC jest podobna do tej którą podałeś to czas obsługi przetwania jest bardzo duży.
    W przerwaniu od ADC należy tylko odczytać rejestr ADC a całą resztę przenieść do głównej pętli.
  • #27 10328256
    bubu2606
    Poziom 15  
    kod
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #28 10328431
    janbernat
    Poziom 38  
    Tu nie ma żadnego powiązania między przepełnieniem Timer0 a uruchomieniem pomiaru z ADC.
    Samo ustawienie reestru SFIOR tego nie zapewnia- trzeba nieco inaczej zrobić funkcję ADC_init().
    Na pewno musi być ustawiony bit ADATE a (chyba) ADSC- nie.
    Wtedy dopiero decydujemy- czy ADC odczytujemy w przerwaniu- wtedy trzeba ustawić bit ADIE- czy też w pętli głównej po sprawdzeniu bitu ADIF- wtedy po odczycie ADC bit ADIF kasujemy recznie.
  • #29 10328620
    bubu2606
    Poziom 15  
    czyli ustawiam
    ADCSRA=(1<<ADEN)|(1<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);

    a w main
    SFIOR|=(1<<ADTS2|1<<ADTS1); //przepełnienie licznika T1

    a w jaki sposób mogę wykorzystać
    ISR(ADC_vect)
    {
    adc=ADC;
    }

    Dodano po 15 [minuty]:

    czy może zrobić tak że pomiar częstotliwości zrobić w przerwaniu i w tym przerwaniu zatrzymać zliczanie impulsów na wejściu T0 i wznowić go dopiero po wyświetleniu wyniku a pomiar na ADC zrobić normalnie tak jak mam to zapisane??
  • #30 10328803
    janbernat
    Poziom 38  
    Ustawiasz w konfiguracji ADC_init() jedno i drugie.
    No bo jedno i drugie dotyczy konfiguracji ADC.
    A w głównej pętli sprawdzasz if-em czy nie jest ustawiona flaga ADIF.
    Jeśli jest- to odczytujesz ADC i kasujesz flagę ADIF.
    W takim wypadku nie wykorzystujesz przerwania od ADC- czyli nie ustawiasz flagi ADIE w ADC_init().
    Każde przerwanie powinno być jak najkrótsze- czyli w przerwaniu tylko ustawiamy jakąś flagę abo tylko coś odczytujemy.
    Obliczenia powinny być w głównej pętli.
REKLAMA