I have experience with the same issue as the OP, and will describe my findings and thoughts here.
Initial setup:
I have a traditional 3-axis cnc mill, using horizontal plane movements for X & Y, and vertical movement on the Z-axis. I want to laser engrave an image onto a surface using a raster engraving process. I’m running LinuxCnC 2.7.8.
Expected Outcome:
I want to control an engraving laser using Linux to vary the output power of the laser. The laser output power is typically a 0-100% setting. The preferred outcome of this setup would allow me to engrave as fast as my machine can do so, theoretically allowing infinite speed of the laser power output control (as the OP is hoping to achieve as well).
Possibility #1:
Controlling the laser output via M3 SXXX and/or SXXX commands.
I found that this approach is interfering with the trajectory planner in some way, and as a result we get erratic movement of the laser because the X&Y axes (what is moving the laser) are constantly accelerating/decelerating each time an SXXX command is encountered. The larger changes in SXX, say from S01 to S99, result in the greatest deceleration. I’m not sure what is causing the delay, perhaps Linux pwm generator, maybe it is internally allowing some time for (what it thinks is a spindle) to adjust. After testing this approach it “works” but is not great; some reasons for this are:
#1: I want the laser to travel at a constant velocity any time it is engraving. If the X & Y axis speed varies then the engraving will be darker when the X/Y axis is slowing down, and lighter when it is moving at max speed. This gives an unwanted shading effect on the image.
#2: Raster engraving can be quite time cumbersome, and by not running at maximum velocity for the largest amount of time you increase your run time. This can be quite significant when you are engraving a large image and are constantly speeding up and slowing down vs running at maximum velocity for the extents of the image.
(These thoughts were pointed out in the discussion above, but noted here again for clarity.)
Thoughts:
Ok, so SXXX is breaking the que, and we are losing speed. Let's try another solution...
Possibility #2:
Controlling the laser output via M67 E0 QXXX
I found that this approach is interfering with the trajectory planner in some way as well, and as a result we get erratic movement of the laser because the X&Y axes are constantly accelerating/decelerating each time an M67 command is encountered. The larger changes in QXX, say from Q01 to Q99, result in the greatest deceleration. I’m not sure what is causing the delay, perhaps Linux pwm generator? The results using this method seem slightly better than using M3 SXXX, but still not what I would consider ‘good’ results. This method will ‘work’, but I am still having the same accel/decel problem when trying to vary the intensity of the laser. I expected this solution to work better, but am unable to get good results from it either.
Let's try another solution...
Possibility #3:
Control the laser intensity directly using a (fake) axis movement. I did this by adding a new axis, we’ll call it axis A, so I went from an XYZ traditional 3-axis mill to an XYZA, where the A axis is a fake axis whose stepper signals we will use to control the laser. I know Linux pulses the axes wicked fast, so this should be a good approach. I set the A axis to have crazy high acceleration and velocity rates, as I'm not actually moving any axis, just controlling power being sent to the laser (note: I’m not actually powering the laser with the stepper motor signals, in this setup I’m reading the stepper pulses on the laser driver board and converting them to laser intensity).
I added the necessary lines of code into the Linux configuration files and ran some test engravings. This is where things got interesting, and I will try to be clear on what’s happening here:
1.) When processing the XYZ commands, the machine behaves as it normally does -> good, this is the expected outcome
2.) When processing the following A axis movement commands:
a. G0 A0
b. G0 A100
c. G0 A50
d. G0 A0
e. G0 A100
f. G0 A0
The A axis properly controls the laser, is adjusting the power correctly and is doing so really fast -> good, this is the expected outcome
3.) When processing XYA commands (now varying the laser during raster engraving) the A axis commands are causing my XY movements to slow down -> bad, this is not what I want to happen
I honestly do not know what is happening here, or how to fix this problem. My best explanation for this (gathered from watching my machine and observing what is physically happening, not looking into the source code) is that Linux is restricting the axis movement to consider the slowest axis which is currently moving, or about to be moving. In my case the limiting speed is my X&Y axes, as they are set as I normally have them, while the A axis has velocity and accel set to the point just before my machine trips the “axis following error”.
I did further testing on this, and the results are more or less linear in that linux ‘bogs down’ and can only maintain a constant speed of ~40% of the maximum XY velocity during engraving. In other words:
a.) X/Y axes velocity set at 100mm/min -> Linux can hold a constant speed when using G1 F40 commands. Using a velocity greater than F40 causes the velocity to drop to 40 at points of large laser power changes (say from 0 to 100%)
b.) X/Y axes velocity set at 1500mm/min -> Linux can hold a constant speed when using G1 F600 commands
c.) X/Y axes velocity set at 3000mm/min -> Linux can hold a constant speed when using G1 F1200 commands
I do not know why, but 40% seems to be the constant speed that Linux was able to sustain under all my velocity tests.
This possibility yielded the best results for me, with M67 performing 2nd best, and M3 giving the worst results.
My recommended solution:
If possible, control your laser power via step pulses and maintain your raster engraving at the highest speed you feel comfortable having your machine go. There are real world variables in play here, so I can’t recommend a speed for you other than to know your machine limits, as high velocity and/or accelerations have an effect on your hardware life. If you are comfortable running at 1000mm/min then set your G1 speed to F1000 and back-calculate your axis max velocity ( = 1000 / 0.4 = 2500 ) and set accordingly in your .ini file (***note -> I highly recommend you make sure and do not execute ***any*** G0 X/Y/Z commands if you do this, otherwise your machine might get damaged, as it'll be going 2,500mm/min rather than the 1,000mm/min you are comfortable with.)
If you don’t want to deal with stepper motor pulses, then controlling via M67 offered me 50-75% of the speed I could get using step pulses, so it’s not the end of the world.
Thoughts:
My preferred solution would be to tell Linux that my A axis is not actually an axis, and to decouple its commands from the XYZ commands. This would be similar to telling Linux that the A axis controls a separate machine, so the XYZ commands are entirely different from the A commands. That way the XYZ commands would follow their movement equations and the A axis would follow its own separate movement equation and be free to vary its laser intensity near instantly.
Requests for help:
If anyone see’s any flaw in my logic or thought process please let me know. I do not have further plans to test this, but only because I can’t think of any other approaches to try.