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 printStat(self): # Extrusion adjust adjustedExtrusion = self.maxRate + pow(self.maxRate, 2) * NozzleProfile.getExtrusionAdjustFactor() if self.maxRate: print "Maximal net Extrusion Rate (Extruder A): %.1f mm³/s, adjusted/gross: %.1f mm³/s, move:" % (self.maxRate, adjustedExtrusion) self.move.pprint("Max. extrusion Move") print "Net Max10: ", self.max10 print "Maximal Extrusion Rate (Extruder A) 5 second average: %.1f" % self.maxAvgRate, "mm³/s\n"
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 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 __init__(self, comment, # stepped_point, displacement_vector, displacement_vector_steps, feedrate, # mm/s ): self.comment=comment self.displacement_vector3=displacement_vector[:3] self.displacement_vector_steps3=displacement_vector_steps[:3] self.extrusion_displacement_raw = displacement_vector[3:] self.extrusion_displacement_steps_raw = displacement_vector_steps[3:] # # Move distance in XYZAB plane # self.distance = displacement_vector.len5() # # Move distance in XYZ plane # self.distance3 = displacement_vector.len3() # self.eOnly = self.displacement_vector3 == 3*[0] self.eOnly = self.distance3 == 0 # # Limit feedrate by maximum extrusion rate # self.feedrateS = feedrate # mm/s # Do not count very small moves, the computation of the extrusion rate is inaccurate because of the # discretization in the gcodeparser (map float values to discrete stepper values). if self.distance3 >= 0.1 and self.isExtrudingMove(A_AXIS) or self.isExtrudingMove(B_AXIS): matArea = MatProfile.getMatArea() assert(not self.eOnly) t = self.distance3 / feedrate extrusionVolume = displacement_vector[A_AXIS] * matArea extrusionRate = extrusionVolume / t # print "extrusionRate:", displacement_vector[A_AXIS], t, extrusionRate if extrusionRate > NozzleProfile.getNetMaxExtrusionRate(): print "Warning, extrusion rate to high: %.1f mm³/s, Move: '%s', len: %.3f., extrusionVolume: %.5f" % (extrusionRate, comment, self.distance3, extrusionVolume) # xxx feedrate adjust disabled ### print "Warning, extrusion rate to high: %.1f mm³/s, reducing to %.1f mm³/s, Move: '%s', len: %.3f., extrusionVolume: %.5f" % (extrusionRate, NozzleProfile.getNetMaxExtrusionRate(), comment, self.distance3, extrusionVolume) ### self.feedrateS = feedrate * (NozzleProfile.getNetMaxExtrusionRate() / extrusionRate) # print "Adjusted feedrate: ", feedrate, self.feedrateS self.trueStartSpeed = self.nominalStartSpeed = None self.trueEndSpeed = self.nominalEndSpeed = None self.accelData = AccelData() self.stepData = StepData() self.lastMove = None self.nextMove = None self.moveNumber = 0 # debug self.state = 0 # 1: joined, 2: accel planned, 3: steps planned self.streamed = False # Time for the three phases of this move self.accelTime = 0 self.linearTime = 0 self.deccelTime = 0
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 __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()