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.

[..2313] Pomiar długości impulsu

AF7018 24 Cze 2008 19:02 2456 10
  • #1 24 Cze 2008 19:02
    AF7018
    Poziom 10  

    Witam,
    Chciałbym mierzyć czas trwania impulsu i napisałem taki prosty programik ale

    Code:
    $regfile = "2313def.dat"
    
    $crystal = 8000000

    Config Portb.0 = 1
           Portb.0 = 1
    Config Portb.1 = 1
           Portb.1 = 1
    Config Portd = &B0000000

    Config Portd = &B1111111


    Config Timer1 = Timer , Prescale = 256





     Dim Czas As Integer
     Dim Zmienna As Bit

      Czas = 0
      Zmienna = 0


    On Timer1

     Do

    If Pind.2 = 0 And Zmienna = 0 Then : Zmienna = 1 : Timer1 = 0 : Start Timer1 : End If
    If Pind.2 = 1 And Zmienna = 1 Then : Zmienna = 0 : Stop Timer1 : End If
    Czas = Timer1


     Cls
    Lcd "czas"

    Lowerline
    Lcd Czas
    Waitms 100
     Loop
     End

    problem w tym, że na wyświetlaczu pojawiają się jakieś liczby od zera do 9999 a nie tak jak zakładałem zbliżone do siebie wartości. Dlaczego tak jest bo próbowałem w różny sposób i ciągle to samo?

    0 10
  • #2 24 Cze 2008 20:19
    ZbeeGin
    Poziom 38  

    Zauważ, że zanim program ponownie wejdzie w warunki to LCD + WAITMS zabierze tyle czasu, że impuls już dawno przejdzie, a program dopiero zacznie wykrywać jego zakończenie.
    Ponadto użycie w poleceniu CONFIG TIMER1 opcji PRESCALE od razu włącza zliczanie.

    Wykorzystaj przerwania INT0 wyzwalane zboczem opadającym i tam podłącz sygnał mierzony. Będzie o wiele dokładniej. Oczywiście w procedurze jego obsługi czekasz, aż impuls zaniknie - a przy wyjściu dopiero wyświetli się czas.

    0
  • #3 24 Cze 2008 21:25
    AF7018
    Poziom 10  

    próbowałem już z przerwaniami ale coś nie mogłem odczytać z TIMERA wartości na jakiej został zatrzymany przy przyjściu przerwania INT.
    Bo właściwie to nie wiem jak poczekać na przerwanie tak żeby np. w pierwszym INT kasować TIMER a w następnym odczytywać.
    A czy można zdefiniować równocześnie przerwanie na zbocze opadające i narastające i kiedy przyjdzie przerwanie od zbocza narastającego kasować TIMER a kiedy przerwanie od zbocza opadającego odczytywać stan TIMERA? Jeśli tak to proszę o jakieś wskazówki.

    0
  • #4 25 Cze 2008 08:23
    ZbeeGin
    Poziom 38  

    Łopatologicznie:
    1. zgłasza się przerwanie ze zbocza opadającego. wywołana jest procedura jego obsługi. jesteśmy teraz w niej.
    2. włączasz licznik by zliczał impulsy zegarowe przez prescaler.
    3. czekasz tak długo aź stan na INT0 się zmieni na przeciwny - koniec impulsu.
    4. zatrzymujesz licznik. odczytujesz zawartosc licznika i zapamiętujesz w zmiennej. licznik zerujesz.
    5. opuszczasz przerwanie i ustawiasz flage wyswietl.

    W programie głównym jesli flaga wyswietl jest ustawiona to wartosc idze na wyswietlacz. Inaczej program nic innego nie robi tylko kręci się w kółko.

    PISAĆ!

    Cytat:
    A czy można zdefiniować równocześnie przerwanie na zbocze opadające i narastające i kiedy przyjdzie przerwanie od zbocza narastającego kasować TIMER a kiedy przerwanie od zbocza opadającego odczytywać stan TIMERA?

    Tak, ale tylko w mikrokontrolerach posiadających przerwania PCINT.

    0
  • #5 25 Cze 2008 21:13
    AF7018
    Poziom 10  

    Dzieki za "łopatologię", dzięki temu stworzyłem coś takiego:

    Code:
    $regfile = "2313def.dat"
    
    $crystal = 8000000
    Config Pinb.1 = Output
    Config Pinb.0 = Output

    Config Timer1 = Timer , Prescale = 256

    Config Int0 = Rising
    Dim A As Integer

    Enable Interrupts
    Enable Timer1
    Enable Int0
    On Int0 Zlicz

    Do

     Cls
     Lcd A

    Waitms 100

    Loop
    End

    Zlicz:

    Start Timer1
    If Pind.2 = 0 Then : Stop Timer1 : End If
    A = Timer1
    Timer1 = 0
    Return

    Robiłem już wcześniej w podobny sposób ale nie działało, ponieważ w złym miejscu wstawiałem zerowanie Timera tzn na początku procedury obsługi przerwania INT.
    Z tym kodem jest pomiar zliczeń Timera ale przy większych częstotliwościach powyżej 10Hz znowu pojawia mi się cała gama liczb zamiast zbliżonej wartości jak poprzednio.
    Kolejny problem polega na tym, że jeśli zatrzymam generator to wyświetlacz cały czas pokazuje ostatnią wartość zamiast np. zero.
    Docelowo ten program ma służyć porównywania długości impulsu i sygnalizować w zależności od przekroczenia bądź nie ustalonej wartości.
    A co jeśli impulsy zanikną a zmienna zatrzyma się na wartości spełniającej warunek przekroczenia minimalnego czasu trwania impulsu?
    Jak temu zaradzić?
    Pozdrawiam

    0
  • #6 26 Cze 2008 18:20
    ZbeeGin
    Poziom 38  

    AF7018 napisał:
    Z tym kodem jest pomiar zliczeń Timera ale przy większych częstotliwościach powyżej 10Hz znowu pojawia mi się cała gama liczb zamiast zbliżonej wartości jak poprzednio.
    Kolejny problem polega na tym, że jeśli zatrzymam generator to wyświetlacz cały czas pokazuje ostatnią wartość zamiast np. zero.

    Zatem trzeba skonfigurować przerwania Timera. No i oczywiście w przerwaniu INT0 trzeba włączyć dalsze przerwania. Jeśli licznik się przepełni to impuls trwa zbyt długo. Wtedy możesz opuścić przerwanie INT0 ze zwróconą wartością zero.

    Dodatkowo możesz skorzystać z INT1 i skonfigurować go by reagował na zbocze narastające przebiegu. Wtedy INT0 włącza zliczanie, a INT1 będzie go wyłączał. Przerwanie z TIMER1 za to zasygnalizuje przekroczenie zakresu. A program główny może się zająć wyświetlaniem czy innymi głupotami.

    0
  • #7 27 Cze 2008 12:24
    AF7018
    Poziom 10  

    Dzięki za pomoc ZbeeGin Dzięki Twoim wskazówkom zaczyna coś mi z tego wychodzić.
    Zmodyfikowałem kod i mam coś takiego

    Code:
    $regfile = "2313def.dat"
    
    $crystal = 8000000
    Config Pinb.1 = Output
    Config Pinb.0 = Output

    Config Timer1 = Timer , Prescale = 256

    Config Int0 = Rising
    Config Int1 = Falling
    Dim A As Integer
    Dim B As Bit
    Dim C As Bit


    Enable Interrupts
    Enable Timer1
    Enable Int0
    Enable Int1
    On Int0 Poczatek
    On Int1 Koniec
    On Timer1 Zero

    Do
    If A < 1500 And C = 0 Then Portb.0 = 1 Else Portb.0 = 0
    If A < 120 And C = 0 Then Portb.1 = 1 Else Portb.1 = 0

     Cls
     Lcd A

    Waitms 100

    Loop
    End

    Poczatek:

    Timer1 = 0
    C = 0

    Return

    Koniec:

    A = Timer1
    Return

    Zero:

    A = 0
    C = 1
    Return

    Już coraz bardziej zaczyna to pracować tak jak chcę.
    Jednak nadal pozostaje problem różnych wartości zliczeń Timera1.
    Przy granicznych wartościach częstotliwości (na granicy warunków w kodzie) następuje przypadkowe miganie diód podpiętych do portów B.
    Nie wiem z czego to wynika i jak można na podobnej zasadzie zrobić czasomierz skoro są takie rozbieżności.
    Następny krok to pomiar długości impulsów z kilku różnych źródeł równolegle.
    Mam Attiny2313 i zamierzam ją wykorzystać. Zdaje się, że Attiny2313 może przyjmować przerwania z 8 wejść.

    0
  • #8 27 Cze 2008 12:27
    Balu
    Poziom 38  

    Nie... nie może;)

    Dodano po 1 [minuty]:

    (Przynajmniej nie przez INT:) )

    0
  • #9 27 Cze 2008 13:59
    AF7018
    Poziom 10  

    A dlaczego jest taka rozbieżność w pomiarze impulsów Timera?

    0
  • #10 27 Cze 2008 19:05
    ZbeeGin
    Poziom 38  

    AF7018 napisał:
    Mam Attiny2313 i zamierzam ją wykorzystać. Zdaje się, że Attiny2313 może przyjmować przerwania z 8 wejść.

    Owszem. Jest taka możliwość. Z tym, że zawsze jest to jedno przerwanie PCINT i do Ciebie zależy sprawdzenie jaka zmiana stanu wywołała to przerwanie. Ponadto znajduje się ono niżej w hierarchii przerwań układu.
    Stosowanie INT0 i INT1 jest moim zdaniem lepszym rozwiązaniem, gdyż wybraną zmianę stanu rozpoznaje sprzęt a nie program.

    AF7018 napisał:
    Jednak nadal pozostaje problem różnych wartości zliczeń Timera1.

    Jakiego rzędu są to rozbieżności? Może warto zmienić preskaler licznika.

    AF7018 napisał:
    Przy granicznych wartościach częstotliwości (na granicy warunków w kodzie) następuje przypadkowe miganie diód podpiętych do portów B.

    Zmień warunek na mniejsze lub równe.

    0
  • #11 01 Lip 2008 07:45
    AF7018
    Poziom 10  

    Witam

    Cytat:
    Jakiego rzędu są to rozbieżności? Może warto zmienić preskaler licznika.

    Rozbieżności są dość znaczne rzędu ± 30%. Kombinowałem z preskalerem i częstotliwością procesora i nic to nie pomaga. No chyba, że Proteus przekłamuje bo nie sprawdzam tego fizycznie, nie mam generatora z regulowaną częstotliwością.

    Warunek oczywiście można zmienić ale to nie ma zasadniczo znaczenia bo jest ustawiony na razie ok 5-10% poniżej częstotliwości mierzonej. Gdyby pomiary Timera były w porządku to chyba reszta działała by OK.
    Już nie mam pomysłu jak poprawić działanie tego kodu.

    Jak na razie to prawidłowo działa tylko prosty program wykorzystujący Timer jako licznik w instrukcją WAIT ale nie mierzy długości impulsu tylko częstotliwość.

    Pozdrawiam

    0
  Szukaj w 5mln produktów