Xmega sprzętowa obsługa enkodera -to takie proste

Rodzina procesorów bogatszych w wiele nowych rozwiązań i dlatego warto po nie sięgnąć.
Zablokowany
Awatar użytkownika
Pikczu
Posty: 390
Rejestracja: 17 sie 2015, 13:46
Lokalizacja: Dublin, Ireland
Kontakt:

Xmega sprzętowa obsługa enkodera -to takie proste

Post autor: Pikczu » 29 kwie 2017, 17:44

Minęło już kilka lat od wprowadzenia na rynek przez firmę Atmel nowej rodziny procesorów z serii Xmega.
Przez długi okres czasu trzymałem się od nich z daleka. Częściowo ze strachu przed nowym oraz chronicznym brakiem czasu.
Aż do momentu gdy Bartek namówił mnie na zakup płytki testowej z LEON INSTRUMENTS z Xmega128A3U na pokładzie.
http://www.leon-instruments.pl/

Oczywiście układ musiał nabrać mocy prawnej przeleżał na półce prawie rok aż w końcu nadszedł czas na testy.
Pierwszym pozytywnym zaskoczeniem było programowanie przy pomocy FLIP-a wpinamy USB naciskamy dwa przyciski zwalniamy najpierw RESET potem FLIP i gotowe. Teraz wystarczy kliknąć OK i nasz układ jest już zaprogramowany.
Pierwsze kroki i zdecydowany plus.
Kolejnym zdecydowanym plusem (w moim prywatnym odczuciu) było zasilanie układu z 3.3V gdy zaistniała potrzeba podłączenia się do jednego z modułów WIFI.
W miarę "dotykania" nowa Xmega zaskakiwała mnie coraz bardziej niekończącą się listą usprawnień i udogodnień w stosunku do swoich poprzedników.
Nie ma sensu w tym momencie wymieniać wszystkich.
Dlatego wymienię tylko trzy:
Taktowanie 32Mhz
Duża ilość uartów (Xmega 128A3U ma ich aż 8)
Oraz wbudowana sprzętowa obsługa enkoderów inkrementalnych.

Chcąc koniecznie zrozumieć działanie systemu zdarzeń oraz w końcu skorzystać z wbudowanej obsługi enkodera.
Natrafiłem na przykład napisany przez jednego z bascomowych wyjadaczy użytkownika MAK3 z forum bascomforum.de
https://www.mcselec.com/index.php?optio ... &Itemid=57
Było tam kilka operacji na rejestrach ponieważ Mark Alberts jeszcze nie skończył pisać bibliotek do Bascoma.

