Laser power scaling based on speed and direction
09 Oct 2024 22:49 #311680
by iforce2d
Laser power scaling based on speed and direction was created by iforce2d
Recently I have been playing around with a cheap laser module, and found myself wanting to scale the power based on speed and direction. The reason for scaling with speed should be obvious. The reason for scaling with direction is that the laser beam is kinda rectangular and therefore cuts more effectively along one axis than the other - seems to be common with these cheap diode lasers.
I know there is already a component to handle some of these requirements, but I wanted to try making my own. Here is what I came up with:
One nice side effect is that I can now pause the job at any point and the laser will turn off, and resuming from the middle of a cut works nicely too. Previously I had to be careful to only pause between cuts, otherwise the laser would stay on!
Here is an example .hal file to use the component. This assumes that laser power is controlled by setting spindle speed, and is expressed in gcode as a value between 0 and 100 (eg. M3 S95). For my machine the desired final output is a value between 0 and 65535 so I'm using a lincurve to map to that range, you can remove or change that as appropriate for your case. This example also assumes that joint0 and joint1 have a trivkins type relation to movement in the X and Y axes respectively.
The current speed in each axis is obtained from joint.N.vel-cmd which might not be the actual speed, but it doesn't matter because all we need is the ratio between x/y to know the direction. My laser cuts more effectively in Y than X, so this configuration will scale the power down for Y movements. Swap the X and Y vel-cmd if your laser is the other way around. The value of 0.75 for 'share' comes from some experimentation to see how much a cut with pure Y movement needed to be scaled down to give the same cut effectiveness as a pure X movement. A value of 1 will result in no scaling.
Some examples of the outcome. First, the result without using any power compensation:
With speed compensation only:
With speed and direction compensation (could still use a little less power in Y moves):
I know there is already a component to handle some of these requirements, but I wanted to try making my own. Here is what I came up with:
component laserreg "";
pin in float inpower "Desired laser power at constant speed";
pin in float reqspd "Requested speed, connect to motion.requested-vel";
pin in float curspd "Current speed, connect to motion.current-vel";
pin in float velx "Current speed x component, connect to joint.0.vel-cmd";
pin in float vely "Current speed y component, connect to joint.1.vel-cmd";
pin in float share "Fraction of power given to pure Y movement, eg. 0.6";
pin out float outpower "Scaled output laser power";
function _ fp "Update the laser power";
license "GPL";
;;
#include <math.h>
FUNCTION(_) {
outpower = inpower * (curspd / reqspd);
float angle = atan2(fabs(velx), fabs(vely)); // angle away from y in radians
float horz = angle / (0.5*M_PI); // 1 when moving perfectly along x axis
outpower *= share + (1-share) * horz;
if ( outpower > inpower )
outpower = inpower;
if ( outpower > 100 )
outpower = 100;
if ( outpower < 0 )
outpower = 0;
}
One nice side effect is that I can now pause the job at any point and the laser will turn off, and resuming from the middle of a cut works nicely too. Previously I had to be careful to only pause between cuts, otherwise the laser would stay on!
Here is an example .hal file to use the component. This assumes that laser power is controlled by setting spindle speed, and is expressed in gcode as a value between 0 and 100 (eg. M3 S95). For my machine the desired final output is a value between 0 and 65535 so I'm using a lincurve to map to that range, you can remove or change that as appropriate for your case. This example also assumes that joint0 and joint1 have a trivkins type relation to movement in the X and Y axes respectively.
The current speed in each axis is obtained from joint.N.vel-cmd which might not be the actual speed, but it doesn't matter because all we need is the ratio between x/y to know the direction. My laser cuts more effectively in Y than X, so this configuration will scale the power down for Y movements. Swap the X and Y vel-cmd if your laser is the other way around. The value of 0.75 for 'share' comes from some experimentation to see how much a cut with pure Y movement needed to be scaled down to give the same cut effectiveness as a pure X movement. A value of 1 will result in no scaling.
loadrt lincurve personality=2
loadrt laserreg
addf lincurve.0 servo-thread
addf laserreg.0 servo-thread
# Laser power mapping (0-100 -> 0-65535)
setp lincurve.0.x-val-00 0
setp lincurve.0.y-val-00 0
setp lincurve.0.x-val-01 100
setp lincurve.0.y-val-01 65535
net laser-requested-speed motion.requested-vel => laserreg.0.reqspd
net laser-current-speed motion.current-vel => laserreg.0.curspd
net laser-velx joint.0.vel-cmd => laserreg.0.velx
net laser-vely joint.1.vel-cmd => laserreg.0.vely
setp laserreg.0.share 0.75
net laser-percent spindle.0.speed-out => laserreg.0.inpower
net laser-regulated-percent laserreg.0.outpower => lincurve.0.in
net laser-65535 lincurve.0.out => weeny.spindle.set-speed
Some examples of the outcome. First, the result without using any power compensation:
With speed compensation only:
With speed and direction compensation (could still use a little less power in Y moves):
Attachments:
Please Log in or Create an account to join the conversation.
09 Oct 2024 23:04 #311681
by iforce2d
Replied by iforce2d on topic Laser power scaling based on speed and direction
btw here is the program I used to cut those test squares with various speeds and laser powers. Change the first four lines as required. Note that the comparisons in the loop are 'less than' and 'greater than', not 'greater than or equal', the power loop increments and the speed loop decrements, so the result of the settings as shown will be powers from 10 - 90, and speeds from 800 - 400. The line immediately before each 'endwhile' can be changed to increment by different amounts. 'Size' and 'margin' can be changed to alter the size of the cut squares.
#<minpwr>=10
#<maxpwr>=91
#<maxspd>=800
#<minspd>=399
#<size>=6
#<margin>=2
#<stride>=[#<size>+#<margin>]
g21
#<x>=0
#<y>=0
#<pwr>=#<minpwr>
#<spd>=#<maxspd>
o101 while [#<pwr> LT #<maxpwr>]
#<y> = 0
#<spd>=#<maxspd>
o110 while [#<spd> GT #<minspd>]
g0 x#<x> y#<y>
m3 s[#<pwr>]
g1 y[#<y> + #<size>] f#<spd>
g1 x[#<x> +#<size>]
g1 y#<y>
g1 x#<x>
m5
#<y> = [#<y> + #<stride>]
#<spd> = [#<spd> - 100]
o110 endwhile
#<x> = [#<x> + #<stride>]
#<pwr> = [#<pwr> + 10]
o101 endwhile
m2
The following user(s) said Thank You: tommylight
Please Log in or Create an account to join the conversation.
- tommylight
- Away
- Moderator
Less
More
- Posts: 19300
- Thank you received: 6462
09 Oct 2024 23:25 #311684
by tommylight
Replied by tommylight on topic Laser power scaling based on speed and direction
Nicely done, thank you.
Please Log in or Create an account to join the conversation.
Time to create page: 0.281 seconds