Open dvc94ch opened 3 months ago
Hey, good plan. Aside from getting rid of the E term at the end of G1 commands, is there anything else required?
Don't know yet, still working with the plotter to get the geometry right. To vary the Energy/Area to produce a gradient I guess the speed can be varied instead of laser power. In addition turning the laser on/off before/after a G1 block might be necessary using M3/M5. Don't recall if G1 moves do that automatically.
These are all easy enough to do 👍 if you write your exact GCode requirements and any additional design requirements (e.g. to change laser power) and associated GCode for them, I'll implement a custom laser cutting FullControl
Doesn't seem like producing a gradient is possible as you can't specify an acceleration or an increment like with E in marlin.
Is this sufficient information?
Computing the Energy per Area would be a bonus:
E/A = max_power (S/1000) / F spot_size
Where max_power is in W, F in mm/s, spot_size in mm seems to work out (units are J/mm2).
Mostly looks easy but is G91 required. Can it work with G90. FullControl already works with G90 but would need revising to make it work with G91. For G21, that's fine and can appear at the start of the program.
Also for point 4, do you mean so that the fullcontrol preview fc.transform(steps, 'plot')
shows the correct line width?
G90 is also fine. Well the existing extruder geometry works fine. But if you disable the extruder you only emit G0 moves. But a 2d circular geometry might be more accurate, if the beam profile can be ignored since the laser is strongest at the center and gets weaker as it spreads outwards.
What do you mean by "But if you disable the extruder you only emit G0 moves" - are G0 moves not good for you?
And also, what do you mean by 2d circular geometry? Ignoring the beam profile, won't the path look almost exactly like the currently preview if it's viewed top-down, aside from minor issues at corners?
What do you mean by "But if you disable the extruder you only emit G0 moves" - are G0 moves not good for you?
grbl disables the laser on G0 moves. right now I use fc.Extruder(on=True/False)
to switch from G0/G1 and this gives the correct plots. but this emits E gcode.
And also, what do you mean by 2d circular geometry? Ignoring the beam profile, won't the path look almost exactly like the currently preview if it's viewed top-down, aside from minor issues at corners?
yes that's right
Think this would be really cool. These features would also let people produce gcode for CNC, although you'd need to add a subtractive mode to the plotter if you wanted to do that.
Currently working on a 2d slicer (left-right fill and outline fill) using the opencascade kernel (via the build123d python package). Think extending it to 3d wouldn't be too hard, just intersect the model with a z-plane would be sufficient to support stereolithography, and adding support for partial fill layers and overhang supports would support FDM.
Ah I understand what you meant with G0/G1. Yep I'll also make it so G1 has no E value. With regards to the plot, would it make most sense for the designer to specify laser width or laser power - e.g. designer directly writes fc.Laser(spotsize=XX) or with fc.Laser(power=XX)
It would be nice if the designer didn't need to write the same information twice (once to control the line width in the plot and once to control the gcode M3 commands. Is the relationship between spotsize and power always known (even for basic users)? If so, we can have the user design with either spotsize
or power
, as they prefer, and fullcontrol will update the other parameter as necessary.
With regards to filling strategies, I need to get this stuff all together. I'm in touch with a few different people, who have all developed different strategies, and need to get everyone working cohesively. I intend to create some 'Projects' within this github library in the next week or two. One will be for filling. I'll try to remember to tag you or this issue when the project is live. But keep an eye out. There are so many things that can be reused across machining, robotics, 3D printing, laser cutting, etc.
FYI I'm already doing extrusion and machining at my university as research. So am also keen for a nice viewer to simulate the additive+subtractive toolpath. Ideally, build directly into FullControl python rather than needing to export to a CAD/CAM package (although that would be useful to support too! But their additive previews are nowhere near the standard/value of their subtractive ones). Anyway, it's in the pipeline!
Let me know about fc.Laser(spotsize=XX) or fc.Laser(power=XX) or something else
you need to specify the spot size and the power. the spot size is the diameter at which the beam intensity drops below 1/e2, while the power determines the pulse width. so at 100% power the laser is always on, at 1% power the laser is only on 1% of the time.
already made progress on the slicing:
here is a resistor and capacitor sliced using outline fill, for patterning a layer of graphene on polyimide film. there are still a few issues with it as you can see, but it's getting there
Ah, very cool! Note that there is an offline path function in fclab.offset_path().
Can spot size be changed during the process, or is it something that is typically set once and left? Not just for your cutter, but for laser cutters in general? This will affect whether it is best as a design object or an initialization parameter.
Laser cutting is quite nice compared to extrusion 3D printing cos it doesn't matter if you go over the same area twice or overlap your lines too much, am I right? Since if the laser goes over hole, it doesn't matter? With extrusion 3D printing, you'd end up with too much material being deposited, so you need to be careful to get just the right overlap (too little = bad porous structure; too much = messy over-deposition).
Spot size is a property of the laser. You could do a tool change during the job, but I think it's fine as an initialization parameter.
Yes, gave the builtin offset a go, but since I'm already using build123d to define the geometry to export for cad etc. seems like doing something custom is fine. Also easier to handle curves, the builtin only handles polygons.
I think laser cutting is worse, with 3d printing, you can speed up, but with a laser cutter the spot size is given. If you're just cutting I guess it doesn't matter, but for my use case I want to get the right amount of energy on the plastic film as uniformly as possible. First to graphenize the sheet (if you over or under expose, the graphene layer will have different conductivity) and later to dope the graphene lattice with B or N atoms to produce semiconductors by submerging the film in ammonia or boric acid. I don't know yet how finicky this will be yet as I haven't tried it yet.
On the other hand I'm designing the geometry to be multiples of spot size, with 3d printing you get what you get...
Hey, chat gpt told me that some laser system do have adjustable spot size with dynamic focus and maybe also with Z adjustment. It doesn't really matter, but I'll make it so spot size could theoretically be adjusted during the process since we have that functionality so readily accessible in FullControl for variable extrusion width. Even if the most common method in FullControl is simply to state it as an initialization parameter.
For your energy requirements, I can definitely see the challenges, potentially more that for 3D printing as you say. And these mean opportunity for FullControl when you get to do fancy custom things to really get what you want rather than using pre-defined path strategies from automatic commercial software. I examined a PhD thesis that looked at this sort of thing for surface modification (talking all about things like energy density and pulse overlaps, etc. Very interesting stuff!
I think that's all the info I'll need, so I'll try to create a modified FullControl or script in the next few days.
I guess it's possible, but I don't think it's a feature commonly supported by cheap laser cutters. Can you link the PhD thesis you're referring to? Sounds very interesting.
I'm afraid I can't link to the thesis as it isn't public yet, as far as I'm aware. It wasn't investigating a similar topic to you, but the idea of uniform energy density is clearly of value to a wide range of applications/research within the overall laser processing field
can I give it a try soon? some methods on the laser to configure the energy density would be nice. this is what I'm currently using.
class Laser:
def __init__(self, max_speed=10000, max_power=5, spot_size=0.06):
self.max_speed = max_speed
self.max_power = max_power
self.spot_size = spot_size
def energy_density(self, s=1000, f=None):
power = self.max_power * s / 1000
speed = (f or self.max_speed) / 60
return power / (speed * self.spot_size)
def laser_s(self, energy_density, f=None):
speed = (f or self.max_speed) / 60
power = energy_density * speed * self.spot_size
return round(power / self.max_power * 1000)
def laser_f(self, energy_density, s=1000):
power = self.max_power * s / 1000
speed = power / energy_density / self.spot_size
return round(speed * 60)
def laser_sf(self, energy_density):
cutoff = self.energy_density()
if energy_density <= cutoff:
s = self.laser_s(energy_density)
f = self.max_speed
else:
s = 1000
f = self.laser_f(energy_density)
return (s, f)
Done an initial implementation!
Check it out with this:
import fullcontrol as fc
import lab.fullcontrol as fclab
steps = fc.rectangleXY(fc.Point(x=10, y=10, z=0), 10, 10)
steps.append(fclab.Laser(cutting_speed=400, power=2.5, on=True))
steps.extend(fc.travel_to(fc.Point(x=12, y=12)))
steps.extend(fc.rectangleXY(fc.Point(x=12, y=12), 6, 6))
steps.insert(0, fclab.Laser(cutting_speed=800, travel_speed=3000, power=5, spotsize=0.8, on=True ))
steps.append(fc.ManualGcode(text='M5'))
# fc.transform(steps, 'plot', fc.PlotControls(color_type='print_sequence'))
print(fclab.transform(steps, 'laser_cutter_gcode', fc.GcodeControls(printer_name='generic'), show_tips=False))
one additional thing would be adding a fclab.Laser(dynamic=True)
to emit M4
instead of M3
. will give it a try soon
Just tweaked it to have options for either 'constant_power' or 'dynamic_power':
import fullcontrol as fc
import lab.fullcontrol as fclab
steps = fc.rectangleXY(fc.Point(x=10, y=10, z=0), 10, 10)
steps.append(fclab.Laser(cutting_speed=400, dynamic_power=2.5, on=True))
steps.extend(fc.travel_to(fc.Point(x=12, y=12)))
steps.extend(fc.rectangleXY(fc.Point(x=12, y=12), 6, 6))
steps.insert(0, fclab.Laser(cutting_speed=800, travel_speed=3000, constant_power=5, spotsize=0.8, on=True))
steps.append(fc.ManualGcode(text='M5'))
# fc.transform(steps, 'plot', fc.PlotControls(color_type='print_sequence'))
print(fclab.transform(steps, 'laser_cutter_gcode', fc.GcodeControls(printer_name='generic'), show_tips=False))
produces gcode:
G0 F8000 X10 Y10
M3 S5.0
G1 F800 X20
G1 Y20
G1 X10
G1 Y10
M4 S2.5
G0 F3000 X12 Y12
G1 F400 X18
G1 Y18
G1 X12
G1 Y12
M5
something is wrong with travel moves:
steps = [
Laser(on=True, constant_power=None, dynamic_power=1000.0, cutting_speed=2500.0, travel_speed=10000.0, spotsize=0.06),
Point(x=0.0, y=0.0, z=0.0, color=None),
]
fclab.transform(
steps,
'laser_cutter_gcode',
fc.GcodeControls(
printer_name='generic',
initialization_data={
'travel_speed': 10000.0,
}),
show_tips=False,
)
)
G0 F10000 X0 Y0 None
M4 S1000.0
FYI, bug was introduced in latest commit
Fixed it now. Thanks for pointing it out!
Still haven't found the ideal solution for generating toolpaths. After doing some custom generation for special cases, it felt non scalable, especially since the geometry would have to be exported from existing cad solutions.
After learning more about laser optics it seems that defocusing the laser does change the beam diameter and there is a simple relationship between the z axis and the beam width, as you suggested earlier.
Now I'm trying to find a solution to slice a shape using variable width sections. It seems that your paper convex does just that, but it seems focused on printer settings to achieve the filament width. Is there any description of how you compute these variable width offsets for an arbitrary polygon which might contain holes?
Now I'm trying to find a solution to slice a shape using variable width sections. It seems that your paper convex does just that, but it seems focused on printer settings to achieve the filament width. Is there any description of how you compute these variable width offsets for an arbitrary polygon which might contain holes?
In case it's relevant / of interest, I put a few ideas down a while ago around variable-width path generation, as part of a broader "shape slicing" type approach. I'm yet to finish implementation there, but there's at least some code as a starting point.
My main ideas there for hole handling are to perform the initial interpolative path generation assuming there are no holes, and then either jump over the holes as travel moves (i.e. "cut" the path), or warp the existing path lines out of the way around the holes (i.e. "push aside" or "bend" the path).
Now I'm trying to find a solution to slice a shape using variable width sections. It seems that your paper convex does just that, but it seems focused on printer settings to achieve the filament width. Is there any description of how you compute these variable width offsets for an arbitrary polygon which might contain holes?
There isn't I'm afraid. With convex, you subdivide the shape into sections that can be 'streamline sliced'. I've used it for shapes with holes in before. For a square with a circular hole in, you can do it in two sections. One for the top half, one for the bottom. Then you run convex twice. For the top half, your 'top' outline would be the straight top line of the square, split into lots of points (probably not equidistant). The 'bottom' outline would be a short straight line, then a semicircle, then another short straight line. You'd need the same number of points on the 'top' and 'bottom' lines. I'd be tempted to do the top line as lots of coincident points at either end, or some other skew, where the points or biased towards the end of the line. This will give a nice segmentation transition to matched the natural linear bias resulting from a (typically equidistant) points on a circle. When E-Alexander says "bend the path" that's what I'm suggesting here (manually identifying the bend).
Is this for research? Happy to put more effort in and have a call if this is for publication.
Once you have the convex function working, you can just replace extrusion width objects generated with convex with laser power objects based on extrusion width.
Is this for research? Happy to put more effort in and have a call if this is for publication.
I'm no researcher, I don't even own a bachelors degree... I do make a living as a software engineer.
I did find this paper and github repo, I'll see if I can integrate it with my workflow [0], which uses kicad to draw a schematic, a model + optimization algrithm to design the footprints from the schematic and then generating a toolpath from the pcb layout. my current issue is gaps in the toolpaths, due to fixed width offsetting, which is obviously no good.
I think my laser simulation is working now taking (s,f,z) and laser/machine parameters into account. Here you can see the energy density and the cross sections in movement and perpendicular direction.
The main take away is to overlap lines by 50% which doubles the energy density in the overlapped areas and leads to a nice uniform density which drops to zero within the non overlapped area. depending on the pwm frequency, duty cycle and travel speed the dimensions can shrink in the travel direction.
would at least require supplying a custom tool to the state to override gcode_e.