def commonInit(args, parser): planner = parser.planner printer = planner.printer printer.commandInit(args) ddhome.home(parser, args.fakeendstop) downloadTempTable(printer) printer.sendPrinterInit()
def stopMove(args, parser): planner = parser.planner printer = planner.printer if printer.isHomed(): parser.reset() planner.reset() ddhome.home(parser, args.fakeendstop) printer.sendCommand(CmdStopMove) printer.sendCommand(CmdDisableSteppers)
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 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 printFile(self): try: self.parser.reset() self.planner.reset() ddhome.home(self.parser, self.args.fakeendstop) util.downloadTempTable(self.planner) self.printer.sendPrinterInit() # Send heat up command self.log("\nPre-Heating bed (t0: %d)...\n" % self.mat_t0) self.printer.heatUp(HeaterBed, self.mat_t0) t = int(self.mat_t1 * 0.5) self.log("\nPre-Heating extruder (t1: %d)...\n" % t) self.printer.heatUp(HeaterEx1, t) # Send printing moves f = self.parser.preParse(self.fn.get_value()) # Send priming moves util.prime(self.parser) lineNr = 0 printStarted = False lastUpdate = time.time() for line in f: self.parser.execute_line(line) # # Send more than one 512 byte block for dlprint # # if lineNr > 1000 and (lineNr % 250) == 0: if time.time() > (lastUpdate + 0.5): # check temp and start print if lineNr > 1000 and not printStarted: self.log("\nHeating bed (t0: %d)...\n" % self.mat_t0) self.printer.heatUp(HeaterBed, self.mat_t0, wait=self.mat_t0) self.log("\nHeating extruder (t1: %d)...\n" % self.mat_t1) self.printer.heatUp(HeaterEx1, self.mat_t1, self.mat_t1 - 1) # Send print command self.printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printStarted = True status = self.printer.getStatus() # self.guiQueue.put(SyncCall(self.updateStatus, status)) if printStarted and not self.printer.stateMoving(status): break lastUpdate = time.time() lineNr += 1 print "Parsed %d gcode lines." % lineNr # # Add a move to lift the nozzle from the print if not ultigcode flavor # # if not self.parser.ultiGcodeFlavor: util.endOfPrintLift(self.parser) self.planner.finishMoves() self.printer.sendCommand(CmdEOT) # XXX start print if less than 1000 lines or temp not yet reached: if not printStarted: self.log("\nHeating bed (t0: %d)...\n" % self.mat_t0) self.printer.heatUp(HeaterBed, self.mat_t0, self.mat_t0) self.log("\nHeating extruder (t1: %d)...\n" % self.mat_t1) self.printer.heatUp(HeaterEx1, self.mat_t1, self.mat_t1 - 1) # Send print command self.printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) status = self.printer.getStatus() # self.guiQueue.put(SyncCall(self.updateStatus, status)) while status['state'] != StateIdle: time.sleep(2) status = self.printer.getStatus() # self.guiQueue.put(SyncCall(self.updateStatus, status)) self.printer.coolDown(HeaterEx1) self.printer.coolDown(HeaterBed) ddhome.home(self.parser, self.args.fakeendstop) self.printer.sendCommand(CmdDisableSteppers) except stoppableThread.StopThread: # Stop of current action requested self.printThread.incStopCount() self.log("printFile(): Caught StopThread, bailing out.") return except FatalPrinterError, ex: self.log("printFile(): Caught FatalPrinterError: ", ex.msg) # Reset line numbers in case of a printer restart. self.printer.resetLineNumber()
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 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 printFile(self): try: self.parser.reset() self.planner.reset() ddhome.home(self.parser, self.args.fakeendstop) util.downloadTempTable(self.printer) self.printer.sendPrinterInit() # Send heat up command self.log( "\nPre-Heating bed (t0: %d)...\n" % self.mat_t0) self.printer.heatUp(HeaterBed, self.mat_t0) t = int(self.mat_t1 * 0.5) self.log( "\nPre-Heating extruder (t1: %d)...\n" % t) self.printer.heatUp(HeaterEx1, t) # Send printing moves f = self.parser.preParse(self.fn.get_value()) # Send priming moves util.prime(self.parser) lineNr = 0 printStarted = False lastUpdate = time.time() for line in f: self.parser.execute_line(line) # # Send more than one 512 byte block for dlprint # # if lineNr > 1000 and (lineNr % 250) == 0: if time.time() > (lastUpdate + 0.5): # check temp and start print if lineNr > 1000 and not printStarted: self.log( "\nHeating bed (t0: %d)...\n" % self.mat_t0 ) self.printer.heatUp(HeaterBed, self.mat_t0, wait=self.mat_t0) self.log( "\nHeating extruder (t1: %d)...\n" % self.mat_t1 ) self.printer.heatUp(HeaterEx1, self.mat_t1, wait=self.mat_t1 - 10) # Send print command self.printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) printStarted = True status = self.printer.getStatus() # self.guiQueue.put(SyncCall(self.updateStatus, status)) if printStarted and not self.printer.stateMoving(status): break lastUpdate = time.time() lineNr += 1 print "Parsed %d gcode lines." % lineNr # # Add a move to lift the nozzle from the print if not ultigcode flavor # if not self.parser.ultiGcodeFlavor: util.endOfPrintLift(self.parser) self.planner.finishMoves() self.printer.sendCommand(CmdEOT) # XXX start print if less than 1000 lines or temp not yet reached: if not printStarted: self.log( "\nHeating bed (t0: %d)...\n" % self.mat_t0 ) self.printer.heatUp(HeaterBed, self.mat_t0, self.mat_t0) self.log( "\nHeating extruder (t1: %d)...\n" % self.mat_t1 ) self.printer.heatUp(HeaterEx1, self.mat_t1, wait=self.mat_t1 - 10) # Send print command self.printer.sendCommandParamV(CmdMove, [MoveTypeNormal]) status = self.printer.getStatus() # self.guiQueue.put(SyncCall(self.updateStatus, status)) while status['state'] != StateIdle: time.sleep(2) status = self.printer.getStatus() # self.guiQueue.put(SyncCall(self.updateStatus, status)) self.printer.coolDown(HeaterEx1) self.printer.coolDown(HeaterBed) ddhome.home(self.parser, self.args.fakeendstop) self.printer.sendCommand(CmdDisableSteppers) except stoppableThread.StopThread: # Stop of current action requested self.printThread.incStopCount() self.log("printFile(): Caught StopThread, bailing out.") return except FatalPrinterError, ex: self.log("printFile(): Caught FatalPrinterError", ex.msg) # Reset line numbers in case of a printer restart. self.printer.resetLineNumber()
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 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)])