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

Atmega8-bascom-Układ opóźniający

nouki 16 Lut 2010 17:05 2318 24
REKLAMA
  • #1 7703578
    nouki
    Poziom 25  
    Witam.

    Mam taki problem.
    Chce zrobić układ który po stwierdzeniu zbocza opadającego i odliczeniu opóźnienia ( 1-1000ms ) zmieni stan 2 portów na przeciwny.
    Czas zwłoki jest zmienny ale w tym nie problem.
    Więc po uruchomieniu jest porx=1 porty=0 po podaniu zbocza ( zwarcie do masy) układ zamienia diody w nieskończoność sam.
    Co robię nie tak?? w C działa bez problemów

    
    
    $crystal = 8000000
    $regfile = "m8def.dat"
    
    Config Timer0 = Timer , Prescale = 64                                 , co 0,002s
    Config Timer1 = Counter , Edge = Falling
    
    Dim Wartosc As Word
    
    Config Portb.1 = Output
    Reset Portb.1
    Config Portb.2 = Output
    Set Portb.2
    Config Pinb.0 = Input
    Set Pinb.0
    
    Dim Licznik As Integer
    On Timer0 Timer0_int
    Enable Interrupts
    Timer0 = 6
    Licznik = 0
    Wartosc = 0
    Counter1 = 0
    
    Do
    Counter1 = Wartosc
    If Wartosc = 1 Then
    Counter1 = 0
    Wartosc = 0
    Enable Timer0
    End If
    
    Loop
    
    
    
    Timer0_int:
    Counter0 = Counter0 + 6
    Incr Licznik
    If Licznik = 50 Then                         '100ms
    Toggle Portb.1
    Toggle Portb.2
    disable timer0
    Licznik = 0
    End If
    
    
    Return
    
    
    
    


    Dzięki.
  • REKLAMA
  • #2 7704577
    sp3ots
    Poziom 38  
    Witam !
    Nie brakuje czasem zakończenia programu ?
    po linii
    Loop
    End
    Pozdrawiam. Stefan
  • #3 7704842
    pief
    Poziom 17  
    Witam

    Proponowałbym w przerwaniu od timera zostawić

    Timer0_int:
    Counter0 = Counter0 + 6
    Incr Licznik
    Return

    a reszta do pętli programu głównego .
  • #4 7704935
    janbernat
    Poziom 38  
    Stasznie mętnie to opisujesz.
    Żadnych sensownych komentarzy
    Po zmianie kodu na taki:
    
    $crystal = 8000000
    $regfile = "m8def.dat"
    
    Config Timer0 = Timer , Prescale = 64                                 , co 0,002s
    Config Timer1 = Counter , Edge = Falling
    
    Dim Wartosc As Word
    
    Config Portb.1 = Output
    Reset Portb.1
    Config Portb.2 = Output
    Set Portb.2
    Config Pinb.0 = Input
    Set Pinb.0
    
    Dim Licznik As Integer
    On Timer0 Timer0_int
    Enable Interrupts
    Enable Timer0
    Timer0 = 6
    Licznik = 0
    Wartosc = 0
    Counter1 = 0
    
    Do
    Counter1 = Wartosc
    If Wartosc = 1 Then
    Counter1 = 0
    Wartosc = 0
    'Enable Timer0
    End If
    
    Loop
    End
    
    
    Timer0_int:
    Counter0 = Counter0 + 6
    Incr Licznik
    If Licznik = 50 Then                         '100ms
    Toggle Portb.1
    Toggle Portb.2
    'disable timer0
    Licznik = 0
    End If
    
    
    Return
    

    Diody mrugają co 0.1s
    Oczywiście nie reagują na ICP1(czyli PB.0 )- bo tego w Twoim programie nie ma.
    Trzeba to tak przerobić- ale to tylko domysły- aby po wystąpieniu przerwania na jakimś INT starował Timer1 i po jakimś czasie- prescaler itp.- zapisywał że sygnał z z ICP1 go zatrzymał.
    Dlaczego w C działa- mogę tylko podejrzewać.
  • REKLAMA
  • #5 7705374
    nouki
    Poziom 25  
    W bascomie nie mam aż tak wielkiej wprawy.
    Chce by działało tak:

    część
    
    
    Timer0_int:
    Counter0 = Counter0 + 6
    Incr Licznik
    If Licznik = 50 Then                         '100ms
    Toggle Portb.1
    Toggle Portb.2
    disable timer0
    Licznik = 0
    End If
    
    Return
    


    odpowiada za opóźnienie czyli wartość 50 będzie się zmieniała od 1 do 1000 powiedzmy co da nam czas opóźnienia.

    Natomiast chce by zbocze opadające z zewnętrznego źródła podane uruchamiało właśnie timer0 i tak w koło.

    Czyli zbocze opadające (Counter1=1) startuje timer0 i odliczane jest opóźnienie po którym wykonana jest zmiana stanu wyjść
    Toggle Portb.1
    Toggle Portb.2
    timer0 staje
    następne zbocze opadające i znów timer0 startuje
    Toggle Portb.1
    Toggle Portb.2
    I tak w koło.

    po namysłach i szukaniach wywnioskowałem że powinno być tak :
    
    
    $crystal = 8000000
    $regfile = "m8def.dat"
    
    Config Timer0 = Timer , Prescale = 64                       ' 8 us
    Config Timer1 = Counter , Edge = Rising
    
    Dim Wartosc As Word
    Dim Licznik As Integer
    Config Portb.1 = Output
    Reset Portb.1
    Config Portb.2 = Output
    Set Portb.2
    
    
    On Timer0 Timer0_int
    Enable Interrupts
    Timer0 = 131
    Licznik = 0
    Wartosc = 0
     Timer1 = 0
    
    Do
    If Timer1 = 1 Then
    Timer1 = 0
    Enable Timer0
    Waitus 800
    End If
    
    Loop
    
    
    
    Timer0_int:
    Counter0 = Counter0 + 131                                   'przerwanie co 1ms
    Incr Licznik
    If Licznik = 50 Then                                        '50ms
    Toggle Portb.1
    Toggle Portb.2
    disable timer0
    Licznik = 0
    End If
    
    
    Return
    


    Jutro to sprawdzę - zmieniłem na zbocze rosnące
  • REKLAMA
  • #6 7706251
    mirekk36
    Poziom 42  
    sp3ots napisał:
    Witam !
    Nie brakuje czasem zakończenia programu ?
    po linii
    Loop
    End
    Pozdrawiam. Stefan


    Panowie nie wymyślajcie świata od nowa ..... tego END'a po pętli głównej Do..Loop nigdy nie musi być.

    End daje się tylko wtedy gdybyś nie zastosował pętli Do ... Loop.

    A kiedy można nie zastosować pętli Do ... Loop - ano wtedy gdy program np działa tylko w oparciu o przerwanie(-a) a pętla jest pusta. Wtedy można pominąć pętlę Do...Loop ale zamiast tego wtedy MUSI BYĆ ..... nasz END bo to on będzie pełnił rolę tej pętli ;)
  • #7 7706349
    Konto nie istnieje
    Poziom 1  
  • #8 7706387
    mirekk36
    Poziom 42  
    atom1477 --> święta racja że w tym przypadku który opisałem trza użyć STOP zamiast END.

    Ale generalnie nie zmienia to faktu, że ani END ani STOP po pętli głównej nie są potrzebne jeśli nie jest ona przerywana.
  • #9 7706666
    Konto nie istnieje
    Poziom 1  
  • #10 7706684
    Konto nie istnieje
    Poziom 1  
  • #11 7708956
    nouki
    Poziom 25  
    Timer0 startuje natychmiast po skonfigurowaniu ? skoro nie ma polecenia enebled to jak startuje?
    Jak dla mnie
    If Timer1 = 1 Then
    Timer1 = 0
    Enable Timer0
    ...

    uruchomi timer0

    w przerwaniu
    Timer0_int:
    Counter0 = Counter0 + 131

    Więc rozumuje to jako:

    $crystal = 8000000
    Config Timer0 = Timer , Prescale = 64
    Wiec co 8us zwieksza
    256 -131= 125
    125*8us=1000us (1ms)

    Na oko czas zmiany po podaniu zbocza jest taki sam Testowane na 1s opóźnienia.

    Jak sie mylę popraw mnie. To wnioski jakie mam po przeczytaniu pomocy bascoma
  • REKLAMA
  • Pomocny post
    #12 7709199
    janbernat
    Poziom 38  
    Niedokładnie przeczytałeś.
    W zakładce nawigator:
    Config Timer- uwaga! po ustawieniu prascale licznik natychmiast zaczyna zliczanie.
    Można użyć start Timerx i stop Timerx
    Np.
    Config timerx, prescale 'timer zaczyna liczyć
    stop Timerx 'timer stoi- ale już coś zliczył
    Timerx=y 'timer ma wartość początkową =y - np.0
    Start timerx ' Timerx zaczyna liczyć od wartości y
    Jak doliczy do swojej pojemności to wysyła żądanie przerwania.
    O ile w programie jest:
    Enable Timerx- zezwolenie na przerwanie od przepełnienia Timerx.
    Inaczej- Enable ovfx.
    Jest to tylko zezwolenie na obsługę przerwania a nie skasowanie flagi żądania przerwania.
  • #13 7709298
    nouki
    Poziom 25  
    Czyli reasumując

    
    Kod: 
    
    
    $crystal = 8000000 
    $regfile = "m8def.dat" 
    
    Config Timer0 = Timer , Prescale = 64                       ' 8 us 
    Config Timer1 = Counter , Edge = Rising 
    
    Dim Wartosc As Word 
    Dim Licznik As Integer 
    Config Portb.1 = Output 
    Reset Portb.1 
    Config Portb.2 = Output 
    Set Portb.2 
    
    On Timer0 Timer0_int 
    Enable Interrupts 
    stop timer0
    Timer0 = 131 
    Licznik = 0 
    Wartosc = 0 
     Timer1 = 0 
    
    Do 
    If Timer1 = 1 Then 
    Timer1 = 0 
    start timer0
    Enable Timer0 
    Waitus 800 
    End If 
    
    Loop 
    
    
    
    Timer0_int: 
    Counter0 = Counter0 + 131                                   'przerwanie co 1ms 
    Incr Licznik 
    If Licznik = 50 Then                                        '50ms 
    Toggle Portb.1 
    Toggle Portb.2 
    disable timer0 
    Licznik = 0 
    End If 
    
    
    Return
    
  • #14 7709461
    janbernat
    Poziom 38  
    Skopiowałem, skompilowałem, wgrałem.
    Reasumpcja przedwczesna.
    Co w zasadzie ma wyzwolić to opóźnienie?
    Co za pomysł konfigurować zezwolenie na obsługę przerwania od przepełnienia Timer0 w pętli głównej?
  • #15 7709545
    nouki
    Poziom 25  
    Więc sprawdziłem i takie wyniki.

    Testowane na układzie i oscyloskopie 2 kanałowym.

    Zmiana opóźnienia If Licznik = 1 Then do 1000 daje włąśnie to opóźnienie lecz mam uszkodzona podstawę czasu w oscyloskopie i nie bardzo jestem w stanie sprawdzić ile trwa.
    Po podaniu impulsu czas zmian portów wydłuża się i skraca zgodznie z watroscia 1 do 1000.

    Lecz działa na tym kodzie
    
    
    
    $crystal = 8000000 
    $regfile = "m8def.dat" 
    
    Config Timer0 = Timer , Prescale = 64                       ' 8 us 
    Config Timer1 = Counter , Edge = Rising 
    
    Dim Wartosc As Word 
    Dim Licznik As Integer 
    Config Portb.1 = Output 
    Reset Portb.1 
    Config Portb.2 = Output 
    Set Portb.2 
    
    
    On Timer0 Timer0_int 
    Enable Interrupts 
    Timer0 = 131 
    Licznik = 0 
    Wartosc = 0 
     Timer1 = 0 
    
    Do 
    If Timer1 = 1 Then 
    Timer1 = 0 
    Enable Timer0 
    Waitus 800 
    End If 
    
    Loop 
    
    
    
    Timer0_int: 
    Counter0 = Counter0 + 131                                   'przerwanie co 1ms 
    Incr Licznik 
    If Licznik = 50 Then                                        '50ms 
    Toggle Portb.1 
    Toggle Portb.2 
    disable timer0 
    Licznik = 0 
    End If 
    
    
    Return
    


    Więc jak Kolega proponuje??
    założenia są takie :
    portx=0 porty=1
    czeka na jakieś tam zbocze na t1
    jeśli się pojawi odlicza zwłokę i zamienia stan portx=1 porty=0
    i czeka na następne zbocze
    i tak w koło.
  • #16 7709720
    janbernat
    Poziom 38  
    Daj jakiś schemat.
    Bo już nic z tego nie rozumiem.
    Co ma wyzwolić opóźnienie?
    Bo Timer1= counter zlicza impulsy z PD.5.
    Czy na tę końcówkę podajesz impulsy jakieś?
  • #17 7709789
    nouki
    Poziom 25  
    Tak właśnie tam podaje impuls.

    Czyli
    If Timer1 = 1 Then
    Timer1 = 0
    Enable Timer0
    Waitus 800
    End If

    jest impuls to uruchomi przerwanie timer0 on odliczy zmieni porty i wyłączy i od nowa



    Schemat
    t1 -pd.5 impuls
    Portb.1 Portb.2 wyjścia (zmiana stanów po odliczeniu opóźnienia)
    I cały układ już jest.
  • #18 7709915
    janbernat
    Poziom 38  
    Dobrze, ale skąd to PD.5 dostaje impulsy?
    I gdzie jest skonfigurowane PD.5 jako input?
    I nie wiem czy ten wąż zjadający własny ogon będzie działał.
    P.S.
    To tak docelowo ma być?
  • #19 7710022
    nouki
    Poziom 25  
    Impulsy są z czujnika z zewnątrz - powiedzmy klawisza który podaje 5v czy tam mase.

    Konfiguracja jest tu
    Config Timer1 = Counter , Edge = Rising

    czyli t1 jest wejściem i zbocze zwiększa wartość timer1 co spełnia warunek
    If Timer1 = 1 Then
    Timer1 = 0
    i tyle.
    Działa bo widzę na układzie tylko czy czasy sie zgadzają nie mam pojęcia
    skoro mam
    Counter0 = Counter0 + 131
    to nie wiem czy jest potrzeba jeszcze timer0=131 lub odwrotnie.
  • #20 7710412
    janbernat
    Poziom 38  
    "Impulsy są z czujnika z zewnątrz - powiedzmy klawisza który podaje 5v czy tam mase."
    No to trochę wyjaśnia.
    Jak nie daje drgań to tak.
    Ale Timer1= counter zlicza impulsy z zewnątrz.
    No a powinno być tak:
    Coś przychodzi na dowolną końcówkę ustawioną jako wejście.
    Odliczamy czas.
    Zmieniamy stam wyjść.
    Najbardziej prymitywny program:
    If pin.x=0 then
    wait1
    toggle dioda
    end if.
    No ale program powinien być lepszy.
  • #21 7711158
    nouki
    Poziom 25  
    Więc popraw. Przedstawiając własną propozycje.

    Drgania maja mały wpływ w tym przypadku.

    "Ale Timer1= counter zlicza impulsy z zewnątrz. " zgadza się i na dodatek ma przydatną funkcje reakcji na zbocze która się tu przydaje

    Na pin.x będzie niedokładnie to jedno.
    Stan na pinie jak będzie 1 cały czas to cały czas będzie sie zmieniał stan wyjść a nie tylko gdy jest impuls.

    Reakcja na zbocze jest bardziej dokładna niż stan na pinie.
    Na dodatek czas ma być regulowany a nie stały wpisany.
    Polecenie waitxxx zatrzyma całą pętle programu w którym moge robić coś innego.

    W tym co wymyśliłem po impulsie jest czas na zrobienie czegoś innego w pętli głównej nim nie odliczy czasu zwłoki bo impulsy będą i tak ignorowane na czas odliczania opóźnienia więc mam najmniej 1ms.
    Przykładowo wartość opóźnienia będzie ustawiana potencjometrem
    wiec polecenie getadc.x mogę dodać, którego wynik następnie podstawie w miejsce
    If Licznik = xxx Then

    Proste ale chyba jeszcze bardziej prymitywne rozwiązanie przedstawiłeś przemyśl to.
  • #22 7711430
    Konto nie istnieje
    Poziom 1  
  • #23 7711495
    nouki
    Poziom 25  
    zasada prosta zbocze na t1 odlicza czas zwłoki zmienia 2 porty na przeciwne i tak w koło
    
    
    
    $crystal = 8000000 
    $regfile = "m8def.dat" 
    
    Config Timer0 = Timer , Prescale = 64                       ' 8 us 
    Config Timer1 = Counter , Edge = Rising 
    
    Dim Wartosc As Word 
    Dim Licznik As Integer 
    Config Portb.1 = Output 
    Reset Portb.1 
    Config Portb.2 = Output 
    Set Portb.2 
    
    
    On Timer0 Timer0_int 
    Enable Interrupts 
    Timer0 = 131 
    Licznik = 0 
    Wartosc = 0 
     Timer1 = 0 
    
    Do 
    If Timer1 = 1 Then 
    Timer1 = 0 
    Enable Timer0 
    Waitus 800 
    End If 
    
    Loop 
    
    
    
    Timer0_int: 
    Counter0 = Counter0 + 131                                   'przerwanie co 1ms 
    Incr Licznik 
    If Licznik = 50 Then                                        '50ms 
    Toggle Portb.1 
    Toggle Portb.2 
    disable timer0 
    Licznik = 0 
    End If 
    
    
    Return
    


    A pytanie jest odnośnie tego czy dokładnie będzie odmierzać czas :
    If Licznik = 50 Then '50ms
    w takiej formie programu czy wymaga poprawki jakiejś
  • Pomocny post
    #24 7711543
    mirekk36
    Poziom 42  
    Wystarczy jedno wejście INTx, które będzie wykrywało ten impuls. Ale jeśli to będzie impuls "z ręki" jakiś klawisz to bez sensu - ze względu na drgania styków a potrzebny minimalny czas np 1ms.

    Jeśli to będzie impuls z jakiegoś wyjścia cyfrowego to ok.

    Założenia:

    - wykorzystamy tylko jedno wejście INTx
    - wykorzystamy tylko jeden Timer sprzętowy

    Przygotować sobie np Timer1 żeby tykał dokładnie co 1ms

    W tym przerwaniu INTx odpalić Timer1 .

    W przerwaniu Timera1 inkrementować jakąś zmienną od 1 do 1000 i w zależności czy będzie ona równa parametrowi opóźnienie - dokonać zmiany stanu na dowolnych wyjściach też w tym przerwaniu oraz zresetować tą zmienną na 0, żeby po ponownym odliczaniu zaczęło znowu od początku i na końcu wyłączyć Timer.

    Czekać znowu na impuls na INTx

    W przerwaniu INTx można sprawdzać czy właśnie trwa opóźnienie jakąś flagą i ew nie zezwalać na załączenie kolenego opóźnienia w takim przypadku.

    gdzie tu problem ?

    A na zakończenie powiem też tylko, że jak gdzieś w kodzie widzę w przerwaniu obojętnie jakim polecenie typu Waitus , Waitms czy Wait - to mi się włosy jeżą na głowie. To po co Timery wymyślono ???? ;)
  • #25 7718379
    janbernat
    Poziom 38  
    Atmega8-bascom-Układ opóźniający



    
    $crystal = 8000000
    $regfile = "m8def.dat"
    
    Config Timer0 = Timer , Prescale = 64
    
    Dim Licznik As Word
    Dim Flaga_1ms As Byte
    Dim Temp_1 As Byte
    Dim Liczniczek_1 As Byte
    
    Config Portb.1 = Output
    Reset Portb.1
    Config Portb.2 = Output
    Set Portb.2
    Config Pinb.0 = Input
    Set Portb.0
    
    Enable Interrupts
    Enable Ovf0
    
    On Timer0 Timer0_int
    
    
    
    Do
    
    If Flaga_1ms = 1 Then
      Flaga_1ms = 0
    
        If Temp_1 = 0 Then
    
          If Pinb.0 = 0 Then
            Incr Liczniczek_1
              If Liczniczek_1 >= 20 Then
                Temp_1 = 1
                Liczniczek_1 = 0
              End If
          End If
        Else
          Incr Licznik
            If Licznik >= 1500 Then
              Toggle Portb.1
              Toggle Portb.2
              Temp_1 = 0
              Licznik = 0
    
            Else
              Temp_1 = 1
            End If
    
      End If
    End If
    
    Loop
    
    
    
    Timer0_int:
    
      Flaga_1ms = 1
      Timer0 = 130
    
    Return
    


    Teraz to działa.
REKLAMA