Example #1
0
    def updateStatus(self, status):

        self.printerState = status["state"]
        self.pState.set_value( "%8s" % self.stateNames[status["state"]])
        self.pState.update()
        self.updateTemps(status["t0"], status["t1"], status["targetT1"])
        self.swapSize.set_value( "%8s" % str(status["Swap"]))
        self.swapSize.update()
        self.sdrSize.set_value( "%8s" % str(status["SDReader"]))
        self.sdrSize.update()
        self.sbSisze.set_value( "%8s" % str(status["StepBuffer"]))
        self.sbSisze.update()
        self.underrun.set_value( "%8s" % str(status["StepBufUnderRuns"]))
        self.underrun.update()

        st = status["targetExtrusionSpeed"]
        sa = status["actualExtrusionSpeed"]

        grip = 100.0
        if st:
            grip = (sa*100.0) / st

        rt = st * MatProfile.getMatArea()
        ra = sa * MatProfile.getMatArea()

        self.extRate.set_value( "%8.1f / %4.1f" % (ra, rt) )
        self.extRate.update()

        self.extGrip.set_value( "%4.1f %%" % grip )
        self.extGrip.update()
Example #2
0
def initParser(args, mode=None, gui=None):

    printerProfileName = "UM2" # xxx get from commandline args

    # profile = profile.Profile(printerProfileName)
    # parser.setProfile(profile)

    # Create printer profile singleton instance
    PrinterProfile(printerProfileName)
    # Create material profile singleton instance
    mat = MatProfile(args.mat, args.smat)

    # Overwrite settings from profile with command line arguments:
    if args.t0:
        mat.override("bedTemp", args.t0)
    if args.t1:
        mat.override("hotendBaseTemp", 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()
    parser = gcodeparser.UM2GcodeParser()

    return (parser, planner, printer)
Example #3
0
    def layerChange(self, layer):

        self.advance.layerChange(layer)

        if layer == 0:

            print "layer 0, increasing temp by", Layer0TempIncrease
            self.l0TempIncrease = Layer0TempIncrease

        else:

            self.l0TempIncrease = 0

        if layer == 2:

            self.partNumber -= 1
            if self.partNumber:
                return

            # Reduce bedtemp
            bedTemp = MatProfile.getBedTempReduced()
            self.gui.log("Layer2, reducing bedtemp to: ", bedTemp)
            self.addSynchronizedCommand(CmdSyncTargetTemp,
                                        p1=packedvalue.uint8_t(HeaterBed),
                                        p2=packedvalue.uint16_t(bedTemp))
Example #4
0
def prime(parser):

    planner = parser.planner
    # printer = planner.printer

    parser.execute_line("G0 F%f Y0 Z%f" % (planner.HOMING_FEEDRATE[X_AXIS]*60, ddprintconstants.PRIMING_HEIGHT))

    pos = parser.getRealPos()

    aFilament = MatProfile.getMatArea()

    parser.execute_line("G0 F%f A%f" % (
        ((ddprintconstants.PRIMING_MM3_PER_SEC / aFilament) * 60),
        pos[A_AXIS] + (ddprintconstants.PRIMING_MM3 / aFilament)))

    # Set E to 0
    current_position = parser.getRealPos()
    current_position[A_AXIS] = 0.0
    parser.set_position(current_position)

    #
    # Retract
    #
    # parser.execute_line("G10")

    # Wipe priming material if not ultigcode flavor 
    if not parser.ultiGcodeFlavor:
        # parser.execute_line("G10")
        # parser.execute_line("G0 F%f X50 Z0.5" % (planner.HOMING_FEEDRATE[X_AXIS]*60))
        parser.execute_line("G0 F9000 X20 Z0.1")
Example #5
0
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()
Example #6
0
    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
Example #7
0
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)
Example #8
0
    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()
Example #9
0
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)
Example #10
0
    def __init__(self, planner):

        self.planner = planner

        self.path = []
        self.count = -10

        # AutoTemp
        if UseExtrusionAutoTemp:

            self.lastTemp = MatProfile.getHotendStartTemp()

        # Some statistics
        self.maxExtrusionRate = MaxExtrusionRate()
Example #11
0
    def preParse(self, fn):

        # Copy file to prevet problems with overwritten files
        # while reading.
        tmpfname = ("/tmp/%d_" % id(fn)) + os.path.basename(fn)
        shutil.copyfile(fn, tmpfname)

        f = open(fn)

        print "Unlinking temp. copy of gcode input: ", tmpfname
        os.unlink(tmpfname)

        self.numParts = 0

        print "pre-parsing ", fn
        for line in f:
            line = line.strip()
            if line.startswith(";"):
                upperLine = line.upper()
                # Cura: "LAYER:"
                if "LAYER:" in upperLine:
                    layerNum = getCuraLayer(line)
                    if layerNum == 1:
                        self.numParts += 1
                        self.planner.newPart(self.numParts)

                # # Simplify3D: "; LAYER "
                # elif "; LAYER " in upperLine:
                    # layerNum = getSimplifyLayer(line)
                    # if layerNum == 1:
                        # self.numParts += 1
                        # self.planner.newPart(self.numParts)

                # Simplify3D: "; skirt "
                elif upperLine.startswith("; SKIRT"):
                    self.numParts += 1
                    self.planner.newPart(self.numParts)

                # ;FLAVOR:UltiGCode
                elif "FLAVOR:ULTIGCODE" in upperLine:
                    self.ultiGcodeFlavor = True
                    # To compute extrude length from volume (see getValues()):
                    # V = A * h, h = V / A, A = pi/4 * diameter²
                    # self.e_to_filament_length *= 4 / (math.pi * pow(MatProfile.getMatDiameter(), 2))
                    aFilament = MatProfile.getMatArea()
                    self.e_to_filament_length = self.e_to_filament_length / aFilament

        print "pre-parsing # parts:", self.numParts
        f.seek(0) # rewind
        return f
Example #12
0
def heatHotend(args, parser):

    planner = parser.planner
    printer = planner.printer

    printer.commandInit(args)

    t1 = MatProfile.getHotendBaseTemp()

    printer.heatUp(HeaterEx1, t1, wait=t1-5)

    raw_input("Press return to stop heating...")

    if not args.noCoolDown:
        printer.coolDown(HeaterEx1, wait=150)
Example #13
0
    def m106_fan_on(self, line, values):
        # print "m106_fan_on", values
        fanSpeed = (values["S"] * MatProfile.getFanPercent()) / 100

        # "Blip fan" for Cura (S3D supports blip fan)
        if fanSpeed < 50 and self.ultiGcodeFlavor:
            # Start fan with full power
            self.planner.addSynchronizedCommand(CmdSyncFanSpeed,
                                                p1=packedvalue.uint8_t(255))
            # Dwell 0.25s
            self.planner.addSynchronizedCommand(CmdDwellMS,
                                                p1=packedvalue.uint16_t(250))

        self.planner.addSynchronizedCommand(CmdSyncFanSpeed,
                                            p1=packedvalue.uint8_t(fanSpeed))
Example #14
0
    def layerChange(self, layer):

        if layer == 2:

            self.partNumber -= 1
            if self.partNumber:
                return

            # Reduce bedtemp
            bedTemp = MatProfile.getBedTempReduced()
            self.gui.log("Layer2, reducing bedtemp to: ", bedTemp)
            self.addSynchronizedCommand(
                CmdSyncTargetTemp, 
                p1 = packedvalue.uint8_t(HeaterBed),
                p2 = packedvalue.uint16_t(bedTemp))
