Gantry-Jogging in emcrsh AND soft limits ignored
I have a somewhat unconventional use for an XYZ gantry machine. I am not milling, but attaching a camera to the tool holder; the idea is to have the machine follow flatworms around for use in research. The actual machine is the one pictured here groups.yahoo.com/group/micRo-cnc/ . After working all summer, today I finally finished, but a couple of bugs in LinuxCNC are killing me:
1 (MOST important). I am controlling the project by setting its velocity through a self-programmed PID controller, about 10 times a second. The main program is in LabVIEW, so I am trying to to interface with LinuxCNC through a local TCP connection to linuxcncrsh. However, I just realized that I can only jog 1 axis at once from linuxcncrsh! As soon as I tell another axis to jog (with "set jog 0 100"), the first one stops moving. Is there any fix?
If not, I suppose I could translate the velocity from my PID into an MDI command by dividing by the timestep. So "set jog 0 100" would become "set mdi G93 F0.100 X0.166667". However, you can't cancel an MDI command, and LinuxCNC queues them up - what if each takes a little longer than I told it to, and the machine starts to get behind?
2. When I am in Joint mode (or MDI mode, I think), soft limits work perfectly. However, when I am in World/Teleop mode (which you have to be for a gantry), the soft limit will stop me once, but if I issue another jog command in the same direction, it will be ignored! This is a real problem for programmatic control. I have provisions for this in my LabVIEW code, but I'd like another safety net. I've heard that gantrykins might be responsible for ignoring the limit?
Strangely, if I set a limit at 5.0000, in World mode the machine will go a little past, say to 5.1301. But if I switch back to Joint mode, AXIS says that it's at 5.0000 exactly - a bit hard to believe.
Here are my config files (I can convert them to customary units if you prefer). Thank you so much!
INI: pastebin.com/gwiCZpYc
HAL: pastebin.com/N7Z0qryW
Please Log in or Create an account to join the conversation.
InterestingI have a somewhat unconventional use for an XYZ gantry machine. I am not milling, but attaching a camera to the tool holder; the idea is to have the machine follow flatworms around for use in research.
Anyway: I am not sure that it makes any sense at all to use LinuxCNC in this situation. You might be better using Matlab and external step-generation hardware (perhaps a SmoothStepper).
However, given that what you have almost works:
I think you should move the motion control into Matlab and use only the parts of LinuxCNC which are useful to you. I am fairly sure that flatworms are not well-known for their speed.
You could do what you want mainly in HAL, not loading the LinuxCNC GUI and the G-code interpreter. (And quite possibly not the motion controller either).
Assuming that the control loop is velocity-mode based on image data, then you could use velocity-mode stepgens and set the velocity directly from Matlab.
put the following in a file called test.hal
loadrt threads name1=base-thread period1=50000 name2=servo-thread period2=1000000
loadrt stepgen control_type=v,v,p #velocity control X and Y, position Z.
loadrt hal_parport cfg="0"
addf stepgen.0.make-pulses base-thread
addf parport.0.write base-thread
addf stepgen.0.capture-position servo-thread
addf stepgen.0.update-freq servo-thread
net xstep stepgen.0.step parport.0.pin-01-out # Edit to suit..
net xdir stepgen.0.step parport.0.pin-02-out
net ystep stepgen.0.step parport.0.pin-03-out
net ydir stepgen.0.step parport.0.pin-04-out
net zstep stepgen.0.step parport.0.pin-05-out
net zstep stepgen.0.step parport.0.pin-06-out
setp stepgen.0.maxvel XXXX #set to suit the machine limits
setp stepgen.0.maxaccel YYYY # ditto
setp stepgen.0.scale 200 #to suit machine
start
You can then halrun -I -f test.hal
That will load up the realtime system and HAL, and interpret the above HAL file, but won't load any of the more visible parts of LinuxCNC.
In a separate terminal windo you should now be able to type
halcmd setp stepgen.0.velocity-cmd 0.1
And see the X-stepper move at a constant rate of 0.1 units/second. It will carry on moving until you set the velocity to zero.
You can set the Y velocity independently.
For a gantry controlled like this I think you would need to net both sets of of parport pins to the same stepgen.
It is rather useful that stepgen enforces velocity and accel limits internally, or this would not work.
halcmd getp stepgen.0.position-fb can be used to check the current position.
How you communicate with Matlab depends on what suits best. You could simply use halcmd as shown in place of your emcrsh. Or you could write a simple HAL component to interpret serial data or similar.
Please Log in or Create an account to join the conversation.
Thank you, this is exactly what I need! LinuxCNC seemed like overkill and very difficult to programatically control, but I only ever found out about linuxcncrsh. The hal command-line client should work nicely. I do have just a few follow-up questions:
1. Unfortunately, the lab I'm working in is moving across the country in a week, so I don't think I'll have time to obtain and implement a SmoothStepper. Out of curiosity, though, what am I missing out on from that setup instead of just using halcmd?
2. I actually don't know much about PID controllers, but setting the velocity seemed to make the most sense to me, even if the conversion from position units in the image to velocity units of the machine seemed a little iffy. Would it make more sense to set position or acceleration at each time step? It does sound a bit painful when the velocity is switched several times a second.
3. I've tried to net the same stepgen to multiple parport pins before, but I never managed to get it.
EDIT: I was trying to net stepgen.0 to the input of both xstep and ustep, which was an error. However, it seems that I can net the output of xstep to two parport pins, so this works! I got my current configuration premade, so it has some problems
This is solved, so hiding it in spoiler tags:
The error looks like this:
M3.emc2.4.hal:117: Pin 'stepgen.0.step' was already linked to signal 'xstep'
Relevant parts of .hal:
net xstep => parport.0.pin-02-out
net xdir => parport.0.pin-03-out
net ustep => parport.0.pin-04-out
net udir => parport.0.pin-05-out
net xpos-cmd axis.0.motor-pos-cmd => stepgen.0.position-cmd
net xpos-fb stepgen.0.position-fb => axis.0.motor-pos-fb
net xstep <= stepgen.0.step
net xdir <= stepgen.0.dir
net upos-cmd axis.3.motor-pos-cmd => stepgen.3.position-cmd
net upos-fb stepgen.3.position-fb => axis.3.motor-pos-fb
net ustep <= stepgen.0.step
net udir <= stepgen.0.dir
P.S. I wish I could use MATLAB! But other people will be using this machine later, so my boss wanted me to use LabVIEW. It should be just as good for sending shell commands though.
Thanks again! I think it should all be done after this.
Please Log in or Create an account to join the conversation.
Well, I don't know much about the Smoothstepper, I just know that it is used by the Mach3 guys as a way to compensate for not having a realtime system. I think it just buffers steps though. Considering that buffering assumes you know where you want to go next, though, and you might have a tricksy flatworm that dodges and weaves…1. Unfortunately, the lab I'm working in is moving across the country in a week, so I don't think I'll have time to obtain and implement a SmoothStepper. Out of curiosity, though, what am I missing out on from that setup instead of just using halcmd?
I think sending velocity is the way to go, but it is probably nicer to use a velocity-mode stepgen than a position one.but setting the velocity seemed to make the most sense to me, even if the conversion from position units in the image to velocity units of the machine seemed a little iffy. Would it make more sense to set position or acceleration at each time step? It does sound a bit painful when the velocity is switched several times a second.
I know you have solved it, but there are a few ways of writing the same thing, and all work.3. I've tried to net the same stepgen to multiple parport pins before, but I never managed to get it.
net xstep stepgen.0.step parport.0.pin-00-out parport.0.pin-01-out
or
net xtep stepgen.0.step parport.0.pin-00-out
net xstep parport.0.pin-00-out
or even
net anysignalnameyoufancyactuallyandinanyorder parport.0.pin-01-out
net anysignalnameyoufancyactuallyandinanyorder parport.0.pin-00-out
net anysignalnameyoufancyactuallyandinanyorder stepgen.0.step
There is a Realtime variant of LabView, and that might well have modules to control steppers. Has that been looked at? I developed a system which used it, though at the time it required special hardware.P.S. I wish I could use MATLAB! But other people will be using this machine later, so my boss wanted me to use LabVIEW
Please Log in or Create an account to join the conversation.
I did end up going with halcmd, using a velocity-mode stepgen. Oddly, the sound the motors make seems to oscillate a bit more running velocity-mode in halcmd than just jogging normally in AXIS. But it seems to work fine. I don't think I can use homing switches or limits in HAL with this setup, so I just set safe limits in my LabVIEW code. I don't need the precision.
LabVIEW Real-time seems to only exist for Windows... is it really possible to even have realtime in Windows? Ah well, don't care much, since my system works! The halcmd stepgen is just fine.
I'm still using my cruddy TB6560 4V3 red board. The motors make an annoying hissing noise, but oh well. I would like to upgrade to a better stepper driver, just don't know where to find one. Shame you can't drive the motors straight with software!
Finally, just in case someone else needs to do this, there were a couple typos in Andy's code. HAL has pretty helpful errors, so it's easy to figure out, but here's my final config:
#loadrt trivkins
loadrt threads name1=base-thread period1=30637 name2=servo-thread period2=1000000
loadrt probe_parport
loadrt hal_parport cfg="0x378 out "
setp parport.0.reset-time 4700
# step/dir control, velocity control for X and Y, position for Z
loadrt stepgen step_type=0,0,0 ctrl_type=v,v,p
addf parport.0.read base-thread #unnecessary?
addf stepgen.make-pulses base-thread
addf parport.0.write base-thread
addf parport.0.reset base-thread #unnecessary?
loadrt pwmgen output_type=0 #unnecessary?
addf pwmgen.make-pulses base-thread #unnecessary?
addf stepgen.capture-position servo-thread
#addf motion-command-handler servo-thread #unnecessary?
#addf motion-controller servo-thread #unnecessary?
addf stepgen.update-freq servo-thread
#net spindle-cmd <= motion.spindle-speed-out #unnecessary?
net xstep <= stepgen.0.step => parport.0.pin-02-out parport.0.pin-04-out
net xdir <= stepgen.0.dir => parport.0.pin-03-out parport.0.pin-05-out
setp parport.0.pin-02-out-reset 1
setp parport.0.pin-03-out-invert 1
setp parport.0.pin-04-out-reset 1
setp parport.0.pin-05-out-invert 1
net ystep <= stepgen.1.step => parport.0.pin-06-out
net ydir <= stepgen.1.dir => parport.0.pin-07-out
setp parport.0.pin-06-out-reset 1
net zstep <= stepgen.2.step => parport.0.pin-08-out
net zdir <= stepgen.2.dir => parport.0.pin-09-out
setp parport.0.pin-08-out-reset 1
#breakout shares pin 1 as enable for all axes
net on => parport.0.pin-01-out
setp parport.0.pin-01-out-invert 1
#homing - useless without GUI
#net home-x <= parport.0.pin-10-in
#net home-u <= parport.0.pin-11-in
#net home-y <= parport.0.pin-12-in
#net home-z <= parport.0.pin-13-in
#breakout A, axis X "X1", joint 0
setp stepgen.0.position-scale 755.905511811
setp stepgen.0.steplen 1
setp stepgen.0.stepspace 0
setp stepgen.0.dirhold 31400
setp stepgen.0.dirsetup 31400
setp stepgen.0.maxaccel 950
setp stepgen.0.maxvel 15
#breakout C, axis Y, joint 1
setp stepgen.1.position-scale 755.905511811
setp stepgen.1.steplen 1
setp stepgen.1.stepspace 0
setp stepgen.1.dirhold 31400
setp stepgen.1.dirsetup 31400
setp stepgen.1.maxaccel 950
setp stepgen.1.maxvel 15
#breakout D, axis Z, joint 2
setp stepgen.2.position-scale 755.905511811
setp stepgen.2.steplen 1
setp stepgen.2.stepspace 0
setp stepgen.2.dirhold 31400
setp stepgen.2.dirsetup 31400
setp stepgen.2.maxaccel 950
setp stepgen.2.maxvel 15
#enable axes. Still have to enable machine also
net allenable stepgen.0.enable stepgen.1.enable stepgen.2.enable
start
Please Log in or Create an account to join the conversation.