Wspomagając się notą aplikacyjną dla Xmega_Au postanowiłem uruchomić sprzętową obsługę enkodera co okazało się wręcz banalne.
Poniżej przedstawiam dwa działające przykłady obsługi enkodera inkrementalnego.
Przykład pierwszy jest wycinkiem kodu kolegi MAK3 z wykorzystaniem rejestrów.
  1. '***********************************************************************
  2. 'Xmega quadrature encoder test base on MAK3 exaple
  3. ' Przykład 1
  4. '$sim
  5. $regfile = "xm128a3udef.dat"
  6. $crystal = 32000000
  7. $hwstack = 64
  8. $swstack = 64
  9. $framesize = 64
  10.  
  11. 'Enable The Osc
  12. Config Osc = Enabled , 32mhzosc = Enabled
  13.  
  14. ' ***************** SYSTEM CLOCK CONFIG ********************************
  15. '                INTERNAL 32MHz NO PRESCALE
  16. '
  17. Config Osc = Disabled , 32mhzosc = Enabled , 32khzosc = Enabled
  18. Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
  19. '
  20. 'ENABLING AUTOMATIC OSCILLATOR CALIBRATION
  21. Osc_dfllctrl.0 = 1
  22. Dfllrc32m_ctrl.0 = 1
  23. '
  24. '***********************************************************************
  25. Config Priority = Static , Vector = Application , Lo = Enabled       'Enable Lo Level Interrupts
  26. '***********************************************************************
  27. '*******************Xmega 128A3U***********************
  28. '* UART *********** TX pin  *  RX pin                 *
  29. '* ****************************************************
  30. '* COM1 - UART_C0 * PORTC.3 * PORTC.2                 *
  31. '******************************************************
  32. '* COM2 - UART_C1 * PORTC.7 * PORTC.6                 *
  33. '******************************************************
  34. '* COM3 - UART_D0 * PORTD.3 * PORTD.2                 *
  35. '******************************************************
  36. '* COM4 - UART_D1 * PORTD.7 * PORTD.6                 *
  37. '******************************************************
  38. '* COM5 - UART_E0 * PORTE.3 * PORTE.2                 *
  39. '******************************************************
  40. '* COM6 - UART_E1 * PORTE.7 * PORTE.6                 *
  41. '******************************************************
  42. '* COM7 - UART_F0 * PORTF.3 * PORTF.2                 *
  43. '******************************************************
  44. '* COM8 - UART_F1 * PORTF.7 * PORTF.6                 *
  45. '******************************************************
  46.  
  47. '***********************************************************************
  48. Dim Buart_channel As Byte                                   '0 = COM1 ...... 7 = COM8
  49. Config Com3 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8       'COM3 - UART_D0 PORTD.3 PORTD.2
  50. Config Com1 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8       'COM1 - UART_C0 PORTC.3 PORTC.2
  51. Buart_channel = 2
  52. Print #buart_channel , "This use COM3"                      'print current Uart
  53. Print #buart_channel , "MCU Rev. = " ; Mcu_revid            'version of the MCU
  54.  
  55.  
  56. '***********************************************************************
  57. DIm enkoder_tmp as dword                                    'zmienna dla enkodera                                  '
  58. Enable Interrupts                                           'włacz przerwania globalne
  59.  
  60. '--------------------------MAK3 example---------------------------------
  61. Config PortA.0 = Input                                      'PinA.0 = A
  62. PortA_pin0ctrl = &B00_000_011                               'Totempole/low level
  63.                        '^   ^
  64.                        '^   low level
  65.                        '^
  66.                        'No Pull configuration
  67. Config PortA.1 = Input                                      'PinA.1 = B
  68. PortA_pin1ctrl = &B00_000_011                               'Totempole/low level
  69.  
  70. '***********************************************************************
  71. Evsys_ch0mux = &B0101_0_000                                 'PortA Pin 0 i automatycznie pin 1
  72.                  '^       ^                                  'manual xmega_Au page 78
  73.                  '^       ^
  74.                  '^       ^Pin0
  75.                  'portA
  76. reset Evsys_ch0ctrl.2 : Set Evsys_ch0ctrl.1 : Set Evsys_ch0ctrl.0       '011- Digital Filter dla  4 probki
  77. Set Evsys_ch0ctrl.3                                         'właczenie enkodera strona 78 xmega_Au manual
  78. '***********************************************************************
  79. 'ustawiamy Timer/Counter D0 aby zliczał impusly ekondera z systemu zdażen
  80. TcD0_ctrld = &B011_0_1000                                   'Event Action = Quadratur Encoding, nasłuchuj na kanale 0
  81.               '^  '^ '^
  82.               '^  '^ 'EVSEL[3:0]
  83.               '^
  84.               'Evact[7:5] manual xmega_Au strona 175
  85. '000 OFF None
  86. '001 CAPT Input capture
  87. '010 UPDOWN Externally controlled up/ down count
  88. '011 QDEC Quadrature decode
  89. '100 RESTART Restart waveform period
  90. '101 FRQ Frequency capture
  91. '110 PW Pulse width capture
  92. '111 Reserved
  93.  
  94. 'EVDLY
  95. 'EVSEL[3:0]
  96. '1nnn CHn Event channel n, n={0,...,7}
  97. '**********************************************************************
  98. Tcd0_ctrla = &B0000_1000                                    'Start Timer  event chanel 0 xmega manual_Au strona 175
  99. '**********************************************************************
  100. enkoder_tmp = 0
  101.  
  102. Do
  103.  
  104.    if TCD0_cnt <> enkoder_tmp then                          'jesli zawartosc timera TCD0 jest różna od naszej zmiennej to
  105.       enkoder_tmp = TCD0_cnt                                'przepisz nową wartość z timera TCD0 do zmiennej enkoder_tmp
  106.       Print #buart_channel , enkoder_tmp                    'wyśli przez port szeregowy 2  zmienna buart=2
  107.    end if
  108.  
  109. Loop
  110.  
  111. end                                                         'end program
Przykład drugi robi dokładnie to samo z użyciem składni Bascoma.
Wystarcz tylko sześć linii kodu aby uruchomić obsługę enkodera.
Przechwytywanie zdarzeń wykonywane jest automatycznie w tle bez potrzeby dodatkowego kodu.