Example #15
0
    def preParse(self, fn):

        # Copy file to prevet problems with overwritten files
        # while reading.
        tmpfname = ("/tmp/%d_" % id(fn)) + os.path.basename(fn)
        shutil.copyfile(fn, tmpfname)

        f = open(tmpfname)

        print "Unlinking temp. copy of gcode input: ", tmpfname
        os.unlink(tmpfname)

        self.numParts = 0

        print "pre-parsing ", fn, tmpfname
        for line in f:
            line = line.strip()
            if line.startswith(";"):

                upperLine = line.upper()

                # Cura: "LAYER:"
                layerNum = getCuraLayer(line)
                if layerNum == 1:
                    self.numParts += 1
                    self.planner.newPart(self.numParts)

                # layerNum = getSimplifyLayer(line)
                # if layerNum == 1:
                # self.numParts += 1
                # self.planner.newPart(self.numParts)

                # Simplify3D: "; skirt "
                if upperLine.startswith("; SKIRT"):
                    self.numParts += 1
                    self.planner.newPart(self.numParts)

                # ;FLAVOR:UltiGCode
                elif "FLAVOR:ULTIGCODE" in upperLine:
                    self.ultiGcodeFlavor = True
                    # To compute extrude length from volume (see getValues()):
                    # V = A * h, h = V / A, A = pi/4 * diameter²
                    aFilament = MatProfile.getMatArea()
                    self.e_to_filament_length = self.e_to_filament_length / aFilament

        print "pre-parsing # parts:", self.numParts
        f.seek(0)  # rewind
        return f
Example #16
0
    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()
Example #17
0
    def stat(self, move):

        # 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 move.distance3 < 0.1:
            return

        # Get maximum extrusion rate, take plateau speed into account only
        # length of max constant speed:
        reachedEExtrusion = move.topSpeed.speed(
        ).eSpeed * MatProfile.getMatArea()

        if reachedEExtrusion > self.maxRate:

            # print "New max reachedEExtrusion: ", reachedEExtrusion, "mm³/s"

            self.maxRate = reachedEExtrusion
            self.move = move

            self.max10.append(reachedEExtrusion)
            if len(self.max10) > 10:
                self.max10 = self.max10[1:]
Example #18
0
    def stat(self, move):

        # 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 move.distance3 < 0.1:
            return 

        # Get maximum extrusion rate, take plateau speed into account only
        # length of max constant speed:
        reachedESpeed = abs( move.getReachedSpeedV()[util.A_AXIS] ) # [mm/s]
        reachedEExtrusion = reachedESpeed * MatProfile.getMatArea()

        if reachedEExtrusion > self.maxRate:

            # print "New max reachedEExtrusion: ", reachedEExtrusion, "mm³/s"

            self.maxRate = reachedEExtrusion
            self.move = move

            self.max10.append(reachedEExtrusion)
            if len(self.max10) > 10:
                self.max10 = self.max10[1:]
Example #19
0
def retract(args, parser, doCooldown = True):

    planner = parser.planner
    printer = planner.printer

    commonInit(args, parser)

    t1 = MatProfile.getHotendBaseTemp()
    printer.heatUp(HeaterEx1, t1, wait=t1 - 5)

    # hack
    # parser.retracted = False
    parser.execute_line("G10")

    planner.finishMoves()

    printer.sendCommandParamV(CmdMove, [MoveTypeNormal])
    printer.sendCommand(CmdEOT)

    printer.waitForState(StateIdle)

    if doCooldown:
        printer.coolDown(HeaterEx1,wait=150)
Example #20
0
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)
Example #21
0
 def m106_fan_on(self, line, values):
     # print "m106_fan_on", values
     fanSpeed = (values["S"] * MatProfile.getFanPercent()) / 100
     self.planner.addSynchronizedCommand(CmdSyncFanSpeed, p1=packedvalue.uint8_t(fanSpeed))
