Step or velocity control for servo gantry

More
07 Jul 2014 19:57 #48490 by crisiacuf
Hello everybody,

I just finished the mechanical construction of a 4 axis gantry.
I am using Mitsubishi MRJ2S-A servos, 5um linear glass scales on each axis(X,Y1,Y2,Z) and MESA boards: 5i25 , 7i76, 7i77, 7i85S.
My Y axis has dual drive. I initially tried position control and used the Y servos as master-slave(got the step signal from Y1 output and feed it to Y2; used the 5i25 and 7i76).
Now I added linear scales on each axis and want to use them in a closed loop. The servos have their own closed loop.

My dilemma is THIS: shell I use step control or speed control?
And my question is THIS: How should I configure pncconf to use 2 joints on Y axis and create a closed loop using the linear scales and the available MESA boards?
Any help is greatly appreciated. I looked everywhere for a similar setup with servos and linear scales but no luck.


Best regards

Please Log in or Create an account to join the conversation.

More
07 Jul 2014 20:08 #48491 by emcPT
7i77 for speed control

Regarding a gantry method look to DaBit recent post (+-3 months) ago. Several approaches were taken in account.
The following user(s) said Thank You: crisiacuf

Please Log in or Create an account to join the conversation.

More
07 Jul 2014 21:16 - 07 Jul 2014 21:23 #48494 by DaBit
I am using servos for the X and Y1/Y2 axes (stepper on Z) on my gantry-style machine under construction using linear scales for position feedback. I just finished the mechanical install of the Y-axes scales but did not yet hook them up. X and Z scales are in place, hooked up and added to the positioning loop.

X axis is using a (SINO) 5um resolution scale, Y and Z axes are using (Ditron) 1um resolution scales. 5um does work, but is a bit coarse. 1um is much better for closing the loop.

I am running my servos in torque mode (because I had to, not because I wanted to), controlled using analog -10V ..+10V using a Mesa 7i77.
The Z-axis stepper is controlled in velocity mode using step/dir. If I had modern servo drives I could have used step/dir with the LinuxCNC/Mesa stepgen in velocity mode.

I toyed around with gantrykins, with the JA4 branch, and modified the homing code to keep the gantry square during the homing process.
But in the end I got tired of all the little issues that pop up using a not-entirely-trivial kinematics configuration and configured the machine as a regular 3-axis trivial kinematics machine. Both Y axes are slaved in HAL and I have a HAL signal available to create an offset between the two when desired.

Someday I might want to do something smart with finding the index pulses on the scales and setting the offset according to the findings. But constructing a CNC mill from the ground up takes a lot of time and there are 'nice to haves' and 'must haves'. Until now the gantry seems mechanically stable; without ballscrews attached and one side locked it takes 40N to push it 0,01mm out of square. So I moved the automatic-squaring to the 'nice to have, can do that later' list for now.

I did not use PnCConf to generate config files, but handcrafted them myself from the ground up. Setups using servos with scales in the feedback loop etcetera are not point 'n click material anyway.

If you want to have a look: here is my current configuration.

Fairly recent photo of the machine involved: here

Please keep in mind that this is still work in progress, not polished and not bugfree (gmoccapy toolchange window is not coming up, for example).
Last edit: 07 Jul 2014 21:23 by DaBit.

Please Log in or Create an account to join the conversation.

More
10 Jul 2014 22:45 #48615 by crisiacuf
Thank you very much for your info.
I finally start it today but I have joint following errors for speeds above 600mm/s
Here is a picture of my setup:




Any idea why I have these errors?
Attachments:

Please Log in or Create an account to join the conversation.

More
10 Jul 2014 22:57 - 10 Jul 2014 23:00 #48616 by crisiacuf
My config files:

File Attachment:

File Name: my_LinuxCN...nef2.ini
File Size:4 KB


File Attachment:

File Name: my_LinuxCN...nef2.hal
File Size:13 KB
Attachments:
Last edit: 10 Jul 2014 23:00 by crisiacuf.

Please Log in or Create an account to join the conversation.

More
10 Jul 2014 23:18 #48617 by DaBit
Without further information: no.

We would need config files and some halscope plots of PID outputs, f-error, etc. to determine the cause of those errors. Did you do an effort to tune the system?

BTW: I have my Y-axes running with scale feedback too. So now all my axes are running with scale feedback.

Regarding speed: I am limited to 20 meters/minute for my setup because that's the maximum speed of the 1-micron scales, so I set LinuxCNC to 18 meters/minute to have some headroom. Without scales or with 5u scales I can go up to 35 meters/minute or so before the servo's start running out of revs.