config pinA.1 = input
config PinA.0 = input
Config Xpin = PortA.1 , Outpull = pullup , Sense = low_level
Config Xpin = PortA.0 , Outpull = pullup , Sense = low_level

config Event_system = Dummy , Mux0 = portA.0 , QD0 = enabled , Digflt0 = 8
Config Tcd0 = Normal , Prescale = e0 , Event_source = E0 , Event_action = QDEC
  1. '***********************************************************************
  2. 'Xmega quadrature encoder test base on MAK3 exaple
  3.  'Przyklad 2
  4. '$sim
  5. $regfile = "xm128a3udef.dat"
  6. $crystal = 32000000
  7. $hwstack = 64
  8. $swstack = 64
  9. $framesize = 64
  10.  
  11. 'Enable The Osc
  12. Config Osc = Enabled , 32mhzosc = Enabled
  13.  
  14. ' ***************** SYSTEM CLOCK CONFIG ********************************
  15. '                INTERNAL 32MHz NO PRESCALE
  16. '
  17. Config Osc = Disabled , 32mhzosc = Enabled , 32khzosc = Enabled
  18. Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
  19. '
  20. 'ENABLING AUTOMATIC OSCILLATOR CALIBRATION
  21. Osc_dfllctrl.0 = 1
  22. Dfllrc32m_ctrl.0 = 1
  23. '
  24. '***********************************************************************
  25. Config Priority = Static , Vector = Application , Lo = Enabled       'Enable Lo Level Interrupts
  26. '***********************************************************************
  27. '*******************Xmega 128A3U***********************
  28. '* UART *********** TX pin  *  RX pin                 *
  29. '* ****************************************************
  30. '* COM1 - UART_C0 * PORTC.3 * PORTC.2                 *
  31. '******************************************************
  32. '* COM2 - UART_C1 * PORTC.7 * PORTC.6                 *
  33. '******************************************************
  34. '* COM3 - UART_D0 * PORTD.3 * PORTD.2                 *
  35. '******************************************************
  36. '* COM4 - UART_D1 * PORTD.7 * PORTD.6                 *
  37. '******************************************************
  38. '* COM5 - UART_E0 * PORTE.3 * PORTE.2                 *
  39. '******************************************************
  40. '* COM6 - UART_E1 * PORTE.7 * PORTE.6                 *
  41. '******************************************************
  42. '* COM7 - UART_F0 * PORTF.3 * PORTF.2                 *
  43. '******************************************************
  44. '* COM8 - UART_F1 * PORTF.7 * PORTF.6                 *
  45. '******************************************************
  46.  
  47. '***********************************************************************
  48. Dim Buart_channel As Byte                                   '0 = COM1 ...... 7 = COM8
  49. Config Com3 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8       'COM3 - UART_D0 PORTD.3 PORTD.2
  50. Config Com1 = 115200 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8       'COM1 - UART_C0 PORTC.3 PORTC.2
  51. Buart_channel = 2
  52. Print #buart_channel , "This use COM3"                      'print current Uart
  53. Print #buart_channel , "MCU Rev. = " ; Mcu_revid            'version of the MCU
  54.  
  55.  
  56. '***********************************************************************
  57. DIm enkoder_tmp as dword                                    'zmienna dla enkodera
  58. Enable Interrupts                                           'włacz przerwania globalne
  59. '***********************************************************************
  60. 'config pinA.2 = input                                       'index pin of the encoder
  61. config pinA.1 = input                                       'enkoder B
  62. config PinA.0 = input                                       'enkoder A
  63. 'Config Xpin = PinA.2 , Outpull = pullup , Sense = low_level
  64. Config Xpin = PortA.1 , Outpull = pullup , Sense = low_level       'enable Pull up and reaction on low level
  65. Config Xpin = PortA.0 , Outpull = pullup , Sense = low_level
  66. 'konfigurujemy system zdarzeń
  67.  
  68. config Event_system = Dummy , Mux0 = portA.0 , QD0 = enabled , Digflt0 = 8
  69. 'konfiguracja systemu zdarzeń multiplexer kanał 0 , portA.0, obsługa enkodera QDO właczona, filtr  cyfrowy 8
  70.  
  71. 'gdy używamy idndexu musimy dodać QDIO=enabled
  72. 'config Event_system = Dummy , Mux0 = portA.0 , QD0 = enabled , QDI0 = enabled , Digflt0 = 8
  73.  
  74.  
  75. '***********************************************************************
  76. Config Tcd0 = Normal , Prescale = e0 , Event_source = E0 , Event_action = QDEC
  77.  
  78. 'konfiguracja timera TCD0 normal= bez generowania sygnałów, preskaler =e0, zródło zdarzenia=podajemy zródło czyli event system
  79. 'kanał 0 , event action =czyli reakcja na zdarzenie QDEC właczenie obsługi enkodera
  80. '***********************************************************************
  81.  
  82. enkoder_tmp = 0
  83.  
  84. Do
  85.  
  86.    if TCD0_cnt <> enkoder_tmp then                          'jesli zawartosc timera TCD0 jest różna od naszej zmiennej to
  87.       enkoder_tmp = TCD0_cnt                                'przepisz nową wartość z timera TCD0 do zmiennej enkoder_tmp
  88.       Print #buart_channel , enkoder_tmp                    'wyśli przez port szeregowy 2 (zmienna buart=2)
  89.    end if
  90.  
  91.   'na ekranie termianla zobaczymy liczbe impulsów policzonych przez nasz timer.
  92.   'na jeden przeskok enkodera przypadaja 4 impulsy
  93.  
  94.  
  95. Loop
  96.  
  97. end                                                         'end program
