Created
August 12, 2025 23:48
-
-
Save aavogt/29776e5fc1822ddc0808a4e6e76b238d to your computer and use it in GitHub Desktop.
offset strip fin using fullcontrol.xyz example for why I started htpl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import fullcontrol as fc | |
| import math | |
| import time | |
| import os | |
| # the main thing is to reduce the temperature | |
| # do I add retraction? Z or E? M207, G10 G11 | |
| # do I slow it down? | |
| # do I make them closer together? | |
| # do I add a horizontal line that gets cut off? This way I | |
| # cut right next to the line and it's guaranteed to be open then | |
| # does it make sense to do lines more than once? | |
| # how do I transpose it? | |
| # I can rewrite the whole function swapping x and y | |
| # I can also process the output, swapping x and y | |
| # when I make the lines thin, I don't have enough adhesion | |
| # I need to draw a brim. | |
| # This means the first line has to be much thicker | |
| import inspect | |
| def transposing(fn): | |
| """def f(x, mx, Y, fYs): | |
| g = transposing(f) | |
| -- g(y, my, X, fXs) | |
| """ | |
| sig = inspect.signature(fn) | |
| param_names = list(sig.parameters.keys()) | |
| param_defaults = {k: v.default for k, v in sig.parameters.items() if | |
| v.default is not inspect.Parameter.empty} | |
| def wrapper(*args, **kwargs): | |
| # Map positional arguments to their parameter names | |
| ps = param_defaults.copy() | |
| ps.update(zip(param_names, args)) | |
| ps.update(kwargs) | |
| # Replace x with y and y with x in the combined | |
| for k in list(ps.keys())[4:7]: | |
| kl = list(k) | |
| for i in range(len(kl)): | |
| def recase(d): | |
| if kl[i].isupper(): | |
| return d.upper() | |
| else: | |
| return d | |
| match kl[i].lower(): | |
| case 'x': | |
| kl[i] = recase('y') | |
| case 'y': | |
| kl[i] = recase('x') | |
| kn = ''.join(kl) | |
| # only swap once | |
| if kn < k: | |
| ps[kn], ps[k] = ps[k], ps[kn] | |
| print(ps) | |
| print(param_defaults) | |
| result = fn(**ps) | |
| # Swap x and y in the result | |
| def swap_xy(obj): | |
| ##if hasattr(obj, 'x') and hasattr(obj, 'y'): | |
| # obj.x, obj.y = obj.y, obj.x | |
| # return obj | |
| # return a new Point object: | |
| if isinstance(obj, fc.Point): | |
| return fc.Point(x=obj.y, y=obj.x, z=obj.z, color=obj.color) | |
| return obj | |
| return [swap_xy(p) for p in result] | |
| return wrapper | |
| def create_line_grid(x0 = 50, y0 = 50, z0 = 0.2, | |
| Ny = 15, Nx = 5, | |
| X = 160, | |
| Y = 44, | |
| side_width = 0.3, | |
| main_width = 0.1, | |
| overlap = 0.25, | |
| passes = 4, # one pass | |
| pass_dz = 0.20): | |
| Lx = X / (2*Nx - 1 - overlap * (2*Nx - 2)) | |
| DX = - Lx * overlap | |
| S_x = 2* (Lx + DX) | |
| S_y = Y / (Ny + 1) | |
| lines = [] | |
| def setw(w): | |
| lines.append(fc.ExtrusionGeometry(width=w)) | |
| p = fc.Point(x=x0, y=y0, z=z0) | |
| def on(): | |
| lines.append(fc.Extruder(on=True)) | |
| # G11 | |
| lines.append(fc.ManualGcode(text="G1 E0.5")) | |
| def off(): | |
| lines.append(fc.Extruder(on=False)) | |
| # G10 | |
| lines.append(fc.ManualGcode(text="G1 E-0.5")) | |
| lines.append(fc.ManualGcode(text="M0 P300")) | |
| def side_wall(yv=y0): | |
| setw(side_width) | |
| off() | |
| lines.append(fc.Point(x=x0+X, y=yv, z=z0)) | |
| on() | |
| for k in range(passes): | |
| # left side wall doesn't render, why? | |
| lines.append(fc.Point(x=x0+X, y=yv, z=z0 + k * pass_dz)) | |
| lines.append(fc.Point(x=x0, y=yv, z=z0 + k * pass_dz)) | |
| lines.append(fc.Point(x=x0, y=yv, z=z0 + k * (pass_dz + 1))) | |
| off() | |
| # side_wall() | |
| setw(main_width) | |
| # offset strip fins in a s-pattern | |
| for j in range(1,Ny+1): # in the y direciton | |
| xiter = range(Nx) | |
| if j % 2 == 0: | |
| xiter = reversed(xiter) | |
| for i in xiter: # in the x direction | |
| # Skip odd lines when i is the last column | |
| if i == Nx-1 and j % 2 != 0: | |
| continue | |
| # Add DX to x coordinate when j is odd and i is not the end | |
| if j % 2 != 0 and i != Nx-1: | |
| x_offset = Lx + DX | |
| else: | |
| x_offset = 0 | |
| p1 = fc.Point(x=x0 + i*S_x + x_offset, y=y0+ j*S_y, z=z0) | |
| p2 = fc.Point(x=x0 + i*S_x + x_offset + Lx, y=y0 + j*S_y, z=z0) | |
| def qd(a, b): | |
| return (a.x - b.x)**2 + (a.y - b.y)**2 + (a.z - b.z)**2 | |
| if qd(p1, p) > qd(p2, p): | |
| p1, p2 = p2, p1 | |
| for k in range(passes): | |
| p1 = p1.copy() | |
| p2 = p2.copy() | |
| p1.z = z0 + k * pass_dz | |
| p2.z = z0 + k * pass_dz | |
| lines.append(p1) | |
| on() | |
| lines.append(p2) | |
| off() | |
| # lines.append(p1) # back some percentage instead? | |
| p = p2 | |
| # side_wall(y0 + Y*2) | |
| off() | |
| return lines | |
| create_line_grid_h = transposing(create_line_grid) | |
| # shouldn't this be the bounding box of extrusion? | |
| # why should travel be larger than extrusion? | |
| def get_bounding_box(objects): | |
| if not objects: | |
| return None | |
| min_x = min_y = min_z = float('inf') | |
| max_x = max_y = max_z = float('-inf') | |
| for obj in objects: | |
| if hasattr(obj, 'x') and hasattr(obj, 'y') and hasattr(obj, 'z'): | |
| min_x = min(min_x, obj.x) | |
| min_y = min(min_y, obj.y) | |
| min_z = min(min_z, obj.z) | |
| max_x = max(max_x, obj.x) | |
| max_y = max(max_y, obj.y) | |
| max_z = max(max_z, obj.z) | |
| return { | |
| 'min': { 'x' : min_x, 'y' : min_y, 'z' : min_z}, | |
| 'max': { 'x' : max_x, 'y' : max_y, 'z' : max_z}, | |
| } | |
| def draw_l_corners(sequence, corner_length=10, corner_lengthy = 2, offset=2, z=0.2): | |
| bbox = get_bounding_box(sequence) | |
| if bbox is None: | |
| return [] | |
| x_min, y_min = bbox["min"]["x"] - offset, bbox["min"]["y"] - offset | |
| x_max, y_max = bbox["max"]["x"] + offset, bbox["max"]["y"] + offset | |
| corners = [] | |
| # counterclockwise | |
| corner_points = [ | |
| (x_min+corner_length, y_min), | |
| (x_min, y_min), | |
| (x_min, y_min + corner_lengthy), | |
| (x_min, y_max - corner_lengthy), | |
| (x_min, y_max), | |
| (x_min+corner_length, y_max), | |
| (x_max-corner_length, y_max), | |
| (x_max, y_max), | |
| (x_max, y_max-corner_lengthy), | |
| (x_max, y_min+corner_lengthy), | |
| (x_max, y_min), | |
| (x_max-corner_length, y_min) | |
| ] | |
| corners.append(fc.Extruder(on=False)) | |
| for i, (x, y) in enumerate(corner_points): | |
| corners.append(fc.Point(x=x, y=y, z=z)) | |
| if i % 3 == 0: | |
| corners.append(fc.Extruder(on=True)) | |
| if i % 3 == 2: | |
| corners.append(fc.Extruder(on=False)) | |
| return corners | |
| line_grid = create_line_grid() | |
| result = [fc.ExtrusionGeometry(width=2.5, height=0.2), | |
| fc.ManualGcode(text="M207 F100 S10"), | |
| fc.ManualGcode(text="M203 X50 Y50"), | |
| fc.Fan(speed_percent=0)] | |
| def on(): | |
| result.append(fc.Extruder(on=True)) | |
| result.append(fc.ManualGcode(text="G1 E0.5")) | |
| def off(): | |
| result.append(fc.Extruder(on=False)) | |
| result.append(fc.ManualGcode(text="G1 E-0.5")) | |
| # result += draw_l_corners(line_grid) | |
| result.append(fc.Extruder(on=False)) | |
| # get out of the way, and then pause | |
| def away(): | |
| off() | |
| result.append(fc.Point(x=180, y=180, z=10)) | |
| result.append(fc.ManualGcode(text="M0")) | |
| away() | |
| def stack(layers = 5): | |
| global result | |
| for i in range(layers): | |
| result += create_line_grid(z0=0.1 + 0.2*8*i) | |
| away() | |
| result += create_line_grid_h(z0=0.1 + 0.2*8*(i+0.5), Ny = math.floor(15*160/44)) | |
| if i < layers-1: | |
| away() | |
| def side_by_side(xrange=(0, 220), w = 45): | |
| global result | |
| for x in range(xrange[0], xrange[1], w): | |
| result += create_line_grid(x0=x) | |
| side_by_side() | |
| print('\n\n-----------------\n\n') | |
| # have to set the temperature before the "move to the start position" | |
| # myprinter = fc.GcodeControls(printer_name="Cura/Creality Ender-5 S1", | |
| # initialization_data={"primer": "travel"}) | |
| with open("tape.gcode", "w") as file: | |
| file.write(fc.transform(result, 'gcode')) # | |
| file.close() | |
| print(f'wrote gcode {time.ctime()}') | |
| # fc.transform(result, 'plot') | |
| # preheat without waiting, then preheat and wait | |
| # before the cura primer gcode | |
| # "nozzle_temp"" : "230" adds the M109 S230 too late | |
| # https://github.com/FullControlXYZ/fullcontrol/issues/93#issuecomment-2258953005 | |
| temperature = 230 | |
| bed_temperature = 60 | |
| fan = 25 # why am I repeating myself here? | |
| os.system(f"sed -i -e '1i\\M104 S{temperature}\\nM140 S{bed_temperature}\\nG28' -e '11i\\M190 S{bed_temperature}\\nM109 S{temperature}\\nM106 S{fan}' tape.gcode") | |
| # copy to sd card overwriting tape.gcode if it's plugged | |
| if os.path.exists("/dev/mmcblk0p1"): | |
| if not os.path.exists("/media/aavogt/F089-C8E2/"): | |
| os.system("udisksctl mount -b /dev/mmcblk0p1") | |
| os.system("cp tape.gcode /media/aavogt/disk") | |
| os.system("udisksctl unmount -b /dev/mmcblk0p1") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment