def initParser(args, mode=None, gui=None): printerProfileName = "UM2" # xxx todo: get from commandline args # Create printer profile singleton instance printerProfile = PrinterProfile(printerProfileName) # Create material profile singleton instance mat = MatProfile(args.mat, args.smat) # Overwrite settings from printer profile with command line arguments: if args.retractLength: printerProfile.override("RetractLength", args.retractLength) # Overwrite settings from material profile with command line arguments: if args.t0: mat.override("bedTemp", args.t0) if args.t1: mat.override("hotendStartTemp", args.t1) nozzle = NozzleProfile(args.nozzle) # Create the Printer singleton instance printer = Printer(gui) # Create the planner singleton instance planner = Planner(args, gui) # Create parser singleton instance parser = gcodeparser.UM2GcodeParser() return (parser, planner, printer)
def g11_retract_recover(self, line, values): # print "g11_retract_recover", values if self.retracted: current_position = self.getRealPos() values = { "F": PrinterProfile.getRetractFeedrate(), "A": current_position[A_AXIS] + PrinterProfile.getRetractLength(), } self.g0("G11", values) self.retracted = False
def g10_retract(self, line, values): # print "g10_retract", values # Compute retract if not self.retracted: current_position = self.getRealPos() values = { "F": PrinterProfile.getRetractFeedrate(), "A": current_position[A_AXIS] - PrinterProfile.getRetractLength(), } self.g0("G10", values) self.retracted = True
def __init__(self): if UM2GcodeParser.__single: raise RuntimeError('A UM2GcodeParser already exists') UM2GcodeParser.__single = self self.reset() self.commands = { # G0 and G1 are the same "G0": self.g0, "G1": self.g0, "G4": self.g4_dwell, "G10": self.g10_retract, "G11": self.g11_retract_recover, "G21": self.g21_metric_values, "G28": self.g28_home, "G29": self.g29_autolevel, "G80": self.g80_bed_leveling, "G90": self.g90_abs_values, "G91": self.g91_rel_values, "G92": self.g92_set_pos, "M25": self.m25_stop_reading, "M82": self.m82_extruder_abs_values, "M83": self.m83_extruder_relative_values, "M84": self.m84_disable_motors, "M104": self.m104_extruder_temp, "M106": self.m106_fan_on, "M107": self.m107_fan_off, "M109": self.m109_extruder_temp_wait, "M117": self.m117_message, "M140": self.m140_bed_temp, "M190": self.m190_bed_temp_wait, "M204": self.m204_set_accel, "M501": self.m501_reset_params, "M502": self.m502_reset_params, "M900": self.m900_set_kAdvance, "M907": self.m907_motor_current, "T0": self.t0, "U": self.unknown, # unknown command for testing purposes } # Apply material flow parameter from material profile self.e_to_filament_length = MatProfile.getFlow() / 100.0 self.steps_per_mm = PrinterProfile.getStepsPerMMVector() self.mm_per_step = map(lambda dim: 1.0 / self.steps_per_mm[dim], range(5)) self.maxFeedrateVector = PrinterProfile.getMaxFeedrateVector() self.planner = Planner.get()
def printTempTable(printer, temp, tempTable): of = open("/tmp/temptable_printer.txt", "w") of.write("# xxx mat, nozzle, settings...\n") of.write("# basetemp: %d, autoTempFactor: %f\n" % (temp, 0)) of.write("# temp rate steprate timer\n") print "TempTable (basetemp: %d):" % temp mmpermm3 = 1 / MatProfile.getMatArea() spm = PrinterProfile.getStepsPerMM(A_AXIS) for timerValue in tempTable: steprate = fTimer / timerValue speed = (steprate / spm) / mmpermm3 print " Temp: %d, max extrusion: %.1f mm³/s, steps/s: %d, timervalue: %d" % (temp, speed, int(steprate), timerValue) of.write("%d %4.1f %d %d\n" % (temp, speed, int(steprate), timerValue)) temp += 2 of.close()
def manualMove(parser, axis, distance, feedrate=0, absolute=False): planner = parser.planner printer = planner.printer printer.sendPrinterInit() assert(printer.isHomed()) # Get current pos from printer and set our virtual pos getVirtualPos(parser) if not feedrate: feedrate = PrinterProfile.getMaxFeedrate(axis) current_position = parser.getRealPos() if absolute: d = distance - current_position[A_AXIS] assert(abs(d) <= 1000) parser.execute_line("G0 F%d %s%f" % (feedrate*60, dimNames[axis], distance)) else: assert(abs(distance) <= 1000) parser.execute_line("G0 F%d %s%f" % (feedrate*60, dimNames[axis], current_position[axis] + distance)) planner.finishMoves() printer.sendCommand(CmdEOT) # time.sleep(1) printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.waitForState(StateIdle) printer.readMore(10)
def __init__(self): if UM2GcodeParser.__single: raise RuntimeError('A UM2GcodeParser already exists') UM2GcodeParser.__single = self self.reset() self.commands = { # G0 and G1 are the same "G0": self.g0, "G1": self.g0, "G4": self.g4_dwell, "G10": self.g10_retract, "G11": self.g11_retract_recover, "G21": self.g21_metric_values, "G28": self.g28_home, "G29": self.g29_autolevel, "G90": self.g90_abs_values, "G92": self.g92_set_pos, "M25": self.m25_stop_reading, "M82": self.m82_extruder_abs_values, "M84": self.m84_disable_motors, "M104": self.m104_extruder_temp, "M106": self.m106_fan_on, "M107": self.m107_fan_off, "M109": self.m109_extruder_temp_wait, "M117": self.m117_message, "M140": self.m140_bed_temp, "M190": self.m190_bed_temp_wait, "M907": self.m907_motor_current, "T0": self.t0, "U": self.unknown, # unknown command for testing purposes } # Apply material flow parameter from material profile self.e_to_filament_length = MatProfile.getFlow() / 100.0 self.steps_per_mm = PrinterProfile.getStepsPerMMVector() self.mm_per_step = map(lambda dim: 1.0 / self.steps_per_mm[dim], range(5)) self.maxFeedrateVector = PrinterProfile.getMaxFeedrateVector() self.planner = Planner.get()
def g11_retract_recover(self, line, values): # print "g11_retract_recover", values current_position = self.getPos() rl = PrinterProfile.getRetractLength() current_position[A_AXIS] += rl self.planner.addMove( TravelMove(line, displacement_vector=Vector([0.0, 0.0, 0.0, rl, 0.0]), displacement_vector_steps=[ 0.0, 0.0, 0.0, rl * self.steps_per_mm[A_AXIS], 0.0 ], feedrate=min(PrinterProfile.getRetractFeedrate(), PrinterProfile.getMaxFeedrate(3)))) self.setPos(current_position)
def getJerk(self): jerk = [] for dim in dimNames: jerk.append(PrinterProfile.getValues()['axes'][dim]['jerk']) # self.jerk = Vector(jerk) # self.gui.log("Jerk vector: ", self.jerk) # self.gui.log("Jerk vector: ", jerk) return jerk
def __init__(self, comment, displacement_vector, displacement_vector_steps, feedrate, # mm/s maxAccelV, ): RealMove.__init__(self, comment) # # Move distance in XYZ plane # self.distance3 = displacement_vector.length(3) self.advanceData = AdvanceData(self) self.e_steps_per_mm = PrinterProfile.getStepsPerMM(A_AXIS) self.displacement_vector_raw3 = Vector(displacement_vector[:3]) self.displacement_vector_steps_raw3 = displacement_vector_steps[:3] self.direction3 = self.displacement_vector_raw3.normalized() ### Apply extrusion adjust ### if UseExtrusionAdjust: direction5 = displacement_vector.normalized() self.eDistance = displacement_vector[A_AXIS] # xxx todo: add override self.eSteps = displacement_vector_steps[A_AXIS] self.eDirection = self.eDistance / self.distance3 # Compute nominal eSpeed v = VelocityVector32(feedrate*self.eDirection, feedrate = feedrate, direction = self.direction3) self.startSpeed = VelocityOverride(v) self.topSpeed = VelocityOverride(v) self.endSpeed = VelocityOverride(v) # self.__direction5 = displacement_vector.normalized() # av = self.__getMaxAllowedAccelVector5(maxAccelV) accelVector = direction5.scale(_MAX_ACCELERATION) av = accelVector.constrain(maxAccelV) or accelVector # xxx rework accel, store default xyz and eaccel, make start- and eaccel overridable self.startAccel = AccelOverride([av[:3], av[A_AXIS]], self.direction3) self.endAccel = AccelOverride([av[:3], av[A_AXIS]], self.direction3)
def removeFilament(args, parser): planner = parser.planner printer = planner.printer printer.commandInit(args) ddhome.home(parser, args.fakeendstop) printer.sendPrinterInit() # Move to mid-position # MAX_POS = (X_MAX_POS, Y_MAX_POS, Z_MAX_POS) # feedrate = PrinterProfile.getMaxFeedrate(Z_AXIS) # parser.execute_line("G0 F%d Z%f" % (feedrate*60, MAX_POS[Z_AXIS])) feedrate = PrinterProfile.getMaxFeedrate(X_AXIS) parser.execute_line("G0 F%d X%f Y%f" % (feedrate*60, planner.MAX_POS[X_AXIS]/2, planner.MAX_POS[Y_AXIS]/2)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle) t1 = MatProfile.getHotendBaseTemp() printer.heatUp(HeaterEx1, t1, wait=t1) # Etwas vorwärts um den retract-pfropfen einzuschmelzen manualMove(parser, A_AXIS, PrinterProfile.getRetractLength() + 5, 5) manualMove(parser, A_AXIS, -1.3*FILAMENT_REVERSAL_LENGTH) if not args.noCoolDown: printer.coolDown(HeaterEx1,wait=150)
def changeNozzle(args, parser): planner = parser.planner printer = planner.printer retract(args, parser, doCooldown = False) feedrate = PrinterProfile.getMaxFeedrate(X_AXIS) execSingleGcode(parser, "G0 F%d X%f Y%f" % (feedrate*60, planner.MAX_POS[X_AXIS]/2, planner.MAX_POS[Y_AXIS]*0.1)) raw_input("Now change nozzle, Press return to stop heating...") execSingleGcode(parser, "G11") if not args.noCoolDown: printer.coolDown(HeaterEx1, wait=100)
def calibrateFilSensor(args, parser): planner = parser.planner printer = planner.printer printer.commandInit(args) steps_per_mm = PrinterProfile.getStepsPerMMVector()[util.A_AXIS] # ddhome.home(parser, args.fakeendstop) current_position = parser.getRealPos() apos = current_position[util.A_AXIS] fsstepsum = 0 distsum = 0 # ramp up speed from 3mm/s to 13mm/s, that is about 7.2 to 31 mm³/s flowrate (1.75mm filament) for feedrate in range(11): feedrate += 3 # choose length of move to get about 25 points per feedrate step distance = 2.5 * feedrate apos += distance printer.sendPrinterInit() parser.execute_line("G0 F%d %s%f" % (feedrate*60, util.dimNames[util.A_AXIS], apos)) planner.finishMoves() printer.sendCommand(CmdEOT) printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.waitForState(StateIdle) time.sleep(0.25) fssteps = printer.getFilSensor() print "Speed: %d, dist: %.2f, FSsteps: %d, fssteps/mm: %.4f" % (feedrate, distance, fssteps, fssteps/distance) distsum += distance fsstepsum += fssteps print "Average fssteps/mm: %.4f" % (fsstepsum/distsum)
def getHomePos(self): # Get additional z-offset from eeprom add_homeing_z = self.printer.getAddHomeing_z() assert((add_homeing_z <= 0) and (add_homeing_z >= -35)) print "add_homeing_z from eeprom: ", add_homeing_z # Virtuelle position des druckkopfes falls 'gehomed' homePosMM = util.MyPoint( X = self.X_HOME_POS, Y = self.Y_HOME_POS, Z = self.Z_HOME_POS + add_homeing_z, ) # Diese stepper position wird gesetzt falls der drucker 'gehomed' ist homePosStepped = vectorMul(homePosMM.vector(), PrinterProfile.getStepsPerMMVector()) return (homePosMM, homePosStepped)
def getHomePos(self): # Get additional z-offset from eeprom add_homeing_z = self.printer.getAddHomeing_z() assert ((add_homeing_z <= 0) and (add_homeing_z >= -35)) print "add_homeing_z from eeprom: ", add_homeing_z # Virtuelle position des druckkopfes falls 'gehomed' homePosMM = util.MyPoint( X=self.X_HOME_POS, Y=self.Y_HOME_POS, Z=self.Z_HOME_POS + add_homeing_z, ) # Diese stepper position wird gesetzt falls der drucker 'gehomed' ist homePosStepped = vectorMul(homePosMM.vector(), PrinterProfile.getStepsPerMMVector()) return (homePosMM, homePosStepped)
def doAutoTemp(self, moves): # Sum up path time and extrusion volume of moves tsum = 0 vsum = 0 for move in moves: tsum += move.accelData.getTime() vsum += move.getExtrusionVolume(MatProfile.get()) avgERate = vsum / tsum print "Average extrusion rate: ", avgERate, "mm³/s", "layer 0 increase: ", self.planner.l0TempIncrease # Compute temperature for this segment and add tempcommand into the stream. newTemp = \ MatProfile.getTempForFlowrate(avgERate * (1.0+AutotempSafetyMargin), PrinterProfile.getHwVersion(), NozzleProfile.getSize()) + \ self.planner.l0TempIncrease # Don't go below startTemp from material profile newTemp = max(newTemp, MatProfile.getHotendStartTemp()) # Don't go above max temp from material profile newTemp = min(newTemp, MatProfile.getHotendMaxTemp()) if newTemp != self.lastTemp: # and self.mode != "pre": print "Newtemp:", avgERate, newTemp # Schedule target temp command self.planner.addSynchronizedCommand( CmdSyncTargetTemp, p1=packedvalue.uint8_t(HeaterEx1), p2=packedvalue.uint16_t(newTemp), moveNumber=move.moveNumber) self.lastTemp = int(newTemp) if debugAutoTemp: print "AutoTemp: collected moves with %.2f s duration." % tsum print "AutoTemp: max. extrusion rate: %.2f mm³/s." % avgERate print "AutoTemp: new temp: %d." % newTemp
def zRepeatability(parser): import random printer.commandInit(args) feedrate = PrinterProfile.getMaxFeedrate(Z_AXIS) ddhome.home(parser, args.fakeendstop) printer.sendPrinterInit() for i in range(10): parser.execute_line("G0 F%d X115 Y210 Z10" % (feedrate*60)) parser.execute_line("G0 F%d Z%f" % (feedrate*60, random.randint(20, 150))) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle)
def genTempTable(printer): baseTemp = MatProfile.getHotendBaseTemp() area04 = pow(0.4, 2)*math.pi/4 extrusionLow = MatProfile.getBaseExtrusionRate() * (NozzleProfile.getArea() / area04) f = MatProfile.getAutoTempFactor() mmpermm3 = 1 / MatProfile.getMatArea() spm = PrinterProfile.getStepsPerMM(A_AXIS) of = open("/tmp/temptable0.txt", "w") of.write("# xxx mat, nozzle, settings...\n") of.write("# basetemp: %d, autoTempFactor: %f\n" % (baseTemp, f)) of.write("# temp rate steprate timer\n") print "TempTable (basetemp: %d):" % baseTemp table = [] for i in range(NExtrusionLimit): t = baseTemp + i*2 dspeed = i*2 / f speed = extrusionLow + dspeed steprate = speed * mmpermm3 * spm tvs = 1.0/steprate timerValue = int(fTimer / steprate) print " Temp: %d, max extrusion: %.1f mm³/s, steps/s: %d, steprate: %d us, timervalue: %d" % (t, speed, int(steprate), int(tvs*1000000), timerValue) table.append(timerValue) of.write("%d %4.1f %d %d\n" % (t, speed, int(steprate), timerValue)) of.close() return (baseTemp, table)
def planTravelAcceleration(self, move): if debugMoves: print "***** Start planTravelAcceleration() *****" move.pprint("planTravelAcceleration") move.state = 2 allowedAccel = allowedDecel = move.getMaxAllowedAccelNoAdv5() # # Check if the speed difference between startspeed and endspeed can be done with # this acceleration in this distance # startSpeedS = move.startSpeed.speed().feedrate endSpeedS = move.endSpeed.speed().feedrate deltaSpeedS = endSpeedS - startSpeedS if abs(deltaSpeedS) > 0.001: ta = abs(deltaSpeedS) / allowedAccel if deltaSpeedS >= 0: # acceleration sa = util.accelDist(startSpeedS, allowedAccel, ta) else: # deceleration sa = util.accelDist(startSpeedS, -allowedAccel, ta) if (sa - move.distance5) > 0.001: print "VStart %f mm/s kann nicht innerhalb von %f mm auf Endgeschwindigkeit %f mm/s gebracht werden!" % ( startSpeedS, move.distance5, endSpeedS) print "Dafür werden %f mm benötigt" % sa assert (0) # # Compute distance to accel from start speed to nominal speed: # ta = 0.0 sa = 0.0 deltaStartSpeedS = move.topSpeed.speed().feedrate - startSpeedS maxAccel = PrinterProfile.getMaxAxisAcceleration() if deltaStartSpeedS: ta = deltaStartSpeedS / allowedAccel # print "accel time (for %f mm/s): %f [s]" % (deltaStartSpeedS, ta) # debug Check axxis acceleration deltaSpeedV = move.direction5.scale(deltaStartSpeedS) for dim in range(5): dimAccel = abs(deltaSpeedV[dim]) / ta if (dimAccel / maxAccel[dim]) > 1.001: print "dim %d verletzt max accel: " % dim, dimAccel, " > ", maxAccel[ dim] assert (0) #end debug sa = util.accelDist(startSpeedS, allowedAccel, ta) # # Compute distance to decel from nominal speed to endspeed: # tb = 0.0 sb = 0.0 deltaEndSpeedS = move.topSpeed.speed().feedrate - endSpeedS # [mm/s] if deltaEndSpeedS: tb = deltaEndSpeedS / allowedAccel # [s] # print "decel time (for %f mm/s): %f [s]" % (deltaEndSpeedS, tb) # debug Check axxis acceleration deltaSpeedV = move.direction5.scale(deltaEndSpeedS) for dim in range(5): dimDecel = abs(deltaSpeedV[dim]) / tb if (dimDecel / maxAccel[dim]) > 1.001: print "dim %d verletzt max accel: " % dim, dimDecel, " [mm/s] > ", maxAccel[ dim], " [mm/s]" assert (0) # end debug sb = util.accelDist(endSpeedS, allowedAccel, tb) # print "e_distance: %f, sbeschl, sbrems: %f, %f" % (move.e_distance, sa, sb) if move.distance5 < (sa + sb): # # Strecke zu kurz, Trapez nicht möglich, geschwindigkeit muss abgesenkt werden. # if debugMoves: print "Trapez nicht möglich: s: %f, sbeschl (%f) + sbrems (%f) = %f" % ( move.distance5, sa, sb, sa + sb) # ??? assert (sa > 0 and sb > 0) topSpeed = move.topSpeed.speed() sa = (2 * allowedAccel * move.distance5 - pow(startSpeedS, 2) + pow(endSpeedS, 2)) / (4 * allowedAccel) sb = move.distance5 - sa if debugMoves: print "sbeschl, sbrems neu: %f, %f" % (sa, sb) # # Geschwindigkeit, die auf strecke sa mit erreicht werden kann # v = math.sqrt(2 * allowedAccel * sa + pow(startSpeedS, 2)) # debug, test v2 = math.sqrt(2 * allowedAccel * sb + pow(endSpeedS, 2)) # print "move.feedrate neu: %f (test: %f, diff: %f)" % (v, v2, abs(v - v2)) assert (abs(v - v2) < 0.001) deltaSpeedS = v - startSpeedS # [mm/s] # Handle rounding errors if deltaSpeedS < 0: assert (deltaSpeedS > -0.000001) deltaSpeedS = 0 v = startSpeedS ta = deltaSpeedS / allowedAccel # print "ta: ", ta, deltaSpeedS deltaSpeedS = v - endSpeedS # [mm/s] # Handle rounding errors if deltaSpeedS < 0: assert (deltaSpeedS > -0.000001) deltaSpeedS = 0 v = endSpeedS tb = deltaSpeedS / allowedAccel # print "tb: ", tb, deltaSpeedS topSpeed.feedrate = v move.topSpeed.setSpeed( topSpeed, "planTravelAcceleration - max reachable topspeed") move.setDuration(ta, 0, tb) if debugMoves: move.pprint("planTravelAcceleration") print print "***** End planTravelAcceleration() *****" return # # Strecke reicht aus, um auf nominal speed zu beschleunigen # # print "ta: ", ta, deltaStartSpeedS, sa # print "tb: ", tb, deltaEndSpeedS, sb nominalSpeed = move.topSpeed.speed().feedrate # [mm/s] slin = move.distance5 - (sa + sb) tlin = slin / nominalSpeed # print "tlin: ", tlin, slin move.setDuration(ta, tlin, tb) if debugMoves: move.pprint("planTravelAcceleration") print print "***** End planTravelAcceleration() *****"
def home(parser, fakeHomingEndstops=False, force=False): planner = parser.planner printer = planner.printer print "*" print "* Start homing..." print "*" if printer.isHomed() and not force: print "Printer is homed already..." # Send init command printer.sendPrinterInit() # Get current pos from printer and set our virtual pos curPosMM = util.getVirtualPos(parser) (homePosMM, homePosStepped) = planner.getHomePos() # print "Printer should be at [mm]: ", homePosMM, ", [steps]: ", homePosStepped # Move to home if not curPosMM.equal(homePosMM, "XYZ"): # # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern # der buildplatte oder mit objekten auf der druckplatte zu vermeiden. # if not curPosMM.equal(homePosMM, "Z"): parser.execute_line( "G0 F%d Z%f" % (PrinterProfile.getMaxFeedrate(util.Z_AXIS) * 60, homePosMM.Z)) if not curPosMM.equal(homePosMM, "XY"): parser.execute_line( "G0 F%d X%f Y%f" % (PrinterProfile.getMaxFeedrate(util.X_AXIS) * 60, homePosMM.X, homePosMM.Y)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.05) # # Set Virtual E-pos 0: # parser.setPos(homePosMM) print "*" print "* Done homing..." print "*" return # # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern # der buildplatte oder mit einem modell zu vermeiden. # for dim in [util.Z_AXIS, util.X_AXIS, util.Y_AXIS]: # Try fast home if endstop is pressed if printer.endStopTriggered(dim, fakeHomingEndstops): print "Homing: endstop %d is triggered, trying fast home." % dim if homeBounce(parser, dim, fakeHomingEndstops): continue # Try fast home if head/bed is near the endstop print "Homing: doing short/fast home." if homeMove(parser, dim, 1, planner.MAX_POS[dim] / 10.0, fakeHomingEndstops): # Move towards endstop fast print "Homing: endstop %d is triggered, trying fast home." % dim if homeBounce(parser, dim, fakeHomingEndstops): continue # Do the full slow homing move print "Homing: doing full/slow home." if not homeMove(parser, dim, 1, planner.MAX_POS[dim] * 1.25, fakeHomingEndstops): # Move towards endstop fast print "Error, Endstop %d NOT hit!" % dim assert (0) if not homeBounce(parser, dim, fakeHomingEndstops): print "Error, Bounce %d!" % dim assert (0) # # Set position in steps on the printer side and set our 'virtual position': # # xxx set end-of-print retraction e-pos also here? # # parser.setPos(planner.homePosMM) # payload = struct.pack("<iiiii", *planner.homePosStepped) (homePosMM, homePosStepped) = planner.getHomePos() parser.setPos(homePosMM) # print "Tell printer its position [steps]:", homePosStepped payload = struct.pack("<iiiii", *homePosStepped) printer.sendCommand(CmdSetHomePos, binPayload=payload) print "*" print "* Done homing..." print "*"
def main(): argParser = argparse.ArgumentParser(description='%s, Direct Drive USB Print.' % sys.argv[0]) argParser.add_argument("-d", dest="device", action="store", type=str, help="Device to use, default: /dev/ttyACM0.", default="/dev/ttyACM0") argParser.add_argument("-b", dest="baud", action="store", type=int, help="Baudrate, default 115200.", default=115200) # argParser.add_argument("-b", dest="baud", action="store", type=int, help="Baudrate, default 230400.", default=230400) # argParser.add_argument("-b", dest="baud", action="store", type=int, help="Baudrate, default 500000.", default=500000) # argParser.add_argument("-b", dest="baud", action="store", type=int, help="Baudrate, default 1000000.", default=1000000) argParser.add_argument("-t0", dest="t0", action="store", type=int, help="Temp 0 (heated bed), default comes from mat. profile.") argParser.add_argument("-t1", dest="t1", action="store", type=int, help="Temp 1 (hotend 1), default comes from mat. profile.") argParser.add_argument("-mat", dest="mat", action="store", help="Name of generic material profile to use [pla, abs...], default is pla.", default="pla_1.75mm") argParser.add_argument("-smat", dest="smat", action="store", help="Name of specific material profile to use.") argParser.add_argument("-noz", dest="nozzle", action="store", help="Name of nozzle profile to use [nozzle40, nozzle80...], default is nozzle40.", default="nozzle40") argParser.add_argument("-np", dest="noPrime", action="store_const", const=True, help="Debug: don't prime nozzle, to test extrusion-less moves.") # fake endstops as long we have no real ones argParser.add_argument("-F", dest="fakeendstop", action="store", type=bool, help="Debug: fake endstops", default=False) argParser.add_argument("-nc", dest="noCoolDown", action="store", type=bool, help="Debug: don't wait for heater cool down after print.", default=False) argParser.add_argument("-fr", dest="feedrate", action="store", type=float, help="Feedrate for move commands.", default=0) subparsers = argParser.add_subparsers(dest="mode", help='Mode: mon(itor)|print|store|reset|pre(process).') sp = subparsers.add_parser("autoTune", help=u"Autotune hotend PID values.") sp = subparsers.add_parser("binmon", help=u"Monitor serial printer interface (binary responses).") sp = subparsers.add_parser("changenozzle", help=u"Heat hotend and change nozzle.") sp = subparsers.add_parser("mon", help=u"Monitor serial printer interface (asci).") sp = subparsers.add_parser("print", help=u"Download and print file at once.") sp.add_argument("gfile", help="Input GCode file.") # sp = subparsers.add_parser("store", help=u"Store file as USB.G on sd-card.") # sp.add_argument("gfile", help="Input GCode file.") sp = subparsers.add_parser("writeEepromFloat", help=u"Store float value into eeprom.") sp.add_argument("name", help="Valuename.") sp.add_argument("value", action="store", type=float, help="value (float).") # sp = subparsers.add_parser("reset", help=u"Try to stop/reset printer.") sp = subparsers.add_parser("pre", help=u"Preprocess gcode, for debugging purpose.") sp.add_argument("gfile", help="Input GCode file.") sp = subparsers.add_parser("dumpeeprom", help=u"dump eeprom settings.") sp = subparsers.add_parser("factoryReset", help=u"FactoryReset of eeprom settings, new bed leveling needed.") sp = subparsers.add_parser("test", help=u"Debug: tests for debugging purpose.") sp = subparsers.add_parser("disableSteppers", help=u"Disable stepper current (this dis-homes the printer).") sp = subparsers.add_parser("home", help=u"Home the printer.") sp = subparsers.add_parser("measureTempFlowrateCurve", help=u"Determine temperature/flowrate characteristic.") sp = subparsers.add_parser("moverel", help=u"Debug: Move axis manually, relative coords.") sp.add_argument("axis", help="Axis (XYZAB).", type=str) sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("moveabs", help=u"Debug: Move axis manually, absolute coords.") sp.add_argument("axis", help="Axis (XYZAB).", type=str) sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("insertFilament", help=u"Insert filament (heatup, forward filament).") sp = subparsers.add_parser("removeFilament", help=u"Remove filament (heatup, retract filament).") sp = subparsers.add_parser("bedLeveling", help=u"Do bed leveling sequence.") sp = subparsers.add_parser("bedLevelAdjust", help=u"Adjust bedleveling offset - dangerous.") sp.add_argument("distance", action="store", help="Adjust-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("heatHotend", help=u"Heat up hotend (to clean it, etc).") sp = subparsers.add_parser("genTempTable", help=u"Generate extrusion rate limit table.") sp = subparsers.add_parser("getEndstops", help=u"Get current endstop state.") sp = subparsers.add_parser("getFilSensor", help=u"Get current filament position.") sp = subparsers.add_parser("getpos", help=u"Get current printer and virtual position.") sp = subparsers.add_parser("getTemps", help=u"Get current temperatures (Bed, Extruder1, [Extruder2]).") sp = subparsers.add_parser("getTempTable", help=u"Output temperature-speed table.") sp = subparsers.add_parser("getStatus", help=u"Get current printer status.") sp = subparsers.add_parser("zRepeatability", help=u"Debug: Move Z to 10 random positions to test repeatability.") sp = subparsers.add_parser("stop", help=u"Stop print, cooldown, home, disable steppers.") sp = subparsers.add_parser("stepResponse", help=u"Measure and plot stepResponse of hotend PID.") sp = subparsers.add_parser("retract", help=u"Debug: Do the end-of-print retract manually after heating up.") sp = subparsers.add_parser("fanspeed", help=u"Set fan speed manually.") sp.add_argument("speed", help="Fanspeed 0 - 255.", type=int) sp = subparsers.add_parser("testFilSensor", help=u"Debug: move filament manually, output filament sensor measurement.") sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("calibrateFilSensor", help=u"Debug: helper to determine the ratio of stepper to flowrate sensor.") # sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) args = argParser.parse_args() # print "args: ", args (parser, planner, printer) = initParser(args, mode=args.mode) steps_per_mm = PrinterProfile.getStepsPerMMVector() if args.mode == 'autoTune': util.zieglerNichols(args, parser) elif args.mode == 'changenozzle': util.changeNozzle(args, parser) elif args.mode == "binmon": printer.initSerial(args.device, args.baud) while True: try: (cmd, payload) = printer.readResponse() except RxTimeout: pass else: print "Response cmd :", cmd print "Response payload:", payload.encode("hex") printer.checkErrorResponse(cmd, payload, False) elif args.mode == 'print': util.commonInit(args, parser) t0 = MatProfile.getBedTemp() t1 = MatProfile.getHotendBaseTemp() # Send heat up command print "\nPre-Heating bed...\n" printer.heatUp(HeaterBed, t0) print "\nPre-Heating extruder...\n" printer.heatUp(HeaterEx1, 150) # Send printing moves # f = open(args.gfile) f = parser.preParse(args.gfile) # Send priming moves if not args.noPrime: util.prime(parser) lineNr = 0 printStarted = False for line in f: parser.execute_line(line) # # Send more than one 512 byte block for dlprint # if lineNr > 1000 and (lineNr % 250) == 0: # check temp and start print if not printStarted: print "\nHeating bed (t0: %d)...\n" % t0 printer.heatUp(HeaterBed, t0, t0) print "\nHeating extruder (t1: %d)...\n" % t1 printer.heatUp(HeaterEx1, t1, wait=0.95 * t1) # Send print command printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printStarted = True else: # Stop sending moves on error status = printer.getStatus() pprint.pprint(status) if not printer.stateMoving(status): break lineNr += 1 print "Parsed %d gcode lines." % lineNr # # Add a move to lift the nozzle from the print if not ultigcode flavor # if not parser.ultiGcodeFlavor: util.endOfPrintLift(parser) planner.finishMoves() printer.sendCommand(CmdEOT) # XXX start print if less than 1000 lines or temp not yet reached: if not printStarted: print "\nHeating bed (t0: %d)...\n" % t0 printer.heatUp(HeaterBed, t0, t0) print "\nHeating extruder (t1: %d)...\n" % t1 printer.heatUp(HeaterEx1, t1, wait=0.95 * t1) # Send print command printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.waitForState(StateIdle) printer.coolDown(HeaterEx1) printer.coolDown(HeaterBed) ddhome.home(parser, args.fakeendstop) printer.sendCommand(CmdDisableSteppers) if not args.noCoolDown: printer.coolDown(HeaterEx1, wait=150) printer.coolDown(HeaterBed, wait=55) printer.readMore() ### Simulator/profiling ### printer.sendCommand(CmdExit) elif args.mode == "pre": # Virtuelle position des druckkopfes falls 'gehomed' homePosMM = util.MyPoint( X = planner.X_HOME_POS, Y = planner.Y_HOME_POS, Z = planner.Z_HOME_POS, # - 20, ) parser.set_position(homePosMM) f = parser.preParse(args.gfile) lineNr = 0 for line in f: parser.execute_line(line) lineNr += 1 print "Parsed %d gcode lines." % lineNr planner.finishMoves() elif args.mode == "mon": printer.initSerial(args.device, args.baud) while True: printer.readMore() elif args.mode == 'dumpeeprom': printer.commandInit(args) resp = printer.query(CmdGetEepromVersion) if util.handleGenericResponse(resp): print "Eepromversion: ", util.getResponseString(resp[1], 1) settingsDict = printer.getEepromSettings() print "eepromSettings: ", pprint.pprint(settingsDict) elif args.mode == 'factoryReset': printer.commandInit(args) printer.sendCommand(CmdEepromFactory) elif args.mode == 'disableSteppers': printer.commandInit(args) printer.sendCommand(CmdDisableSteppers) elif args.mode == 'measureTempFlowrateCurve': util.measureTempFlowrateCurve(args, parser) elif args.mode == 'moverel': assert(args.axis.upper() in "XYZAB") printer.commandInit(args) axis = util.dimIndex[args.axis.upper()] util.manualMove(parser, axis, args.distance, args.feedrate) elif args.mode == 'moveabs': assert(args.axis.upper() in "XYZAB") printer.commandInit(args) axis = util.dimIndex[args.axis.upper()] util.manualMove(parser, axis, args.distance, args.feedrate, True) elif args.mode == 'insertFilament': util.insertFilament(args, parser) elif args.mode == 'removeFilament': util.removeFilament(args, parser) elif args.mode == 'bedLeveling': util.bedLeveling(args, parser) elif args.mode == 'bedLevelAdjust': util.bedLevelAdjust(args, parser) elif args.mode == 'heatHotend': util.heatHotend(args, parser) elif args.mode == 'genTempTable': util.genTempTable(printer) elif args.mode == 'getEndstops': printer.commandInit(args) res = printer.getEndstops() print "Endstop state: ", res elif args.mode == 'getFilSensor': printer.commandInit(args) print "Filament pos:", printer.getFilSensor() elif args.mode == 'getpos': printer.commandInit(args) res = printer.getPos() curPosMM = util.MyPoint( X = res[0] / float(steps_per_mm[0]), Y = res[1] / float(steps_per_mm[1]), Z = res[2] / float(steps_per_mm[2]), A = res[3] / float(steps_per_mm[3]), # B = res[4] / float(steps_per_mm[4]), ) (homePosMM, homePosStepped) = planner.getHomePos() print "Printer pos [steps]:", res print "Printer pos [mm]:", curPosMM print "Virtual home pos [mm]: ", homePosMM elif args.mode == 'getTemps': printer.commandInit(args) printer.getTemps() elif args.mode == 'getTempTable': printer.commandInit(args) (baseTemp, tempTable) = printer.getTempTable() print "tempTable: ", pprint.pprint(tempTable) util.printTempTable(printer, baseTemp, tempTable) elif args.mode == 'getStatus': printer.commandInit(args) status = printer.getStatus() print "Status: " pprint.pprint(status) elif args.mode == 'home': printer.commandInit(args) ddhome.home(parser, args.fakeendstop) elif args.mode == 'zRepeatability': util.zRepeatability(parser) elif args.mode == 'stepResponse': util.stepResponse(args, parser) elif args.mode == 'retract': util.retract(args, parser) elif args.mode == 'stop': printer.commandInit(args) util.stopMove(args, parser) elif args.mode == 'fanspeed': printer.commandInit(args) printer.sendCommandParamV(CmdFanSpeed, [packedvalue.uint8_t(args.speed)]) elif args.mode == 'testFilSensor': ddtest.testFilSensor(args, parser) elif args.mode == 'calibrateFilSensor': ddtest.calibrateFilSensor(args, parser) elif args.mode == 'test': printer.commandInit(args) util.downloadTempTable(printer) printer.readMore() elif args.mode == "writeEepromFloat": util.writeEEpromFloat(args, parser) else: print "Unknown command: ", args.mode assert(0)
def calibrateFilSensor(args, parser): def writeDataSet(f, data): for tup in data: f.write("%f %f\n" % tup) f.write("E\n") planner = parser.planner printer = planner.printer maxFeedrate = args.feedrate or 15 eAccel = PrinterProfile.getMaxAxisAcceleration()[A_AXIS] printer.commandInit(args) ddhome.home(parser, args.fakeendstop) # Disable flowrate limit printer.sendCommandParamV(CmdEnableFRLimit, [packedvalue.uint8_t(0)]) # Disable temp-flowrate limit util.downloadDummyTempTable(printer) # XXX todo set filament sensor calibration factor to 1.0: assert ( 0 ) # printer.sendCommandParamV(CmdSetFRCalFactor, [packedvalue.float_t(1.0)]) feedrate = 0.25 startPos = parser.getPos()[A_AXIS] calFile = open("calibrateFilSensor.json", "w") calFile.write('{\n "filSensorCalibration": [\n') calValues = [] while feedrate <= maxFeedrate: tStartup = util.getStartupTime(feedrate) tAccel = feedrate / eAccel accelDistance = 5 * feedrate print "accelDistance: ", accelDistance current_position = parser.getPos() apos = current_position[A_AXIS] printer.sendPrinterInit() parser.execute_line( "G0 F%d %s%f" % (feedrate * 60, util.dimNames[A_AXIS], apos + accelDistance)) planner.finishMoves() printer.sendCommand(CmdEOT) printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) status = printer.getStatus() while status["slippage"] > 1.5: print "wait for startup..." status = printer.getStatus() time.sleep(0.1) data = [] t = time.time() while status["state"] != StateIdle: tMeasure = time.time() - t if tMeasure >= tStartup: data.append(status["slippage"]) status = printer.getStatus() time.sleep(0.01) # Cut the last tAccel: cut = int(tAccel / 0.01 + 1) del data[-cut:] # Average of ratio for this speed grip = sum(data) / len(data) # Calibration value, targetSpeed/measuredSensorSpeed, this ist the value # to multiply the measured sensor speed to get the real speed: print "speed:", feedrate, "ratio:", grip calValues.append((feedrate, grip)) feedrate += 0.25 f = open("calibrateFilSensor.gnuplot", "w") f.write(""" set grid set yrange [0:%f] plot '-' using 1:2 with linespoints title 'ratio' """ % max(1.5, feedrate * 2)) writeDataSet(f, calValues) f.write("pause mouse close\n") calFile.write(",\n".join( map(lambda tup: " [%f, %f]" % tup, calValues))) calFile.write("\n ]\n") calFile.write("}\n") calFile.close() printer.sendPrinterInit() parser.execute_line("G0 F%d %s%f" % (maxFeedrate * 60, util.dimNames[A_AXIS], startPos)) planner.finishMoves() printer.sendCommand(CmdEOT) printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.waitForState(StateIdle) # Enable flowrate limit printer.sendCommandParamV(CmdEnableFRLimit, [packedvalue.uint8_t(1)])
def bedLeveling(args, parser): planner = parser.planner printer = planner.printer printer.commandInit(args) # Reset bedlevel offset in printer eeprom payload = struct.pack("<%dpf" % (len("add_homeing_z")+1), "add_homeing_z", 0) printer.sendCommand(CmdWriteEepromFloat, binPayload=payload) ddhome.home(parser, args.fakeendstop, True) zFeedrate = PrinterProfile.getMaxFeedrate(Z_AXIS) kbd = GetChar("Enter (u)p (d)own (U)p 1mm (D)own 1mm (2-5) Up Xmm (q)uit") def manualMoveZ(): current_position = parser.getRealPos() zofs = current_position[Z_AXIS] print "curz: ", zofs ch = " " while ch not in "q\n": ch = kbd.getc() print "ch: ", ch if ch == "u": # head down, 'small' step zofs -= 0.05 elif ch == "U": # head down, 'big' step zofs -= 1 elif ch == "d": # head up, 'small' step zofs += 0.05 elif ch == "D": # head up, 'big' step zofs += 1 else: try: o = int(ch) # up x mmm except ValueError: continue if o < 2 or o > 5: continue zofs -= o printer.sendPrinterInit() parser.execute_line("G0 F%d Z%f" % (zFeedrate*60, zofs)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.1) feedrate = PrinterProfile.getMaxFeedrate(X_AXIS) ####################################################################################################### print "Level point 1/3" printer.sendPrinterInit() parser.execute_line("G0 F%d X%f Y%f Z%f" % (feedrate*60, planner.X_MAX_POS/2, planner.Y_MAX_POS - 10, planner.HEAD_HEIGHT)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.1) manualMoveZ() current_position = parser.getRealPos() print "curz: ", current_position[Z_AXIS] add_homeing_z = -1 * current_position[Z_AXIS]; print "\nZ-Offset: ", add_homeing_z, "\n" # Store into printer eeprom: payload = struct.pack("<%dpf" % (len("add_homeing_z")+1), "add_homeing_z", add_homeing_z) printer.sendCommand(CmdWriteEepromFloat, binPayload=payload) # Finally we know the zero z position # current_position[Z_AXIS] = 0 current_position[Z_AXIS] = planner.LEVELING_OFFSET; # Adjust the virtual position parser.set_position(current_position) # Adjust the printer position posStepped = vectorMul(current_position, parser.steps_per_mm) payload = struct.pack("<iiiii", *posStepped) printer.sendCommand(CmdSetHomePos, binPayload=payload) ####################################################################################################### print "Level point 2/3", current_position printer.sendPrinterInit() parser.execute_line("G0 F%d Z5" % (zFeedrate*60)) parser.execute_line("G0 F%d X35 Y20" % (feedrate*60)) parser.execute_line("G0 F%d Z0.1" % (zFeedrate*60)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.1) raw_input("\nAdjust left front buildplate screw and press <Return>\n") ####################################################################################################### print "Level point 3/3", current_position printer.sendPrinterInit() parser.execute_line("G0 F%d Z5" % (zFeedrate*60)) parser.execute_line("G0 F%d X%f" % (feedrate*60, planner.X_MAX_POS-10)) parser.execute_line("G0 F%d Z0.1" % (zFeedrate*60)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.1) raw_input("\nAdjust right fron buildplate screw and press <Return>\n") ddhome.home(parser, args.fakeendstop)
def getMaxAllowedAccelVectorNoAdv5(self): accelVector = self.direction5.scale(_MAX_ACCELERATION) return abs(accelVector.constrain(PrinterProfile.getMaxAxisAcceleration()) or accelVector)
def measureTempFlowrateCurve(args, parser): def writeDataSet(f, dataSet): for dataStr in dataSet: f.write(dataStr) f.write("\n") f.write("E\n") fssteps_per_mm = 265.0 # xxx hardcoded, get from profile or printer... planner = parser.planner printer = planner.printer printer.commandInit(args) ddhome.home(parser, args.fakeendstop) # Disable flowrate limit printer.sendCommandParamV(CmdEnableFRLimit, [packedvalue.uint8_t(0)]) # Move to mid-position printer.sendPrinterInit() feedrate = PrinterProfile.getMaxFeedrate(X_AXIS) parser.execute_line("G0 F%d X%f Y%f" % (feedrate*60, planner.MAX_POS[X_AXIS]/2, planner.MAX_POS[Y_AXIS]/2)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle) current_position = parser.getRealPos() apos = current_position[A_AXIS] t1 = MatProfile.getHotendBaseTemp() # start temperature area04 = pow(0.4, 2)*math.pi/4 flowrate = MatProfile.getBaseExtrusionRate() * (NozzleProfile.getArea() / area04) aFilament = MatProfile.getMatArea() print "t1: ", t1 print "flowrate: ", flowrate print "aFilament: ", aFilament print "feedrate: ", flowrate / aFilament # xxx todo if using small nozzles assert(flowrate > 2) f = open("temp-flowrate-curve.gnuplot", "w") f.write(""" set grid set yrange [0:35] # Startwert steigung a=0.5 # Startwert y-achse b=5 f(x)=b+a*(x-%d) fit f(x) "-" using 1:3 noerror via a,b\n""" % t1) dataSet = [] printer.sendCommandParamV(CmdFanSpeed, [packedvalue.uint8_t(100)]) retracted = False while t1 <= MatProfile.getHotendMaxTemp(): print "Heating:", t1 printer.heatUp(HeaterEx1, t1, wait=t1) # time.sleep(10) # temp settle wait = 5 while wait: time.sleep(1) temps = printer.getTemps() if abs(t1 - int(temps[HeaterEx1])) <= 1: wait -= 1 else: wait = 5 print "temp wait: ", wait flowrate -= 1 ratio = 1.0 while ratio >= 0.9: feedrate = flowrate / aFilament # distance = 5 * feedrate # xxx distance = 50 apos += distance print "Feedrate for flowrate:", feedrate, flowrate printer.sendPrinterInit() if retracted: parser.execute_line("G11") parser.execute_line("G0 F%d %s%f" % (feedrate*60, dimNames[A_AXIS], apos)) parser.execute_line("G10") planner.finishMoves() printer.sendCommand(CmdEOT) printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.waitForState(StateIdle) time.sleep(0.25) fssteps = printer.getFilSensor() fsdist = fssteps / fssteps_per_mm ratio = fsdist / distance actualFlowrate = flowrate * ratio print "t1, flowrate, fsdist, distance, ratio:", t1, flowrate, fsdist, distance, ratio flowrate += 1 retracted = True print "Feeder grip:", t1, flowrate-1, ratio dataStr = "%f %f %.2f %.3f" % (t1, flowrate - 1, actualFlowrate, ratio) f.write(dataStr + "\n") f.flush() dataSet.append(dataStr) t1 += 2 # next temp f.write("E\n") f.write(""" plot "-" using 1:2 with linespoints title "Target Flowrate", \\ "-" using 1:3 with linespoints title "Actual Flowrate", \\ "-" using 1:3 with linespoints smooth bezier title "Actual Flowrate smooth", \\ f(x) title sprintf("y=B+A*x, A=%.2f, B=%.1f, TempFactor 1/A: %.2f", a, b, 1/a)\n""") writeDataSet(f, dataSet) writeDataSet(f, dataSet) writeDataSet(f, dataSet) f.close() printer.coolDown(HeaterEx1) # Enable flowrate limit printer.sendCommandParamV(CmdEnableFRLimit, [packedvalue.uint8_t(1)])
def planSteps(self, move): if debugMoves: print "***** Start planSteps() *****" move.pprint("PlanSTeps:") move.state = 3 dirBits = 0 abs_displacement_vector_steps = [] leadAxis = 0 leadAxis_value = 0 for i in range(5): dirBits += (move.displacement_vector_steps_raw()[i] >= 0) << i adjustedDisplacement = move.displacement_vector_steps_adjusted(NozzleProfile, MatProfile, PrinterProfile) s = abs(adjustedDisplacement[i]) if s > leadAxis_value: leadAxis = i leadAxis_value = s abs_displacement_vector_steps.append(s) if dirBits != self.printer.curDirBits: move.stepData.setDirBits = True move.stepData.dirBits = dirBits self.printer.curDirBits = dirBits steps_per_mm = PrinterProfile.getStepsPerMM(leadAxis) # # Bresenham's variables # deltaLead = abs_displacement_vector_steps[leadAxis] move.stepData.setBresenhamParameters(leadAxis, abs_displacement_vector_steps) # # Create a list of stepper pulses # # debnegtimer nominalSpeed = abs( move.getReachedSpeedV()[leadAxis] ) # [mm/s] reachedSpeedV = move.getReachedSpeedV() reachedSpeedFr = reachedSpeedV.len5() # debnegtimer accel = abs(move.getAllowedAccelVector()[leadAxis]) accel_steps_per_square_second = accel * steps_per_mm # startSpeed = move.getStartFr() # debnegtimer v0 = abs(move.getFeedrateV(move.getStartFr())[leadAxis]) # [mm/s] # endSpeed = move.getEndFr() # debnegtimer v1 = abs(move.getFeedrateV(move.getEndFr())[leadAxis]) # [mm/s] # debnegtimer steps_per_second_0 = steps_per_second_accel = v0 * steps_per_mm steps_per_second_1 = steps_per_second_deccel = v1 * steps_per_mm steps_per_second_nominal = nominalSpeed * steps_per_mm # # Acceleration variables # # tAccel = 0 # [s], sum of all acceeration steptimes # tAccel mit der initialen zeitspanne vorbelegen, da wir bereits im # ersten schleifendurchlauf (d.h. ab t=0) eine beschleunigung haben wollen. tAccel = 1.0 / steps_per_second_0 # [s], sum of all acceeration steptimes tDeccel = 1.0 / steps_per_second_1 stepNr = 0 if debugPlot: accelPlotData = [] deccelPlotData = [] if not circaf(move.getStartFr(), reachedSpeedFr, 0.1) and not circaf(move.getEndFr(), reachedSpeedFr, 0.1): # # Acceleration ramp on both sides. # # Ramp up both sides in parallel to not exeed available steps # done = False while not done and stepNr < deltaLead: done = True # # Compute acceleration timer values # if steps_per_second_accel < steps_per_second_nominal: # # Compute timer value # steps_per_second_accel = min(steps_per_second_0 + tAccel * accel_steps_per_square_second, steps_per_second_nominal) dt = 1.0 / steps_per_second_accel timerValue = int(fTimer / steps_per_second_accel) # print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue if debugPlot: if move.eOnly: accelPlotData.append((steps_per_second_accel/steps_per_mm, 2, dt)) else: accelPlotData.append((steps_per_second_accel/steps_per_mm, 1, dt)) tAccel += dt if timerValue > maxTimerValue24: move.pprint("PlanSTeps:") print "v0: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue assert(0) move.stepData.addAccelPulse(timerValue) stepNr += 1 done = False if stepNr == deltaLead: break # # Compute ramp down (in reverse), decceleration # if steps_per_second_deccel < steps_per_second_nominal: # # Compute timer value # steps_per_second_deccel = min(steps_per_second_1 + tDeccel * accel_steps_per_square_second, steps_per_second_nominal) dt = 1.0 / steps_per_second_deccel timerValue = int(fTimer / steps_per_second_deccel) # print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue, ", v: ", steps_per_second_deccel/steps_per_mm if debugPlot: if move.eOnly: deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 2, dt)) else: deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 1, dt)) tDeccel += dt if timerValue > maxTimerValue24: move.pprint("PlanSTeps:") print "v0: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue assert(0) move.stepData.addDeccelPulse(timerValue) stepNr += 1 done = False elif not circaf(move.getStartFr(), reachedSpeedFr, 0.1): # # Acceleration only # # # Compute acceleration timer values # while steps_per_second_accel < steps_per_second_nominal and stepNr < deltaLead: # # Compute timer value # steps_per_second_accel = min(steps_per_second_0 + tAccel * accel_steps_per_square_second, steps_per_second_nominal) dt = 1.0 / steps_per_second_accel timerValue = int(fTimer / steps_per_second_accel) # print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue if debugPlot: if move.eOnly: accelPlotData.append((steps_per_second_accel/steps_per_mm, 2, dt)) else: accelPlotData.append((steps_per_second_accel/steps_per_mm, 1, dt)) tAccel += dt if timerValue > maxTimerValue24: move.pprint("PlanSTeps:") print "v0: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue assert(0) move.stepData.addAccelPulse(timerValue) stepNr += 1 else: # # Decceleration only # # # Compute ramp down (in reverse), decceleration # while steps_per_second_deccel < steps_per_second_nominal and stepNr < deltaLead: # # Compute timer value # steps_per_second_deccel = min(steps_per_second_1 + tDeccel * accel_steps_per_square_second, steps_per_second_nominal) dt = 1.0 / steps_per_second_deccel timerValue = int(fTimer / steps_per_second_deccel) # print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue, ", v: ", steps_per_second_deccel/steps_per_mm if debugPlot: if move.eOnly: deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 2, dt)) else: deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 1, dt)) tDeccel += dt if timerValue > maxTimerValue24: move.pprint("PlanSTeps:") print "v0: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue assert(0) move.stepData.addDeccelPulse(timerValue) stepNr += 1 # # Linear phase # timerValue = fTimer / steps_per_second_nominal move.stepData.setLinTimer(timerValue) if debugPlot: self.plotfile.write("# Acceleration:\n") for (speed, color, dt) in accelPlotData: self.plotfile.write("%f %f %d\n" % (self.plottime, speed, color)) self.plottime += dt self.plotfile.write("# Linear top:\n") self.plotfile.write("%f %f 0\n" % (self.plottime, steps_per_second_nominal/steps_per_mm)) self.plottime += timerValue / fTimer self.plotfile.write("# Decceleration:\n") deccelPlotData.reverse() for (speed, color, dt) in deccelPlotData: self.plotfile.write("%f %f %d\n" % (self.plottime, speed, color)) self.plottime += dt if debugMoves: print "# of steps for move: ", deltaLead move.pprint("move:") print move.stepData.checkLen(deltaLead) if debugMoves: print "***** End planSteps() *****" return # XXXXXXXXXXXXXX old, unused ........... # # Compute acceleration timer values # # while v0 and steps_per_second < steps_per_second_nominal: # lastTimer = None while steps_per_second < steps_per_second_nominal: # and stepNr < deltaLead: assert(stepNr < deltaLead) # # Compute timer value # steps_per_second = min(steps_per_second_0 + tAccel * accel_steps_per_square_second, steps_per_second_nominal) dt = 1.0 / steps_per_second timerValue = int(fTimer / steps_per_second) # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue if debugPlot: if move.eOnly: self.plotfile.write("%f %f 2\n" % (self.plottime, steps_per_second/steps_per_mm)) else: self.plotfile.write("%f %f 1\n" % (self.plottime, steps_per_second/steps_per_mm)) self.plottime += dt tAccel += dt # debnegtimer # if timerValue <= 0: # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue # assert(0) # debtimeroverflow if timerValue > maxTimerValue24: move.pprint("PlanSTeps:") print "v0: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue assert(0) move.stepData.addAccelPulse(timerValue) stepNr += 1 # if lastTimer: # assert((lastTimer - timerValue) < maxTimerValue16) # lastTimer = timerValue # Benutze als timer wert für die lineare phase den letzen timerwert der # beschleunigungsphase falls es diese gab. Sonst: # berechne timervalue ausgehend von linear feedrate: # if not timerValue: # timerValue = fTimer / steps_per_second # dt = 1.0 / steps_per_second # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue timerValue = fTimer / steps_per_second_nominal move.stepData.setLinTimer(timerValue) if debugPlot: self.plotfile.write("# Linear top:\n") self.plotfile.write("%f %f 0\n" % (self.plottime, steps_per_second/steps_per_mm)) self.plottime += timerValue / fTimer self.plotfile.write("# Decceleration:\n") # # Compute ramp down (in reverse), decceleration # tDeccel = 1.0 / steps_per_second_nominal steps_per_second = steps_per_second_nominal steps_per_second_1 = v1 * steps_per_mm # lastTimer = None while steps_per_second > steps_per_second_1: # and stepNr < deltaLead: if stepNr >= deltaLead: print "stepNr, deltaLead:", stepNr, deltaLead assert(stepNr < deltaLead) # # Compute timer value # steps_per_second = max(steps_per_second_nominal - tDeccel * accel_steps_per_square_second, steps_per_second_1) dt = 1.0 / steps_per_second timerValue = int(fTimer / steps_per_second) # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue, ", v: ", steps_per_second/steps_per_mm if debugPlot: if move.eOnly: self.plotfile.write("%f %f 2\n" % (self.plottime, steps_per_second/steps_per_mm)) else: self.plotfile.write("%f %f 1\n" % (self.plottime, steps_per_second/steps_per_mm)) self.plottime += dt tDeccel += dt # debnegtimer # assert(timerValue > 0) if timerValue > maxTimerValue24: move.pprint("PlanSTeps:") print "v0: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue assert(0) move.stepData.addDeccelPulse(timerValue) stepNr += 1 # if lastTimer: # assert((timerValue - lastTimer) < maxTimerValue16) # lastTimer = timerValue if debugMoves: print "# of steps for move: ", deltaLead move.pprint("move:") print move.stepData.checkLen(deltaLead) if debugMoves: print "***** End planSteps() *****"
def planTravelSteps(self, move): if debugMoves: print "***** Start planTravelSteps() *****" move.pprint("planTravelSTeps:") move.state = 3 move.initStepData(StepDataTypeBresenham) # Round step values dispF = move.displacement_vector_steps_raw5 dispS = self.stepRounders.round(dispF) if dispS == emptyVector5: if debugMoves: print "Empty move..." print "***** End planTravelSteps() *****" self.stepRounders.rollback() return move.isStartMove = True self.stepRounders.commit() abs_displacement_vector_steps = vectorAbs(dispS) # Determine the 'lead axis' - the axis with the most steps leadAxis = move.leadAxis(disp=dispS) leadAxis_steps = abs_displacement_vector_steps[leadAxis] dirBits = util.directionBits(dispS, self.printer.curDirBits) if dirBits != self.printer.curDirBits: move.stepData.setDirBits = True move.stepData.dirBits = dirBits self.printer.curDirBits = dirBits steps_per_mm = PrinterProfile.getStepsPerMM(leadAxis) # # Bresenham's variables # move.stepData.setBresenhamParameters(leadAxis, abs_displacement_vector_steps) # # Create a list of stepper pulses # nominalSpeed = abs(move.topSpeed.speed().vv()[leadAxis]) # [mm/s] allowedAccel = move.getMaxAllowedAccelVectorNoAdv5()[leadAxis] v0 = abs(move.startSpeed.speed()[leadAxis]) # [mm/s] nominalSpeed = abs(move.topSpeed.speed()[leadAxis]) # [mm/s] v1 = abs(move.endSpeed.speed()[leadAxis]) # [mm/s] nAccel = 0 if move.accelTime(): accelClocks = util.accelRamp( leadAxis, v0, nominalSpeed, allowedAccel, leadAxis_steps) # maximum number of steps move.stepData.addAccelPulsees(accelClocks) nAccel = len(accelClocks) nDecel = 0 if move.decelTime(): decelClocks = util.decelRamp( leadAxis, nominalSpeed, v1, allowedAccel, leadAxis_steps) # maximum number of steps move.stepData.addDecelPulsees(decelClocks) nDecel = len(decelClocks) # # Linear phase # nLin = leadAxis_steps - (nAccel + nDecel) # print "# linear steps:", nLin if nLin > 0: steps_per_second_nominal = nominalSpeed * steps_per_mm timerValue = fTimer / steps_per_second_nominal move.stepData.setLinTimer(timerValue) else: if nLin < 0: if nAccel and nDecel: # Überschüssige steps im verhältnis von nAccel zu nDecel abschneiden cd = int(-nLin / ((float(nAccel) / nDecel) + 1)) ca = -nLin - cd if ca: del move.stepData.accelPulses[:ca] if cd: del move.stepData.accelPulses[-cd:] assert (len(move.stepData.accelPulses) + len(move.stepData.decelPulses) == leadAxis_steps) elif nAccel: del move.stepData.accelPulses[:-nLin] assert (len(move.stepData.accelPulses) == leadAxis_steps) else: del move.stepData.decelPulses[nLin:] assert (len(move.stepData.decelPulses) == leadAxis_steps) move.stepData.setLinTimer(0xffff) # timerValue = fTimer / steps_per_second_nominal # move.stepData.setLinTimer(timerValue) if debugMoves: print "# of steps for move: ", leadAxis_steps move.pprint("move:") print move.stepData.checkLen(leadAxis_steps) if debugMoves: print "***** End planTravelSteps() *****"
def insertFilament(args, parser): planner = parser.planner printer = planner.printer def manualMoveE(): current_position = parser.getRealPos() aofs = current_position[A_AXIS] print "cura: ", aofs kbd = GetChar("Enter (f)orward (b)ackwards (F)orward 10mm (B)ackwards 10mm (q)uit") ch = " " while ch not in "q\n": ch = kbd.getc() print "ch: ", ch if ch == "f": # filament forward, 'small' step aofs += 1 elif ch == "F": # filament forward, 'big' step aofs += 10 elif ch == "b": # filament backwards, 'small' step aofs -= 1 elif ch == "B": # filament backwards, 'big' step aofs -= 10 printer.sendPrinterInit() # XXX hardcoded feedrate parser.execute_line("G0 F%d A%f" % (5*60, aofs)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.1) commonInit(args, parser) # Move to mid-position feedrate = PrinterProfile.getMaxFeedrate(X_AXIS) parser.execute_line("G0 F%d X%f Y%f" % (feedrate*60, planner.MAX_POS[X_AXIS]/2, planner.MAX_POS[Y_AXIS]/2)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle) t1 = MatProfile.getHotendBaseTemp() printer.heatUp(HeaterEx1, t1, wait=t1 - 5) print "\nInsert filament.\n" manualMoveE() print "\nForwarding filament.\n" manualMove(parser, A_AXIS, FILAMENT_REVERSAL_LENGTH * 0.85) print "\nExtrude filament.\n" manualMoveE() # # Retract # printer.sendPrinterInit() parser.execute_line("G10") planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle) if not args.noCoolDown: printer.coolDown(HeaterEx1, wait=150)
def main(): argParser = argparse.ArgumentParser(description='%s, Direct Drive USB Print.' % sys.argv[0]) argParser.add_argument("-d", dest="device", action="store", type=str, help="Device to use, default: /dev/ttyACM0.", default="/dev/ttyACM0") argParser.add_argument("-b", dest="baud", action="store", type=int, help="Baudrate, default 500000.", default=500000) argParser.add_argument("-t0", dest="t0", action="store", type=int, help="Temp 0 (heated bed), default comes from mat. profile.") argParser.add_argument("-t1", dest="t1", action="store", type=int, help="Temp 1 (hotend 1), default comes from mat. profile.") argParser.add_argument("-kAdvance", dest="kAdvance", action="store", type=float, help="K-Advance factor, default comes from mat. profile.") argParser.add_argument("-startAdvance", dest="startAdvance", action="store", type=float, help="Gradual advance: advance startvalue.") argParser.add_argument("-advIncrease", dest="advIncrease", action="store", type=float, help="Gradual advance: increase kAdvance by advIncrease after each step.") argParser.add_argument("-advStepHeight", dest="advStepHeight", action="store", type=int, help="Gradual advance: height of each step (number of layers).") argParser.add_argument("-mat", dest="mat", action="store", help="Name of generic material profile to use [pla, abs...], default is pla.", default="pla_1.75mm") argParser.add_argument("-smat", dest="smat", action="store", help="Name of specific material profile to use.") argParser.add_argument("-noz", dest="nozzle", action="store", help="Name of nozzle profile to use [nozzle40, nozzle80...], default is nozzle40.", default="nozzle40") argParser.add_argument("-np", dest="noPrime", action="store_const", const=True, help="Debug: don't prime nozzle, to test extrusion-less moves.") # fake endstops as long we have no real ones argParser.add_argument("-F", dest="fakeendstop", action="store", type=bool, help="Debug: fake endstops", default=False) argParser.add_argument("-nc", dest="noCoolDown", action="store", type=bool, help="Debug: don't wait for heater cool down after print.", default=False) argParser.add_argument("-fr", dest="feedrate", action="store", type=float, help="Feedrate for move commands.", default=0) argParser.add_argument("-rl", dest="retractLength", action="store", type=float, help="Retraction length, default comes from printer profile.", default=0) subparsers = argParser.add_subparsers(dest="mode", help='Mode: mon(itor)|print|store|reset|pre(process).') sp = subparsers.add_parser("autoTune", help=u"Autotune hotend PID values.") sp = subparsers.add_parser("binmon", help=u"Monitor serial printer interface (binary responses).") sp = subparsers.add_parser("changenozzle", help=u"Heat hotend and change nozzle.") sp = subparsers.add_parser("mon", help=u"Monitor serial printer interface (asci).") sp = subparsers.add_parser("print", help=u"Download and print file at once.") sp.add_argument("gfile", help="Input GCode file.") sp = subparsers.add_parser("writeEepromFloat", help=u"Store float value into eeprom.") sp.add_argument("name", help="Valuename.") sp.add_argument("value", action="store", type=float, help="value (float).") # sp = subparsers.add_parser("reset", help=u"Try to stop/reset printer.") sp = subparsers.add_parser("pre", help=u"Preprocess gcode, for debugging purpose.") sp.add_argument("gfile", help="Input GCode file.") sp = subparsers.add_parser("dumpeeprom", help=u"dump eeprom settings.") sp = subparsers.add_parser("factoryReset", help=u"FactoryReset of eeprom settings, new bed leveling needed.") sp = subparsers.add_parser("test", help=u"Debug: tests for debugging purpose.") sp = subparsers.add_parser("disableSteppers", help=u"Disable stepper current (this dis-homes the printer).") sp = subparsers.add_parser("home", help=u"Home the printer.") sp = subparsers.add_parser("measureTempFlowrateCurve", help=u"Determine temperature/flowrate properties of filament.") sp.add_argument("tstart", action="store", type=int, help="Start temperature.") sp.add_argument("tend", action="store", type=int, help="End temperature.") sp.add_argument("-tstep", action="store", type=int, help="Temperature step width.", default=2) sp = subparsers.add_parser("moverel", help=u"Debug: Move axis manually, relative coords.") sp.add_argument("axis", help="Axis (XYZAB).", type=str) sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("moveabs", help=u"Debug: Move axis manually, absolute coords.") sp.add_argument("axis", help="Axis (XYZAB).", type=str) sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("insertFilament", help=u"Insert filament (heatup, forward filament).") sp = subparsers.add_parser("removeFilament", help=u"Remove filament (heatup, retract filament).") sp = subparsers.add_parser("bedLeveling", help=u"Do bed leveling sequence.") sp = subparsers.add_parser("bedLevelAdjust", help=u"Adjust bedleveling offset - dangerous.") sp.add_argument("distance", action="store", help="Adjust-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("heatHotend", help=u"Heat up hotend (to clean it, etc).") sp = subparsers.add_parser("genTempTable", help=u"Generate extrusion rate limit table.") sp = subparsers.add_parser("getEndstops", help=u"Get current endstop state.") sp = subparsers.add_parser("getFilSensor", help=u"Get current filament position.") sp = subparsers.add_parser("getpos", help=u"Get current printer and virtual position.") sp = subparsers.add_parser("getTemps", help=u"Get current temperatures (Bed, Extruder1, [Extruder2]).") sp = subparsers.add_parser("getTempTable", help=u"Get temperature-speed table from printer, print it to stdout and to /tmp/temptable_printer.txt.") sp = subparsers.add_parser("getStatus", help=u"Get current printer status.") sp = subparsers.add_parser("zRepeatability", help=u"Debug: Move Z to 10 random positions to test repeatability.") sp = subparsers.add_parser("stop", help=u"Stop print, cooldown, home, disable steppers.") sp = subparsers.add_parser("stepResponse", help=u"Measure and plot stepResponse of hotend PID.") sp = subparsers.add_parser("retract", help=u"Debug: Do the end-of-print retract manually after heating up.") sp = subparsers.add_parser("fanspeed", help=u"Set fan speed manually.") sp.add_argument("speed", help="Fanspeed 0 - 255.", type=int) sp = subparsers.add_parser("testFilSensor", help=u"Debug: move filament manually, output filament sensor measurement.") sp.add_argument("distance", action="store", help="Move-distance (+/-) in mm.", type=float) sp = subparsers.add_parser("calibrateFilSensor", help=u"Debug: helper to determine the ratio of stepper to flowrate sensor.") args = argParser.parse_args() (parser, planner, printer) = initParser(args, mode=args.mode) steps_per_mm = PrinterProfile.getStepsPerMMVector() if args.mode == 'autoTune': util.measureHotendStepResponse(args, parser) elif args.mode == 'changenozzle': util.changeNozzle(args, parser) elif args.mode == "binmon": printer.initSerial(args.device, args.baud) while True: try: (cmd, payload) = printer.readResponse() except RxTimeout: pass else: print "Response cmd :", cmd print "Response payload:", payload.encode("hex") printer.checkErrorResponse(cmd, payload, False) elif args.mode == 'print': util.commonInit(args, parser) t0 = MatProfile.getBedTemp() t1 = MatProfile.getHotendStartTemp() + planner.l0TempIncrease # Send heat up command print "\nPre-Heating bed...\n" printer.heatUp(HeaterBed, t0) print "\nPre-Heating extruder...\n" printer.heatUp(HeaterEx1, t1/2) f = parser.preParse(args.gfile) if not args.noPrime: util.prime(parser) lineNr = 0 printStarted = False for line in f: parser.execute_line(line) # # Send more than one 512 byte block for dlprint # if lineNr > 1000 and (lineNr % 250) == 0: # check temp and start print if not printStarted: print "\nHeating bed (t0: %d)...\n" % t0 printer.heatUp(HeaterBed, t0, t0) print "\nHeating extruder (t1: %d)...\n" % t1 printer.heatUp(HeaterEx1, t1, t1-1) # Send print command printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printStarted = True else: # Stop sending moves on error status = printer.getStatus() pprint.pprint(status) if not printer.stateMoving(status): break lineNr += 1 print "Parsed %d gcode lines." % lineNr # # Add a move to lift the nozzle end of print # util.endOfPrintLift(parser) planner.finishMoves() printer.sendCommand(CmdEOT) # Start print if less than 1000 lines or temp not yet reached: if not printStarted: print "\nHeating bed (t0: %d)...\n" % t0 printer.heatUp(HeaterBed, t0, t0) print "\nHeating extruder (t1: %d)...\n" % t1 printer.heatUp(HeaterEx1, t1, t1-1) # Send print command printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.waitForState(StateIdle) printer.coolDown(HeaterEx1) printer.coolDown(HeaterBed) ddhome.home(parser, args.fakeendstop) printer.sendCommand(CmdDisableSteppers) if not args.noCoolDown: printer.coolDown(HeaterEx1, wait=150) printer.coolDown(HeaterBed, wait=55) printer.readMore() # Exit simulator for profiling # printer.sendCommand(CmdExit) elif args.mode == "pre": # Virtuelle position des druckkopfes falls 'gehomed' homePosMM = util.MyPoint( X = planner.X_HOME_POS, Y = planner.Y_HOME_POS, Z = planner.Z_HOME_POS, # - 20, ) parser.setPos(homePosMM) f = parser.preParse(args.gfile) lineNr = 0 for line in f: parser.execute_line(line) lineNr += 1 print "Parsed %d gcode lines." % lineNr planner.finishMoves() elif args.mode == "mon": printer.initSerial(args.device, args.baud) while True: printer.readMore() elif args.mode == 'dumpeeprom': printer.commandInit(args) resp = printer.query(CmdGetEepromVersion) if util.handleGenericResponse(resp): print "Eepromversion: ", util.getResponseString(resp[1], 1) settingsDict = printer.getEepromSettings() print "eepromSettings: ", pprint.pprint(settingsDict) elif args.mode == 'factoryReset': printer.commandInit(args) printer.sendCommand(CmdEepromFactory) elif args.mode == 'disableSteppers': printer.commandInit(args) printer.sendCommand(CmdDisableSteppers) elif args.mode == 'measureTempFlowrateCurve': util.measureTempFlowrateCurve(args, parser) elif args.mode == 'moverel': assert(args.axis.upper() in "XYZAB") printer.commandInit(args) axis = util.dimIndex[args.axis.upper()] util.manualMove(parser, axis, args.distance, args.feedrate) elif args.mode == 'moveabs': assert(args.axis.upper() in "XYZAB") printer.commandInit(args) axis = util.dimIndex[args.axis.upper()] util.manualMove(parser, axis, args.distance, args.feedrate, True) elif args.mode == 'insertFilament': util.insertFilament(args, parser, args.feedrate) elif args.mode == 'removeFilament': util.removeFilament(args, parser, args.feedrate) elif args.mode == 'bedLeveling': util.bedLeveling(args, parser) elif args.mode == 'bedLevelAdjust': util.bedLevelAdjust(args, parser) elif args.mode == 'heatHotend': util.heatHotend(args, parser) elif args.mode == 'genTempTable': util.genTempTable(planner) elif args.mode == 'getEndstops': printer.commandInit(args) res = printer.getEndstops() print "Endstop state: ", res elif args.mode == 'getFilSensor': printer.commandInit(args) print "Filament pos:", printer.getFilSensor() elif args.mode == 'getpos': printer.commandInit(args) res = printer.getPos() curPosMM = util.MyPoint( X = res[0] / float(steps_per_mm[0]), Y = res[1] / float(steps_per_mm[1]), Z = res[2] / float(steps_per_mm[2]), A = res[3] / float(steps_per_mm[3]), # B = res[4] / float(steps_per_mm[4]), ) (homePosMM, homePosStepped) = planner.getHomePos() print "Printer pos [steps]:", res print "Printer pos [mm]:", curPosMM print "Virtual home pos [mm]: ", homePosMM elif args.mode == 'getTemps': printer.commandInit(args) printer.getTemps() elif args.mode == 'getTempTable': printer.commandInit(args) (baseTemp, tempTable) = printer.getTempTable() print "tempTable: ", pprint.pprint(tempTable) util.printTempTable(baseTemp, tempTable) elif args.mode == 'getStatus': printer.commandInit(args) status = printer.getStatus() print "Status: " pprint.pprint(status) elif args.mode == 'home': printer.commandInit(args) ddhome.home(parser, args.fakeendstop) elif args.mode == 'zRepeatability': util.zRepeatability(parser) elif args.mode == 'stepResponse': util.stepResponse(args, parser) elif args.mode == 'retract': util.retract(args, parser) elif args.mode == 'stop': printer.commandInit(args) util.stopMove(args, parser) elif args.mode == 'fanspeed': printer.commandInit(args) printer.sendCommandParamV(CmdFanSpeed, [packedvalue.uint8_t(args.speed)]) elif args.mode == 'testFilSensor': ddtest.testFilSensor(args, parser) elif args.mode == 'calibrateFilSensor': ddtest.calibrateFilSensor(args, parser) elif args.mode == 'test': printer.commandInit(args) """ dirbits = printer.getDirBits() print "dirbits:", dirbits # printer.readMore() import time while True: temp = printer.getTemp(doLog=False)[1] print "T1:", temp time.sleep(0.1) """ if args.feedrate == 0: printer.sendCommandParamV(CmdContinuousE, [packedvalue.uint16_t(0)]) else: import time printer.sendCommandParamV(CmdContinuousE, [packedvalue.uint16_t(util.eTimerValue(planner, 0.5))]) for s in range(int(args.feedrate)): time.sleep(1) printer.sendCommandParamV(CmdSetContTimer, [packedvalue.uint16_t(util.eTimerValue(planner, 1+s))]) elif args.mode == "writeEepromFloat": util.writeEEpromFloat(args, parser) else: print "Unknown command: ", args.mode assert(0)
def home(parser, fakeHomingEndstops=False, force=False): planner = parser.planner printer = planner.printer print "*" print "* Start homing..." print "*" if printer.isHomed() and not force: print "Printer is homed already..." # Send init command printer.sendPrinterInit() # Get current pos from printer and set our virtual pos curPosMM = util.getVirtualPos(parser) (homePosMM, homePosStepped) = planner.getHomePos() # print "Printer should be at [mm]: ", homePosMM, ", [steps]: ", homePosStepped # Move to home if not curPosMM.equal(homePosMM, "XYZ"): # # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern # der buildplatte oder mit objekten auf der druckplatte zu vermeiden. # if not curPosMM.equal(homePosMM, "Z"): parser.execute_line("G0 F%d Z%f" % ( PrinterProfile.getMaxFeedrate(util.Z_AXIS)*60, homePosMM.Z)) if not curPosMM.equal(homePosMM, "XY"): parser.execute_line("G0 F%d X%f Y%f" % ( PrinterProfile.getMaxFeedrate(util.X_AXIS)*60, homePosMM.X, homePosMM.Y)) planner.finishMoves() printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printer.sendCommand(CmdEOT) printer.waitForState(StateIdle, wait=0.05) # # Set Virtual E-pos 0: # parser.set_position(homePosMM) print "*" print "* Done homing..." print "*" return # # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern # der buildplatte oder mit einem modell zu vermeiden. # for dim in [util.Z_AXIS, util.X_AXIS, util.Y_AXIS]: # Try fast home if endstop is pressed if printer.endStopTriggered(dim, fakeHomingEndstops): print "Homing: endstop %d is triggered, trying fast home." % dim if homeBounce(parser, dim, fakeHomingEndstops): continue # Try fast home if head/bed is near the endstop print "Homing: doing short/fast home." if homeMove(parser, dim, 1, planner.MAX_POS[dim] / 10.0, fakeHomingEndstops): # Move towards endstop fast print "Homing: endstop %d is triggered, trying fast home." % dim if homeBounce(parser, dim, fakeHomingEndstops): continue # Do the full slow homing move print "Homing: doing full/slow home." if not homeMove(parser, dim, 1, planner.MAX_POS[dim] * 1.25, fakeHomingEndstops): # Move towards endstop fast print "Error, Endstop %d NOT hit!" % dim assert(0) if not homeBounce(parser, dim, fakeHomingEndstops): print "Error, Bounce %d!" % dim assert(0) # # Set position in steps on the printer side and set our 'virtual position': # # xxx set end-of-print retraction e-pos also here? # # parser.set_position(planner.homePosMM) # payload = struct.pack("<iiiii", *planner.homePosStepped) (homePosMM, homePosStepped) = planner.getHomePos() parser.set_position(homePosMM) # print "Tell printer its position [steps]:", homePosStepped payload = struct.pack("<iiiii", *homePosStepped) printer.sendCommand(CmdSetHomePos, binPayload=payload) print "*" print "* Done homing..." print "*"
def __init__(self, args, gui=None): if Planner.__single: raise RuntimeError('A Planner already exists') Planner.__single = self if gui: self.gui = gui else: self.gui = dddumbui.DumbGui() self.args = args self.printer = Printer.get() # self.parser = UM2GcodeParser.get() jerk = [] for dim in dimNames: jerk.append(PrinterProfile.getValues()['axes'][dim]['jerk']) self.jerk = VVector(jerk) self.gui.log("Jerk vector: ", self.jerk) self.zeroPos = util.MyPoint() # Lowest allowed speed in mm/s for every dimension self.min_speeds = 5 * [0] for dim in range(5): # vmin = (fTimer / maxTimerValue) / steps_per_mm if PrinterProfile.getStepsPerMM(dim): self.min_speeds[dim] = float(fTimer) / (maxTimerValue24 * PrinterProfile.getStepsPerMM(dim)) self.gui.log( "min speeds: ", self.min_speeds) # # Constants, xxx todo: query from printer and/or profile # self.HOMING_FEEDRATE = [100, 100, 40] # set the homing speeds (mm/s) self.HOME_RETRACT_MM = 7 # [mm] # ENDSTOP SETTINGS: # Sets direction of endstops when homing; 1=MAX, -1=MIN self.X_HOME_DIR = -1 self.Y_HOME_DIR = 1 self.Z_HOME_DIR = 1 self.HOME_DIR = (self.X_HOME_DIR, self.Y_HOME_DIR, self.Z_HOME_DIR) # XXX defined in profile !!! # Travel limits after homing self.X_MIN_POS = 0 self.X_MAX_POS = 225.0 # 230.0 # X_MIN_POS = 0 self.Y_MAX_POS = 225.0 # 230.0 # Y_MIN_POS = 0 # self.Z_MAX_POS = 229.0 # 230.0 // Dauerdruckplatte hat 5mm im vergleich zur glassplatte 4mm self.Z_MAX_POS = 212.25 # solex nozzle # Z_MIN_POS = 0 self.MAX_POS = (self.X_MAX_POS, self.Y_MAX_POS, self.Z_MAX_POS) # Bed leveling constants self.LEVELING_OFFSET = 0.1 # Assumed thickness of feeler gauge/paper used in leveling (mm) # self.HEAD_HEIGHT = 35.0 # Let enough room for the head, XXX UM2 specific !!! self.HEAD_HEIGHT = 15.0 # Let enough room for the head, XXX UM2 specific !!! # Homing self.X_HOME_POS = self.X_MIN_POS self.Y_HOME_POS = self.Y_MAX_POS self.Z_HOME_POS = self.Z_MAX_POS # XXX + add_homeing_z # # End Constants # self.plotfile = None # Headspeed/extrusionspeed where autotemp increase starts self.ExtrusionAmountLow = 30 # [mm/s] for a 1mm nozzle if UseExtrusionAutoTemp: # self.ExtrusionAmountLow = 7.5 # [mm³/s] for a 1mm nozzle area04 = pow(0.4, 2)*math.pi/4 self.ExtrusionAmountLow = MatProfile.getBaseExtrusionRate() * (NozzleProfile.getArea() / area04) self.reset()