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

[Mega8][Bascom] Pomiar prędkości obrotowej

nauritius 17 Mar 2010 12:33 4038 13
  • #1 7841939
    nauritius
    Poziom 9  
    Celem jest pomiar prędkosci obrotowej. Program się kompiluje, ale wyświetla cały czas 0.0 rpm. Nie wiem gdzie tkwi błąd, czy ktoś może mi pomóc?

    
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    
    Config Timer1 = Timer , Prescale = 8 , Capture Edge = Rising
    Config Int0 = Rising
    
    
    Dim Wynik As Single
    Dim Zmienna As Single
    
    
    Enable Interrupts
    Enable Timer1
    Enable Int0
    
    
    
    On Int0 Przerwanie
    
    Do
    cls
    
    Lcd "obrotomierz"
    Lowerline
    Lcd Wynik ; " rpm"
    Loop
    End
    
    
    Przerwanie:
    
    Stop Timer1
    Zmienna = Timer1
    Wynik = 60000000 / Zmienna
    Start Timer1
    
    Return
    
    
  • #2 7842044
    M. S.
    Poziom 34  
    Wstaw przed Do instrukcję Start Timer1. Z helpa nie wynika, że Config włącza timer automatycznie, a jeśli ten się nie uruchomi to nie będzie przerwania i nie zadziałają instrukcje Start/Stop w podprogramie obsługi przerwania.

    P. S. Nie miga ci wyświetlacz? Zastosuj Locate albo Upperline zamiast CLS.
  • #3 7842610
    janbernat
    Poziom 38  
    Sprawdź połączenia- czy na wejście INT0 wchodzi jakiś sygnał.
  • #4 7843396
    nauritius
    Poziom 9  
    OK, dzięki;) Faktycznie, sygnał miałem podpięty do pind.5...
  • #5 7843732
    janbernat
    Poziom 38  
    Co nie zmienia faktu że głopoty pokazuje.
  • #6 7845390
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #7 7845779
    Konto nie istnieje
    Poziom 1  
  • #8 7848055
    nauritius
    Poziom 9  
    Nie byłem pewien, czy Capture Edge jest potrzebne, ale sprawa już się wyjaśniła. Na razie nie mam możliwości "polowego" przetestowania, bo coś szwankuje mi generator. Mierze okres między dwoma impulsami (zbocza narastające). Przy prescalerze 8 minimalna mierzona prędkość to ok. 920rpm, także dodam jeszcze fragment zliczający przepełnienia. Dlaczego prescale 64 byłby lepszy? Czy nie zmniejszy się dokładność?
  • #9 7848435
    Konto nie istnieje
    Poziom 1  
  • #10 7849245
    nauritius
    Poziom 9  
    Zrobiłem przypadek ze zliczaniem przepełnień timera1:

    
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    
    Config Timer1 = Timer , Prescale = 8
    Config Int0 = Rising
    
    
    Dim Wynik As Single
    Dim Zmienna As Single
    Dim Zmienna2 As Single
    Dim M As Byte
    Dim N As Byte
    
    
    Enable Interrupts
    Enable Timer1
    Enable Int0
    
    M = 0                                                       'ilość przepelnien timera1
    N = 0                                                       '0-pierwszy pomiar;1-pomiary kolejne
    On Int0 Przerwanie
    
    Do
    
    If Timer1 = 65536 Then
       Stop Timer1
       Timer1 = 0
       Incr M
       Start Timer1
    End If
    
    Wynik = 60000000 / Zmienna                                  'obliczanie rpm
    Cls
    Lcd "obrotomierz"
    Lowerline
    Lcd Wynik ; " rpm"
    
    Loop
    End
    
    
    Przerwanie:
    
    Stop Timer1
    If N = 0 Then                                               'sprawdzam, czy to pierwszy pomiar
       Start Timer1
       N = 1                                                    'ustawiam,ze pierwszy pomiar wykonano
       Return
    Else
       If M = 0 Then                                            ' rpm mieszcza sie w zakresie  licznika timer1
       Zmienna = Timer1
       Else                                                     'nastapiło m przepelnien
       Zmienna2 = M * 65536
       Zmienna = Zmienna2 + Timer1
       Timer1 = 0
       M = 0
       N = 1
       End If
    End If
    Start Timer1
    
    Return
    


    jak myślicie, zadziała? Mam takie pytania:
    1. Czy stop timer1 automatycznie zeruje timer?
    2. Opłaca się uwzględniać, to , że w pierwszym przerwaniu będe miał 0-rowy okres?
  • #11 7849481
    Konto nie istnieje
    Poziom 1  
  • #12 7850429
    Konto nie istnieje
    Poziom 1  
  • #13 7851133
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #14 7856044
    janbernat
    Poziom 38  
    
    'Działa od 30rpm do 300000rpm
    
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    Config Timer1 = Timer , Prescale = 64
    Config Int0 = Rising
    
    Dim Flaga As Byte
    Dim Text As String * 10
    Dim Wynik As Single
    Dim Zmienna As Word
    Dim Okres As Long
    Dim Predkosc As Single
    Dim Timer1_msb As Byte
    
    Enable Interrupts
    
    Enable Int0
    enable OVF1
    
    Cls
    Lcd "obrotomierz"
    Cursor Off
    
    On Int0 Przerwanie_int0
    On Ovf1 Przerwanie_timer1
    
    Do
       If Flaga = 1 Then
          cli
          Predkosc = Okres        'atomowy dostęp do zmiennej bo przerwanie od Timera też z niej korzysta
          sei
          Wynik = 7500000 / Predkosc
          Flaga = 0
          Text = Fusing(wynik , "#.&")      
          Lowerline
          Lcd "rpm: " ; Text ;"             "
        End If
    Loop
    
    Przerwanie_int0:
    
        Okres = Timer1_msb
        Shift Okres , Left , 16   'a tu była mała pomyłka
        Okres = Okres + Timer1
        Timer1 = 0
        Timer1_msb = 0
        Flaga = 1
    
    Return
    
    Przerwanie_timer1:
        'Timer1_msb = Timer1_msb + 1;  'A to nie działa-nie wiem dlaczego
      Incr Timer1_msb
        If Timer1_msb >= 100 Then 'Zabezpieczenie przed przepełnieniem
            Timer1 = 0
            Timer1_msb = 0
            Predkosc = 0
        End If
    Return
    

    Chociaż wynalazków atoma to tak do końca nie rozumiem- ale chyba ten typ tak ma.
    No ale sprawdziłem w praktyce- działa.
    Pewnie sam bym to starał się zrobić w bardziej tradycyjny sposób- a nie tak "atomowy"- ale pewnie by zajęło więcej kodu.
    P.S.
    Przy braku impulsów na INT pokazuje ostatni wynik- a nie 0.
REKLAMA