# The MIT License (MIT) # # Copyright (c) # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # Printer nozzle_diameter = 0.8 # Object obj_x = 290/2 obj_y = 290/2 obj_radius = 25 obj_segments = 128 obj_layers = 40 # Print speed_layer0 = 20 speed_slow = 20 speed_fast = 70 speed_travel = 200 height_layer0 = 0.25 height_layer = 0.4 brims = 5 # Filament filament_diameter = 1.75 extrusion_factor = 0.99 # Temperatures temp_bed_layer0 = 70 temp_bed = 60 temp_extruder_layer0 = 215 temp_extruder = 205 # Retraction retract_distance = 1.2 retract_speed = 35 retract_extra_restart = 0.1 retract_lift = height_layer/2 # PRessure advance pa_start = 0.0 pa_stop = 0.2 from math import pi, cos, sin, sqrt # GCode class, helper to generate G-code class GCode: # GCode constructor def __init__(self): self.curr_x = 0 self.curr_y = 0 self.curr_z = 0 self.curr_e = 0 self.curr_f = 0 self.set_filament(1.75, 1.0) self.set_nozzle(0.4) self.set_retraction(1.0, 30, 0, 0, 150) # Set filament data # Params: # diameter Filament diameter [mm] # extrusion factor def set_filament(self, diameter, extrusion_factor): self.filament_area = pi*(filament_diameter/2)**2 if extrusion_factor < 0: extrusion_factor = 0 self.extrusion_factor = extrusion_factor # Set nozzle size # Params: # diameter Nozzle diameter [mm} def set_nozzle(self, diameter): self.extrusion_width = diameter*1.125 # Set retraction settings # Params: # distance Retraction distance [mm] # retract_speed Retraction speed [mm/s] # extra_restart Feed extra filament when de-retracting [mm] # lift Z-lift after retraction [mm] # lift_speed Travel speed for nozzle lift [mm/s] def set_retraction(self, distance, retract_speed, extra_restart, lift, lift_speed): self.retract_distance = distance self.retract_feed = retract_speed*60 self.retract_extra_restart = extra_restart self.retract_lift = lift self.retract_lift_speed= lift_speed # Print method, placeholder for future support of generating multiple files # Params: # line String to print on separate line def print(self, line): print(line) # Generate move without extrusion # Params: # x target x position [mm] # y target y position [mm] # z target z position [mm] # speed movement speed [mm/s] def move(self, x, y, z, speed): cmd = "G1" # Position if x != self.curr_x: cmd += " X%.3f" % x self.curr_x = x if y != self.curr_y: cmd += " Y%.3f" % y self.curr_y = y if z != self.curr_z: cmd += " Z%.3f" % z self.curr_z = z # Feed feed = speed * 60 if feed != self.curr_f: cmd += " F%.3f" % feed self.curr_f = feed if cmd != "G1": self.print(cmd) # Generate extrude command # Params: # x target x position [mm] # y target y position [mm] # z target z position [mm] # speed movement speed [mm/s] # height Print height [mm] def extrude(self, x, y, z, speed, height): cmd = "G1" # Position if x != self.curr_x: cmd += " X%.3f" % x self.curr_x = x if y != self.curr_y: cmd += " Y%.3f" % y self.curr_y = y if z != self.curr_z: cmd += " Z%.3f" % z self.curr_z = z # Extrusion # calculations from http://manual.slic3r.org/advanced/flow-math area = (self.extrusion_width-height)*height+(height/2)**2*pi length = sqrt((x-self.curr_x)**2 + (y-self.curr_y)**2 + (z-self.curr_z)**2) volume = length * area * self.extrusion_factor if volume > 0: self.curr_e += volume/self.filament_area cmd += " E%.3f" % self.curr_e # Feed feed = speed * 60 if feed != self.curr_f: cmd += " F%.3f" % feed self.curr_f = feed self.print(cmd) # Generate retract def retract(self): self.curr_e -= self.retract_distance self.print("G1 E%.3f F%d" % (self.curr_e, self.retract_feed)) self.move(self.curr_x, self.curr_y, self.curr_z+self.retract_lift, self.retract_lift_speed) # Genreate de-retract def deretract(self): self.move(self.curr_x, self.curr_y, self.curr_z-self.retract_lift, self.retract_lift_speed) self.curr_e += self.retract_distance + self.retract_extra_restart self.print("G1 E%.3f F%d" % (self.curr_e, self.retract_feed)) # Set bed temperature # Params: # temp Bed temperature [deg C] def set_bed_temp(self, temp): self.print("M140 S%d" % temp) # Set bed temperature and wait for it to be reached # Params: # temp Bed temperature [deg C] def set_bed_temp_wait(self, temp): self.print("M190 S%d" % temp) # Set extruder temperature # Params: # temp Extruder temperature [deg C] def set_extruder_temp(self, temp): self.print("M104 S%d" % temp) # Set extruder temperature and wait for it to be reached # Params: # temp Extruder temperature [deg C] def set_extruder_temp_wait(self, temp): self.print("M109 S%d" % temp) # Set fan speed # Params: # speed Fan speed [%] def set_fan_speed(self, speed): pwm = speed/100 if pwm < 0: pwm = 0 elif pwm > 1: pwm = 1 self.print("M106 S%.2f" % pwm) # Set pressure advance # Params: # pressure_advance Pressure advance factor [mm*s*s] def set_pressure_advance(self, pressure_advance): self.print("M572 D0 S%.3f" % pressure_advance) # Misc. init commands def init(self): self.print("G21") self.print("M82") self.print("G92 E0") self.print("G90") # Home one or more axis # Params: # x Home X-axis [bool] # y Home Y-axis [bool] # z Home Z-axis [bool] def home(self, x, y, z): cmd = "G28" if not x or not y or not z: if x: cmd += " X" if y: cmd += " Y" if z: cmd += " Z" self.print(cmd) # Use absolute prositions def absolute_pos(self): self.print("G90") # Use relative positions def relative_pos(self): self.print("G91") # Disable motor drivers def disable_motors(self): self.print("M18"); # Generate comment in g-code # Params: # comment Comment string to put in G-code def comment(self, comment): self.print("; " + comment) # Helper function to generate a range of angles given a number of circle segments # Params: # segments Number of circle segments def angles(segments): a = 0 while a < 2*pi: yield a a += 2*pi/segments pa_cal = GCode() pa_cal.set_filament(filament_diameter, extrusion_factor) pa_cal.set_nozzle(nozzle_diameter) pa_cal.set_retraction(retract_distance, retract_speed, retract_extra_restart, retract_lift, speed_travel) #init pa_cal.set_bed_temp_wait(temp_bed_layer0) pa_cal.set_extruder_temp(temp_extruder_layer0) pa_cal.init() pa_cal.home(True, True, True) pa_cal.move(obj_x, obj_y, 5, speed_travel) pa_cal.set_extruder_temp_wait(temp_extruder_layer0) pa_cal.set_pressure_advance(pa_start) #brim for b in range(brims, 0, -1): r = obj_radius + b*pa_cal.extrusion_width pa_cal.comment("Brim %d, r=%.3f" % (b, r)) pa_cal.move(obj_x+r, obj_y, height_layer0, speed_travel) for a in angles(obj_segments): pa_cal.extrude(obj_x+r*cos(a), obj_y+r*sin(a), height_layer0, speed_layer0, height_layer0); #adhesion layer pa_cal.comment("Adhesion layer") for a in angles(obj_segments): pa_cal.extrude(obj_x+obj_radius*cos(a), obj_y+obj_radius*sin(a), height_layer0, speed_layer0, height_layer0); pa_cal.set_bed_temp(temp_bed) pa_cal.set_extruder_temp(temp_extruder) pa_cal.set_fan_speed(100) #Spiral vase start pa_cal.comment("Spiral vase start") for a in angles(obj_segments): height = height_layer * a/(2*pi) pa_cal.extrude(obj_x+obj_radius*cos(a), obj_y+obj_radius*sin(a), height_layer0+height, speed_fast, height); # Main layers for l in range(1, obj_layers): z = height_layer0+l*height_layer pa = pa_start + (pa_stop-pa_start)*(l/obj_layers) pa_cal.comment("Layer %d, Z=%.3f mm, PA=%.3f" % (l, z, pa)) pa_cal.set_pressure_advance(pa) for a in angles(obj_segments): speed = speed_fast if 0 < a < pi/4 or pi < a < 5*pi/4: speed = speed_slow pa_cal.extrude(obj_x+obj_radius*cos(a), obj_y+obj_radius*sin(a), z+height_layer*a/(2*pi), speed, height_layer); # suffix pa_cal.retract() pa_cal.move(pa_cal.curr_x, pa_cal.curr_y, pa_cal.curr_z+5, speed_travel) pa_cal.home(True, False, False) pa_cal.set_bed_temp(0) pa_cal.set_extruder_temp(0) pa_cal.set_fan_speed(0) pa_cal.disable_motors()