That's 500mm/sec, slower than your 600mm/sec. In the end it also depends on screw pitch, transmission ratio between motor and screw, rotating mass, moving mass, etc.

Acceleration is different: I limited that to 0,3G for testing and because I need to brace the frame better (I am moving around ~130kg gantry+Z and that mass is up high ..). But the servo's are scratching their nose at those speeds. Even with 1G they are still not delivering their nominal continuous torque.

Please Log in or Create an account to join the conversation.

More
11 Jul 2014 17:58 #48644 by crisiacuf
First of all I meant 600mm/min :whistle:
I can't go above that on any of the axis without joint following errors.
Here are my specs:

X

Hiwin 4x HWG25, rails with 1500mm length
2005 ballscrew, dual DFU2005 nuts
Direct drive by HC-KFS43 , 1.3Nm Nom, 3.8Nm max, 3000RPM Nom, 4500RPM max, electronic gear setup with 4000Pulse/rev
Total traveling mass 60KG


Y dual axis
IKO 4x LWH30, rails 1200mm length
2005 ballscrew , dual DFU2005 nuts
1:2 Motor to blalscrew ratio, servo HC-KFS43 , 1.3Nm Nom, 3.8Nm max, 3000RPM Nom, 4500RPM max, electronic gear setup with 4000Pulse/rev
Total traveling mass 180KG


Z axis

Hiwin 4x HWG25, rails with 680mm length
2005 ballscrew , dual DFU2005 nuts
1:2 Motor to blalscrew ratio, servo HC-KFS43 , 1.3Nm Nom, 3.8Nm max, 3000RPM Nom, 4500RPM max, electronic gear setup with 4000Pulse/rev


Dual DFU2005 nuts for rigidity on each axis.


Mesa 5I25 PCI card on PC, 7I76 step/dir & 7I85S for encoders.

4x Delos 5um, RS422 encoders, without index(it seems) , max traveling speed 1m/sec.


The HAL and ini config files are in my above post.

I spent a day trying to configure it(lots of guess work as It's a pretty steep learning curve) but no luck until now.
In test mode my servos are working fine at :
X which is direct drive
V=15000mm/s A=2500mm/s2 R=3000rpm Pulse speed: 200kpps
Torque reported by MRJ2S drive is less than 80%

Y 20/40 pulley
V=6000mm/s A=1000mm/s2 R=2600rpm
Torque < 40%

Z 20/40 pulley
V=6000mm/s A=1500mm/s2 R=2600rpm
Torque < 40%

In the .ini file I have:

[AXIS_0]
TYPE = LINEAR
HOME = 100.0
FERROR = 1.0
MIN_FERROR = 1.0
MAX_VELOCITY = 250.0
MAX_ACCELERATION = 2500.0
# The values below should be 25% larger than MAX_VELOCITY and MAX_ACCELERATION
# If using BACKLASH compensation STEPGEN_MAXACCEL should be 100% larger.
STEPGEN_MAXVEL = 312.5
STEPGEN_MAXACCEL = 3125.0
P = 1.0
I = 0.0
D = 0.0
FF0 = 0.0
FF1 = 1.0
FF2 = 0.0
BIAS = 0.0
DEADBAND = 0.025
MAX_OUTPUT = 10.0
ENCODER_SCALE = 200.0
# these are in nanoseconds
DIRSETUP = 1000
DIRHOLD = 1000
STEPLEN = 1000
STEPSPACE = 1000
STEP_SCALE = 800.0
MIN_LIMIT = -0.0
MAX_LIMIT = 1200.0
HOME_OFFSET = 0.000000
HOME_SEARCH_VEL = -0.050000
HOME_LATCH_VEL = -0.016667
HOME_FINAL_VEL = 1.666667
HOME_USE_INDEX = NO
HOME_IGNORE_LIMITS = YES

At a Jog speed above 600m/min I get a joint following error in AXIS.
I will post the scope data as soon as I figure how :D

Please Log in or Create an account to join the conversation.

More
11 Jul 2014 18:52 #48650 by crisiacuf
And here is what I got:

Attachments:

Please Log in or Create an account to join the conversation.

More
11 Jul 2014 20:12 - 11 Jul 2014 20:15 #48652 by DaBit
ferror is rising linear, so I think there is a delay or a mismatch between linuxcnc speed en servo speed.
I think you should do some tuning effort. You can do that from within AXIS, pick 'calibration' from the menu.

- Tune the servo drives to the motors/load. See the manual on how to do that with your particular combination.

- You are commanding speed on your servos. Make STEPGEN_MAXACCEL/MAXVEL a lot higher or turn them completely off. You want maximum power from the servo to correct an error if it is needed and there is no such thing as a stepper stall here.

- Set MIN_FERROR and FERROR to large values such as 10mm so you have some headroom during tuning.

- Set P and D to zero, set I to a very small value such as 0.5. For now you are only setting I to get ferror zeroed out for repeated jogs.

- Tune FF1 so the ferror line in halscope is as horizontal as possible during a jog. Try multiple speeds.

- Tune FF2 to get it more symmetric around zero.

- Increase P until things become unstable. Then add a slight bit of D and see if it becomes stable again. Increase P. Slight bit of D. Once you cannot get it stable anymore backoff P and D a bit so you are for certain in a stable region.

- Now add I until things become unstable again. Then set I to 50-70% of that value.

- You might want to repeat twiddling FF1/FF2/P/D a few times to converge to the optimum.


This tuning advice is different from others in the sense that I prefer to get the feedforwards OK first before moving on to the error correction parameters. Also keep in mind that I have tuning experience with only one servo system: my own.

Another potential problem is that you have only one position feedback, and that is the scale. Many people tried using only the scale for position feedback and failed. There is also a risk: if the scale ever fails the axis runs at full speed towards an end stop.

I am using the motor encoder as the main position feedback and let the scale do only small corrections.
You might want to do the same: put the servodrives (and LinuxCNC stepgen) in positioning mode, and use a scale PID with only I to do the 'finetuning' on the position.

In pseudo-HAL that would be:

axis.motor-pos-cmd => scalepid.command
scaleencoder.position => scalepid.feedback
scalepid.output => stepgen.position-cmd

setp scalepid.FF0 1.0
setp scalepid.Igain 100.0

In real INI/HAL:
[AXIS_0]
TYPE =                  LINEAR
MAX_VELOCITY =          300.0
MAX_ACCELERATION =      4000.0
BACKLASH =              0.000
FERROR =                1
MIN_FERROR =            0.5
INPUT_SCALE =           -818.67
INPUT_SCALE_LINEAR = 	-200
OUTPUT_SCALE =          3
OUTPUT_SCALE_NEG =	-3
OUTPUT_OFFSET =         0.0
MAX_OUTPUT =            3
MIN_LIMIT =             -520.0
MAX_LIMIT =             15.0
DEADBAND =              0.001
P =                     10
I =                     70
D =                     0.015
FF0 =                   0
FF1 =                   0.004
FF2 =			9e-05
BIAS =                  0
SCALE_P =		0
SCALE_I = 		100
SCALE_DEADBAND = 	0.006
SCALE_MAXCORR = 	0.2

..
..


# ################
# X [0] Axis
# ################

# axis enable chain
net xenable <= axis.0.amp-enable-out
net xenable => xservo_pid.enable => xscale_pid.enable
net xenable => hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogena
 
# encoder feedback, rotary
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.counter-mode 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.filter 1
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.index-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.index-mask 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.index-mask-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.scale  [AXIS_0]INPUT_SCALE
net xpos-servo-fb hm2_[HOSTMOT2](BOARD).0.encoder.00.position => xservo_pid.feedback
net xvel <= hm2_[HOSTMOT2](BOARD).0.encoder.00.velocity => xservo_pid.feedback-deriv

# encoder feedback, linear
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.counter-mode 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.filter 1
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.index-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.index-mask 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.index-mask-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.scale  [AXIS_0]INPUT_SCALE_LINEAR

# index homing, position feedback and ferror suppression
net xindex_enable hm2_[HOSTMOT2](BOARD).0.encoder.03.index-enable <=> hm2_[HOSTMOT2](BOARD).0.encoder.00.index-enable <=> axis.0.index-enable <=> xservo_pid.index-enable <=> xscale_pid.index-enable
net xscalepos <= hm2_[HOSTMOT2](BOARD).0.encoder.03.position => xscale_pid.feedback => axis.0.motor-pos-fb

# set PID loop gains from inifile
setp xservo_pid.Pgain [AXIS_0]P
setp xservo_pid.Igain [AXIS_0]I
setp xservo_pid.Dgain [AXIS_0]D
setp xservo_pid.bias [AXIS_0]BIAS
setp xservo_pid.FF0 [AXIS_0]FF0
setp xservo_pid.FF1 [AXIS_0]FF1
setp xservo_pid.FF2 [AXIS_0]FF2
setp xservo_pid.deadband [AXIS_0]DEADBAND
setp xservo_pid.maxoutput [AXIS_0]MAX_OUTPUT
setp xservo_pid.error-previous-target 1

setp xscale_pid.Pgain [AXIS_0]SCALE_P
setp xscale_pid.Igain [AXIS_0]SCALE_I
setp xscale_pid.deadband [AXIS_0]SCALE_DEADBAND
setp xscale_pid.FF0 0.0
setp xscale_pid.maxerrorI [AXIS_0]SCALE_MAXCORR
setp xscale_pid.maxoutput [AXIS_0]SCALE_MAXCORR
setp xscale_pid.error-previous-target 1

# position command signals

# linear scale position PID

net xpos-cmd axis.0.motor-pos-cmd => xscale_pid.command => xscale_sum2.in0
net xpos-scalepidoutput xscale_pid.output => xscale_sum2.in1
net xpos-corrected xscale_sum2.out => xservo_pid.command

setp hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0-scalemax [AXIS_0]OUTPUT_SCALE
setp hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0-maxlim [AXIS_0]OUTPUT_SCALE
setp hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0-minlim [AXIS_0]OUTPUT_SCALE_NEG
net xmotor-command xservo_pid.output  =>  hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0

Only the section around xscale_pid is interesting, the servo-pid is doing the positioning which would be in your drive if you let the drive do the positioning magic. Thus, what goes to my xservo_pid.command would go to your stepgen.position-cmd.
Last edit: 11 Jul 2014 20:15 by DaBit.

Please Log in or Create an account to join the conversation.

More
11 Jul 2014 21:34 - 11 Jul 2014 21:35 #48656 by crisiacuf

ferror is rising linear, so I think there is a delay or a mismatch between linuxcnc speed en servo speed.
I think you should do some tuning effort. You can do that from within AXIS, pick 'calibration' from the menu.

- Tune the servo drives to the motors/load. See the manual on how to do that with your particular combination.


Did this with the melservo autotune.

- You are commanding speed on your servos. Make STEPGEN_MAXACCEL/MAXVEL a lot higher or turn them completely off. You want maximum power from the servo to correct an error if it is needed and there is no such thing as a stepper stall here.


I set them both to 0.


- Set MIN_FERROR and FERROR to large values such as 10mm so you have some headroom during tuning.

- Set P and D to zero, set I to a very small value such as 0.5. For now you are only setting I to get ferror zeroed out for repeated jogs.


Did that..

- Tune FF1 so the ferror line in halscope is as horizontal as possible during a jog. Try multiple speeds.

- Tune FF2 to get it more symmetric around zero.


As the rest does not work I didn't try this as being subtle details.


- Increase P until things become unstable. Then add a slight bit of D and see if it becomes stable again. Increase P. Slight bit of D. Once you cannot get it stable anymore backoff P and D a bit so you are for certain in a stable region.

- Now add I until things become unstable again. Then set I to 50-70% of that value.

- You might want to repeat twiddling FF1/FF2/P/D a few times to converge to the optimum.


Did this first thing but did not work.
My "P" got unstable at around 4. I increased "I" till 200 with no success. It just became more unstable and oscillations increased.

This tuning advice is different from others in the sense that I prefer to get the feed forwards OK first before moving on to the error correction parameters. Also keep in mind that I have tuning experience with only one servo system: my own.


Another potential problem is that you have only one position feedback, and that is the scale. Many people tried using only the scale for position feedback and failed. There is also a risk: if the scale ever fails the axis runs at full speed towards an end stop.


I am using the motor encoder as the main position feedback and let the scale do only small corrections.
You might want to do the same: put the servodrives (and LinuxCNC stepgen) in positioning mode, and use a scale PID with only I to do the 'finetuning' on the position.


In pseudo-HAL that would be:

axis.motor-pos-cmd => scalepid.command
scaleencoder.position => scalepid.feedback
scalepid.output => stepgen.position-cmd

setp scalepid.FF0 1.0
setp scalepid.Igain 100.0


You lost me here. What is pseudo hal?


In real INI/HAL:
[AXIS_0]
TYPE =                  LINEAR
MAX_VELOCITY =          300.0
MAX_ACCELERATION =      4000.0
BACKLASH =              0.000
FERROR =                1
MIN_FERROR =            0.5
INPUT_SCALE =           -818.67
INPUT_SCALE_LINEAR = 	-200
OUTPUT_SCALE =          3
OUTPUT_SCALE_NEG =	-3
OUTPUT_OFFSET =         0.0
MAX_OUTPUT =            3
MIN_LIMIT =             -520.0
MAX_LIMIT =             15.0
DEADBAND =              0.001
P =                     10
I =                     70
D =                     0.015
FF0 =                   0
FF1 =                   0.004
FF2 =			9e-05
BIAS =                  0
SCALE_P =		0
SCALE_I = 		100
SCALE_DEADBAND = 	0.006
SCALE_MAXCORR = 	0.2

..
..


# ################
# X [0] Axis
# ################

# axis enable chain
net xenable <= axis.0.amp-enable-out
net xenable => xservo_pid.enable => xscale_pid.enable
net xenable => hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogena
 
# encoder feedback, rotary
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.counter-mode 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.filter 1
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.index-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.index-mask 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.index-mask-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.00.scale  [AXIS_0]INPUT_SCALE
net xpos-servo-fb hm2_[HOSTMOT2](BOARD).0.encoder.00.position => xservo_pid.feedback
net xvel <= hm2_[HOSTMOT2](BOARD).0.encoder.00.velocity => xservo_pid.feedback-deriv

# encoder feedback, linear
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.counter-mode 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.filter 1
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.index-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.index-mask 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.index-mask-invert 0
setp hm2_[HOSTMOT2](BOARD).0.encoder.03.scale  [AXIS_0]INPUT_SCALE_LINEAR

# index homing, position feedback and ferror suppression
net xindex_enable hm2_[HOSTMOT2](BOARD).0.encoder.03.index-enable <=> hm2_[HOSTMOT2](BOARD).0.encoder.00.index-enable <=> axis.0.index-enable <=> xservo_pid.index-enable <=> xscale_pid.index-enable
net xscalepos <= hm2_[HOSTMOT2](BOARD).0.encoder.03.position => xscale_pid.feedback => axis.0.motor-pos-fb

# set PID loop gains from inifile
setp xservo_pid.Pgain [AXIS_0]P
setp xservo_pid.Igain [AXIS_0]I
setp xservo_pid.Dgain [AXIS_0]D
setp xservo_pid.bias [AXIS_0]BIAS
setp xservo_pid.FF0 [AXIS_0]FF0
setp xservo_pid.FF1 [AXIS_0]FF1
setp xservo_pid.FF2 [AXIS_0]FF2
setp xservo_pid.deadband [AXIS_0]DEADBAND
setp xservo_pid.maxoutput [AXIS_0]MAX_OUTPUT
setp xservo_pid.error-previous-target 1

setp xscale_pid.Pgain [AXIS_0]SCALE_P
setp xscale_pid.Igain [AXIS_0]SCALE_I
setp xscale_pid.deadband [AXIS_0]SCALE_DEADBAND
setp xscale_pid.FF0 0.0
setp xscale_pid.maxerrorI [AXIS_0]SCALE_MAXCORR
setp xscale_pid.maxoutput [AXIS_0]SCALE_MAXCORR
setp xscale_pid.error-previous-target 1

# position command signals

# linear scale position PID

net xpos-cmd axis.0.motor-pos-cmd => xscale_pid.command => xscale_sum2.in0
net xpos-scalepidoutput xscale_pid.output => xscale_sum2.in1
net xpos-corrected xscale_sum2.out => xservo_pid.command

setp hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0-scalemax [AXIS_0]OUTPUT_SCALE
setp hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0-maxlim [AXIS_0]OUTPUT_SCALE
setp hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0-minlim [AXIS_0]OUTPUT_SCALE_NEG
net xmotor-command xservo_pid.output  =>  hm2_[HOSTMOT2](BOARD).0.7i77.0.1.analogout0

Only the section around xscale_pid is interesting, the servo-pid is doing the positioning which would be in your drive if you let the drive do the positioning magic. Thus, what goes to my xservo_pid.command would go to your stepgen.position-cmd.


Now if you could just tell me this. Why my displayed jog speed does not match my real axis speed.
I set the jog speed at 3000mm/min, I get no folowing error because I set it very high(50), but the real measured(with a tachometer) speed of my axis is below 600mm/min.
My max jitter was max 7000 so the hardware is out of the question.

I am suspecting there is a problem caused by the fact I have 2 PID loops.
One in my servo and one in linuxCNC and they fight each-other never reaching a target.
Do you think I should change to velocity control using 7i77?
Last edit: 11 Jul 2014 21:35 by crisiacuf.

Please Log in or Create an account to join the conversation.

Time to create page: 0.226 seconds
Powered by Kunena Forum