Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Xmega 256a3u, stepper driver using a rotary encoder

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
sq2eer

Bascom Member



Joined: 16 Aug 2011
Posts: 7
Location: Pelplin

poland.gif
PostPosted: Sun Oct 11, 2020 10:17 pm    Post subject: Xmega 256a3u, stepper driver using a rotary encoder Reply with quote

Hello, I would like to ask for help in writing a program that controls a stepper motor using a rotary encoder.
My Bascom :
Don't forget that Serial numbers should not be sent to the user list.
Make sure you sent your email to support and not a public list !

Compiler version :2.0.8.3
Compiler build :2.0.8.3.005
IDE version :2.0.8.3.003
Serial number Madx-xxxx-xxxxx
Windows OS :Windows 7 Ultimate
Company :
Owner :Jacek
Windows dir :C:\Windows
App data dir :C:\Users\Jacek\AppData\Roaming\MCS Electronics
System dir :C:\Windows\system32

the microcontroller is xmega 256a3u, encoder configuration

Code:

Config Pina.3 = Input                                       'enkoder osi Z kanał A
Config Pina.4 = Input                                       'enkoder osi Z kanał B
Config Pina.5 = Input                                       'enkoder osi Z kanał Index
Config Xpin = Porta.3 , Outpull = Totem , Sense = Both
Config Xpin = Porta.4 , Outpull = Totem , Sense = Both
Config Xpin = Porta.5 , Outpull = Totem , Sense = Both
 

Code:

Config Event_system = Dummy , Mux2 = Porta.3 , Qd2 = Enabled , Qdi2 = Enabled , Qdirm2 = 0 , Digflt2 = 8
Config Tcd0 = Normal , Prescale = E2 , Event_source = E2 , Event_action = Capture       'Qdec
 


connecting a stepper motor to xmega
Code:

Config Portb.3 = Output                                     'DIR OŚ Z
Config Xpin = Portb.3 , Outpull = Totem
Config Portb.4 = Output                                     'ENABLE OŚ Z
Config Xpin = Portb.4 , Outpull = Totem
Config Portc.0 = Output                                     'STEP OŚ Z
Config Xpin = Portc.0 , Outpull = Totem
 

program for capturing impulses from the encoder
Code:
'odczyt pokrętła osi Z
$nocompile
Sub Z_os_odczyt
   If Tcd0_cnt <> Z_enkoder_tmp Then                        'jesli zawartosc timera TCD0 jest ró&#380;na od naszej zmiennej to
      Z_enkoder_tmp = Tcd0_cnt                              'przepisz now&#261; warto&#347;&#263; z timera TCD0 do zmiennej enkoder_tmp
      Z_enkoder_tmp_1 = Tcd0_cnt / 4                        '  four inpulses per one step of teh encoder  so wee need only one
      If Z_enkoder_tmp_1 <> Z_enkoder_tmp_2 Then            'Je&#347;li zmienna Enkoder_tmp_1 jest ró&#380;na od zmiennej  Enkoder_tmp_2
         Z_enkoder_tmp_2 = Z_enkoder_tmp_1                  'wstaw warto&#347;&#263; zmiennej Enkoder_tmp_1 do zmiennej Enkoder_tmp_2
      End If
   End If
End Sub
 

subroutine call
Code:

Do
'''Waitms 500
'''Printbin #dwin , &H5A ; &HA5 ; &H04 ; &H83 ; &H140 ; &H01   '[pl] wyslij zapytanie do LCD  [en] sent request to lcd
'#dwin -[pl] numer portu com deklarowany w w prgramie glownym  [en] com port declared in mian file
'&H5a -[pl] naglowek transmisi 1 [en] transmistion header 1
'&Ha5 -[pl] naglowek transmisi 2 [en] transmistion header 2
'&H04 -[pl] ile bajtow wysylamy  [en] nuber of bytes to sent
'&H83- [pl] komenda odczyt       [en] read commnad
'Dwin_ad- [pl] adres w pamieci wyswietlacza [en] memmory adress
'&H01-[pl] ile zimmeych odczytaj (word) [en] numer of words to read
'[pl] tu odczytujemy tyko jednego worda [en] we are reading only one word here

   Call Rpm_odczyt
   Call Z_os_odczyt

   If Tcf0_intflags.0 = 1 Then
      Flaga10ms = 1
      Incr Timer_tikx10
      Tcf0_intflags.0 = 1
   End If

   If Timer_tikx10 >= 10 Then
      Incr Timer_tikx100
      Flaga100ms = 1
      Timer_tikx10 = 0
   End If

   If Timer_tikx100 >= 5 Then
      Incr Timer_tikx500
      Flaga500ms = 1
      Timer_tikx100 = 0
   End If

   If Timer_tikx500 >= 2 Then
      Incr Timer_tikx1000
      Flaga1s = 1
      Timer_tikx500 = 0
   End If

'



  ' Tcc0_cca = 15942                                         '500Hz
'   Wait 5
'   Tcc0_cca = 1595                                          '5kHz
'   Wait 5
'   Tcc0_cca = 750                                           '10,6kHz
'   Wait 5
'   Tcc0_cca = 375                                           '21,2kHz
'   Wait 5
'    Tcc0_cca = 350                                          '22,7 kHz
'   Wait 5
'    Tcc0_cca = 375                                          '21,2kHz
'   Wait 5
'   Tcc0_cca = 750                                           '10,6kHz
'   Wait 5
'   Tcc0_cca = 1595                                          '5kHz
'   Wait 5
   '==========================================================
   If Flaga10ms = 1 Then
      Tcd0_cnt = 0
      Flaga10ms = 0
   End If
   If Flaga100ms = 1 Then
      Flaga100ms = 0
   End If
   If Flaga500ms = 1 Then
      Toggle Portc.5
      Flaga500ms = 0
   End If

   If Flaga1s = 1 Then

      Rpm_a = Rpm_enkoder_tmp_2 / 720
      Rpm_c = Rpm_a * 60
      Rpm_r = Rpm_c

      'Print #4 , "wynik " ; Dwin_var_rx
      'Print #4 , "tab_rx 1 " ; Hex(dwin_arr_rx(1))
      'Print #4 , "tab_rx 2 " ; Hex(dwin_arr_rx(2))
      'Print #4 , "tab_rx 3 " ; Hex(dwin_arr_rx(3))          'ile zmiennych 5 defaultowo!
      'Print #4 , "tab_rx 4 " ; Hex(dwin_arr_rx(4))          'read
      'Print #4 , "tab_rx 5 " ; Hex(dwin_arr_rx(5))          'address_h"
      'Print #4 , "tab_rx 6 " ; Hex(dwin_arr_rx(6))          'address_l
      'Print #4 , "tab_rx 7 " ; Hex(dwin_arr_rx(7))          'ile word odczyta&#263;
      'Print #4 , "tab_rx 8 " ; Hex(dwin_arr_rx(Cool)          'value_h
      'Print #4 , "tab_rx 9 " ; Hex(dwin_arr_rx(9))          'value_l
      'Print #4 , "Obroty " ; Rpm_r
      'Print #4 , "Z_enkoder_tmp_2 " ; Z_enkoder_tmp_2
      'Print #4 , "Z_enkoder_tmp_1 " ; Z_enkoder_tmp_1
      'Print #4 , "Posuw Z lcd " ; Posuw_z_lcd
      'Print #4 , "Posuw X lcd  " ; Posuw_x_lcd
      'Print #4 , "TCC0_CCA Timer Step Z " ; Tcc0_cca
      'Print #4 , "TCD0_CNT Timer Enkoder Z " ; Tcd0_cnt
      'Print #4 , "TCE0_CNT Timer RPM " ; Tce0_cnt

      Posuw_z_lcd = Dwin_lcd_get_var_value(&H140 )          'wstaw do zmiennej warto&#347;&#263; z adresu hex
      If Posuw_z_lcd <> Posuw_z Then                        'je&#347;li zmienna programu jest ró&#380;na od zmiennej z adresu hex
         Posuw_z = Posuw_z_lcd                              'to do zmiennej programu wstaw warto&#347;&#263; zmiennej z adresu hex
         Posuw_z_eeprom = Posuw_z_lcd                       'warto&#347;&#263; zmiennej z adresu hex wstaw do zmiennej do zapisu zmiennej w eeprom
         Posuw_z_tmp_1 = Posuw_z_lcd / 1000
         Print #4 , "NOWY SKOK POSUWU Z " ; Posuw_z_tmp_1
         Writeeeprom Posuw_z_eeprom , 100                   ' zapisz zmienn&#261; w eeprom w komórce
      End If

     'Posuw_x_lcd = Dwin_lcd_get_var_value(&H160 )           'odczytaj z adresu hex
      Call Lcd_var_write(&H120 , Rpm_r)
      Tce0_cnt = 0                                          'Zerowanie Timer'a enkodera RPM
      Flaga1s = 0
   End If









Loop

End
 

I wish it would work like in this movie https://www.youtube.com/watch?v=To7S_rLIJwk&t=115s
5min 05sec.
unfortunately I don't know how to do it to make it work best as a subroutine.
sorry for my english but i use google translator
greetings Jacek.

(BASCOM-AVR version : 2.0.8.3 )
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Tue Oct 13, 2020 9:54 am    Post subject: Reply with quote

The video explains it quite well, however the stepper functionality is encapsulated within a lib called 'AccelStepper', this functionality you have to implement yourself.
For this purpose I suggest to use a timer interrupt, to compare actual with set position and put out step/en/dir.

Code for stepper control is short and can be placed directly into the interrupt service routine.
Motor speed can be controlled by TOP of timer (in combination with config timer CLEAR_TIMER), alternatively a soft timer, as you've tried to implement, is thinkable.
Controlling the interrupt speed itself will be likely faster, will eat up less power and run smoother than creating an 1/00s timer value and updating steppers in the main loop.
One more (power hungry) way is a fast timer interrupt, wherein a soft timer works, speed is controlled via this soft timer and stepper is updated also from therein, this would be the approach if more steppers need to be taken care of. Speed of the timer decides then over max speed of the motors.

The whole thing will become a bit more complicated if you want to have acceleration ramps, however for this simple experiment with one motor you can likely omit ramps and control directly via timer ISR.
Back to top
View user's profile
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 971

poland.gif
PostPosted: Tue Oct 13, 2020 11:17 am    Post subject: Reply with quote

Cause me and Jacek we are from Poland then we know each other from polish forums.

Jacek`s goal was to use Xmegas bulit in hardware quadrature encoders decoding with using event system.
This gives result in the 16bit timer/counter 0-65535.

Jacek want to control motor with the encoder into the left, stop and right manually for test Very Happy

This is not very complicated when first turn it right because value grow from zero->65535. Difference always can be measured by substract prev value from actual. But when first turn is into the left or we overflow timer turning encoder backward then from 0 we got 65535. This was some challenge Very Happy

So yesterday, after quick scratch my head I came with this simple solution (for test only, without any interrupts).

Code:

 Dim Encoder_tmp As Word , Encoder_prev As Word ,  Steps As Integer

Do

       Encoder_tmp = Tcd0_cnt

       If Encoder_prev <> Encoder_tmp Then

             Select Case Encoder_prev
               Case 0
                If Encoder_tmp = 1 Then Incr Steps Else Decr Steps
               Case Else
                Select Case Encoder_tmp
                 Case Is < Encoder_prev : Decr Steps
                 Case Is > Encoder_prev : Incr Steps
                End Select
              End Select

        Encoder_prev = Encoder_tmp
          Print #buart_channel , Steps
       End If
'------------------------------------[every 1ms only for some step execute]---
       If 1ms = 1 Then
        1ms = 0

          If Motor_step_pin = 1 Then
           Reset Motor_step_pin
          Else

             Select Case Steps
              Case Is < 0
               Incr Steps
                Call Set_direction_l
               Set Motor_step_pin
              Case Is > 0
               Decr Steps
                Call Set_direction_r
               Set Motor_step_pin
             End Select

          End If

       End If
'-------------------------------------------------------------------------------
Loop


This is the first think. Maybe this can be recognized better? Very Happy
There is a DIR bit in the TCD0_CTRLFCLR that maybe I must study and can be helpful here. I dont know yet.

The ramp for speed should not be dificult.
After all yesterday motor works like a slave for the encoder Very Happy but maybe someone have better solution Wink
Back to top
View user's profile Visit poster's website
sq2eer

Bascom Member



Joined: 16 Aug 2011
Posts: 7
Location: Pelplin

poland.gif
PostPosted: Tue Oct 13, 2020 8:42 pm    Post subject: Reply with quote

Hello everyone, this is a test control of the Z axis from the lathe in manual mode. The video shows how nicely the motor reacts to turning the encoder https://www.youtube.com/watch?v=uV2L4_Cck_I then I had not yet set the timer division by four (four edges of channels a and b) so the motor did four times as many revolutions as the encoder at the end of the movie, I exaggerated with shooting and a driver error popped up now, when I give thanks, the reading from the encoder for four is very good and all thanks to Bartek EDC, I greet everyone Jacek.
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Wed Oct 14, 2020 1:56 pm    Post subject: Reply with quote

sq2eer wrote:
this is a test control of the Z axis from the lathe in manual mode.
Most lathe have no Z-axis, as then they would be called 'mill'. I assume you mean X-axis (horizontal feed)?!

Quote:
I exaggerated with shooting and a driver error popped up
The trick is to be as fast as the encoder (which is given and handled internally by the XMega), while not pushing pulses out faster than the driver hardware can handle. Your sample code shows this flaw, it lacks a mechanism to respect maximum specs of the driver.

As the goal is an electronic gearbox, I do not expect an elevated challenge for speed and change of direction, so this code may work well for its purpose.
But on the other hand you will not be happy, if you just cut a thread on the lathe and the horizontal feed suddenly stalls, because the hardware-driver shuts down with an error.
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Fri Oct 16, 2020 4:02 pm    Post subject: Reply with quote

Just my input on ramps for steppers. I usually use a percentage calculation of the Distance to be accomplished with max. acceleration and start out frequency as limits. This works quite well and does not need a "FUZZY License". Could also be implemented with rotary sensor.
Best regards
Hubert
Back to top
View user's profile
sq2eer

Bascom Member



Joined: 16 Aug 2011
Posts: 7
Location: Pelplin

poland.gif
PostPosted: Fri Oct 16, 2020 9:08 pm    Post subject: Reply with quote

Hello

MWS - we have such a coordinate system in lathes
as EDC wrote earlier this is a test program and needs some fine-tuning.

hgrueneis - can you explain it with some example.

Regards Jacek.
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Sat Oct 17, 2020 6:50 am    Post subject: Reply with quote

sq2eer wrote:
MWS - we have such a coordinate system in lathes

In my coordinate system, Z is the vertical axis.
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum