Got the XYZ servos mounted and tuned. The first video shows a test program with some drilling G-codes. Rapids are set at 5000mm/min with around 400 mm/s^2 accelerations. Following errors stay below 0.02 mm. The second video shows a 40 mm face-mill at 3000 rpm cutting a 20 mm wide aluminium bar with 1 mm depth of cut and 500 mm/min feed. We think this is pretty good for this size of minimill. The stability and sound will not be as nice as this without linear rails, ballscrews, and a good spindle.
Category: CNC
X-axis test
I mounted a servo on the x-axis of the mill today and did some PID tuning. The video shows a ca 300mm rapid move at 5500mm/min (217 IPM). Below some hal-scope views of what's going on in the PID loop during the move.
Here only P-gain is used and the machine needs to lag behind the commanded position (blue) a bit (slightly less than 1 mm, red trace) for the DAC output (green) to reach to reach the required level.
The lagging behind is curable with FF1, 1st order feed-forward. FF1 adds to the DAC output in proportion to the commanded velocity. With too little FF1 (top, note scale for red trace is 20x finer than in the first pic) the machine still lags behind. Wit too much FF1 (middle) the machine leads commanded position, and I figure the bottom trace has about the right amount of FF1 since the error is small and symmetrical around zero during the 'cruise'-phase (constant velocity) of the move.
I found FF2 much more tricky. Note again the scale is finer than before (100x finer compared to the first pic!). FF2 is 2nd order feed-forward and adds DAC output in proportion to the acceleration of the commanded position. In A there is no FF2 and the machine lags during acceleration and leads during deceleration. In B I've added FF2 and the error during acceleration seems to be a bit better. C has more FF2 and both the acceleration- and deceleration-phase errors are better. Then in D it seems I've overdone FF2 since the acceleration-phase error gets much worse (machine is leading commanded position), while the deceleration error improves.
I'm confused. What could be asymmetric so that FF2 acts differently during acceleration and deceleration? I should add that I am using an m5i20 to generate PWM for pico-systems servodrives (basically a H-bridge). There is no motor current, motor voltage, or velocity feedback, only feedback from a 4000 pulse encoder. The ballscrews are 2.5 mm/rev so one count is 0.000625 mm. The peak error during acc./dec. in the FF2 figure above is around 0.01 mm or 16 encoder counts. During cruise-phase the error is smaller, maybe only +/- 8 counts.
I then tested the inverse-deadband component which is supposed to linearise the DAC-motor system. I'm not sure what these results mean yet. The first error-peak is lowered, but there's an opposite effect during deceleration. This is a slower move and shows some periodic error during the cruise-phase, I wonder what that could be?
Finally some traces recorded with different length moves and different feed-rates. In reality 1000 mm/min is about the highest feed-rate used while machining, and everything higher than that is mostly for show only 🙂
Clearly higher feed-rates are more difficult for the PID loop. The acceleration/deceleration phases are still difficult, and there remains an asymmetry where with the current PID-parameters the acceleration phase works a bit better than the deceleration phase. I think with another choice of FF2 that could be reversed so that deceleration is fine but there is more error during acceleration.
I wonder if there is something peculiar to only torque-mode servo PID-loops that I should take into account? Something to do with the asymmetry between acceleration/deceleration...
EMC2 test run
The servos are now almost ready to go on the mill. Some dry-running of EMC2, the servo electronics, and the VFD today. I've made this pyVCP panel for AXIS which displays the commanded and actual spindle RPM, the spindle current (in some uncalibrated unit), the PID outputs and following errors for X/Y/Z. The jog-pendant box shows the mode of the jogwheel (X-jog, Y-jog, Z-jog, Off, Feed-override, Spindle-override), and the jog-increment (0.01 mm above). The four pendant buttons are now wired to turn on/off the coolant (blue button), to start the spindle forward or stop it (yellow button), to step through the program (green button), and to pause/resume the program (red button).
A video of the setup.
0:00 Actors, in order of appearance: EMC2, jog-pendant, electronics box, limit-switch box, X/Y/Z servos, VFD, Spindle motor.
0:30 Running a program. Load-meters. Rotating servos. Rotating spindle. Note professional mount and axis-coupler for spindle-encoder. The encoder will eventually be mounted on the other end of the motor.
1:30 Load-monitor demonstration. Running the machine from (300,300,300) to (0,0,0) with a rapid move (6000mm/min or around 2400 RPM on the servo shaft) and watching the bar-graphs show the commanded PWM to the amps.
It's best to store all the working config files here in case of disk crashes or other data loss:
- INI
- HAL (I should write a post about everything that is in this file some day)
- pyVCP
- postgui-HAL
FinnTec '08
FinnTec is an annual show for metalworking, toolmaking, CAD/CAM etc. Some video shot with my latest toy, an N95 8Gb.
0:00 5-axis machining on a mazak.
0:35 coordinate measurement machine
0:55 Haas Toolroom lathe. Something to copy or take ideas from if I'm going to build a lathe?
1:27 another lathe
1:45 Hexapod (makes you want to start building one right away!)
2:30 laser cutting. They move around a whole lot of iron at high acceleration and feed although in principle only the laser beam needs to be moved. The machine and floor shakes while cutting!
3:45 waterjet cutting at the Knuth stand
4:02 wire-edm machine and some wire-edm cut parts
4:30 cut-out of an SKF spindle (bearings and motor nicely visible)
toggle2nist
EMC uses 'nist-logic' for most IO, meaning there is one on-switch/signal to switch a thing on, one off-switch/signal to switch it off, and one indicator-signal to tell you the state.
To connect momentary-on pushbuttons to EMC you need at least the toggle component, but I've found that it doesn't work that great with things that can be set/reset by other parts of EMC. For example the coolant state might be set from the AXIS checkbox, G-code, MDI, a pyVCP button, or a hardware button through halui.
I made toggle2nist to set the coolant state with a momentary-on pushbutton. The hardware button connects to a toggle, and the toggle output connects to toggle2nist. It also needs the is-on signal, and produces as outputs the on/off signals (to halui.flood.on and halui.flood.off in this case).
component toggle2nist "toggle button to nist logic";
pin in bit in;
pin in bit is_on;
pin out bit on;
pin out bit off;
variable int old_in;
variable int to_state=0;
function _;
license "GPL";
;;
FUNCTION(_) {
if (in!=old_in) /* a toggle has occurred */ {
if (is_on) { /* turn OFF if it's on */
on=0;
off=1;
to_state=0;
}
else if (!is_on) { /* turn ON if it's off */
on=1;
off=0;
to_state=1;
}
}
else {
/* reset pins when we see the desired state */
if (to_state==is_on) {
on=0;
off=0;
}
}
old_in=in;
}
idb - Inverse Deadband component for EMC2
Due to the open-loop response of my servo motors I found I need 'inverse-deadband' on the PID output to achieve a 'tight' PID loop.
The idea is that since the motors don't respond to DAC outputs between around -0.2 to +0.2 it's not a good idea to use this interval of the DAC. I'm mapping the -10 to +10 output of the PID loop to two ranges, -10 to -0.2 and +0.2 to +10, thus avoiding the [-0.2 , +0.2] interval where the amps/motors don't respond.
Comp is a fantastic tool for writing quick custom HAL components. As usual I received knowledgeable help on IRC and was able to test my 16-line idb-component within minutes.
component idb "Inverse Deadband"; pin in float in "Input"; pin out float out "Output"; param rw float amount; function _ ; license "GPL"; ;; FUNCTION(_) { if (in==0.0) out=in; else if (in<0.0) out=in-amount; else if (in>0.0) out=in+amount; }
PID Tunig
For a few weekends now I have been 'dry-running' the servo electronics that are going to replace stepper motors on the cnc mill. So far the servos are working in closed loop, I can control the VFD forward/reverse and set the RPM, I can read in a spindle-encoder to verify the RPM and also do rigid tapping. The coolant relay works. There's a jogwheel that can be used for jogging the machine or adjusting spindle/feed-override.
Still on the to-do list are limit switches, home switches and homing, improvements to the E-stop loop, and linking up some pendant buttons.
I did a little PID-tuning today with one servo motor just sitting on the bench - no load. The final PID parameters when the motor is hooked up to the machine are probably going to be different from these, but at least I got some experience with tuning. I'm using the Mesa m5i20 to read encoder counts and output PWM to pico-systems servo amplifiers. The servos have 1000-line encoders so I get 4000 counts per revolution. The ballscrews are 2.5mm/revolution, so one encoder count corresponds to 0.000625 mm.
When tuning I did a 200 mm long G0 (rapid) move which allowed the motors to get up to max speed which was set to 6000 mm/min. With the servo directly coupled to the 2.5mm/rev screw that corresponds to 2400 RPM. When coasting at 6 m/min the DAC output was at around 8.7, so this is about as fast as the motors will go (unloaded). In the machine I might not be able to reach 6 m/min. Below some hal-scope screenshots that show how the pid-error changes when tuning the PID parameters.
First I tried only Pgain. The error clearly shows the three phases of the EMC2 trapezoidal trajectory generator. There's an initial acceleration phase during which the error grows, then the cruise phase where it stays constant, and then a deceleration phase at the end. The following error is big, more than 1mm. Obviously I've set FERROR and MIN_FERROR quite high in my ini file so EMC2 doesn't respond with a following error and stop all motion.
Next I tried increasing the 1st order feed-forward, or FF1, parameter. That worked well, and the error is cut more than ten fold!
So FF1 is a good thing? More of that then! Well not quite. Here I've increased FF1 to 0.2 and get sustained oscillations at the end of the move.
It's back to FF1=0.1 and a little D-term to the rescue for damping out the oscillations. Seems to work quite well.
Finally I ramped up the Igain. That helps to reduce the cruise-phase error a lot, but there still remains some following error during the accel/decel phases. There are spikes at the beginning and end of the accel/decel phases which I should try to get rid of. I guess some spikes will always remain since EMC2's trajectory planner outputs a trajectory which is only once differentiable (i.e. the velocity plot has 'sharp corners', and the acceleration plot has discontinuities, see pic here). I'm also using the inverse-deadband component to compensate for the open-loop response of the motors (see next post).
The maximum error is around 0.02 mm, or ca 32 encoder counts. I'm hoping the motors will perform at least as good as this when in the machine!
Hard disks are not forever
Just had a 2-3 year old SATA drive fail on me. If you're reading this, go and take backups of critical data. Do it. Now.
This is the cnc-mill controller machine so hopefully no critical data was lost. Some notes on the EMC2 install process, just in case I need to do it all over again sometime soon...
- Install WinXP on a 50 Gb NTFS partition
- Installed Ubuntu 6.06LTS from CD. Manual partition, 50 Gb for root file system, 2 Gb for swap.
- Ubuntu update manager suggests 301 updates (278M) to install. I'm in Finland, but strangely my sources.list points me to au.something servers. Reboot.
- Install EMC2 using emc2-install.sh. Reboot.
- 'latency-test' shows reasonable jitter values - good.
- Configure X to enable 1280x1024 resolution: 'sudo dpkg-reconfigure xserver-xorg'. Answer lots of techy-questions, remember to add the correct screen resolution and the correct keyboard (pc102). I wasn't able to log in the first time I tried this because I had chosen an incorrect keyboard type/layout.
VFD control board
This small PCB is going to sit between the M5i20 optoisolators and the VFD that runs the spindle on the mill.
Starting from the lower edge of the card there are three outputs that drive optoisolators on the VFD through BC337 transistors. On the VFD they are wired to Forward Start/Stop, Reverse Start/Stop, and External Fault.
The next signal goes in the opposite direction, from VFD to EMC. The VFD has a general purpose analog output which can be programmed to monitor motor current, power, etc. Since the m5i20 doesn't have analog inputs I'm using the V-2-f converter AD654. It's hidden below the board since it was only available in surface mount. As seen below it seems to work nicely. I designed the output to be at 1000 Hz with 10V input, but I'm only supplying 12 V to the AD654 which means the output goes all funny somewhere after 8 V input. Maybe the VFD software can scale the 0-10V output, or I can put a voltage divider in front of the AD654 to get maximum 8 V input. I need to come up with a HAL config that reads a general purpose IO pin and figures out the frequency (think big green/red pyVCP spindle load meter in AXIS).
The top two connections are for the frequency reference, a pulse train, and for an NC E-stop relay.
This card together with a spindle encoder should allow for rigid-tapping.
drop-cutter with kd-tree
First test with drop-cutter aided by the kd-tree. The output toolpath looks very much like the one without kd-tree, which is good. Less great is that I expected a speed-up of the algorithm - but in fact when I use kd-tree the program slows down! Something to investigate over the next few days.