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

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

AF7018 24 Cze 2008 19:02 2819 10
  • #1 5281284
    AF7018
    Poziom 11  
    Witam,
    Chciałbym mierzyć czas trwania impulsu i napisałem taki prosty programik ale
    $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?
  • #2 5281558
    ZbeeGin
    Poziom 39  
    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.
  • #3 5281802
    AF7018
    Poziom 11  
    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.
  • #4 5282803
    ZbeeGin
    Poziom 39  
    Ł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.
  • #5 5285151
    AF7018
    Poziom 11  
    Dzieki za "łopatologię", dzięki temu stworzyłem coś takiego:
    $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
  • #6 5287978
    ZbeeGin
    Poziom 39  
    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.
  • #7 5290196
    AF7018
    Poziom 11  
    Dzięki za pomoc ZbeeGin Dzięki Twoim wskazówkom zaczyna coś mi z tego wychodzić.
    Zmodyfikowałem kod i mam coś takiego
    $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ść.
  • #9 5290511
    AF7018
    Poziom 11  
    A dlaczego jest taka rozbieżność w pomiarze impulsów Timera?
  • #10 5291475
    ZbeeGin
    Poziom 39  
    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.
  • #11 5301569
    AF7018
    Poziom 11  
    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
REKLAMA