Aby zrozumieć składnię użytą do konfiguracji systemu zdarzeń zrobiłem prosta tabelke w exelu.
Którą można pobrać z mojego droboxa.
https://www.dropbox.com/sh/ot7nltgx0kjc ... Heqta?dl=0

Co tak naprawdę jest wymagane do uruchomienia naszego enkodera dokładnie widać w przykładzie pierwszym.
Koniecznie musimy wybrać piny ale muszą to być dwa (lub trzy jeśli używamy Indexu) w kolejności.
  1. config pinA.1 = input                                       'encoder B
  2. config PinA.0 = input                                       'enkoder A
  3.  
  4. Config Xpin = PortA.1 , Outpull = pullup , Sense = low_level       'enable Pull up and reaction on low level
  5. Config Xpin = PortA.0 , Outpull = pullup , Sense = low_level
  6. 'konfigurujemy system zdarzeń
Konfigurujemy system zdarzeń w rejestrze o nazwie CHnMUX xmega Au manual strona 77
Obrazek
Ustawiamy bity według tabeli dla portu A będzie to:
Evsys_ch0mux = &B0101_0_000 'PortA Pin 0 i automatycznie pin 1


Obrazek

Kolejny krok to ustawienie odpowiednich bitów w rejestrze CHnCTRL- Event Channel n Control register
  1. reset Evsys_ch0ctrl.2 : Set Evsys_ch0ctrl.1 : Set Evsys_ch0ctrl.0       '011- Digital Filter dla  4 probki
  2. Set Evsys_ch0ctrl.3                                         'właczenie enkodera strona 78 xmega_Au manual
Obrazek


Wybieramy 4 próbki bity 2 do 0 oraz włączamy obsługę naszego enkodera bit 3.
Jeśli nie używamy indexu pomijamy bit 4.

Obrazek

Teraz wystarczy włączyć nasz Timer TCD0 aby zliczał impulsy:
W rejestrze CTRLA dla timera TCD0 wybierając odpowiedni kanał zdarzeń w tym przypadku 0
  1. Tcd0_ctrla = &B0000_1000                                    'Start Timer  event chanel 0 xmega manual_Au strona 175
Obrazek

I możemy cieszyć się sprzętową obsługą enkodera.
Prawda jakie to proste :)




Obrazek

Obrazek
Ostatnio zmieniony 02 paź 2017, 20:02 przez Pikczu, łącznie zmieniany 1 raz.
Awatar użytkownika
Jacek
Posty: 384
Rejestracja: 25 kwie 2016, 19:14

Re: Xmega sprzętowa obsługa enkodera -to takie proste

Post autor: Jacek » 03 maja 2017, 13:40

Witam - ciekawe Paweł jak to będzie działać w urządzeniu które chodzi mi po głowie do................... tokarki hi - ale to jak przyjdzie drugi enkoder 1000imp/obr - pozdrawiam i trzymam kciuki Jacek.
Awatar użytkownika
Pikczu
Posty: 390
Rejestracja: 17 sie 2015, 13:46
Lokalizacja: Dublin, Ireland
Kontakt:

Re: Xmega sprzętowa obsługa enkodera -to takie proste

Post autor: Pikczu » 03 maja 2017, 19:19

Jacek z tego co testowałem z enkoderem na czujniku hala działa wyśmienicie.
Można podpiąć trzy enkodery na raz.
Zablokowany