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

obsługa enkodera obrotowego przez attiny2313 Bascom

tomson5 04 Wrz 2007 17:04 6295 12
REKLAMA
  • #1 4249960
    tomson5
    Poziom 16  
    Posty: 259
    Pomógł: 1
    Ocena: 5
    Witam
    Mam problem z programem który ma obsłużyć enkoder
    Objaw jest taki że obracając go licznik na wyświetlaczu zmienia się co drugi impuls (nie ważne czy robię to szybko czy wolno)

    00 stan spoczynkowy
    01 stan przejściowy
    11 stan spoczynkowy
    10 stan przejściowy
    00 stan spoczynkowy

    Wydaje mi się że program reaguje na stan spoczynkowy 00 ale nie reaguje na stan spoczynkowy 11

    enkoder podłączony mam do INT0 i INT1 podwieszony przez 10K do plusa

    Jak zmusić program aby rozpoznawał stan spoczynkowy 11

    00 - styki rozwarte
    11 - styki zwarte


          $regfile = "attiny2313.dat"
    $crystal = 4000000
    
    Cha Alias Pind.2
    Chb Alias Pind.3
    
    Config Cha = Input
    Config Chb = Input
    Config Pind.6 = Output
    
    Config Int0 = Falling
    Const Debouncetime = 1
    
    Dim Wtime As Byte
    Dim Encounter As Integer
    
    Set Chb
    
    On Int0 Getencoder
    
    Cls
    
    Wtime = 100
    Encounter = 0
    
    Enable Interrupts
    Enable Int0
    
    Do
      Set Portd.6
      Waitms Wtime
      Upperline
      Lcd "encounter: " ; Encounter ; "     "
      Reset Portd.6
      Waitms Wtime
    Loop
    
    Getencoder:
      Waitms Debouncetime
      If Cha = 0 Then
        If Chb = 0 Then Incr Encounter Else Decr Encounter
      End If
      Gifr = 64
    Return
    
    End
  • REKLAMA
  • #2 4251859
    rcpilot
    Poziom 15  
    Posty: 122
    Pomógł: 1
    Ocena: 4
    Moim zdaniem przyczyna leży w obsłudze przerwania. Przerwanie INT0 jest uruchamiane opadającym zboczem (Falling) CHA zmiana sie 1 -> 0. Dodatkowo w przerwaniu są instrukcje sprawdzające czy kanały są w stanie 00. Stan 11 jest pomijany.
    By móc rejestrować zmiany 0 -> 1 można ustawić przerwanie INT1 na wyzwalanie zboczem narastającym (Rising) i sprawdzać warunek czy oba kanały są w stanie 11.
    Wstawiając dodatkową flagę (zmienną) można uzyskać liczenie w górę lub w dół, zależnie w jakiej kolejności zostały wywołane przerwania.
    Przykład użycia enkodera, AN 115, znajduje się na stronie firmowej BascomAVR www.mcselec.com
    Inny przykład obsługi enkoderów z użyciem PCF8574 (przykładowe programy Bascom'a są na końcu artykułu) http://www.circuitcellar.com/library/print/0303/millier152/index.htm
  • #3 4252935
    tomson5
    Poziom 16  
    Posty: 259
    Pomógł: 1
    Ocena: 5
    Dziękuje, bardzo fajnie wyłożyłeś teorię, nie wiem tylko czy dam radę skorzystać z niej
    Dzięki za link do przykładu AN 115
    Sam wcześniej myślałem o wykorzystaniu dwóch przerwań ale nie wychodziło mi to, spróbuje to w jakiś sposób przekrztałcić na mój procesor i wykorzystać ten kod
    Będę próbował...
  • REKLAMA
  • #4 4255181
    rcpilot
    Poziom 15  
    Posty: 122
    Pomógł: 1
    Ocena: 4
    BascomAVR posiada funkcję obsługującą enkodery obrotowe
    zmienna = ENCODER( pin1, pin2, etykieta1, etykieta2, opcja).
    Nie korzysta z przerwań, można podłączyć pod dowolne wyprowadzenia w obrębie jednego portu, dokładny opis w help'ie.
  • REKLAMA
  • #5 4256289
    tomson5
    Poziom 16  
    Posty: 259
    Pomógł: 1
    Ocena: 5
    Próbowałem tego ale coś mi nie działa
    być może to jest do enkoderów typu ALPS gdzie są dwa styki jeden jak w lewo się kręci a drugi jak w prawo
  • Pomocny post
    #6 4256647
    Mad Bekon
    Poziom 23  
    Posty: 794
    Pomógł: 31
    Ocena: 36
    Mi się wydaje, żeby zrobić to na jednym przerwaniu.
    Mamy stan 11
    Ustawiamy na przerwanie na zboczu opadającym.
    Kiedy się wykona przerwanie, sprawdzić drugi pin.
    Jeśli wyjdzie 01 ro znaczy ze obrót był w jedną stronę, jeśli 00 to znaczy, że był w drugą. Teraz trzeba zmienić na przerwanie zboczem narastającym. Jeśli po obrocie mamy 11, to obrót w jedną stronę jeśli 10 to w drugą
  • Pomocny post
    #7 4258605
    rcpilot
    Poziom 15  
    Posty: 122
    Pomógł: 1
    Ocena: 4
    Przepraszam ale w pierwszej wypowiedzi popełniłem błąd logiczny - oba przerwania powinny być ustawione na te same zbocze a nie różne. Dlaczego, bo tak jak napisałem wcześniej nie będzie można określić kierunku zmian, zawsze bedzie ta sama kolejność wywoływania przerwań. Obojętnie czy kręcimy w lewo czy w prawo.

    np. ChA narastanie 0->1 a ChB opadanie 1->0
    Obrót w prawo - 00 ; 01 przerwanie A; 11; 10; 00 przerwanie B
    Obrót w lewo - 00; 10 ; 11 A; 01; 00 B

    Jeżeli przerwania ustawimy na te same zbocze np. narastanie, wówczas
    Obrót w prawo - 00 ; 01 A; 11 B; 10; 00 - kolejność AB = dodawanie
    Obrót w lewo - 00; 10 B; 11; 01; 00 A - kolejność BA = odejmowanie
    ale nie bedzie wykrywany stan 00, jedynie 11 bo oba przerwania 0->1 lub odwrotnie przy ustawieniu przerwań na zbocze opadające.

    Jak zauważyłem w helpie istnieje jeszcze jedna opcja wyzwalania przerwań - CHANGE - działa na dowolną zmianę sygnału. We wcześniejszych kompilatorach ta opcja obsługiwała tylko niektóre ATMEGA. W dostępnym aktualnie demo nie piszą o tym ograniczeniu.

    Obrót w prawo - 00 ; 01 A; 11 B; 10 A; 00 B - kolejność ABAB = dodawanie
    Obrót w lewo - 00; 10 B; 11 A; 01 B; 00 A - kolejność BABA = odejmowanie
    wykrywane są oba stany stabilne, a zmiana kierunku kiedy bieżące i poprzednie przerwanie są z tego samego kanału. Poniżej poglądowo fragment programu, jak ja bym to zrobił (nie sprawdzałem).

    Config INT0=CHANGE
    Config INT1=CHANGE
    On INT0 Akanal
    On INT1 Bkanal

    Do
    Print ENCODER
    Loop

    Akanal:
    nowy_klik = A
    if poprzedni_klik = A then 'zmiana kierunku
    if kierunek = 1 then kierunek = 0 else kierunek = 1
    elseif kierunek = 1 then INCR ENKODER else DECR ENKODER
    endif
    poprzedni_klik = klik
    Return

    Bkanal:
    nowy_klik = B
    if poprzedni_klik = B then 'zmiana_kierunku
    if kierunek = 1 then kierunek = 0 else kierunek = 1
    elseif kierunek = 1 then INCR ENKODER else DECR ENKODER
    endif
    poprzedni_klik = nowy_klik
    Return
  • REKLAMA
  • #8 4272678
    tomson5
    Poziom 16  
    Posty: 259
    Pomógł: 1
    Ocena: 5
    Witam
    Trochę opóźniona odpowiedź bo życie rodzinne się o mnie upomniało :)
    Dziękuje bardzo za fragment kodu który w tej chwili próbuje ogarnąć
    mam tylko takie wątpliwości

    Co to jest za zmienna nowy_klik ??
    skoro ma przypisaną literę (nowy_klik=A) to według książki powinienem zadeklarować
    DIM nowy_klik As STRING

    to samo tyczy się poprzedni_klik
    Rozumiem że zmienna Kierunek jest typu BIT
    DIM Kierunek As BIT
    Kierunek=pind2 ??

    Poprzedni_klik=klik tego trochę nie rozumiem


    Narazie uzupełniłem kod tak jak poniżej
     $regfile = "attiny2313.dat"
    $crystal = 4000000
    
    
    A Alias Pind.2
    B Alias Pind.3
    
    Config A = Input
    Config B = Input
    Dim Enkoder As Integer
    Dim Nowy_klik As Bit
    Dim Poprzedni_klik As Bit
    Dim Kierunek As Byte
    Config Int0 = Change
    Config Int1 = Change
    On Int0 Akanal
    On Int1 Bkanal
    
    Do
     Upperline
      Lcd "encounter: " ; Enkoder ; "     "
    Loop
    
    Akanal:
    Nowy_klik = A
    If Poprzedni_klik = A Then                                  'zmiana kierunku
    If Kierunek = 1 Then Kierunek = 0 Else Kierunek = 1
    Elseif Kierunek = 1 Then Incr Enkoder Else Decr Enkoder
    End If
    Poprzedni_klik = Klik
    Return
    
    Bkanal:
    Nowy_klik = B
    If Poprzedni_klik = B Then                                  'zmiana_kierunku
    If Kierunek = 1 Then Kierunek = 0 Else Kierunek = 1
    Elseif Kierunek = 1 Then Incr Enkoder Else Decr Enkoder
    End If
    Poprzedni_klik = Nowy_klik
    Return


    Są niestety błędy
    Error : 36 Line : 28 THEN expected , in File :
    Error : 28 Line : 29 IF THEN expected , in File :
    Error : 350 Line : 29 Interrupt needs return , in File :
  • #9 4274823
    rcpilot
    Poziom 15  
    Posty: 122
    Pomógł: 1
    Ocena: 4
    Poprzednio prezentowany kod nie był sprawdzany w kompilatorze, miał być jednie wskazówką do napisania prawidłowego programu.
    Ten prezentowany poniżej został przetestowany i sprawdzony na symulatorze programowym Bascom'a. Powinien również działać na procesorze. W prezentowanym kodzie jest wstawiona instrukcja $sim którą należy usunąć przy kompilacji do AVR'a.
    W programie został skonfigurowany wyświetlacz LCD 2 linijki 16 znaków aby na symulatorze można było obserwować pojawiające się zmiany przy wywoływaniu kolejnych przerwań.
    
    $regfile = "attiny2313.dat"
    $crystal = 4000000
    
    ' usunąć linijkę $sim jeżeli kompilacja do procesora
    $sim
    
    Config Lcd = 16 * 2
    
    A Alias Pind.2
    B Alias Pind.3
    
    Config A = Input
    Config B = Input
    
    Dim Enkoder As Integer
    Dim Nowy_klik As Bit                 ' nowe przerwanie - z jakiego kanału
    Dim Poprzedni_klik As Bit           ' zapamiętanie przerwania z jakiego było kanału
    Dim Kierunek As Byte
    
    Const Cha = 1                           ' flaga przerwania z kanału A
    Const Chb = 0                           ' flaga przerwania z kanału B
    
    Config Int0 = Change
    Config Int1 = Change
    
    On Int0 Akanal
    On Int1 Bkanal
    
    Enable Int0
    Enable Int1
    
    Enable Interrupts
    
    Do
      Upperline
      Lcd " Licznik:  " ; Enkoder ; "     "
      Lowerline
      Lcd " Kierunek: " ; Kierunek ; "     "
    Loop
    
    Akanal:
    Nowy_klik = Cha
    If Poprzedni_klik = Cha Then     
    ' jeżeli wcześniejsze przerwanie z tego samego kanału to zmiana kierunku
       If Kierunek = 1 Then
          Kierunek = 0
       Else
          Kierunek = 1
       End If
    Else ' jeżeli poprzednie przerwanie z innego kanału wówczas +/- Enkoder
       If Kierunek = 1 Then
          Incr Enkoder
       Else
          Decr Enkoder
       End If
    End If
    Poprzedni_klik = Nowy_klik
    Return
    
    Bkanal:
    Nowy_klik = Chb
    If Poprzedni_klik = Chb Then  
    '  jeżeli poprzednie przerwanie z tego samego kanału to zmiana kierunku
       If Kierunek = 1 Then
          Kierunek = 0
       Else
          Kierunek = 1
       End If
    Else ' jeżeli poprzednie przerwanie z innego kanału wówczas +/- Enkoder
       If Kierunek = 1 Then
          Incr Enkoder
       Else
          Decr Enkoder
       End If
    End If
    Poprzedni_klik = Nowy_klik
    Return
    
    End ' koniec programu
    
  • #10 4283462
    tomson5
    Poziom 16  
    Posty: 259
    Pomógł: 1
    Ocena: 5
    Niestety nie zadziałał ten program :(
    Dziękuje bardzo za poświęcenie czasu
    reaguje tylko kierunek, ale niestety z dużą ilością przekłamań
    Spróbowałem znowu z nową instrukcją encoder w nowej wersji bascoma
      $regfile = "attiny2313.dat"
    $crystal = 4000000
    
    $baud = 19200                                               ' use baud rate
    
    $hwstack = 32                                               ' default use 32 for the hardware stack
    
    $swstack = 10                                               ' default use 10 for the SW stack
    
    $framesize = 40                                             ' default use 40 for the frame space
    
    
    
    
    
    Print "Encoder test"
    
    Dim B As Byte
    
    'we have dimmed a byte because we need to maintain the state of the encoder
    
    
    
    
    Portd = &B11111111                                          ' activate pull up registers
    Portb = &B00000000
    
    
    
    Do
    
       B = Encoder(pind.2 , Pind.3 , Links , Rechts , 0)
    
       '                                               ^--- 1 means wait for change which blocks programflow
    
       '                               ^--------^---------- labels which are called
    
       '              ^-------^---------------------------- port PINs
    
    
    Loop
    
    End
    
    
    
    
    'so while you can choose PINB0 and PINB7,they must be both member of PINB
    
    'this works on all PIN registers
    
    
    
    
    Links:
    
       Cls
      Lcd "lewo"
      Wait 1
      Cls
    Return
    
    
    
    
    Rechts:
       Cls
      Lcd "prawo"
      Wait 1
      Cls
    Return
    
    
    
    
    
    
    
    End

    W takiej postaci program działa dosyć dziwnie
    kręcąc w prawo przy każdym kliknięciu pokazuje na LCD "prawo"
    więc tutaj jest sukces w pełni
    Problemy zaczynają się kręcąc w lewo
    klikam w lewo pokazuje się na LCD "lewo" klikam drugi raz w lewo i pokazuje na LCD "prawo"

    Mam w tej chwili podpięte dwa kanały do plusa przez rezystory 10K
    Może potrzeba podpiąć tylko jeden ??

    W tej chwili jestem już skłonny zgodzić się na sprzętową obsługę enkodera za pomocą LS7183, jeśli go zdobędę
  • #11 4291324
    rcpilot
    Poziom 15  
    Posty: 122
    Pomógł: 1
    Ocena: 4
    W moim programie brakuje konfiguracji podciągania portu D (ciągle zapominam albo o podciąganiu albo o konfiguracji wejść/wyjść). Po instrukcji Config B = Input należy wstawić PortD = &b00001100 lub na cały port PortD = &HFF. Brak podciągania może powodować niestabilnbą pracę. Można również dołączyć rezystory 10k od +5V bezpośrednio do wyprowadzeń procesora.
    Na symulatorze zadziałało więc moim zdaniem powinno działać w 'prawdziwym' układzie. Proszę pamietać o usunięciu linijki "&sim". Niestety nie mam możliwości sprawdzenia tego kodu w układzie.
  • #12 4416487
    korrus666
    Poziom 40  
    Posty: 5219
    Pomógł: 584
    Ocena: 476
    Może mi się wydaje ale mam wrażenie że da sie to rozwiązać w bardzo prosty sposób i to na jednym zewnętrznym przerwaniu. Skoro sygnały są przesunięte w fazie i np. ustawimy przerwanie na narastające zbocze sygnału A to na B będzie 0 lub 1 w zależności od kierunku obrotu. Po zakończeniu obsługi przerwania nie robimy nic tylko czekamy na następne.
    A __----__----__
    B --__----__----__
    Tutaj przy narastającym zboczu A sygnał na B jest 0
    A __----__----__
    B _----__----__
    A tutaj jest 1 na B przy narastającym zboczu na A. Wydaje mi się że rozwiązanie jest banalnie proste. Ale może sie myle i ktoś mnie poprawi.

    Sprawdziłem doświadczalnie i działa bez zarzutu. W dodatku na enkoderze zrobionym ze starej myszki do komputera. To chyba najprostszy możliwy sposób. POZDRAWIAM.
  • #13 6196669
    FastProject
    Poziom 29  
    Posty: 1977
    Pomógł: 64
    Ocena: 194
    Zgadzam się z kolegą wyżej.
    Ja w przerwaniu robie tak:
    Getencoder:                                                 'Wywołane przez przerwanie zboczem narastającym (Config Int0 = Rising)
       Waitus 100
       If Pind.1 = 1 Then
          Decr Steps
          If Steps > 999 Then Steps = 0
       Else
          Incr Steps
          If Steps > 999 Then Steps = 999
       End If
    Return


    Wyjscie enkodera A do PORTD.2 na INT0, B dowolnie(ja miałem na PORTD.1)


    Działa idealnie.Pozdrawiam

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z obsługą enkodera obrotowego podłączonego do mikrokontrolera ATtiny2313 programowanego w Bascom. Głównym problemem jest wykrywanie stanów spoczynkowych enkodera, zwłaszcza stanu 11, który nie jest poprawnie rozpoznawany przy obecnej konfiguracji przerwań. Proponowane rozwiązania obejmują zmianę konfiguracji przerwań INT0 i INT1 na wyzwalanie zboczem narastającym lub opadającym oraz stosowanie przerwań na zmianę (CHANGE), co pozwala na rejestrację wszystkich stanów sygnału. Wskazano, że oba przerwania powinny być ustawione na to samo zbocze, aby poprawnie określić kierunek obrotu. Alternatywnie, Bascom oferuje funkcję ENCODER, która nie korzysta z przerwań i może być użyta do obsługi enkodera na dowolnych pinach jednego portu, choć nie zawsze działa poprawnie z każdym typem enkodera. Wskazano również na konieczność konfiguracji podciągania wejść (pull-up) na portach mikrokontrolera, co wpływa na stabilność odczytu sygnałów. Przykłady kodów i linki do dokumentacji BascomAVR (AN 115) oraz artykułów z Circuit Cellar zostały podane jako pomocne materiały. Ostatecznie, prostsze rozwiązanie z jednym przerwaniem na zbocze narastające sygnału A i odczytem stanu sygnału B w przerwaniu zostało potwierdzone jako skuteczne i stabilne w praktyce.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA