示例#1
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)
示例#2
0
    def g11_retract_recover(self, line, values):
        # print "g11_retract_recover", values

        if self.retracted:
            current_position = self.getRealPos()
            values = {
                    "F": PrinterProfile.getRetractFeedrate(),
                    "A": current_position[A_AXIS] + PrinterProfile.getRetractLength(),
                    }
            self.g0("G11", values)
            self.retracted = False
示例#3
0
    def g10_retract(self, line, values):
        # print "g10_retract", values

        # Compute retract 
        if not self.retracted:
            current_position = self.getRealPos()
            values = {
                    "F": PrinterProfile.getRetractFeedrate(),
                    "A": current_position[A_AXIS] - PrinterProfile.getRetractLength(),
                    }
            self.g0("G10", values)
            self.retracted = True
示例#4
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()
示例#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()
示例#6
0
def manualMove(parser, axis, distance, feedrate=0, absolute=False):

    planner = parser.planner
    printer = planner.printer

    printer.sendPrinterInit()

    assert(printer.isHomed())

    # Get current pos from printer and set our virtual pos
    getVirtualPos(parser)

    if not feedrate:
        feedrate = PrinterProfile.getMaxFeedrate(axis)

    current_position = parser.getRealPos()
    if absolute:
        d = distance - current_position[A_AXIS] 
        assert(abs(d) <= 1000)
        parser.execute_line("G0 F%d %s%f" % (feedrate*60, dimNames[axis], distance))
    else:
        assert(abs(distance) <= 1000)
        parser.execute_line("G0 F%d %s%f" % (feedrate*60, dimNames[axis], current_position[axis] + distance))

    planner.finishMoves()

    printer.sendCommand(CmdEOT)
    # time.sleep(1)

    printer.sendCommandParamV(CmdMove, [MoveTypeNormal])

    printer.waitForState(StateIdle)

    printer.readMore(10)
示例#7
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()
示例#8
0
    def g11_retract_recover(self, line, values):
        # print "g11_retract_recover", values

        current_position = self.getPos()

        rl = PrinterProfile.getRetractLength()

        current_position[A_AXIS] += rl

        self.planner.addMove(
            TravelMove(line,
                       displacement_vector=Vector([0.0, 0.0, 0.0, rl, 0.0]),
                       displacement_vector_steps=[
                           0.0, 0.0, 0.0, rl * self.steps_per_mm[A_AXIS], 0.0
                       ],
                       feedrate=min(PrinterProfile.getRetractFeedrate(),
                                    PrinterProfile.getMaxFeedrate(3))))

        self.setPos(current_position)
示例#9
0
    def getJerk(self):

        jerk = []
        for dim in dimNames:
            jerk.append(PrinterProfile.getValues()['axes'][dim]['jerk'])

        # self.jerk = Vector(jerk)
        # self.gui.log("Jerk vector: ", self.jerk)
        # self.gui.log("Jerk vector: ", jerk)

        return jerk
示例#10
0
    def __init__(self,
                 comment,
                 displacement_vector,
                 displacement_vector_steps,
                 feedrate, # mm/s
                 maxAccelV,
                 ):

        RealMove.__init__(self, comment)

        #
        # Move distance in XYZ plane
        #
        self.distance3 = displacement_vector.length(3)

        self.advanceData = AdvanceData(self)

        self.e_steps_per_mm = PrinterProfile.getStepsPerMM(A_AXIS)

        self.displacement_vector_raw3 = Vector(displacement_vector[:3])
        self.displacement_vector_steps_raw3 = displacement_vector_steps[:3]

        self.direction3 = self.displacement_vector_raw3.normalized()

        ### Apply extrusion adjust
        ### if UseExtrusionAdjust:

        direction5 = displacement_vector.normalized()

        self.eDistance = displacement_vector[A_AXIS]

        # xxx todo: add override
        self.eSteps = displacement_vector_steps[A_AXIS]

        self.eDirection = self.eDistance / self.distance3

        # Compute nominal eSpeed

        v = VelocityVector32(feedrate*self.eDirection, feedrate = feedrate, direction = self.direction3)

        self.startSpeed = VelocityOverride(v)
        self.topSpeed = VelocityOverride(v)
        self.endSpeed = VelocityOverride(v)

        # self.__direction5 = displacement_vector.normalized()
        # av = self.__getMaxAllowedAccelVector5(maxAccelV)

        accelVector = direction5.scale(_MAX_ACCELERATION)
        av = accelVector.constrain(maxAccelV) or accelVector

        # xxx rework accel, store default xyz and eaccel, make start- and eaccel overridable
        self.startAccel = AccelOverride([av[:3], av[A_AXIS]], self.direction3)
        self.endAccel = AccelOverride([av[:3], av[A_AXIS]], self.direction3)
示例#11
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)
示例#12
0
def changeNozzle(args, parser):

    planner = parser.planner
    printer = planner.printer

    retract(args, parser, doCooldown = False)

    feedrate = PrinterProfile.getMaxFeedrate(X_AXIS)
    execSingleGcode(parser, "G0 F%d X%f Y%f" % (feedrate*60, planner.MAX_POS[X_AXIS]/2, planner.MAX_POS[Y_AXIS]*0.1))

    raw_input("Now change nozzle, Press return to stop heating...")

    execSingleGcode(parser, "G11")

    if not args.noCoolDown:
        printer.coolDown(HeaterEx1, wait=100)
示例#13
0
def calibrateFilSensor(args, parser):

    planner = parser.planner
    printer = planner.printer

    printer.commandInit(args)

    steps_per_mm = PrinterProfile.getStepsPerMMVector()[util.A_AXIS]

    # ddhome.home(parser, args.fakeendstop)

    current_position = parser.getRealPos()
    apos = current_position[util.A_AXIS]

    fsstepsum = 0
    distsum = 0

    # ramp up speed from 3mm/s to 13mm/s, that is about 7.2 to 31 mm³/s flowrate (1.75mm filament)
    for feedrate in range(11):

        feedrate += 3

        # choose length of move to get about 25 points per feedrate step
        distance = 2.5 * feedrate

        apos += distance

        printer.sendPrinterInit()

        parser.execute_line("G0 F%d %s%f" % (feedrate*60, util.dimNames[util.A_AXIS], apos))

        planner.finishMoves()
        printer.sendCommand(CmdEOT)
        printer.sendCommandParamV(CmdMove, [MoveTypeNormal])
        printer.waitForState(StateIdle)

        time.sleep(0.25)

        fssteps = printer.getFilSensor()

        print "Speed: %d, dist: %.2f, FSsteps: %d, fssteps/mm: %.4f" % (feedrate, distance, fssteps, fssteps/distance)

        distsum += distance
        fsstepsum += fssteps


    print "Average fssteps/mm: %.4f" % (fsstepsum/distsum)
示例#14
0
    def getHomePos(self):

        # Get additional z-offset from eeprom
        add_homeing_z = self.printer.getAddHomeing_z()

        assert((add_homeing_z <= 0) and (add_homeing_z >= -35))

        print "add_homeing_z from eeprom: ", add_homeing_z

        # Virtuelle position des druckkopfes falls 'gehomed'
        homePosMM = util.MyPoint(
            X = self.X_HOME_POS,
            Y = self.Y_HOME_POS,
            Z = self.Z_HOME_POS + add_homeing_z,
            )

        # Diese stepper position wird gesetzt falls der drucker 'gehomed' ist
        homePosStepped = vectorMul(homePosMM.vector(), PrinterProfile.getStepsPerMMVector())

        return (homePosMM, homePosStepped)
示例#15
0
    def getHomePos(self):

        # Get additional z-offset from eeprom
        add_homeing_z = self.printer.getAddHomeing_z()

        assert ((add_homeing_z <= 0) and (add_homeing_z >= -35))

        print "add_homeing_z from eeprom: ", add_homeing_z

        # Virtuelle position des druckkopfes falls 'gehomed'
        homePosMM = util.MyPoint(
            X=self.X_HOME_POS,
            Y=self.Y_HOME_POS,
            Z=self.Z_HOME_POS + add_homeing_z,
        )

        # Diese stepper position wird gesetzt falls der drucker 'gehomed' ist
        homePosStepped = vectorMul(homePosMM.vector(),
                                   PrinterProfile.getStepsPerMMVector())

        return (homePosMM, homePosStepped)
示例#16
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
示例#17
0
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)
示例#18
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)
示例#19
0
    def planTravelAcceleration(self, move):

        if debugMoves:
            print "***** Start planTravelAcceleration() *****"
            move.pprint("planTravelAcceleration")

        move.state = 2

        allowedAccel = allowedDecel = move.getMaxAllowedAccelNoAdv5()

        #
        # Check if the speed difference between startspeed and endspeed can be done with
        # this acceleration in this distance
        #
        startSpeedS = move.startSpeed.speed().feedrate
        endSpeedS = move.endSpeed.speed().feedrate

        deltaSpeedS = endSpeedS - startSpeedS

        if abs(deltaSpeedS) > 0.001:

            ta = abs(deltaSpeedS) / allowedAccel

            if deltaSpeedS >= 0:
                # acceleration
                sa = util.accelDist(startSpeedS, allowedAccel, ta)
            else:
                # deceleration
                sa = util.accelDist(startSpeedS, -allowedAccel, ta)

            if (sa - move.distance5) > 0.001:
                print "VStart %f mm/s kann nicht innerhalb von %f mm auf Endgeschwindigkeit %f mm/s gebracht werden!" % (
                    startSpeedS, move.distance5, endSpeedS)
                print "Dafür werden %f mm benötigt" % sa
                assert (0)

        #
        # Compute distance to accel from start speed to nominal speed:
        #

        ta = 0.0
        sa = 0.0

        deltaStartSpeedS = move.topSpeed.speed().feedrate - startSpeedS

        maxAccel = PrinterProfile.getMaxAxisAcceleration()

        if deltaStartSpeedS:

            ta = deltaStartSpeedS / allowedAccel
            # print "accel time (for %f mm/s): %f [s]" % (deltaStartSpeedS, ta)

            # debug Check axxis acceleration
            deltaSpeedV = move.direction5.scale(deltaStartSpeedS)
            for dim in range(5):
                dimAccel = abs(deltaSpeedV[dim]) / ta
                if (dimAccel / maxAccel[dim]) > 1.001:
                    print "dim %d verletzt max accel: " % dim, dimAccel, " > ", maxAccel[
                        dim]
                    assert (0)
            #end debug

            sa = util.accelDist(startSpeedS, allowedAccel, ta)

        #
        # Compute distance to decel from nominal speed to endspeed:
        #
        tb = 0.0
        sb = 0.0

        deltaEndSpeedS = move.topSpeed.speed().feedrate - endSpeedS  # [mm/s]

        if deltaEndSpeedS:

            tb = deltaEndSpeedS / allowedAccel  # [s]
            # print "decel time (for %f mm/s): %f [s]" % (deltaEndSpeedS, tb)

            # debug Check axxis acceleration
            deltaSpeedV = move.direction5.scale(deltaEndSpeedS)
            for dim in range(5):
                dimDecel = abs(deltaSpeedV[dim]) / tb
                if (dimDecel / maxAccel[dim]) > 1.001:
                    print "dim %d verletzt max accel: " % dim, dimDecel, " [mm/s] > ", maxAccel[
                        dim], " [mm/s]"
                    assert (0)
            # end debug

            sb = util.accelDist(endSpeedS, allowedAccel, tb)

        # print "e_distance: %f, sbeschl, sbrems: %f, %f" % (move.e_distance, sa, sb)

        if move.distance5 < (sa + sb):

            #
            # Strecke zu kurz, Trapez nicht möglich, geschwindigkeit muss abgesenkt werden.
            #
            if debugMoves:
                print "Trapez nicht möglich: s: %f, sbeschl (%f) + sbrems (%f) = %f" % (
                    move.distance5, sa, sb, sa + sb)

            # ???
            assert (sa > 0 and sb > 0)

            topSpeed = move.topSpeed.speed()

            sa = (2 * allowedAccel * move.distance5 - pow(startSpeedS, 2) +
                  pow(endSpeedS, 2)) / (4 * allowedAccel)
            sb = move.distance5 - sa

            if debugMoves:
                print "sbeschl, sbrems neu: %f, %f" % (sa, sb)

            #
            # Geschwindigkeit, die auf strecke sa mit erreicht werden kann
            #
            v = math.sqrt(2 * allowedAccel * sa + pow(startSpeedS, 2))

            # debug, test
            v2 = math.sqrt(2 * allowedAccel * sb + pow(endSpeedS, 2))
            # print "move.feedrate neu: %f (test: %f, diff: %f)" % (v, v2, abs(v - v2))

            assert (abs(v - v2) < 0.001)

            deltaSpeedS = v - startSpeedS  # [mm/s]

            # Handle rounding errors
            if deltaSpeedS < 0:
                assert (deltaSpeedS > -0.000001)
                deltaSpeedS = 0
                v = startSpeedS

            ta = deltaSpeedS / allowedAccel
            # print "ta: ", ta, deltaSpeedS

            deltaSpeedS = v - endSpeedS  # [mm/s]

            # Handle rounding errors
            if deltaSpeedS < 0:
                assert (deltaSpeedS > -0.000001)
                deltaSpeedS = 0
                v = endSpeedS

            tb = deltaSpeedS / allowedAccel
            # print "tb: ", tb, deltaSpeedS

            topSpeed.feedrate = v
            move.topSpeed.setSpeed(
                topSpeed, "planTravelAcceleration - max reachable topspeed")

            move.setDuration(ta, 0, tb)

            if debugMoves:
                move.pprint("planTravelAcceleration")
                print
                print "***** End planTravelAcceleration() *****"

            return

        #
        # Strecke reicht aus, um auf nominal speed zu beschleunigen
        #

        # print "ta: ", ta, deltaStartSpeedS, sa
        # print "tb: ", tb, deltaEndSpeedS, sb

        nominalSpeed = move.topSpeed.speed().feedrate  # [mm/s]
        slin = move.distance5 - (sa + sb)
        tlin = slin / nominalSpeed
        # print "tlin: ", tlin, slin
        move.setDuration(ta, tlin, tb)

        if debugMoves:
            move.pprint("planTravelAcceleration")
            print
            print "***** End planTravelAcceleration() *****"