Example #22
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)
Example #23
0
    def addMove(self, move):

        # print "addmove ...", move.comment
        if debugMoves:
            print "***** Start addMove() *****"

        move.moveNumber = self.pathData.incCount()

        if not self.pathData.path:

            # First move of this path, startspeed is jerkspeed

            # jerkSpeed = move.vVector().constrain(self.jerk) or move.vVector()
            # move.setNominalStartFr(jerkSpeed)

            move.setNominalJerkStartSpeed(self.jerk)

            # self.prepareMoveEnd(move)
            self.pathData.path.append(move)

            if UseExtrusionAutoTemp:
                self.pathData.time = 0 # Reset path time
                self.pathData.extrusionAmount = 0
                self.pathData.lastTemp = MatProfile.getHotendBaseTemp()

            #
            # Zum end-speed können wir nichts sagen, da der nächste move noch nicht
            # bekannt ist.
            #
            if debugMoves:
                print "***** End addMove() *****"
            return

        lastMove = self.pathData.path[-1]
        lastMove.nextMove = move
        move.lastMove = lastMove

        util.joinSpeed(lastMove, move, self.jerk, self.min_speeds)

        self.pathData.path.append(move)

        if len(self.pathData.path) < 3:
            # Wir brauchen mind. 3 moves um einen 'PathBlock' zu bilden
            if debugMoves:
                print "***** End addMove() *****"
            return

        if self.isIsolationMove(lastMove):

            l = len(self.pathData.path) 
            pathBlock = self.pathData.path[:l-2]

            if debugMoves:
                print "Move #:", lastMove.moveNumber, " is a isolation move."
                print "Streaming block of moves, len: %d/%d" % (len(pathBlock), l), ", blocks: ", pathBlock[0].moveNumber, " - ", pathBlock[-1].moveNumber

            self.streamMoves(pathBlock)
            del self.pathData.path[:l-2]
            assert(len(self.pathData.path) == 2)

        if debugMoves:
            print "***** End addMove() *****"
Example #24
0
    def streamMoves(self, moves, finish = False):

        if debugMoves:
            print "Streaming %d moves..." % len(moves)

        if debugPlot and not self.plotfile:
            self.plottime = 0
            self.plotfile=open("/tmp/accel_%d.plt" % moves[0].moveNumber, "w")
            self.plotfile.write("set grid\n")
            self.plotfile.write("set label 2 at  graph 0.01, graph 0.95 'Note: Trapez top not included, e-only moves green.'\n")
            self.plotfile.write('plot "-" using 1:2:3 with linespoints lc variable\n')

        #################################################################################
        # Backwards move planning
        self.joinMovesBwd(moves)
        #################################################################################

        for move in moves:

            # move.pprint("sanicheck")
            move.sanityCheck(self.jerk)

            self.planAcceleration(move)
            self.planSteps(move)

            #
            # Collect some statistics
            #
            if move.isHeadMove():
                self.pathData.maxExtrusionRate.stat(move)

            #
            # Collect moves if AutoTemp
            #
            if UseExtrusionAutoTemp:
                if move.isExtrudingMove(util.A_AXIS):
                    # Collect moves and sum up path time
                    self.pathData.time += move.getTime()

                    # Sum extrusion volume
                    self.pathData.extrusionAmount += move.getAdjustedExtrusionVolume(util.A_AXIS, NozzleProfile, MatProfile)

                self.pathData.atMoves.append(move)

            else:

                self.streamMove(move)

            move.streamed = True

            # Help garbage collection
            move.lastMove = errorMove
            move.nextMove = errorMove
        
        if UseExtrusionAutoTemp:

            if self.pathData.time >= ATInterval or finish:

                if self.pathData.time > 0:

                    # Compute temperature for this segment and add tempcommand into the stream
                    # Average speed:
                    avgSpeed = self.pathData.extrusionAmount / self.pathData.time

                    # UseAutoTemp: Adjust temp between Tbase and HotendMaxTemp, if speed is greater than 20 mm/s
                    # UseExtrusionAutoTemp: Adjust temp between Tbase and HotendMaxTemp, if speed is greater than 5 mm³/s
                    newTemp = MatProfile.getHotendBaseTemp() # Extruder 1 temp
                    # extrusionLow = self.ExtrusionAmountLow * pow(NozzleProfile.getSize(), 2)
                    if avgSpeed > self.ExtrusionAmountLow:
                        f = MatProfile.getAutoTempFactor()
                        # newTemp += min((avgSpeed - self.ExtrusionAmountLow * pow(NozzleProfile.getSize(), 2)) * f, ATMaxTempIncrease)
                        newTemp += (avgSpeed - self.ExtrusionAmountLow) * f
                        # newTemp *= 1.15 # xxx sync withtemp-speed-adjust
                        newTemp = min(newTemp, MatProfile.getHotendMaxTemp())

                    if debugAutoTemp:
                        print "AutoTemp: collected %d moves with %.2f s duration." % (len(self.pathData.atMoves), self.pathData.time)
                        print "AutoTemp: amount: %.2f, avg extrusion rate: %.2f mm³/s." % (self.pathData.extrusionAmount, avgSpeed)
                        print "AutoTemp: new temp: %.2f." % (newTemp)
                        self.pathData.maxExtrusionRate.avgStat(avgSpeed)

                    if newTemp != self.pathData.lastTemp and self.args.mode != "pre":

                        # Schedule target temp command
                        self.printer.sendCommandParamV(
                            CmdSyncTargetTemp,
                            [packedvalue.uint8_t(HeaterEx1), packedvalue.uint16_t(newTemp)])

                        self.pathData.lastTemp = newTemp

                for move in self.pathData.atMoves:
                    self.streamMove(move)
                   
                self.pathData.atMoves = []
                self.pathData.time = self.pathData.extrusionAmount = 0 # Reset path time
Example #25
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)])
Example #26
0
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)
Example #27
0
    def printWorker(self):

        parser = argparse.ArgumentParser(description='%s, Direct Drive USB Print.' % sys.argv[0])
        parser.add_argument("-d", dest="device", action="store", type=str, help="Device to use, default: /dev/ttyACM0.", default="/dev/ttyACM0")
        parser.add_argument("-b", dest="baud", action="store", type=int, help="Baudrate, default 115200.", default=115200)
        parser.add_argument("-f", dest="file", action="store", type=str, help="Gcode to print")
        parser.add_argument("-F", dest="fakeendstop", action="store", type=bool, help="fake endstops", default=False)
        parser.add_argument("-nc", dest="noCoolDown", action="store", type=bool, help="Debug: don't wait for heater cool down after print.", default=False)
        parser.add_argument("-t0", dest="t0", action="store", type=int, help="Temp 0 (heated bed), default comes from mat. profile.")
        parser.add_argument("-t1", dest="t1", action="store", type=int, help="Temp 1 (hotend 1), default comes from mat. profile.")
        parser.add_argument("-mat", dest="mat", action="store", help="Name of material profile to use [pla, abs...], default is pla.", default="pla_1.75mm")
        parser.add_argument("-smat", dest="smat", action="store", help="Name of specific material profile to use.")
        parser.add_argument("-noz", dest="nozzle", action="store", help="Name of nozzle profile to use [nozzle40, nozzle80...], default is nozzle40.", default="nozzle40")

        self.args = parser.parse_args()
        self.args.mode = "dlprint"

        # print "args: ", self.args

        (self.parser, self.planner, self.printer) = ddprint.initParser(self.args, gui=self)
        # util.commonInit(self.args, self.parser)

        try:
            self.printer.commandInit(self.args)
        except SerialException:
            msg = "Can't open serial device '%s' (baudrate: %d)!\n\nPress OK to exit." % (self.args.device, self.args.baud)
            self.guiQueue.put(SyncCall(self.quit, msg))
            return

        self.mat_t0 = MatProfile.getBedTemp()
        self.mat_t1 = MatProfile.getHotendBaseTemp()

        # self.fn.set_value(self.args.file)
        self.guiQueue.put(SyncCall(self.fn.set_value, self.args.file))

        while True:

            try:

                while True:
                    # self.guiQueue.put("hi")
                    # self.guiQueue.put(SyncCall(self.appLog.buffer, ["juhu"]))

                    workDone = False

                    while not self.cmdQueue.empty():
                        obj = self.cmdQueue.get()
                        obj.call()
                        workDone = True

                    if time.time() - self.lastUpdate > 2.5:
                        # status = self.printer.getStatus()
                        # self.guiQueue.put(SyncCall(self.updateStatus, status))
                        self.printer.getStatus()

                        workDone = True
                        self.lastUpdate = time.time()

                    if not workDone:
                        time.sleep(0.1)

            except stoppableThread.StopThread:
                self.printThread.incStopCount()
                self.log("caught StopThread, continue....")
