View previous topic :: View next topic |
Author |
Message |
sq2eer
Joined: 16 Aug 2011 Posts: 7 Location: Pelplin
|
Posted: Sun Oct 11, 2020 10:17 pm Post subject: Xmega 256a3u, stepper driver using a rotary encoder |
|
|
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 x-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óżna od naszej zmiennej to
Z_enkoder_tmp = Tcd0_cnt 'przepisz nową wartość 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śli zmienna Enkoder_tmp_1 jest różna od zmiennej Enkoder_tmp_2
Z_enkoder_tmp_2 = Z_enkoder_tmp_1 'wstaw wartość 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ć
'Print #4 , "tab_rx 8 " ; Hex(dwin_arr_rx() '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ść z adresu hex
If Posuw_z_lcd <> Posuw_z Then 'jeśli zmienna programu jest różna od zmiennej z adresu hex
Posuw_z = Posuw_z_lcd 'to do zmiennej programu wstaw wartość zmiennej z adresu hex
Posuw_z_eeprom = Posuw_z_lcd 'wartość 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ą 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 |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Tue Oct 13, 2020 9:54 am Post subject: |
|
|
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 |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
|
Back to top |
|
|
sq2eer
Joined: 16 Aug 2011 Posts: 7 Location: Pelplin
|
Posted: Tue Oct 13, 2020 8:42 pm Post subject: |
|
|
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 |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Wed Oct 14, 2020 1:56 pm Post subject: |
|
|
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 |
|
|
hgrueneis
Joined: 04 Apr 2009 Posts: 902 Location: A-4786 Brunnenthal
|
Posted: Fri Oct 16, 2020 4:02 pm Post subject: |
|
|
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 |
|
|
sq2eer
Joined: 16 Aug 2011 Posts: 7 Location: Pelplin
|
Posted: Fri Oct 16, 2020 9:08 pm Post subject: |
|
|
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 |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Sat Oct 17, 2020 6:50 am Post subject: |
|
|
sq2eer wrote: | MWS - we have such a coordinate system in lathes |
In my coordinate system, Z is the vertical axis. |
|
Back to top |
|
|
|
|
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
|
|