示例#20
0
def home(parser, fakeHomingEndstops=False, force=False):

    planner = parser.planner
    printer = planner.printer

    print "*"
    print "* Start homing..."
    print "*"
    if printer.isHomed() and not force:
        print "Printer is homed already..."

        # Send init command
        printer.sendPrinterInit()

        # Get current pos from printer and set our virtual pos
        curPosMM = util.getVirtualPos(parser)

        (homePosMM, homePosStepped) = planner.getHomePos()

        # print "Printer should be at [mm]: ", homePosMM, ", [steps]: ", homePosStepped

        # Move to home
        if not curPosMM.equal(homePosMM, "XYZ"):

            #
            # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern
            # der buildplatte oder mit objekten auf der druckplatte zu vermeiden.
            #
            if not curPosMM.equal(homePosMM, "Z"):

                parser.execute_line(
                    "G0 F%d Z%f" %
                    (PrinterProfile.getMaxFeedrate(util.Z_AXIS) * 60,
                     homePosMM.Z))

            if not curPosMM.equal(homePosMM, "XY"):

                parser.execute_line(
                    "G0 F%d X%f Y%f" %
                    (PrinterProfile.getMaxFeedrate(util.X_AXIS) * 60,
                     homePosMM.X, homePosMM.Y))

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

            printer.waitForState(StateIdle, wait=0.05)

        #
        # Set Virtual E-pos 0:
        #
        parser.setPos(homePosMM)

        print "*"
        print "* Done homing..."
        print "*"
        return

    #
    # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern
    # der buildplatte oder mit einem modell zu vermeiden.
    #
    for dim in [util.Z_AXIS, util.X_AXIS, util.Y_AXIS]:

        # Try fast home if endstop is pressed
        if printer.endStopTriggered(dim, fakeHomingEndstops):

            print "Homing: endstop %d is triggered, trying fast home." % dim
            if homeBounce(parser, dim, fakeHomingEndstops):
                continue

        # Try fast home if head/bed is near the endstop
        print "Homing: doing short/fast home."
        if homeMove(parser, dim, 1, planner.MAX_POS[dim] / 10.0,
                    fakeHomingEndstops):  # Move towards endstop fast

            print "Homing: endstop %d is triggered, trying fast home." % dim
            if homeBounce(parser, dim, fakeHomingEndstops):
                continue

        # Do the full slow homing move
        print "Homing: doing full/slow home."
        if not homeMove(parser, dim, 1, planner.MAX_POS[dim] * 1.25,
                        fakeHomingEndstops):  # Move towards endstop fast
            print "Error, Endstop %d NOT hit!" % dim
            assert (0)

        if not homeBounce(parser, dim, fakeHomingEndstops):
            print "Error, Bounce %d!" % dim
            assert (0)

    #
    # Set position in steps on the printer side and set our 'virtual position':
    #
    # xxx set end-of-print retraction e-pos also here?
    #
    # parser.setPos(planner.homePosMM)
    # payload = struct.pack("<iiiii", *planner.homePosStepped)
    (homePosMM, homePosStepped) = planner.getHomePos()
    parser.setPos(homePosMM)

    # print "Tell printer its position [steps]:", homePosStepped
    payload = struct.pack("<iiiii", *homePosStepped)
    printer.sendCommand(CmdSetHomePos, binPayload=payload)

    print "*"
    print "* Done homing..."
    print "*"
示例#21
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)
示例#22
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)])
示例#23
0
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)
示例#24
0
    def getMaxAllowedAccelVectorNoAdv5(self):

        accelVector = self.direction5.scale(_MAX_ACCELERATION)
        return abs(accelVector.constrain(PrinterProfile.getMaxAxisAcceleration()) or accelVector)
示例#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)])
示例#26
0
    def planSteps(self, move):

        if debugMoves:
            print "***** Start planSteps() *****"
            move.pprint("PlanSTeps:")

        move.state = 3

        dirBits = 0
        abs_displacement_vector_steps = []

        leadAxis = 0
        leadAxis_value = 0

        for i in range(5):
            dirBits += (move.displacement_vector_steps_raw()[i] >= 0) << i
            adjustedDisplacement = move.displacement_vector_steps_adjusted(NozzleProfile, MatProfile, PrinterProfile)

            s = abs(adjustedDisplacement[i])
            if s > leadAxis_value:
                leadAxis = i
                leadAxis_value = s

            abs_displacement_vector_steps.append(s)

        if dirBits != self.printer.curDirBits:
            move.stepData.setDirBits = True
            move.stepData.dirBits = dirBits
            self.printer.curDirBits = dirBits

        steps_per_mm = PrinterProfile.getStepsPerMM(leadAxis)

        #
        # Bresenham's variables
        #
        deltaLead = abs_displacement_vector_steps[leadAxis]
        move.stepData.setBresenhamParameters(leadAxis, abs_displacement_vector_steps)

        #
        # Create a list of stepper pulses
        #

        # debnegtimer
        nominalSpeed = abs( move.getReachedSpeedV()[leadAxis] ) # [mm/s]

        reachedSpeedV = move.getReachedSpeedV()
        reachedSpeedFr = reachedSpeedV.len5()

        # debnegtimer
        accel = abs(move.getAllowedAccelVector()[leadAxis])
        accel_steps_per_square_second = accel * steps_per_mm

        # startSpeed = move.getStartFr()

        # debnegtimer
        v0 = abs(move.getFeedrateV(move.getStartFr())[leadAxis])                # [mm/s]

        # endSpeed = move.getEndFr()

        # debnegtimer
        v1 = abs(move.getFeedrateV(move.getEndFr())[leadAxis])                # [mm/s]

        # debnegtimer
            
        steps_per_second_0 = steps_per_second_accel = v0 * steps_per_mm
        steps_per_second_1 = steps_per_second_deccel = v1 * steps_per_mm
        steps_per_second_nominal = nominalSpeed * steps_per_mm

        #
        # Acceleration variables
        #
        # tAccel = 0  # [s], sum of all acceeration steptimes
        # tAccel mit der initialen zeitspanne vorbelegen, da wir bereits im
        # ersten schleifendurchlauf (d.h. ab t=0) eine beschleunigung haben wollen.
        tAccel = 1.0 / steps_per_second_0  # [s], sum of all acceeration steptimes
        tDeccel = 1.0 / steps_per_second_1

        stepNr = 0

        if debugPlot:
            accelPlotData = []
            deccelPlotData = []

        if not circaf(move.getStartFr(), reachedSpeedFr, 0.1) and not circaf(move.getEndFr(), reachedSpeedFr, 0.1):

            #
            # Acceleration ramp on both sides.
            #
            # Ramp up both sides in parallel to not exeed available steps
            #

            done = False
            while not done and stepNr < deltaLead:

                done = True

                # 
                # Compute acceleration timer values
                # 
                if steps_per_second_accel < steps_per_second_nominal:

                    #
                    # Compute timer value
                    #
                    steps_per_second_accel = min(steps_per_second_0 + tAccel * accel_steps_per_square_second, steps_per_second_nominal)

                    dt = 1.0 / steps_per_second_accel
                    timerValue = int(fTimer / steps_per_second_accel)

                    # print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue

                    if debugPlot:
                        if move.eOnly:
                            accelPlotData.append((steps_per_second_accel/steps_per_mm, 2, dt))
                        else:
                            accelPlotData.append((steps_per_second_accel/steps_per_mm, 1, dt))

                    tAccel += dt

                    if timerValue > maxTimerValue24:
                        move.pprint("PlanSTeps:")
                        print "v0: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue
                        print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue
                        assert(0)

                    move.stepData.addAccelPulse(timerValue)
                    stepNr += 1
                    done = False

                if stepNr == deltaLead:
                    break

                #
                # Compute ramp down (in reverse), decceleration
                #
                if steps_per_second_deccel < steps_per_second_nominal:

                    #
                    # Compute timer value
                    #
                    steps_per_second_deccel = min(steps_per_second_1 + tDeccel * accel_steps_per_square_second, steps_per_second_nominal)

                    dt = 1.0 / steps_per_second_deccel
                    timerValue = int(fTimer / steps_per_second_deccel)

                    # print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue, ", v: ", steps_per_second_deccel/steps_per_mm

                    if debugPlot:
                        if move.eOnly:
                            deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 2, dt))
                        else:
                            deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 1, dt))

                    tDeccel += dt

                    if timerValue > maxTimerValue24:
                        move.pprint("PlanSTeps:")
                        print "v0: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue
                        print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue
                        assert(0)

                    move.stepData.addDeccelPulse(timerValue)
                    stepNr += 1
                    done = False

        elif not circaf(move.getStartFr(), reachedSpeedFr, 0.1): 

            #
            # Acceleration only
            #

            # 
            # Compute acceleration timer values
            # 
            while steps_per_second_accel < steps_per_second_nominal and stepNr < deltaLead:

                #
                # Compute timer value
                #
                steps_per_second_accel = min(steps_per_second_0 + tAccel * accel_steps_per_square_second, steps_per_second_nominal)

                dt = 1.0 / steps_per_second_accel
                timerValue = int(fTimer / steps_per_second_accel)

                # print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue

                if debugPlot:
                    if move.eOnly:
                        accelPlotData.append((steps_per_second_accel/steps_per_mm, 2, dt))
                    else:
                        accelPlotData.append((steps_per_second_accel/steps_per_mm, 1, dt))

                tAccel += dt

                if timerValue > maxTimerValue24:
                    move.pprint("PlanSTeps:")
                    print "v0: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue
                    print "dt: ", dt*1000000, "[uS]", steps_per_second_accel, "[steps/s], timerValue: ", timerValue
                    assert(0)

                move.stepData.addAccelPulse(timerValue)
                stepNr += 1

        else:

            #
            # Decceleration only
            #

            #
            # Compute ramp down (in reverse), decceleration
            #
            while steps_per_second_deccel < steps_per_second_nominal and stepNr < deltaLead:

                #
                # Compute timer value
                #
                steps_per_second_deccel = min(steps_per_second_1 + tDeccel * accel_steps_per_square_second, steps_per_second_nominal)

                dt = 1.0 / steps_per_second_deccel
                timerValue = int(fTimer / steps_per_second_deccel)

                # print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue, ", v: ", steps_per_second_deccel/steps_per_mm

                if debugPlot:
                    if move.eOnly:
                        deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 2, dt))
                    else:
                        deccelPlotData.append((steps_per_second_deccel/steps_per_mm, 1, dt))

                tDeccel += dt

                if timerValue > maxTimerValue24:
                    move.pprint("PlanSTeps:")
                    print "v0: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue
                    print "dt: ", dt*1000000, "[uS]", steps_per_second_deccel, "[steps/s], timerValue: ", timerValue
                    assert(0)

                move.stepData.addDeccelPulse(timerValue)
                stepNr += 1

        #
        # Linear phase
        #
        timerValue = fTimer / steps_per_second_nominal
        move.stepData.setLinTimer(timerValue)

        if debugPlot:
            self.plotfile.write("# Acceleration:\n")
            for (speed, color, dt) in accelPlotData:
                self.plotfile.write("%f %f %d\n" % (self.plottime, speed, color))
                self.plottime += dt

            self.plotfile.write("# Linear top:\n")
            self.plotfile.write("%f %f 0\n" % (self.plottime, steps_per_second_nominal/steps_per_mm))
            self.plottime += timerValue / fTimer

            self.plotfile.write("# Decceleration:\n")
            deccelPlotData.reverse()
            for (speed, color, dt) in deccelPlotData:
                self.plotfile.write("%f %f %d\n" % (self.plottime, speed, color))
                self.plottime += dt

        if debugMoves:
            print "# of steps for move: ", deltaLead
            move.pprint("move:")
            print 

        move.stepData.checkLen(deltaLead)

        if debugMoves:
            print "***** End planSteps() *****"

        return 

        # XXXXXXXXXXXXXX old, unused ...........

        # 
        # Compute acceleration timer values
        # 
        # while v0 and steps_per_second < steps_per_second_nominal:
        # lastTimer = None
        while steps_per_second < steps_per_second_nominal: #  and stepNr < deltaLead:

            assert(stepNr < deltaLead)

            #
            # Compute timer value
            #
            steps_per_second = min(steps_per_second_0 + tAccel * accel_steps_per_square_second, steps_per_second_nominal)

            dt = 1.0 / steps_per_second
            timerValue = int(fTimer / steps_per_second)

            # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue

            if debugPlot:
                if move.eOnly:
                    self.plotfile.write("%f %f 2\n" % (self.plottime, steps_per_second/steps_per_mm))
                else:
                    self.plotfile.write("%f %f 1\n" % (self.plottime, steps_per_second/steps_per_mm))
                self.plottime += dt

            tAccel += dt

            # debnegtimer
            # if timerValue <= 0:
                # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue
                # assert(0)
            # debtimeroverflow
            if timerValue > maxTimerValue24:
                move.pprint("PlanSTeps:")
                print "v0: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue
                print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue
                assert(0)

            move.stepData.addAccelPulse(timerValue)
            stepNr += 1

            # if lastTimer:
                # assert((lastTimer - timerValue) < maxTimerValue16)
            # lastTimer = timerValue

        # Benutze als timer wert für die lineare phase den letzen timerwert der
        # beschleunigungsphase falls es diese gab. Sonst:
        # berechne timervalue ausgehend von linear feedrate:
        # if not timerValue:
            # timerValue = fTimer / steps_per_second
            # dt = 1.0 / steps_per_second
            # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue

        timerValue = fTimer / steps_per_second_nominal
        move.stepData.setLinTimer(timerValue)

        if debugPlot:
            self.plotfile.write("# Linear top:\n")
            self.plotfile.write("%f %f 0\n" % (self.plottime, steps_per_second/steps_per_mm))
            self.plottime += timerValue / fTimer

            self.plotfile.write("# Decceleration:\n")

        #
        # Compute ramp down (in reverse), decceleration
        #
        tDeccel = 1.0 / steps_per_second_nominal
        steps_per_second = steps_per_second_nominal
        steps_per_second_1 = v1 * steps_per_mm

        # lastTimer = None
        while steps_per_second > steps_per_second_1: #  and stepNr < deltaLead:

            if stepNr >= deltaLead:
                print "stepNr, deltaLead:", stepNr, deltaLead

            assert(stepNr < deltaLead)

            #
            # Compute timer value
            #
            steps_per_second = max(steps_per_second_nominal - tDeccel * accel_steps_per_square_second, steps_per_second_1)

            dt = 1.0 / steps_per_second
            timerValue = int(fTimer / steps_per_second)

            # print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue, ", v: ", steps_per_second/steps_per_mm

            if debugPlot:
                if move.eOnly:
                    self.plotfile.write("%f %f 2\n" % (self.plottime, steps_per_second/steps_per_mm))
                else:
                    self.plotfile.write("%f %f 1\n" % (self.plottime, steps_per_second/steps_per_mm))
                self.plottime += dt

            tDeccel += dt

            # debnegtimer
            # assert(timerValue > 0)
            if timerValue > maxTimerValue24:
                move.pprint("PlanSTeps:")
                print "v0: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue
                print "dt: ", dt*1000000, "[uS]", steps_per_second, "[steps/s], timerValue: ", timerValue
                assert(0)

            move.stepData.addDeccelPulse(timerValue)
            stepNr += 1

            # if lastTimer:
                # assert((timerValue - lastTimer) < maxTimerValue16)
            # lastTimer = timerValue

        if debugMoves:
            print "# of steps for move: ", deltaLead
            move.pprint("move:")
            print 

        move.stepData.checkLen(deltaLead)

        if debugMoves:
            print "***** End planSteps() *****"
示例#27
0
    def planTravelSteps(self, move):

        if debugMoves:
            print "***** Start planTravelSteps() *****"
            move.pprint("planTravelSTeps:")

        move.state = 3

        move.initStepData(StepDataTypeBresenham)

        # Round step values
        dispF = move.displacement_vector_steps_raw5
        dispS = self.stepRounders.round(dispF)

        if dispS == emptyVector5:

            if debugMoves:
                print "Empty move..."
                print "***** End planTravelSteps() *****"

            self.stepRounders.rollback()
            return

        move.isStartMove = True

        self.stepRounders.commit()

        abs_displacement_vector_steps = vectorAbs(dispS)

        # Determine the 'lead axis' - the axis with the most steps
        leadAxis = move.leadAxis(disp=dispS)
        leadAxis_steps = abs_displacement_vector_steps[leadAxis]

        dirBits = util.directionBits(dispS, self.printer.curDirBits)

        if dirBits != self.printer.curDirBits:
            move.stepData.setDirBits = True
            move.stepData.dirBits = dirBits
            self.printer.curDirBits = dirBits

        steps_per_mm = PrinterProfile.getStepsPerMM(leadAxis)

        #
        # Bresenham's variables
        #
        move.stepData.setBresenhamParameters(leadAxis,
                                             abs_displacement_vector_steps)

        #
        # Create a list of stepper pulses
        #
        nominalSpeed = abs(move.topSpeed.speed().vv()[leadAxis])  # [mm/s]

        allowedAccel = move.getMaxAllowedAccelVectorNoAdv5()[leadAxis]

        v0 = abs(move.startSpeed.speed()[leadAxis])  # [mm/s]

        nominalSpeed = abs(move.topSpeed.speed()[leadAxis])  # [mm/s]

        v1 = abs(move.endSpeed.speed()[leadAxis])  # [mm/s]

        nAccel = 0
        if move.accelTime():

            accelClocks = util.accelRamp(
                leadAxis, v0, nominalSpeed, allowedAccel,
                leadAxis_steps)  # maximum number of steps

            move.stepData.addAccelPulsees(accelClocks)

            nAccel = len(accelClocks)

        nDecel = 0
        if move.decelTime():

            decelClocks = util.decelRamp(
                leadAxis, nominalSpeed, v1, allowedAccel,
                leadAxis_steps)  # maximum number of steps

            move.stepData.addDecelPulsees(decelClocks)

            nDecel = len(decelClocks)

        #
        # Linear phase
        #
        nLin = leadAxis_steps - (nAccel + nDecel)
        # print "# linear steps:", nLin

        if nLin > 0:

            steps_per_second_nominal = nominalSpeed * steps_per_mm
            timerValue = fTimer / steps_per_second_nominal
            move.stepData.setLinTimer(timerValue)

        else:

            if nLin < 0:

                if nAccel and nDecel:

                    # Überschüssige steps im verhältnis von nAccel zu nDecel abschneiden
                    cd = int(-nLin / ((float(nAccel) / nDecel) + 1))
                    ca = -nLin - cd

                    if ca:
                        del move.stepData.accelPulses[:ca]

                    if cd:
                        del move.stepData.accelPulses[-cd:]

                    assert (len(move.stepData.accelPulses) +
                            len(move.stepData.decelPulses) == leadAxis_steps)

                elif nAccel:
                    del move.stepData.accelPulses[:-nLin]
                    assert (len(move.stepData.accelPulses) == leadAxis_steps)
                else:
                    del move.stepData.decelPulses[nLin:]
                    assert (len(move.stepData.decelPulses) == leadAxis_steps)

            move.stepData.setLinTimer(0xffff)

        # timerValue = fTimer / steps_per_second_nominal
        # move.stepData.setLinTimer(timerValue)

        if debugMoves:
            print "# of steps for move: ", leadAxis_steps
            move.pprint("move:")
            print

        move.stepData.checkLen(leadAxis_steps)

        if debugMoves:
            print "***** End planTravelSteps() *****"
示例#28
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)
示例#29
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)
示例#30
0
def home(parser, fakeHomingEndstops=False, force=False):

    planner = parser.planner
    printer = planner.printer

    print "*"
    print "* Start homing..."
    print "*"
    if printer.isHomed() and not force:
        print "Printer is homed already..."

        # Send init command
        printer.sendPrinterInit()

        # Get current pos from printer and set our virtual pos
        curPosMM = util.getVirtualPos(parser)

        (homePosMM, homePosStepped) = planner.getHomePos()

        # print "Printer should be at [mm]: ", homePosMM, ", [steps]: ", homePosStepped

        # Move to home
        if not curPosMM.equal(homePosMM, "XYZ"):

            #
            # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern
            # der buildplatte oder mit objekten auf der druckplatte zu vermeiden.
            #
            if not curPosMM.equal(homePosMM, "Z"):

                parser.execute_line("G0 F%d Z%f" % (
                    PrinterProfile.getMaxFeedrate(util.Z_AXIS)*60, homePosMM.Z))

            if not curPosMM.equal(homePosMM, "XY"):

                parser.execute_line("G0 F%d X%f Y%f" % (
                    PrinterProfile.getMaxFeedrate(util.X_AXIS)*60, 
                    homePosMM.X, homePosMM.Y))

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

            printer.waitForState(StateIdle, wait=0.05)

        #
        # Set Virtual E-pos 0:
        #
        parser.set_position(homePosMM)

        print "*"
        print "* Done homing..."
        print "*"
        return

    #
    # Z Achse isoliert und als erstes bewegen, um zusammenstoss mit den klammern
    # der buildplatte oder mit einem modell zu vermeiden.
    #
    for dim in [util.Z_AXIS, util.X_AXIS, util.Y_AXIS]:

        # Try fast home if endstop is pressed
        if printer.endStopTriggered(dim, fakeHomingEndstops):

            print "Homing: endstop %d is triggered, trying fast home." % dim
            if homeBounce(parser, dim, fakeHomingEndstops):
                continue

        # Try fast home if head/bed is near the endstop
        print "Homing: doing short/fast home."
        if homeMove(parser, dim, 1, planner.MAX_POS[dim] / 10.0, fakeHomingEndstops): # Move towards endstop fast

            print "Homing: endstop %d is triggered, trying fast home." % dim
            if homeBounce(parser, dim, fakeHomingEndstops):
                continue

        # Do the full slow homing move
        print "Homing: doing full/slow home."
        if not homeMove(parser, dim, 1, planner.MAX_POS[dim] * 1.25, fakeHomingEndstops): # Move towards endstop fast
            print "Error, Endstop %d NOT hit!" % dim
            assert(0)

        if not homeBounce(parser, dim, fakeHomingEndstops):
            print "Error, Bounce %d!" % dim
            assert(0)


    #
    # Set position in steps on the printer side and set our 'virtual position':
    #
    # xxx set end-of-print retraction e-pos also here?
    #
    # parser.set_position(planner.homePosMM)
    # payload = struct.pack("<iiiii", *planner.homePosStepped)
    (homePosMM, homePosStepped) = planner.getHomePos()
    parser.set_position(homePosMM)

    # print "Tell printer its position [steps]:", homePosStepped
    payload = struct.pack("<iiiii", *homePosStepped)
    printer.sendCommand(CmdSetHomePos, binPayload=payload)

    print "*"
    print "* Done homing..."
    print "*"
示例#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()