Example #28
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 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)
Example #29
0
    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
Example #30
0
    def printWorker(self):

        parser = argparse.ArgumentParser(
            description='%s, Direct Drive USB Print.' % sys.argv[0])
        parser.add_argument("-d",
                            dest="device",
                            action="store",
                            type=str,
                            help="Device to use, default: /dev/ttyACM0.",
                            default="/dev/ttyACM0")
        parser.add_argument("-b",
                            dest="baud",
                            action="store",
                            type=int,
                            help="Baudrate, default 500000.",
                            default=500000)
        parser.add_argument("-f",
                            dest="file",
                            action="store",
                            type=str,
                            help="Gcode to print")
        parser.add_argument("-F",
                            dest="fakeendstop",
                            action="store",
                            type=bool,
                            help="fake endstops",
                            default=False)
        parser.add_argument(
            "-nc",
            dest="noCoolDown",
            action="store",
            type=bool,
            help="Debug: don't wait for heater cool down after print.",
            default=False)
        parser.add_argument(
            "-t0",
            dest="t0",
            action="store",
            type=int,
            help="Temp 0 (heated bed), default comes from mat. profile.")
        parser.add_argument(
            "-t1",
            dest="t1",
            action="store",
            type=int,
            help="Temp 1 (hotend 1), default comes from mat. profile.")
        parser.add_argument(
            "-kAdvance",
            dest="kAdvance",
            action="store",
            type=float,
            help="K-Advance factor, default comes from mat. profile.")
        parser.add_argument(
            "-mat",
            dest="mat",
            action="store",
            help=
            "Name of material profile to use [pla, abs...], default is pla.",
            default="pla_1.75mm")
        parser.add_argument(
            "-rl",
            dest="retractLength",
            action="store",
            type=float,
            help="Retraction length, default comes from printer profile.",
            default=0)
        parser.add_argument("-smat",
                            dest="smat",
                            action="store",
                            help="Name of specific material profile to use.")
        parser.add_argument(
            "-noz",
            dest="nozzle",
            action="store",
            help=
            "Name of nozzle profile to use [nozzle40, nozzle80...], default is nozzle40.",
            default="nozzle40")

        self.args = parser.parse_args()
        self.args.mode = "dlprint"

        # print "args: ", self.args

        (self.parser, self.planner,
         self.printer) = ddprint.initParser(self.args, gui=self)
        # util.commonInit(self.args, self.parser)

        try:
            self.printer.commandInit(self.args)
        except SerialException:
            msg = "Can't open serial device '%s' (baudrate: %d)!\n\nPress OK to exit." % (
                self.args.device, self.args.baud)
            self.guiQueue.put(SyncCall(self.quit, msg))
            return

        self.mat_t0 = MatProfile.getBedTemp()
        self.mat_t0_reduced = MatProfile.getBedTempReduced()
        self.mat_t1 = MatProfile.getHotendStartTemp(
        ) + self.planner.l0TempIncrease

        # self.fn.set_value(self.args.file)
        self.guiQueue.put(SyncCall(self.fn.set_value, self.args.file))

        while True:

            try:

                while True:
                    # self.guiQueue.put("hi")
                    # self.guiQueue.put(SyncCall(self.appLog.buffer, ["juhu"]))

                    workDone = False

                    while not self.cmdQueue.empty():
                        obj = self.cmdQueue.get()
                        obj.call()
                        workDone = True

                    if time.time() - self.lastUpdate > 2.5:
                        # status = self.printer.getStatus()
                        # self.guiQueue.put(SyncCall(self.updateStatus, status))
                        self.printer.getStatus()

                        workDone = True
                        self.lastUpdate = time.time()

                    if not workDone:
                        time.sleep(0.1)

            except stoppableThread.StopThread:
                self.printThread.incStopCount()
                self.log("caught StopThread, continue....")
Example #31
0
    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()