Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Bascom AVR - Miernik częstotliwości z opóźnieniem pomiaru

MZT 10 Nov 2014 12:12 2124 17
  • #1
    MZT
    Level 8  
    Potrzebuję zmierzyć częstotliwość w pakiecie impulsów trwającym około 1 sek. Częstotliwość akustyczna. Najpierw są w nim „szumy” czyli na interesujące mnie impulsy nałożone są przypadkowe oscylacje. Po około 0,1 sekundy od pierwszego „piku” mam już czysty sygnał, który trawa około 0,9 sekundy
    Wydaje mi się, że najpierw powinno być „uruchomione” odliczanie tych 0,1 sek, wyzwalane pierwszym pikiem z „paczki”. Potem trzeba odczekać te 0,1 sekundy na zanik „szumów” i zacząć zliczanie w czasie 0,9 sek. Ilość zliczonych pików podzielona przez czas da mi częstotliwość. Wynik ma się utrzymywać na wyświetlaczu do nadejścia następnego pakietu impulsów. Raczej proste, nawet dla mnie.
    Ale pojawia się trudność, częstotliwość muszę podać znacznie dokładniej niż 1 Hz, a to wymaga porównania odpowiedniej ilości zliczonych impulsów z wewnętrznym generatorem kwarcowym o dosyć dużej częstotliwości w stosunku do sygnału mierzonego. A to już nie jest dla mnie proste. Dotychczas przeczytałem (tylko przeczytałem) Mikrokontrolery dla Początkujacych” Góreckiego, długa jeszcze droga przede mną, a lata już nie te… Ale Bascom mi się podoba, łatwo by mi było wprowadzać ewentualne zmiany w programie. No i właśnie zamówiłem zestaw startowy.
    A może już ktoś napisał taki program, może też nie jest to tak trudne jak mi się wydaje?
  • Helpful post
    #2
    bochnio
    Level 13  
    Moim zdaniem koncepcja powinna być taka:

    1. Obsługa przetwornika analog-cyfra.

    Na początek dobrze żebyś umiał dobrze zmierzyć liczbę impulsów. Nie wiem dokładnie jaka jest specyfika Twojego sygnału, jaką amplitudę mają owe szumy, skąd się biorą i czy nie warto by ich po prostu potraktować filtrem dolnoprzepustowym, a jeśli mają odpowiednio niską amplitudę to może należy liczyć wszystko powyżej pewnej wartości?

    http://avrhelp.mcselec.com/index.html?config_adc.htm

    Ja bym zrobił tak:
    Jeśli wiem od jakiej wartości X napięcia, chcę uznać, że sygnał wystąpił to czekam na taką wartość na przetworniku i zwiększam zmienną. Kolejny raz zwiększam pod warunkiem, że pojawiła się wartość mniejsza od X np: o 10% i X wystąpiła potem kolejny raz.

    2. Timer, który odlicza dokładnie 1s.

    Musisz poczytać o przerwaniach wywołanych obsługą timera. Na początek dobrze byś umiał wyświetlić na wyświetlaczu wartość zwiększającej się co sekundę zmiennej przy pomocy przerwań. Jeśli timer osiągnie pewną wartość i stanie się to równo po sekundzie to wywołuje przerwanie i zwiększa zmienną -> na wyświetlacz - i tak w pętli. Jak to Ci się uda to potem obsługa dowolnego przerwania, czy to uruchamiającego funkcję, która dzieli lub robi co innego to nie problem.

    3. Timer, który odlicza 0.1s.

    Jeśli z szumem nic nie da się zrobić i faktycznie musisz odczekać te 0.1s to należy postąpić tak jak w punkcie 2 z tą różnicą, że za sprawą przerwania uruchamiasz obsługę ADC lub ustawiasz zmienną logiczną ADC_START na 1, z tym dasz sobie radę ;)

    Timery mogą działać niezależnie od siebie.

    Tutaj jest trochę o obsłudze TIMERów i przerwań w BASCOM: http://elportal.pl/pdf/k10/54_01.pdf
  • Helpful post
    #3
    bartosz.tarnowski
    Level 17  
    A na jakim to jest procku? ATMEGA czy ATTINY?

    Dużo zależy od czystości sygnału i jego amplitudy.
    Zliczanie można zrealizować na przerwaniu INT0 ale wczśniej dobrze aby sygnał przepuścić przez komparator aby ukształtować ładny prostokąc, można też wykorzystać wbudowany w procek komparator analogowy.
  • Helpful post
    #4
    emarcus
    Level 38  
    MZT wrote:

    Wydaje mi się, że najpierw powinno być „uruchomione” odliczanie tych 0,1 sek, wyzwalane pierwszym pikiem z „paczki”. Potem trzeba odczekać te 0,1 sekundy na zanik „szumów” i zacząć zliczanie w czasie 0,9 sek. Ilość zliczonych pików podzielona przez czas da mi częstotliwość. Wynik ma się utrzymywać na wyświetlaczu do nadejścia następnego pakietu impulsów. Raczej proste, nawet dla mnie.
    Ale pojawia się trudność, częstotliwość muszę podać znacznie dokładniej niż 1 Hz, a to wymaga ...........


    Dokładnie tak, więc zacznij pisac program, w którym użyjesz dwóch timerów i jeden interrupt
    Na przykład:
    Timer1 skonfigurowany jak counter (licznik)
    Timer1=0
    Stop timer1

    Timer0 skonfigurowany do odmierzania czasu; powiedzmy impulsy co 8 msec.
    Nie musi to byc 8 msec, ale dalsze przykładowe rachunki odnoszą się do tej konfiguracji.
    Sygnał badanej częstliwotliwości podłączasz do dwóch pinów processora:
    Int0 oraz T1.
    Pierwszy impuls wyzwala interrupt0 i w jego subrutynie go wyłączasz (disable Int0) po to aby nie reagował na kolejne impulsy i szumy, a także jednocześnie startujesz/zerujesz Timer0.
    w subrutynie przepełnień Timera0 incrementyjesz zmienną (powiedzmy A) zliczającą te 8-milisekundowe impulsy generowane przez Timer0.
    W pętli głównej obserwujesz zmienną A i jeżeli jest ona równa 13 co odpowiada upływowi czasu około 0.1 sec. uruchamiasz Timer1 (Start Timer1).
    W dalszym ciągu w programie głównym obserwujesz zmienną A i jeżeli ona osiągnie 125 co odpowiada dokadnie 1 sekunda od startu pomiaru
    a także juz nie około 0.9 sekundy od startuTimera 1, a dokładnie (125-13)*8msec=0.896 sec.
    W tym momencie odczytujesz zawartośc Timera1 i obliczasz aktualnie zmierzoną częstotliwośc. Zatrzymujesz także timer1 i Tmer0, zerujesz zmienną A (nie jest już potrzebna),a takze przywracasz załączenie Interruptu0 (enable int0); w ten sposób system jest w punkcie poczatkowym, gotowym do następnego pomiaru.
    Przedstawienie wyniku:
    Ponieważ spodziewana wartośc badanej częstotliwości jest w paśmie akustycznym (nie więcej niż 20 kHz), więc spokojnie mozesz liczyc że nie nastąpi przepełnienie Licznika /Timera1. Jego wartośc przed wyzerowaniem przepisujesz do zmienej N typu 'word', natomiast ostateczny wynik częstotliwości F_in = N/0.896 gdzie F_in zwymiarujesz jako 'single'. Pozwoli to uzyskac wynik w postaci liczby zmienno-przecinkowej (w postaci dziesiętnej).
    Są oczywiście metody pominięcia rachunków na liczbach zmienno-przecinkowych, ale to wybiega poza ten i tak już zbyt obszerny instruktarz.
    Processor możesz wybrac dowolny, posiadający dwa timery; np Attiny2313

    e marcus
  • #5
    MZT
    Level 8  
    Czekam na zamówiony zestaw startowy, procesor to Attiny2313.
    "Szumy" mają amplitudę zbliżoną do właściwego sygnału, częstotliwość też zbliżona. Ale po 0,1 sek. ich nie ma, więc chyba najlepiej wyciąć ten kawałek przebiegu.
    Spróbuję doczytać o analogowym komparatorze wbudowanym w procesor, uprościło by to część analogową układu.
    Na chwilę obecną piszę, a właściwie przerabiam ćwiczenie 31 (Pomiar okresu oraz czasu impulsów) ze wspomnianej wyżej książki. Efekt jak na razie nie najlepszy, jak zacznie mi się to wszystko kompilować to spróbuję zamieścić tutaj. Choć pewnie to, że się skompiluje, znaczy tylko że składnia ok, a nie że działa tak jakbym chciał :(
    Dziękuję za dotychczasową pomoc!
  • #6
    vania
    Level 24  
    MZT wrote:
    Czekam na zamówiony zestaw startowy, procesor to Attiny2313.
    "Szumy" mają amplitudę zbliżoną do właściwego sygnału, częstotliwość też zbliżona. Ale po 0,1 sek. ich nie ma, więc chyba najlepiej wyciąć ten kawałek przebiegu.
    Spróbuję doczytać o analogowym komparatorze wbudowanym w procesor, uprościło by to część analogową układu.
    Na chwilę obecną piszę, a właściwie przerabiam ćwiczenie 31 (Pomiar okresu oraz czasu impulsów) ze wspomnianej wyżej książki. Efekt jak na razie nie najlepszy, jak zacznie mi się to wszystko kompilować to spróbuję zamieścić tutaj. Choć pewnie to, że się skompiluje, znaczy tylko że składnia ok, a nie że działa tak jakbym chciał :(
    Dziękuję za dotychczasową pomoc!


    Ten sygnał to rozumiem sygnał analogowy? Jaka amplituda, częstotliwość? Jeśli amplituda jest bardzo mała to prawdopodobnie będzie go trzeba wzmocnić, przefiltrować, podać na komparator i dopiero mierzyć.
  • #7
    MZT
    Level 8  
    Częstotliwość max 10kHz, układ analogowy na płytce stykowej mam już gotowy, amplituda do 5V. Sygnał jest "czysty", tutaj nie przewiduję większych problemów.
  • #8
    MZT
    Level 8  
    Zamieszczam program miernika według wskazówek emarcusa.
    Jest to pierwsza w moim życiu próba napisania czegoś poważniejszego niż zapalanie i gaszenie LED-ów. Program nie kompiluje się, co mnie nie dziwi, są pewnie w nim podstawowe błędy... Ale od czegoś trzeba zacząć. Proszę o poprawienie, podpowiedzi.
    A tak w ogóle to zaczyna mnie wciągać :)


    Code: vbnet
    Log in, to see the code
  • #9
    vania
    Level 24  
    MZT wrote:
    Zamieszczam program miernika według wskazówek emarcusa.
    Jest to pierwsza w moim życiu próba napisania czegoś poważniejszego niż zapalanie i gaszenie LED-ów. Program nie kompiluje się, co mnie nie dziwi, są pewnie w nim podstawowe błędy... Ale od czegoś trzeba zacząć. Proszę o poprawienie, podpowiedzi.
    A tak w ogóle to zaczyna mnie wciągać :)

    Code: vbnet
    Log in, to see the code

    Poprawiłem, powinno Ci się już kompilować.
  • #10
    emarcus
    Level 38  
    MZT wrote:
    Zamieszczam program miernika .......... Program nie kompiluje się, co mnie nie dziwi, są pewnie w nim podstawowe błędy...

    Na pewno Program wypisuje listę błędów..., które należy skorygowac, przed kolejną próbą kompilacji.

    Te co na razie 'pobieżnie' zauważyłem:
    1. z kazdej sybrutyny musi być "Return" do miejsca programu 'skąd przyszedł'.
    2. brakuje konfiguracji interruptu INT0
    3. niepoprawnie skonfigurowany Timer0 i błędnie liczony czas interwałów; o ile te pierwsze 0.1 sec delay nie musi być dokładny, to drugi interwał czas "pomiarowy" wymaga możliwie wysokiej dokładności.
    Skoro stosujesz tryb 'Normal' dla timera0, tp zamiast zliczać jego pełny zakres, który ma się 'nijak' do dokładności (ułamkowe wartości milisec), zastosuj preload tak jak proponowałem, aby mierzył jakieś sensownie wymierne odcinki czasu. Zdaje się że optymalnie byłoby to 8 msec zamiast 16,384msec (i ten nawet przyjąłeś z błędem (15,625 msec ?!). Przecież i tak zliczasz przepełnienia...

    Dobrym nawykiem jest nie umieszczać obliczeń i obsługi LCD w przerwaniach.
    Przerwania winny być możliwie najkrótsze (ograniczone do minimum koniecznych tylko akcji) i jezeli pozostaje coś jeszcze do zrobienia to stawiasz flagę i reszty dokonujesz w programie głównym Do/Loop jednocześnie kasując flagę. W tym akurat przypadku nie jest to aż tak istotne bo wyświetlenie wyniku kończy w zasadzie cały program./

    Quote:

    częstotliwość muszę podać znacznie dokładniej niż 1 Hz, a to wymaga...

    ..a to wymaga troche innego rachunku ....

    e marcus
  • #11
    yokoon
    Level 29  
    vania wrote:
    MZT wrote:
    Zamieszczam program miernika według wskazówek emarcusa.
    Jest to pierwsza w moim życiu próba napisania czegoś poważniejszego niż zapalanie i gaszenie LED-ów. Program nie kompiluje się, co mnie nie dziwi, są pewnie w nim podstawowe błędy... Ale od czegoś trzeba zacząć. Proszę o poprawienie, podpowiedzi.
    A tak w ogóle to zaczyna mnie wciągać :)

    Code: vbnet
    Log in, to see the code

    Poprawiłem, powinno Ci się już kompilować.


    Witam.
    15625 to nie są impulsy milisekundowe (odcinki czasowe) to jest częstotliwość po preskalerze.
  • #12
    MZT
    Level 8  
    Poprawiłem błędy, w tym ten związany z częstotliwością a nie z okresem sygnału.
    Dodałem zmienną typu Single Czestotliwosc, do obliczeń zmiennoprzecinkowych. W Timer0 wpisuję na starcie 131, Config Int0=Rising. Czy dobrze to robię, czy we właściwych miejscach kodu?
    Pytania: Jak zaokrąglić wynik ze zmiennej Czestotliwosc do dwóch miejsc po przecinku? Boję się, że może to być czasem wiele zupełnie nie znaczących cyfr.
    Czy proponowane przez Vanię polecenia Load Timer0=0 i Load Timer1=0 to to samo co Timer0=0 i Timer1=0, czy też wpisują one w te timery 255? Chciałbym je wyzerować.
    Co do obsługi LCD i obliczeń w podprogramie to jeszcze nie potrafię umieszczać tego w programie głównym (albo świetnie to potrafię tylko jeszcze tego nie wiem :D ). Jednak pomiędzy kolejnymi pomiarami będą około minutowe przerwy, więc raczej nie ma pośpiechu dla procesora..
    I na koniec sposób liczenia. Taki jaki napisałem nie sprawdzi się przy niskich częstotliwościach, program będę musiał przerobić tak, aby sygnał wejściowy dzielony był na preskalerze i niejako ten sygnał bramkował licznik, w którym zliczane będą impulsy z generatora kwarcowego. Taką mam koncepcję, bo to pozwoli liczyć pełną liczbę okresów, a w tej chwili liczę tylko zakończone, nie uwzględniam "ostatniego" okresu sygnału, który trwa... Ale to w przyszłości, na początek za trudne :)
    Zamieszczam kod po poprawkach, czy teraz będzie dobrze?
    Code: vbnet
    Log in, to see the code
  • #13
    vania
    Level 24  
    MZT wrote:
    Poprawiłem błędy, w tym ten związany z częstotliwością a nie z okresem sygnału.
    Dodałem zmienną typu Single Czestotliwosc, do obliczeń zmiennoprzecinkowych. W Timer0 wpisuję na starcie 131, Config Int0=Rising. Czy dobrze to robię, czy we właściwych miejscach kodu?
    Pytania: Jak zaokrąglić wynik ze zmiennej Czestotliwosc do dwóch miejsc po przecinku? Boję się, że może to być czasem wiele zupełnie nie znaczących cyfr.

    Instrukcje FUSING, FORMAT
    Quote:

    Czy proponowane przez Vanię polecenia Load Timer0=0 i Load Timer1=0 to to samo co Timer0=0 i Timer1=0, czy też wpisują one w te timery 255? Chciałbym je

    Trochę źle podałem. nie pamiętam już dokładnie składni Bascoma.
    LOAD TIMER0, 10 ładuje do timera 0 wartość 256-10 (przy 16 bitowym TIMER1 65536-10) Natomiast jeśli chcesz wyzerować to pisałeś poprawnie czyli TIMER0 = 0 zeruje timer, TIMER=123 wpisuje do timera 123.
    http://avrhelp.mcselec.com/load.htm
  • #14
    emarcus
    Level 38  
    MZT wrote:

    I na koniec sposób liczenia. Taki jaki napisałem nie sprawdzi się przy niskich częstotliwościach, program będę musiał przerobić tak, aby sygnał wejściowy dzielony był na preskalerze


    Impulsy wejściowe zliczasz Timerem1 skonfigurowanym jako Counter. W takiej konfiguracji nie ma możliwości uzycia prescalera, poza tym nie ma to sensownego uzasadnienia nawet gdyby taka możliwośc istniała.
    Dla niskich częstotliwości wskazane byłoby zastosowac metodę pomiaru czasu pomiędzy dwoma kolejnymi impulsami (pomiędzy dwoma zboczami kolejnych impulsów) i z tego wyliczysz częstotliwośc.
    Możesz to zrobic wykorzystując tylko jeden dowolny timer.

    e marcus
  • #15
    MZT
    Level 8  
    Przepraszam za dłuższą nieobecność. Nie mając nic nowego (i mądrego) nie pisałem. Ale w międzyczasie polutowałem zestaw startowy, a ostatnio napisałem inny program, który umożliwia (w zamyśle) liczenie dokładniej częstotliwości dla "paczki" impulsów, tym razem około 500 Hz. Wiem, że to dosyć skomplikowany tok myślenia, pewnie można to zrobić prościej, ale rozumując logicznie, tak też powinno działać.

    Idea jest taka:
    Sygnał podaję jednocześnie na INT0 i TIMER0. Pierwszy impuls blokuje INT0 i jednocześnie uruchamia TIMER0 który liczy "w koło" od 205 do 255 (LOAD TIMER0=50). Po każdych 50 impulsach (50 imp. a' 500 Hz = 0,1 sek) następuje przerwanie od TIMER0. Po pierwszym takim przerwaniu startuje TIMER1 zliczający niepodzielone (prescale=1) impulsy z generatora kwarcowego. po 10-tym przerwaniu stopuje TIMER1. Po kolejnej sekundzie stopuję TIMER0, zeruję zmienną w której zliczam jego przepełnienia i na koniec odblokowuję INT0. Miernik jest gotowy na kolejną paczkę impulsów.
    Częstotliwość liczę z liczby przepełnień Timer1*65536 +"reszta" w liczniku T1 odniesione do liczby impulsów (tutaj 450).

    Program działa ale źle. Szukając błędu zauważyłem (modyfikując program i mierząc częstotliwość wzorcowego generatora sygnałowego) że jeśli korzystam z wielu przepełnień Timer0 to wynik jest zbliżony do wzorca, jeśli liczę dla trzech bądź dwóch przepełnień (odpowiednio 150 i 100 impulsów) to błąd jest na poziomie parunastu procent. W skrajnym przypadku gdy liczę pomiędzy Przepelnienia_t0=1 a Przepelnienia_t0=2 błąd sięga kilkudziesięciu procent. Wniosek: w zakresie T0=1 i T0=2 program zlicza tylko niektóre impulsy z Timer1.Obliczenia są w pętli głównej, zaczynają się dla bezpieczeństwa sekundę po końcu zliczania T1.
    Gdzie jest błąd, co robię źle???


    Code: vbnet
    Log in, to see the code
  • #16
    emarcus
    Level 38  
    MZT wrote:
    Przepraszam za dłuższą nieobecność. Nie mając nic nowego (i mądrego) nie pisałem. Ale w międzyczasie polutowałem zestaw startowy, a ostatnio napisałem inny program, który umożliwia (w zamyśle) liczenie dokładniej częstotliwości dla "paczki" impulsów, tym razem około 500 Hz. Wiem, że to dosyć skomplikowany tok myślenia, pewnie można to zrobić prościej, ale rozumując logicznie, tak też powinno działać.

    Idea jest taka:
    Sygnał podaję jednocześnie na INT0 i TIMER0. Pierwszy impuls blokuje INT0 i jednocześnie uruchamia TIMER0 który liczy "w koło" od 205 do 255 (LOAD TIMER0=50). Po każdych 50 impulsach (50 imp. a' 500 Hz = 0,1 sek) następuje przerwanie od TIMER0. Po pierwszym takim przerwaniu startuje TIMER1 zliczający niepodzielone (prescale=1) impulsy z generatora kwarcowego. po 10-tym przerwaniu stopuje TIMER1. Po kolejnej sekundzie stopuję TIMER0, zeruję zmienną w której zliczam jego przepełnienia i na koniec odblokowuję INT0. Miernik jest gotowy na kolejną paczkę impulsów.
    Częstotliwość liczę z liczby przepełnień Timer1*65536 +"reszta" w liczniku T1 odniesione do liczby impulsów (tutaj 450).

    Program działa ale źle.


    Teraz pomieszałeś to zupełnie!!!
    Na wstępie zwróc uwagę że masz błędny syntax wpisu wartości początkowych do rejestru dowolnego timera, na co już ktoś wcześniej zwrócił uwagę.
    np:
    Load Timer0 = 50 - zapis błędny, timer liczy na cały swój zakres ignorując to co wpisałeś,
    Jeżeli używasz komendy "Load Timer0", wpisujesz po przecinku (,) ilośc impulsów do odliczenia przez Timer0:
    Load Timer0 , 50 w tym przypadku 50. Bascom przeliczy ile powinna wynosi wartośc początkowa i taką tam wpisze.
    Jezeli chcesz sam to robic , to mozesz obliczyc: ( 256-50 =206)
    I dokonasz takiego wpisu poczatkowej wartości do rejestru Timera0
    Timer0=206 ; timer będzie skonfigurowany tak samo jak wyżej.
    (zauważ że tu użyto znaku "=" a nie ","

    W żaden sposób "nie łapię" tego:
    Quote:

    Idea jest taka:
    Sygnał podaję jednocześnie na INT0 i TIMER0. Pierwszy impuls blokuje INT0 i jednocześnie uruchamia TIMER0 który liczy "w koło" od 205 do 255 (LOAD TIMER0=50). Po każdych 50 impulsach (50 imp. a' 500 Hz = 0,1 sek) następuje przerwanie od TIMER0


    Przecież Timer0 (w/g jego config) miał liczyc impulsy badanej fali, jak więc odliczyłeś 0.1 sec.?

    Nie jest w zasadzie istotne, który timer liczy czas, a który pełni funkcję licznika i zlicza impulsy. Praktyczniej jednak byłoby wybrac odwrotną konfigurację, tak jak zacząłeś poprzednio. Ważne jest aby w programie był poprawny cykl zdarzeń, aby program nadążał za przygotowanym algorytmem.
    spróbuj przeanalizowac ten niżej twój poprzedni program z poprawkami :

    Code: vbnet
    Log in, to see the code

    Czym jest podyktowana potrzeba przedstawienia wyniku z dokładnością do 'n' miejsc po przecinku? Czy pomiar fali o częstotliwości circa 5kHz lub 12 kHz z dokładnościa do 1 Hz nie jest dostatecznie dokładny?
    W powyższym przykładzie czas jest mierzony w odstępach 8 msec co w przeliczeniu na błąd pomiaru częstotliwości daje σ=0.08%

    A może chcesz przyjąc metode pomiaru czasu dla grupy impulsów i z tego wyliczyc srednią freq?. Jeżeli tak, to dla tej metody twój algorytm też nie jest poprawny.

    e marcus
  • #17
    MZT
    Level 8  
    E marcus, dziękuję za pomoc.
    Tak, chciałem policzyć czas grupy impulsów i z tego częstotliwość. Dla przykładu: Timer0 liczy impulsy sygnału o częst. około 500 Hz, wiec 50 impulsów to około 0,1 sek, 450 impulsów to około 0,9 sek. Dlatego Timer1 miał się przeładowywać co 50 i stąd moje nieudolne próby wpisania w niego 206 :cry: Jestem świadomy, że znaczna zmiana mierzonej częstotliwości będzie skutkować koniecznością zmian w programie, tak aby mierzyć sygnał przez około 0,9 sek.
    Ale czy ten mój pomysł ze zliczaniem grupy impulsów jest zły, nieprawidłowy? Dokładność pomiaru małych częstotliwości powinna być wtedy znacznie wyższa. Dla częstotliwości wyższych niż 10 kHz zastosuję program e marcusa.
  • #18
    emarcus
    Level 38  
    MZT wrote:

    Tak, chciałem policzyć czas grupy impulsów i z tego częstotliwość. Dla przykładu: Timer0 liczy impulsy sygnału o częst. około 500 Hz, wiec 50 impulsów to około 0,1 sek, 450 impulsów to około 0,9 sek. Dlatego Timer1 miał się przeładowywać co 50 i stąd moje nieudolne próby wpisania w niego 206 :cry: Jestem świadomy, że znaczna zmiana mierzonej częstotliwości będzie skutkować koniecznością zmian w programie, tak aby mierzyć sygnał przez około 0,9 sek.
    Ale czy ten mój pomysł ze zliczaniem grupy impulsów jest zły, nieprawidłowy?


    Sam koncept nie jest zły, tylko że źle to robisz..
    Skąd wiadomo że te pierwsze impulsy (jak to określiłeś "szumy") w czasie 0.1 sec. są f= 500 Hz?
    Jaki zakres częstotliwości uważasz za przedział niskich 'f' ?
    Jezeli cały pomiar ma trwac nie dłużęj niż 1 sec ( netto 0.9 sec) i jeżeli chcesz próbkowac sygnał Timerem0, paczkami po 50 impulsów, to ile tych paczek pomieścisz w czasie 0.9 sec.?
    Wystąpi tu ścisła zależnośc: - niższa freq => zmiescisz mniej impulsów; chyba że pierwotne założenia z postu #1 już nie obowiązują(?)....
    Skoro przydzieliłeś Timer0 do zliczania impulsów testowanej fali, a Timer 1 do odmierzania czasu, to niech te timery wykonują dokładnie swoje funkcje.
    Timer0 skonfiguruj do pracy w trybie CTC i niech odliczy tylko/(na przykład) 10 impulsów dla których zmierzysz czas timerem1
    Ten początkowy delay (0.1 sec.) odmierz także Timerem1 (60 przepełnień), postaw flagę początku testu i startuj Timer0, zliczając kolejne przepełnienia Timera1 do innej zmiennej niż te poprzednie 60.
    Gdy Timer0 odliczy swoje 10 impulsów, uruchomi ci interrupt OC0A w którym zatrzymasz i odczytasz aktualną zawartośc Timera1 oraz ilośc jego przepełnień, w tym czasie zatrzymasz także Timer0.
    Mając zliczony całkowity czas 10 impulsów, pozostaje prosty rachunek obliczenia freq./. Po dokonaniu obliczeń wyzerujesz pozostałe zmienne.

    e marcus