예제 #1
0
파일: Stepper.py 프로젝트: tomstokes/redeem
    def set_microstepping(self, value, force_update=False):
        """ Microstepping (default = 0) 0 to 5 """
        if not value in [0, 1, 2, 3, 4, 5
                         ]:  # Full, half, 1/4, 1/8, 1/16, 1/32.
            logging.warning(
                "Tried to set illegal microstepping value: {0} for stepper {1}"
                .format(value, self.name))
            return
        self.microsteps = 2**value  # 2^val
        if Stepper.revision in ["A4", "A4A"]:
            # Keep bit 4, 5, 6, 7 intact but replace and reverse bit 1, 2, 3
            self.state = int(
                "0b" + bin(self.state)[2:].rjust(8, '0')[:4] +
                bin(value)[2:].rjust(3, '0')[::-1] + "0", 2)
        else:
            # Keep bit 0, 4, 5, 6 intact but replace bit 1, 2, 3
            self.state = int(
                "0b" + bin(self.state)[2:].rjust(8, '0')[:4] +
                bin(value)[2:].rjust(3, '0') + bin(self.state)[-1:], 2)
            #self.state = int("0b"+bin(self.state)[2:].rjust(8, '0')[:4]+bin(value)[2:].rjust(3, '0')+"0", 2)
        self.mmPrStep = 1.0 / (self.steps_pr_mm * self.microsteps)
        #logging.debug("Updated stepper "+self.name+" to microstepping "+str(self.microsteps))

        # update the Path class with new values
        stepper_num = Path.axis_to_index(self.name)
        Path.steps_pr_meter[stepper_num] = self.get_steps_pr_meter()

        if force_update:
            self.update()
예제 #2
0
    def _home_internal(self, axis):
        """ Private method for homing a set or a single axis """
        logging.debug("homing " + str(axis))

        path_back = {}
        path_center = {}
        path_zero = {}

        speed = Path.home_speed[0]

        for a in axis:
            if not self.printer.steppers[a].has_endstop:
                logging.debug("Skipping homing for " + str(a))
                continue

            path_back[a] = -self.travel_length[a]
            path_center[a] = -self.center_offset[a]
            path_zero[a] = 0
            speed = min(speed, Path.home_speed[Path.axis_to_index(a)])

            # Move until endstop is hit
        p = RelativePath(path_back, speed, True)

        self.add_path(p)

        # Reset position to offset
        p = G92Path(path_center, speed)
        self.add_path(p)

        # Move to offset
        p = AbsolutePath(path_zero, speed)
        self.add_path(p)
        self.wait_until_done()
        logging.debug("homing done for " + str(axis))
예제 #3
0
    def _go_to_home(self, axis):
        """
        go to the designated home position
        do this as a separate call from _home_internal due to delta platforms 
        performing home in cartesian mode
        """
        
        path_home = {}
        
        speed = Path.home_speed[0]
        accel = self.printer.acceleration[0]

        for a in axis:
            path_home[a] = self.home_pos[a]
            speed = min(abs(speed), abs(Path.home_speed[Path.axis_to_index(a)]))
            
        logging.debug("Home: %s" % path_home)
            
        # Move to home position
        p = AbsolutePath(path_home, speed, accel, True, False, False, False)
        self.add_path(p)
        self.wait_until_done()
        
        # Due to rounding errors, we explicitly set the found 
        # position to the right value. 
        # Reset (final) position to offset
        p = G92Path(path_home, speed)
        self.add_path(p)

        return
예제 #4
0
    def _home_internal(self, axis):
        """ Private method for homing a set or a single axis """
        logging.debug("homing " + str(axis))

        path_back = {}
        path_center = {}
        path_zero = {}

        speed = Path.home_speed[0]

        for a in axis:
            if not self.printer.steppers[a].has_endstop:
                logging.debug("Skipping homing for " + str(a))
                continue

            path_back[a] = -self.travel_length[a]
            path_center[a] = -self.center_offset[a]
            path_zero[a] = 0
            speed = min(speed, Path.home_speed[Path.axis_to_index(a)])

            # Move until endstop is hit
        p = RelativePath(path_back, speed, True)

        self.add_path(p)

        # Reset position to offset
        p = G92Path(path_center, speed)
        self.add_path(p)

        # Move to offset
        p = AbsolutePath(path_zero, speed)
        self.add_path(p)
        self.wait_until_done()
        logging.debug("homing done for " + str(axis))
예제 #5
0
    def set_microstepping(self, value, force_update=False):
        """ Todo: Find an elegant way for this """
        EN_CFG1 = (1 << 7)
        DIS_CFG1 = (0 << 7)
        EN_CFG2 = (1 << 5)
        DIS_CFG2 = (0 << 5)
        CFG2_H = (1 << 4)
        CFG2_L = (0 << 4)
        CFG1_H = (1 << 6)
        CFG1_L = (0 << 6)

        if value == 0:  # GND, GND
            state = EN_CFG2 | CFG2_L | EN_CFG1 | CFG1_L
            self.microsteps = 1
        elif value == 1:  # GND, VCC
            state = EN_CFG2 | CFG2_L | EN_CFG1 | CFG1_H
            self.microsteps = 2
        elif value == 2:  # GND, open
            state = EN_CFG2 | CFG2_L | DIS_CFG1 | CFG1_L
            self.microsteps = 2
        elif value == 3:  # VCC, GND
            state = EN_CFG2 | CFG2_H | EN_CFG1 | CFG1_L
            self.microsteps = 4
        elif value == 4:  # VCC, VCC
            state = EN_CFG2 | CFG2_H | EN_CFG1 | CFG1_H
            self.microsteps = 16
        elif value == 5:  # VCC, open
            state = EN_CFG2 | CFG2_H | DIS_CFG1 | CFG1_L
            self.microsteps = 4
        elif value == 6:  # open, GND
            state = DIS_CFG2 | CFG2_L | EN_CFG1 | CFG1_L
            self.microsteps = 16
        elif value == 7:  # open, VCC
            state = DIS_CFG2 | CFG2_L | EN_CFG1 | CFG1_H
            self.microsteps = 4
        elif value == 8:  # open, open
            state = DIS_CFG2 | CFG2_L | DIS_CFG1 | CFG1_L
            self.microsteps = 16

        self.shift_reg.set_state(state, 0xF0)
        self.mmPrStep = 1.0 / (self.steps_pr_mm * self.microsteps)

        # update the Path class with new values
        stepper_num = Path.axis_to_index(self.name)
        Path.steps_pr_meter[stepper_num] = self.get_steps_pr_meter()
        logging.debug("Updated stepper " + self.name + " to microstepping " +
                      str(value) + " = " + str(self.microsteps))
        self.microstepping = value
예제 #6
0
파일: Stepper.py 프로젝트: quillford/redeem
    def set_microstepping(self, value, force_update=False):        
        """ Microstepping (default = 0) 0 to 5 """        
        if not value in [0, 1, 2, 3, 4, 5]: # Full, half, 1/4, 1/8, 1/16, 1/32.
            logging.warning("Tried to set illegal microstepping value: {0} for stepper {1}".format(value, self.name))
            return
        self.microstepping = value
        self.microsteps  = 2**value     # 2^val
        # Keep bit 0, 4, 5, 6 intact but replace bit 1, 2, 3
        self.state = int("0b"+bin(self.state)[2:].rjust(8, '0')[:4]+bin(value)[2:].rjust(3, '0')[::-1]+"0", 2)
        #self.state = int("0b"+bin(self.state)[2:].rjust(8, '0')[:4]+bin(value)[2:].rjust(3, '0')+bin(self.state)[-1:], 2)
        self.mmPrStep    = 1.0/(self.steps_pr_mm*self.microsteps)

        # update the Path class with new values
        stepper_num = Path.axis_to_index(self.name)
        Path.steps_pr_meter[stepper_num] = self.get_steps_pr_meter()
        self.update()
예제 #7
0
파일: Stepper.py 프로젝트: Sciumo/redeem
    def set_microstepping(self, value, force_update=False):                
        """ Todo: Find an elegant way for this """
        EN_CFG1  = (1<<7)
        DIS_CFG1 = (0<<7)
        EN_CFG2  = (1<<5)
        DIS_CFG2 = (0<<5)
        CFG2_H   = (1<<4)
        CFG2_L   = (0<<4)
        CFG1_H   = (1<<6)
        CFG1_L   = (0<<6)

        if   value == 0:   # GND, GND
            state = EN_CFG2 | CFG2_L | EN_CFG1 | CFG1_L
            self.microsteps = 1
        elif value == 1: # GND, VCC
            state = EN_CFG2 | CFG2_L | EN_CFG1 | CFG1_H
            self.microsteps = 2
        elif value == 2: # GND, open
            state = EN_CFG2 | CFG2_L | DIS_CFG1 | CFG1_L
            self.microsteps = 2
        elif value == 3: # VCC, GND
            state = EN_CFG2 | CFG2_H | EN_CFG1 | CFG1_L
            self.microsteps = 4
        elif value == 4: # VCC, VCC
            state = EN_CFG2 | CFG2_H | EN_CFG1 | CFG1_H
            self.microsteps = 16
        elif value == 5: # VCC, open
            state = EN_CFG2 | CFG2_H | DIS_CFG1 | CFG1_L
            self.microsteps = 4
        elif value == 6: # open, GND
            state = DIS_CFG2 | CFG2_L | EN_CFG1 | CFG1_L
            self.microsteps = 16
        elif value == 7: # open, VCC
            state = DIS_CFG2 | CFG2_L | EN_CFG1 | CFG1_H
            self.microsteps = 4
        elif value == 8: # open, open
            state = DIS_CFG2 | CFG2_L | DIS_CFG1 | CFG1_L
            self.microsteps = 16

        self.shift_reg.set_state(state,0xF0)
        self.mmPrStep    = 1.0/(self.steps_pr_mm*self.microsteps)

        # update the Path class with new values
        stepper_num = Path.axis_to_index(self.name)
        Path.steps_pr_meter[stepper_num] = self.get_steps_pr_meter()
        logging.debug("Updated stepper "+self.name+" to microstepping "+str(value)+" = "+str(self.microsteps))   
        self.microstepping = value
예제 #8
0
파일: M201.py 프로젝트: tomstokes/redeem
    def execute(self, g):

        t = self.printer.acceleration[:];
      
        for i in range(g.num_tokens()):
            axis = Path.axis_to_index(g.token_letter(i))
            t[axis] = float(g.token_value(i)) / 3600.0

        if Path.axis_config == Path.AXIS_CONFIG_CORE_XY or Path.axis_config == Path.AXIS_CONFIG_H_BELT:
	    # x and y should have same accelerations for lines to be straight
	    t[1] = t[0]	
        elif Path.axis_config == Path.AXIS_CONFIG_DELTA:
	    # Delta should have same accelerations on all axis
	    t[1] = t[0]
	    t[2] = t[0]
	# setup 3d movement accel
        self.set_acceleration(tuple(t[:3]))
        # Setup the extruder accel
        for i in range(Path.NUM_AXES - 3):
            e = self.printer.path_planner.native_planner.getExtruder(i)
            self.set_extruder_acceleration(e,t[i + 3])
예제 #9
0
파일: M201.py 프로젝트: tomstokes/redeem
    def execute(self, g):

        t = self.printer.acceleration[:]

        for i in range(g.num_tokens()):
            axis = Path.axis_to_index(g.token_letter(i))
            t[axis] = float(g.token_value(i)) / 3600.0

        if Path.axis_config == Path.AXIS_CONFIG_CORE_XY or Path.axis_config == Path.AXIS_CONFIG_H_BELT:
            # x and y should have same accelerations for lines to be straight
            t[1] = t[0]
        elif Path.axis_config == Path.AXIS_CONFIG_DELTA:
            # Delta should have same accelerations on all axis
            t[1] = t[0]
            t[2] = t[0]

# setup 3d movement accel
        self.set_acceleration(tuple(t[:3]))
        # Setup the extruder accel
        for i in range(Path.NUM_AXES - 3):
            e = self.printer.path_planner.native_planner.getExtruder(i)
            self.set_extruder_acceleration(e, t[i + 3])
예제 #10
0
    def _go_to_home(self, axis):
        """
        go to the designated home position
        do this as a separate call from _home_internal due to delta platforms 
        performing home in cartesian mode
        """
        
        path_home = {}
        
        speed = Path.home_speed[0]

        for a in axis:
            path_home[a] = self.home_pos[a]
            speed = min(abs(speed), abs(Path.home_speed[Path.axis_to_index(a)]))
            
        logging.debug("Home: %s" % path_home)
            
        # Move to home position
        p = AbsolutePath(path_home, speed, True, False, False, False)
        self.add_path(p)
        self.wait_until_done()
        
        return
예제 #11
0
    def _go_to_home(self, axis):
        """
        go to the designated home position
        do this as a separate call from _home_internal due to delta platforms
        performing home in cartesian mode
        """

        path_home = {}

        speed = Path.home_speed[0]

        for a in axis:
            path_home[a] = self.home_pos[a]
            speed = min(abs(speed),
                        abs(Path.home_speed[Path.axis_to_index(a)]))

        logging.debug("Home: %s" % path_home)

        # Move to home position
        # p = AbsolutePath(path_home, speed, True, False, False, False)
        # self.add_path(p)
        # self.wait_until_done()

        return
예제 #12
0
파일: Redeem.py 프로젝트: Sciumo/redeem
    def __init__(self):
        firmware_version = "1.1.8~Raw Deal"
        logging.info("Redeem initializing "+firmware_version)

        printer = Printer()
        self.printer = printer
        Path.printer = printer

        printer.firmware_version = firmware_version

        # check for config files
        if not os.path.exists("/etc/redeem/default.cfg"):
            logging.error("/etc/redeem/default.cfg does not exist, this file is required for operation")
            sys.exit() # maybe use something more graceful?
            
        if not os.path.exists("/etc/redeem/local.cfg"):
            logging.info("/etc/redeem/local.cfg does not exist, Creating one")
            os.mknod("/etc/redeem/local.cfg")
    
        # Parse the config files.
        printer.config = CascadingConfigParser(
            ['/etc/redeem/default.cfg', '/etc/redeem/printer.cfg',
             '/etc/redeem/local.cfg'])

        # Get the revision and loglevel from the Config file
        level = self.printer.config.getint('System', 'loglevel')
        if level > 0:
            logging.getLogger().setLevel(level)

        # Set up additional logging, if present:        
        if self.printer.config.getboolean('System', 'log_to_file'):
            logfile = self.printer.config.get('System', 'logfile')
            formatter = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
            printer.redeem_logging_handler = logging.handlers.RotatingFileHandler(logfile, maxBytes=2*1024*1024)
            printer.redeem_logging_handler.setFormatter(logging.Formatter(formatter))
            printer.redeem_logging_handler.setLevel(level)
            logging.getLogger().addHandler(printer.redeem_logging_handler)
            logging.info("-- Logfile configured --")

        # Find out which capes are connected
        self.printer.config.parse_capes()
        self.revision = self.printer.config.replicape_revision
        if self.revision:
            logging.info("Found Replicape rev. " + self.revision)
        else:
            logging.warning("Oh no! No Replicape present!")
            self.revision = "00B3"
        # We set it to 5 axis by default
        Path.NUM_AXES = 5
        if self.printer.config.reach_revision:
            logging.info("Found Reach rev. "+self.printer.config.reach_revision)
        if self.printer.config.reach_revision == "00A0":
            Path.NUM_AXES = 8
        elif self.printer.config.reach_revision == "00B0":
            Path.NUM_AXES = 7

        if self.revision in ["00A4", "0A4A", "00A3"]:
            PWM.set_frequency(100)
        elif self.revision in ["00B1", "00B2", "00B3"]:
            PWM.set_frequency(1000)

        # Test the alarm framework
        Alarm.printer = self.printer
        Alarm.executor = AlarmExecutor()
        alarm = Alarm(Alarm.ALARM_TEST, "Alarm framework operational")

        # Init the Watchdog timer
        printer.watchdog = Watchdog()

        # Enable PWM and steppers
        printer.enable = Enable("P9_41")
        printer.enable.set_disabled()

        # Init the Paths
        Path.axis_config = printer.config.getint('Geometry', 'axis_config')

        # Init the end stops
        EndStop.inputdev = self.printer.config.get("Endstops", "inputdev")
        # Set up key listener
        Key_pin.listener = Key_pin_listener(EndStop.inputdev)
        
        for es in ["Z2", "Y2", "X2", "Z1", "Y1", "X1"]: # Order matches end stop inversion mask in Firmware
            pin = self.printer.config.get("Endstops", "pin_"+es)
            keycode = self.printer.config.getint("Endstops", "keycode_"+es)
            invert = self.printer.config.getboolean("Endstops", "invert_"+es)
            self.printer.end_stops[es] = EndStop(printer, pin, keycode, es, invert)
            self.printer.end_stops[es].stops = self.printer.config.get('Endstops', 'end_stop_'+es+'_stops')

        # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
        if self.revision == "00A3":
            printer.steppers["X"] = Stepper_00A3("GPIO0_27", "GPIO1_29", "GPIO2_4" , 0, "X")
            printer.steppers["Y"] = Stepper_00A3("GPIO1_12", "GPIO0_22", "GPIO2_5" , 1, "Y")
            printer.steppers["Z"] = Stepper_00A3("GPIO0_23", "GPIO0_26", "GPIO0_15", 2, "Z")
            printer.steppers["E"] = Stepper_00A3("GPIO1_28", "GPIO1_15", "GPIO2_1" , 3, "E")
            printer.steppers["H"] = Stepper_00A3("GPIO1_13", "GPIO1_14", "GPIO2_3" , 4, "H")
        elif self.revision == "00B1":
            printer.steppers["X"] = Stepper_00B1("GPIO0_27", "GPIO1_29", "GPIO2_4" , 11, 0, "X")
            printer.steppers["Y"] = Stepper_00B1("GPIO1_12", "GPIO0_22", "GPIO2_5" , 12, 1, "Y")
            printer.steppers["Z"] = Stepper_00B1("GPIO0_23", "GPIO0_26", "GPIO0_15", 13, 2, "Z")
            printer.steppers["E"] = Stepper_00B1("GPIO1_28", "GPIO1_15", "GPIO2_1" , 14, 3, "E")
            printer.steppers["H"] = Stepper_00B1("GPIO1_13", "GPIO1_14", "GPIO2_3" , 15, 4, "H")
        elif self.revision == "00B2":
            printer.steppers["X"] = Stepper_00B2("GPIO0_27", "GPIO1_29", "GPIO2_4" , 11, 0, "X")
            printer.steppers["Y"] = Stepper_00B2("GPIO1_12", "GPIO0_22", "GPIO2_5" , 12, 1, "Y")
            printer.steppers["Z"] = Stepper_00B2("GPIO0_23", "GPIO0_26", "GPIO0_15", 13, 2, "Z")
            printer.steppers["E"] = Stepper_00B2("GPIO1_28", "GPIO1_15", "GPIO2_1" , 14, 3, "E")
            printer.steppers["H"] = Stepper_00B2("GPIO1_13", "GPIO1_14", "GPIO2_3" , 15, 4, "H")
        elif self.revision == "00B3":
            printer.steppers["X"] = Stepper_00B3("GPIO0_27", "GPIO1_29", 90, 11, 0, "X")
            printer.steppers["Y"] = Stepper_00B3("GPIO1_12", "GPIO0_22", 91, 12, 1, "Y")
            printer.steppers["Z"] = Stepper_00B3("GPIO0_23", "GPIO0_26", 92, 13, 2, "Z")
            printer.steppers["E"] = Stepper_00B3("GPIO1_28", "GPIO1_15", 93, 14, 3, "E")
            printer.steppers["H"] = Stepper_00B3("GPIO1_13", "GPIO1_14", 94, 15, 4, "H")
        elif self.revision in ["00A4", "0A4A"]:
            printer.steppers["X"] = Stepper_00A4("GPIO0_27", "GPIO1_29", "GPIO2_4" , 0, 0, "X")
            printer.steppers["Y"] = Stepper_00A4("GPIO1_12", "GPIO0_22", "GPIO2_5" , 1, 1, "Y")
            printer.steppers["Z"] = Stepper_00A4("GPIO0_23", "GPIO0_26", "GPIO0_15", 2, 2, "Z")
            printer.steppers["E"] = Stepper_00A4("GPIO1_28", "GPIO1_15", "GPIO2_1" , 3, 3, "E")
            printer.steppers["H"] = Stepper_00A4("GPIO1_13", "GPIO1_14", "GPIO2_3" , 4, 4, "H")
        # Init Reach steppers, if present. 
        if printer.config.reach_revision == "00A0":
            printer.steppers["A"] = Stepper_reach_00A4("GPIO2_2" , "GPIO1_18", "GPIO0_14", 5, 5, "A")
            printer.steppers["B"] = Stepper_reach_00A4("GPIO1_16", "GPIO0_5" , "GPIO0_14", 6, 6, "B")
            printer.steppers["C"] = Stepper_reach_00A4("GPIO0_3" , "GPIO3_19", "GPIO0_14", 7, 7, "C")
        elif printer.config.reach_revision == "00B0":
            printer.steppers["A"] = Stepper_reach_00B0("GPIO1_16", "GPIO0_5",  "GPIO0_3", 5, 5, "A")
            printer.steppers["B"] = Stepper_reach_00B0("GPIO2_2" , "GPIO0_14", "GPIO0_3", 6, 6, "B")


        # Enable the steppers and set the current, steps pr mm and
        # microstepping
        for name, stepper in self.printer.steppers.iteritems():
            stepper.in_use = printer.config.getboolean('Steppers', 'in_use_' + name)
            stepper.direction = printer.config.getint('Steppers', 'direction_' + name)
            stepper.has_endstop = printer.config.getboolean('Endstops', 'has_' + name)
            stepper.set_current_value(printer.config.getfloat('Steppers', 'current_' + name))
            stepper.set_steps_pr_mm(printer.config.getfloat('Steppers', 'steps_pr_mm_' + name))
            stepper.set_microstepping(printer.config.getint('Steppers', 'microstepping_' + name))
            stepper.set_decay(printer.config.getint("Steppers", "slow_decay_" + name))
            # Add soft end stops
            Path.soft_min[Path.axis_to_index(name)] = printer.config.getfloat('Endstops', 'soft_end_stop_min_' + name)
            Path.soft_max[Path.axis_to_index(name)] = printer.config.getfloat('Endstops', 'soft_end_stop_max_' + name)
            slave = printer.config.get('Steppers', 'slave_' + name)
            if slave:
                Path.add_slave(name, slave)
                logging.debug("Axis "+name+" has slave "+slave)

        # Commit changes for the Steppers
        #Stepper.commit()

        Stepper.printer = printer

        # Delta printer setup
        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            opts = ["Hez", "L", "r", "Ae", "Be", "Ce", "A_radial", "B_radial", "C_radial", "A_tangential", "B_tangential", "C_tangential" ]
            for opt in opts:
                Delta.__dict__[opt] = printer.config.getfloat('Delta', opt)

            Delta.recalculate()

        # Discover and add all DS18B20 cold ends.
        import glob
        paths = glob.glob("/sys/bus/w1/devices/28-*/w1_slave")
        logging.debug("Found cold ends: "+str(paths))
        for i, path in enumerate(paths):
            self.printer.cold_ends.append(ColdEnd(path, "ds18b20-"+str(i)))
            logging.info("Found Cold end "+str(i)+" on " + path)

        # Make Mosfets, thermistors and extruders
        heaters = ["E", "H", "HBP"]
        if self.printer.config.reach_revision:
            heaters.extend(["A", "B", "C"])
        for e in heaters:
            # Mosfets
            channel = self.printer.config.getint("Heaters", "mosfet_"+e)
            self.printer.mosfets[e] = Mosfet(channel)
            # Thermistors
            adc = self.printer.config.get("Heaters", "path_adc_"+e)
            chart = self.printer.config.get("Heaters", "temp_chart_"+e)
            resistance = self.printer.config.getfloat("Heaters", "resistance_"+e)
            self.printer.thermistors[e] = Thermistor(adc, "MOSFET "+e, chart, resistance)
            self.printer.thermistors[e].printer = printer

            # Extruders
            onoff = self.printer.config.getboolean('Heaters', 'onoff_'+e)
            prefix =  self.printer.config.get('Heaters', 'prefix_'+e)
            if e != "HBP":
                self.printer.heaters[e] = Extruder(
                                        self.printer.steppers[e],
                                        self.printer.thermistors[e], 
                                        self.printer.mosfets[e], e, onoff)
            else:
                self.printer.heaters[e] = HBP(
                                        self.printer.thermistors[e],
                                        self.printer.mosfets[e], onoff)
            self.printer.heaters[e].prefix = prefix
            self.printer.heaters[e].P = self.printer.config.getfloat('Heaters', 'pid_p_'+e)
            self.printer.heaters[e].I = self.printer.config.getfloat('Heaters', 'pid_i_'+e)
            self.printer.heaters[e].D = self.printer.config.getfloat('Heaters', 'pid_d_'+e)

            # Min/max settings
            self.printer.heaters[e].min_temp        = self.printer.config.getfloat('Heaters', 'min_temp_'+e)
            self.printer.heaters[e].max_temp        = self.printer.config.getfloat('Heaters', 'max_temp_'+e)
            self.printer.heaters[e].max_temp_rise   = self.printer.config.getfloat('Heaters', 'max_rise_temp_'+e)
            self.printer.heaters[e].max_temp_fall   = self.printer.config.getfloat('Heaters', 'max_fall_temp_'+e)

        # Init the three fans. Argument is PWM channel number
        self.printer.fans = []
        if self.revision == "00A3":
            self.printer.fans.append(Fan(0))
            self.printer.fans.append(Fan(1))
            self.printer.fans.append(Fan(2))
        elif self.revision == "0A4A":
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))
        elif self.revision in ["00B1", "00B2", "00B3"]:
            self.printer.fans.append(Fan(7))
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))
        if printer.config.reach_revision == "00A0":
            self.printer.fans.append(Fan(14))
            self.printer.fans.append(Fan(15))
            self.printer.fans.append(Fan(7))

        # Disable all fans
        for f in self.printer.fans:
            f.set_value(0)

        # Init the servos
        printer.servos = []
        servo_nr = 0
        while(printer.config.has_option("Servos", "servo_"+str(servo_nr)+"_enable")):
            if printer.config.getboolean("Servos", "servo_"+str(servo_nr)+"_enable"):
                channel = printer.config.get("Servos", "servo_"+str(servo_nr)+"_channel")
                pulse_min = printer.config.getfloat("Servos", "servo_"+str(servo_nr)+"_pulse_min")
                pulse_max = printer.config.getfloat("Servos", "servo_"+str(servo_nr)+"_pulse_max")
                angle_min = printer.config.getfloat("Servos", "servo_"+str(servo_nr)+"_angle_min")
                angle_max = printer.config.getfloat("Servos", "servo_"+str(servo_nr)+"_angle_max")
                angle_init = printer.config.getfloat("Servos", "servo_"+str(servo_nr)+"_angle_init")
                s = Servo(channel, pulse_min, pulse_max, angle_min, angle_max, angle_init)
                printer.servos.append(s)
                logging.info("Added servo "+str(servo_nr))
            servo_nr += 1

        # Connect thermitors to fans
        for t, therm in self.printer.heaters.iteritems():
            for f, fan in enumerate(self.printer.fans):
                if not self.printer.config.has_option('Cold-ends', "connect-therm-{}-fan-{}".format(t, f)):
                    continue
                if printer.config.getboolean('Cold-ends', "connect-therm-{}-fan-{}".format(t, f)):
                    c = Cooler(therm, fan, "Cooler-{}-{}".format(t, f), True) # Use ON/OFF on these. 
                    c.ok_range = 4
                    opt_temp = "therm-{}-fan-{}-target_temp".format(t, f)
                    if printer.config.has_option('Cold-ends', opt_temp): 
                        target_temp = printer.config.getfloat('Cold-ends', opt_temp)
                    else:            
                        target_temp = 60    
                    c.set_target_temperature(target_temp)
                    c.enable()
                    printer.coolers.append(c)
                    logging.info("Cooler connects therm {} with fan {}".format(t, f))

        # Connect fans to M106
        printer.controlled_fans = []
        for i, fan in enumerate(self.printer.fans):
            if not self.printer.config.has_option('Cold-ends', "add-fan-{}-to-M106".format(i)):
                continue
            if self.printer.config.getboolean('Cold-ends', "add-fan-{}-to-M106".format(i)):
                printer.controlled_fans.append(self.printer.fans[i])
                logging.info("Added fan {} to M106/M107".format(i))

        # Connect the colds to fans
        for ce, cold_end in enumerate(self.printer.cold_ends):
            for f, fan in enumerate(self.printer.fans):
                option = "connect-ds18b20-{}-fan-{}".format(ce, f)
                if self.printer.config.has_option('Cold-ends', option):
                    if self.printer.config.getboolean('Cold-ends', option):
                        c = Cooler(cold_end, fan, "Cooler-ds18b20-{}-{}".format(ce, f), False)
                        c.ok_range = 4
                        opt_temp = "cooler_{}_target_temp".format(ce)
                        if printer.config.has_option('Cold-ends', opt_temp): 
                            target_temp = printer.config.getfloat('Cold-ends', opt_temp)
                        else:            
                            target_temp = 60    
                        c.set_target_temperature(target_temp)
                        c.enable()
                        printer.coolers.append(c)
                        logging.info("Cooler connects temp sensor ds18b20 {} with fan {}".format(ce, f))

        # Init roatray encs. 
        printer.filament_sensors = []

        # Init rotary encoders
        printer.rotary_encoders = []
        for ex in ["E", "H", "A", "B", "C"]:
            if not printer.config.has_option('Rotary-encoders', "enable-{}".format(ex)):
                continue
            if printer.config.getboolean("Rotary-encoders", "enable-{}".format(ex)):
                logging.debug("Rotary encoder {} enabled".format(ex))
                event = printer.config.get("Rotary-encoders", "event-{}".format(ex))
                cpr = printer.config.getint("Rotary-encoders", "cpr-{}".format(ex))
                diameter = printer.config.getfloat("Rotary-encoders", "diameter-{}".format(ex))
                r = RotaryEncoder(event, cpr, diameter)
                printer.rotary_encoders.append(r)
                # Append as Filament Sensor
                ext_nr = Path.axis_to_index(ex)-3
                sensor = FilamentSensor(ex, r, ext_nr, printer)
                alarm_level = printer.config.getfloat("Filament-sensors", "alarm-level-{}".format(ex))
                logging.debug("Alarm level"+str(alarm_level))
                sensor.alarm_level = alarm_level
                printer.filament_sensors.append(sensor)
    
        # Make a queue of commands
        self.printer.commands = JoinableQueue(10)

        # Make a queue of commands that should not be buffered
        self.printer.sync_commands = JoinableQueue()
        self.printer.unbuffered_commands = JoinableQueue(10)

        # Bed compensation matrix
        Path.matrix_bed_comp = printer.load_bed_compensation_matrix()
        Path.matrix_bed_comp_inv = np.linalg.inv(Path.matrix_bed_comp)
        logging.debug("Loaded bed compensation matrix: \n"+str(Path.matrix_bed_comp))

        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)
            Path.max_speeds[i] = printer.config.getfloat('Planner', 'max_speed_'+axis.lower())
            Path.min_speeds[i] = printer.config.getfloat('Planner', 'min_speed_'+axis.lower())
            Path.jerks[i] = printer.config.getfloat('Planner', 'max_jerk_'+axis.lower())
            Path.home_speed[i] = printer.config.getfloat('Homing', 'home_speed_'+axis.lower())
            Path.home_backoff_speed[i] = printer.config.getfloat('Homing', 'home_backoff_speed_'+axis.lower())
            Path.home_backoff_offset[i] = printer.config.getfloat('Homing', 'home_backoff_offset_'+axis.lower())
            Path.steps_pr_meter[i] = printer.steppers[axis].get_steps_pr_meter()
            Path.backlash_compensation[i] = printer.config.getfloat('Steppers', 'backlash_'+axis.lower())

        dirname = os.path.dirname(os.path.realpath(__file__))

        # Create the firmware compiler
        pru_firmware = PruFirmware(
            dirname + "/firmware/firmware_runtime.p",
            dirname + "/firmware/firmware_runtime.bin",
            dirname + "/firmware/firmware_endstops.p",
            dirname + "/firmware/firmware_endstops.bin",
            self.printer, "/usr/bin/pasm")

        
        printer.move_cache_size = printer.config.getfloat('Planner', 'move_cache_size')
        printer.print_move_buffer_wait = printer.config.getfloat('Planner', 'print_move_buffer_wait')
        printer.min_buffered_move_time = printer.config.getfloat('Planner', 'min_buffered_move_time')
        printer.max_buffered_move_time = printer.config.getfloat('Planner', 'max_buffered_move_time')

        self.printer.processor = GCodeProcessor(self.printer)
        self.printer.plugins = PluginsController(self.printer)

        # Path planner
        travel_default = False
        center_default = False
        home_default = False

        # Setting acceleration before PathPlanner init
        for axis in printer.steppers.keys():
            Path.acceleration[Path.axis_to_index(axis)] = printer.config.getfloat(
                                                        'Planner', 'acceleration_' + axis.lower())

        self.printer.path_planner = PathPlanner(self.printer, pru_firmware)
        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)
            
            # Sometimes soft_end_stop aren't defined to be at the exact hardware boundary.
            # Adding 100mm for searching buffer.
            if printer.config.has_option('Geometry', 'travel_' + axis.lower()):
                printer.path_planner.travel_length[axis] = printer.config.getfloat('Geometry', 'travel_' + axis.lower())
            else:
                printer.path_planner.travel_length[axis] = (Path.soft_max[i] - Path.soft_min[i]) + .1
                if axis in ['X','Y','Z']:                
                    travel_default = True
            
            if printer.config.has_option('Geometry', 'offset_' + axis.lower()):
                printer.path_planner.center_offset[axis] = printer.config.getfloat('Geometry', 'offset_' + axis.lower())
            else:
                printer.path_planner.center_offset[axis] =(Path.soft_min[i] if Path.home_speed[i] > 0 else Path.soft_max[i])
                if axis in ['X','Y','Z']:                
                    center_default = True

            if printer.config.has_option('Homing', 'home_' + axis.lower()):
                printer.path_planner.home_pos[axis] = printer.config.getfloat('Homing', 'home_' + axis.lower())
            else:
                printer.path_planner.home_pos[axis] = printer.path_planner.center_offset[axis]
                if axis in ['X','Y','Z']:                   
                    home_default = True
                
        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            if travel_default:
                logging.warning("Axis travel (travel_*) set by soft limits, manual setup is recommended for a delta")
            if center_default:
                logging.warning("Axis offsets (offset_*) set by soft limits, manual setup is recommended for a delta")
            if home_default:
                logging.warning("Home position (home_*) set by soft limits or offset_*")
                logging.info("Home position will be recalculated...")
        
                # convert home_pos to effector space
                Az = printer.path_planner.home_pos['X']
                Bz = printer.path_planner.home_pos['Y']
                Cz = printer.path_planner.home_pos['Z']
                
                z_offset = Delta.vertical_offset(Az,Bz,Cz) # vertical offset
                xyz = Delta.forward_kinematics2(Az, Bz, Cz) # effector position
                
                # The default home_pos, provided above, is based on effector space 
                # coordinates for carriage positions. We need to transform these to 
                # get where the effector actually is.
                xyz[2] += z_offset
                for i, a in enumerate(['X','Y','Z']):
                    printer.path_planner.home_pos[a] = xyz[i]
                
                logging.info("Home position = %s"%str(printer.path_planner.home_pos))

        # Enable Stepper timeout
        timeout = printer.config.getint('Steppers', 'timeout_seconds')
        printer.swd = StepperWatchdog(printer, timeout)
        if printer.config.getboolean('Steppers', 'use_timeout'):
            printer.swd.start()

        # Set up communication channels
        printer.comms["USB"] = USB(self.printer)
        printer.comms["Eth"] = Ethernet(self.printer)

        if Pipe.check_tty0tty() or Pipe.check_socat():
            printer.comms["octoprint"] = Pipe(printer, "octoprint")
            printer.comms["toggle"] = Pipe(printer, "toggle")
            printer.comms["testing"] = Pipe(printer, "testing")
            printer.comms["testing_noret"] = Pipe(printer, "testing_noret")
            # Does not send "ok"
            printer.comms["testing_noret"].send_response = False
        else:
            logging.warning("Neither tty0tty or socat is installed! No virtual tty pipes enabled")
예제 #13
0
    def _home_internal(self, axis):
        """ Private method for homing a set or a single axis """
        logging.debug("homing internal " + str(axis))
            

        path_search = {}
        path_backoff = {}
        path_fine_search = {}

        path_center = {}
        path_zero = {}

        speed = Path.home_speed[0]

        for a in axis:
            if not self.printer.steppers[a].has_endstop:
                logging.debug("Skipping homing for " + str(a))
                continue
            logging.debug("Doing homing for " + str(a))
            if Path.home_speed[Path.axis_to_index(a)] < 0:
                # Search to positive ends
                path_search[a] = self.travel_length[a]
                path_center[a] = self.center_offset[a]
            else:
                # Search to negative ends
                path_search[a] = -self.travel_length[a]
                path_center[a] = -self.center_offset[a]

            backoff_length = -np.sign(path_search[a]) * Path.home_backoff_offset[Path.axis_to_index(a)]
            path_backoff[a] = backoff_length;
            path_fine_search[a] = -backoff_length * 1.2;
            
            speed = min(abs(speed), abs(Path.home_speed[Path.axis_to_index(a)]))
            fine_search_speed =  min(abs(speed), abs(Path.home_backoff_speed[Path.axis_to_index(a)]))
            
            logging.debug("axis: "+str(a))
        
        logging.debug("Search: %s" % path_search)
        logging.debug("Backoff to: %s" % path_backoff)
        logging.debug("Fine search: %s" % path_fine_search)
        logging.debug("Center: %s" % path_center)

        # Move until endstop is hit
        p = RelativePath(path_search, speed, True, False, True, False)
        self.add_path(p)
        self.wait_until_done()

        # Reset position to offset
        p = G92Path(path_center, speed)
        self.add_path(p)
        self.wait_until_done()

        # Back off a bit
        p = RelativePath(path_backoff, speed, True, False, True, False)
        self.add_path(p)

        # Hit the endstop slowly
        p = RelativePath(path_fine_search, fine_search_speed, True, False, True, False)
        self.add_path(p)
        self.wait_until_done()

        # Reset (final) position to offset
        p = G92Path(path_center, speed)
        self.add_path(p)

        return path_center, speed
예제 #14
0
파일: Redeem.py 프로젝트: quillford/redeem
    def __init__(self):
        """ Init """
        logging.info("Redeem initializing " + version)

        printer = Printer()
        self.printer = printer
        
        # check for config files
        if not os.path.exists("/etc/redeem/default.cfg"):
            logging.error("/etc/redeem/default.cfg does not exist, this file is required for operation")
            sys.exit() # maybe use something more graceful?
            
        # Parse the config files.
        printer.config = CascadingConfigParser(
            ['/etc/redeem/default.cfg', '/etc/redeem/printer.cfg',
             '/etc/redeem/local.cfg'])

        # Find out which capes are connected
        self.printer.config.parse_capes()
        self.revision = self.printer.config.replicape_revision
        if self.revision:
            logging.info("Found Replicape rev. " + self.revision)
            Path.set_axes(5)
        else:
            logging.warning("Oh no! No Replicape present!")
            self.revision = "0A4A"
            # We set it to 5 axis by default
            Path.set_axes(5)
        if self.printer.config.reach_revision:
            Path.set_axes(8)
            logging.info("Found Reach rev. "+self.printer.config.reach_revision)

        # Get the revision and loglevel from the Config file
        level = self.printer.config.getint('System', 'loglevel')
        if level > 0:
            logging.getLogger().setLevel(level)

        if self.revision in ["00A4", "0A4A", "00A3"]:
            PWM.set_frequency(100)
        elif self.revision in ["00B1"]:
            PWM.set_frequency(1000)

        # Init the Paths
        Path.axis_config = printer.config.getint('Geometry', 'axis_config')

        # Init the end stops
        EndStop.callback = self.end_stop_hit
        EndStop.inputdev = self.printer.config.get("Endstops", "inputdev")
        for es in ["X1", "X2", "Y1", "Y2", "Z1", "Z2"]:
            pin = self.printer.config.get("Endstops", "pin_"+es)
            keycode = self.printer.config.getint("Endstops", "keycode_"+es)
            invert = self.printer.config.getboolean("Endstops", "invert_"+es)
            self.printer.end_stops[es] = EndStop(pin, keycode, es, invert)

        # Backwards compatibility with A3
        if self.revision == "00A3":
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00A3("GPIO0_27", "GPIO1_29", "GPIO2_4" , 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00A3("GPIO1_12", "GPIO0_22", "GPIO2_5" , 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00A3("GPIO0_23", "GPIO0_26", "GPIO0_15", 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00A3("GPIO1_28", "GPIO1_15", "GPIO2_1" , 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00A3("GPIO1_13", "GPIO1_14", "GPIO2_3" , 4, "H", 4, 4)
        elif self.revision == "00B1":
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00B1("GPIO0_27", "GPIO1_29", "GPIO2_4" , 11, 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00B1("GPIO1_12", "GPIO0_22", "GPIO2_5" , 12, 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00B1("GPIO0_23", "GPIO0_26", "GPIO0_15", 13, 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00B1("GPIO1_28", "GPIO1_15", "GPIO2_1" , 14, 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00B1("GPIO1_13", "GPIO1_14", "GPIO2_3" , 15, 4, "H", 4, 4)
        else:
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00A4("GPIO0_27", "GPIO1_29", "GPIO2_4" , 0, 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00A4("GPIO1_12", "GPIO0_22", "GPIO2_5" , 1, 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00A4("GPIO0_23", "GPIO0_26", "GPIO0_15", 2, 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00A4("GPIO1_28", "GPIO1_15", "GPIO2_1" , 3, 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00A4("GPIO1_13", "GPIO1_14", "GPIO2_3" , 4, 4, "H", 4, 4)

            if printer.config.reach_revision:
                printer.steppers["A"] = Stepper_00A4("GPIO2_2" , "GPIO1_18", "GPIO0_14", 5, 5, "A", 5, 5)
                printer.steppers["B"] = Stepper_00A4("GPIO1_14", "GPIO0_5" , "GPIO0_14", 6, 6, "B", 6, 6)
                printer.steppers["C"] = Stepper_00A4("GPIO0_3" , "GPIO3_19", "GPIO0_14", 7, 7, "C", 7, 7)


        # Enable the steppers and set the current, steps pr mm and
        # microstepping
        for name, stepper in self.printer.steppers.iteritems():
            stepper.in_use = printer.config.getboolean('Steppers', 'in_use_' + name)
            stepper.direction = printer.config.getint('Steppers', 'direction_' + name)
            stepper.has_endstop = printer.config.getboolean('Endstops', 'has_' + name)
            stepper.set_current_value(printer.config.getfloat('Steppers', 'current_' + name))
            stepper.set_steps_pr_mm(printer.config.getfloat('Steppers', 'steps_pr_mm_' + name))
            stepper.set_microstepping(printer.config.getint('Steppers', 'microstepping_' + name))
            stepper.set_decay(printer.config.getboolean("Steppers", "slow_decay_" + name))
            # Add soft end stops
            Path.soft_min[Path.axis_to_index(name)] = printer.config.getfloat('Endstops', 'soft_end_stop_min_' + name)
            Path.soft_max[Path.axis_to_index(name)] = printer.config.getfloat('Endstops', 'soft_end_stop_max_' + name)

        # Commit changes for the Steppers
        #Stepper.commit()

        # Delta printer setup
        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            opts = ["Hez", "L", "r", "Ae", "Be", "Ce", "A_radial", "B_radial", "C_radial", "A_tangential", "B_tangential", "C_tangential" ]
            for opt in opts:
                Delta.__dict__[opt] = printer.config.getfloat('Delta', opt)

            Delta.recalculate()

        # Set up cold ends
        path = self.printer.config.get('Cold-ends', 'path', 0)
        if os.path.exists(path):
            self.printer.cold_ends.append(ColdEnd(path, "Cold End 0"))
            logging.info("Found Cold end on " + path)
        else:
            logging.info("No cold end present in path: " + path)

        # Make Mosfets, thermistors and extruders
        heaters = ["E", "H", "HBP"]
        if self.printer.config.reach_revision:
            heaters.extend(["A", "B", "C"])
        for e in heaters:
            # Mosfets
            channel = self.printer.config.getint("Heaters", "mosfet_"+e)
            self.printer.mosfets[e] = Mosfet(channel)
            # Thermistors
            adc = self.printer.config.get("Heaters", "path_adc_"+e)
            chart = self.printer.config.get("Heaters", "temp_chart_"+e)
            self.printer.thermistors[e] = Thermistor(adc, "MOSFET "+e, chart)

            # Extruders
            onoff = self.printer.config.getboolean('Heaters', 'onoff_'+e)
            prefix =  self.printer.config.get('Heaters', 'prefix_'+e)
            if e != "HBP":
                self.printer.heaters[e] = Extruder(
                                        self.printer.steppers[e],
                                        self.printer.thermistors[e], 
                                        self.printer.mosfets[e], e, onoff)
            else:
                self.printer.heaters[e] = HBP(
                                        self.printer.thermistors[e],
                                        self.printer.mosfets[e], onoff)
            self.printer.heaters[e].prefix = prefix
            self.printer.heaters[e].P = self.printer.config.getfloat('Heaters', 'pid_p_'+e)
            self.printer.heaters[e].I = self.printer.config.getfloat('Heaters', 'pid_i_'+e)
            self.printer.heaters[e].D = self.printer.config.getfloat('Heaters', 'pid_d_'+e)

        # Init the three fans. Argument is PWM channel number
        self.printer.fans = []
        if self.revision == "00A3":
            self.printer.fans.append(Fan(0))
            self.printer.fans.append(Fan(1))
            self.printer.fans.append(Fan(2))
        elif self.revision == "0A4A":
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))
        elif self.revision == "00B1":
            self.printer.fans.append(Fan(7))
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))


        for f in self.printer.fans:
            f.set_value(0)

        # Init the servos
        printer.servos = []
        servo_nr = 0
        while(printer.config.has_option("Servos", "servo_"+str(servo_nr)+"_enable")):
            if printer.config.getboolean("Servos", "servo_"+str(servo_nr)+"_enable"):
                channel = printer.config.getint("Servos", "servo_"+str(servo_nr)+"_channel")
                angle_off = printer.config.getint("Servos", "servo_"+str(servo_nr)+"_angle_off")
                s = Servo(channel, 500, 750, angle_off)
                s.angle_on = printer.config.getint("Servos", "servo_"+str(servo_nr)+"_angle_on")
                s.angle_off = angle_off
                printer.servos.append(s)
                logging.info("Added servo "+str(servo_nr))
            servo_nr += 1

        # Connect thermitors to fans
        for t, therm in self.printer.heaters.iteritems():
            for f, fan in enumerate(self.printer.fans):
                if self.printer.config.getboolean('Cold-ends', "connect-therm-{}-fan-{}".format(t, f)):
                    c = Cooler(therm, fan, "Cooler-{}-{}".format(t, f), False)
                    c.ok_range = 4
                    c.set_target_temperature(60)
                    c.enable()
                    self.printer.coolers.append(c)
                    logging.info("Cooler connects therm {} with fan {}".format(t, f))

        # Connect fans to M106
        printer.controlled_fans = []
        for i, fan in enumerate(self.printer.fans):
            if self.printer.config.getboolean('Cold-ends', "add-fan-{}-to-M106".format(i)):
                printer.controlled_fans.append(self.printer.fans[i])
                logging.info("Added fan {} to M106/M107".format(i))

        # Connect the cold end 0 to fan 2
        # This is very "Thing" specific, should be configurable somehow.
        if len(self.printer.cold_ends):
            self.printer.coolers.append(
                Cooler(self.printer.cold_ends[0], self.printer.fans[2],
                       "Cooler0", False))
            self.printer.coolers[0].ok_range = 4
            self.printer.coolers[0].set_target_temperature(60)
            self.printer.coolers[0].enable()

        # Make a queue of commands
        self.printer.commands = JoinableQueue(10)

        # Make a queue of commands that should not be buffered
        self.printer.sync_commands = JoinableQueue()
        self.printer.unbuffered_commands = JoinableQueue(10)

        # Bed compensation matrix
        Path.matrix_bed_comp = printer.load_bed_compensation_matrix()
        Path.matrix_bed_comp_inv = np.linalg.inv(Path.matrix_bed_comp)
        logging.debug("Loaded bed compensation matrix: \n"+str(Path.matrix_bed_comp))

        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)
            Path.max_speeds[i] = printer.config.getfloat('Planner', 'max_speed_'+axis.lower())
            Path.home_speed[i] = printer.config.getfloat('Homing', 'home_speed_'+axis.lower())
            Path.home_backoff_speed[i] = printer.config.getfloat('Homing', 'home_backoff_speed_'+axis.lower())
            Path.home_backoff_offset[i] = printer.config.getfloat('Homing', 'home_backoff_offset_'+axis.lower())
            Path.steps_pr_meter[i] = printer.steppers[axis].get_steps_pr_meter()
            Path.backlash_compensation[i] = printer.config.getfloat('Steppers', 'backlash_'+axis.lower())

        dirname = os.path.dirname(os.path.realpath(__file__))

        # Create the firmware compiler
        pru_firmware = PruFirmware(
            dirname + "/firmware/firmware_runtime.p",
            dirname + "/firmware/firmware_runtime.bin",
            dirname + "/firmware/firmware_endstops.p",
            dirname + "/firmware/firmware_endstops.bin",
            self.revision, self.printer.config, "/usr/bin/pasm")

        printer.maxJerkXY = printer.config.getfloat('Planner', 'maxJerk_xy')
        printer.maxJerkZ = printer.config.getfloat('Planner', 'maxJerk_z')
        printer.maxJerkEH = printer.config.getfloat('Planner', 'maxJerk_eh')
        
        printer.move_cache_size = printer.config.getfloat('Planner', 'move_cache_size')
        printer.print_move_buffer_wait = printer.config.getfloat('Planner', 'print_move_buffer_wait')
        printer.min_buffered_move_time = printer.config.getfloat('Planner', 'min_buffered_move_time')
        printer.max_buffered_move_time = printer.config.getfloat('Planner', 'max_buffered_move_time')

        self.printer.processor = GCodeProcessor(self.printer)
        self.printer.plugins = PluginsController(self.printer)

        # Path planner
        travel_default = False
        center_default = False
        home_default = False
        self.printer.path_planner = PathPlanner(self.printer, pru_firmware)
        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)
            
            printer.acceleration[Path.axis_to_index(axis)] = printer.config.getfloat(
                                                        'Planner', 'acceleration_' + axis.lower())
                                                        
            # Sometimes soft_end_stop aren't defined to be at the exact hardware boundary.
            # Adding 100mm for searching buffer.
            if printer.config.has_option('Geometry', 'travel_' + axis.lower()):
                printer.path_planner.travel_length[axis] = printer.config.getfloat('Geometry', 'travel_' + axis.lower())
            else:
                printer.path_planner.travel_length[axis] = (Path.soft_max[i] - Path.soft_min[i]) + .1
                if axis in ['X','Y','Z']:                
                    travel_default = True
            
            if printer.config.has_option('Geometry', 'offset_' + axis.lower()):
                printer.path_planner.center_offset[axis] = printer.config.getfloat('Geometry', 'offset_' + axis.lower())
            else:
                printer.path_planner.center_offset[axis] =(Path.soft_min[i] if Path.home_speed[i] > 0 else Path.soft_max[i])
                if axis in ['X','Y','Z']:                
                    center_default = True

            if printer.config.has_option('Homing', 'home_' + axis.lower()):
                printer.path_planner.home_pos[axis] = printer.config.getfloat('Homing', 'home_' + axis.lower())
            else:
                printer.path_planner.home_pos[axis] = printer.path_planner.center_offset[axis]
                if axis in ['X','Y','Z']:                   
                    home_default = True
                
        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            if travel_default:
                logging.warning("Axis travel (travel_*) set by soft limits, manual setup is recommended for a delta")
            if center_default:
                logging.warning("Axis offsets (offset_*) set by soft limits, manual setup is recommended for a delta")
            if home_default:
                logging.warning("Home position (home_*) set by soft limits or offset_*")
                logging.info("Home position will be recalculated...")
        
                # convert home_pos to effector space
                Az = printer.path_planner.home_pos['X']
                Bz = printer.path_planner.home_pos['Y']
                Cz = printer.path_planner.home_pos['Z']
                
                z_offset = Delta.vertical_offset(Az,Bz,Cz) # vertical offset
                xyz = Delta.forward_kinematics2(Az, Bz, Cz) # effector position
                
                # The default home_pos, provided above, is based on effector space 
                # coordinates for carriage positions. We need to transform these to 
                # get where the effector actually is.
                xyz[2] += z_offset
                for i, a in enumerate(['X','Y','Z']):
                    printer.path_planner.home_pos[a] = xyz[i]
                
                logging.info("Home position = %s"%str(printer.path_planner.home_pos))

        # Enable PWM and steppers
        printer.enable = Enable("P9_41")
        printer.enable.set_enabled()

        # Set up communication channels
        printer.comms["USB"] = USB(self.printer)
        printer.comms["Eth"] = Ethernet(self.printer)

        if Pipe.check_tty0tty() or Pipe.check_socat():
            printer.comms["octoprint"] = Pipe(printer, "octoprint")
            printer.comms["toggle"] = Pipe(printer, "toggle")
            printer.comms["testing"] = Pipe(printer, "testing")
            printer.comms["testing_noret"] = Pipe(printer, "testing_noret")
            # Does not send "ok"
            printer.comms["testing_noret"].send_response = False
        else:
            logging.warning("Neither tty0tty or socat is installed! No virtual tty pipes enabled")
예제 #15
0
    def make_config_file(self):

        # Create a config file
        configFile_0 = os.path.join("/tmp", 'config.h')

        with open(configFile_0, 'w') as configFile:

            # GPIO banks
            banks = {"0": 0, "1": 0, "2": 0, "3": 0}
            step_banks = {"0": 0, "1": 0, "2": 0, "3": 0}
            dir_banks = {"0": 0, "1": 0, "2": 0, "3": 0}
            direction_mask = 0

            # Define step and dir pins
            for name, stepper in self.printer.steppers.iteritems():
                step_pin = str(stepper.get_step_pin())
                step_bank = str(stepper.get_step_bank())
                dir_pin = str(stepper.get_dir_pin())
                dir_bank = str(stepper.get_dir_bank())
                configFile.write('#define STEPPER_' + name + '_STEP_BANK\t\t' +
                                 "STEPPER_GPIO_" + step_bank + '\n')
                configFile.write('#define STEPPER_' + name + '_STEP_PIN\t\t' +
                                 step_pin + '\n')
                configFile.write('#define STEPPER_' + name + '_DIR_BANK\t\t' +
                                 "STEPPER_GPIO_" + dir_bank + '\n')
                configFile.write('#define STEPPER_' + name + '_DIR_PIN\t\t' +
                                 dir_pin + '\n')

                # Define direction
                direction = "0" if self.config.getint(
                    'Steppers', 'direction_' + name) > 0 else "1"
                configFile.write('#define STEPPER_' + name + '_DIRECTION\t\t' +
                                 direction + '\n')

                index = Path.axis_to_index(name)
                direction_mask |= (int(direction) << index)

                # Generate the GPIO bank masks
                banks[step_bank] |= (1 << int(step_pin))
                banks[dir_bank] |= (1 << int(dir_pin))
                step_banks[step_bank] |= (1 << int(step_pin))
                dir_banks[dir_bank] |= (1 << int(dir_pin))

            configFile.write('#define DIRECTION_MASK ' + bin(direction_mask) +
                             '\n')
            configFile.write('\n')

            # Define end stop pins and banks
            for name, endstop in self.printer.end_stops.iteritems():
                bank, pin = endstop.get_gpio_bank_and_pin()
                configFile.write('#define STEPPER_' + name + '_END_PIN\t\t' +
                                 str(pin) + '\n')
                configFile.write('#define STEPPER_' + name + '_END_BANK\t\t' +
                                 "GPIO_" + str(bank) + '_IN\n')

            configFile.write('\n')

            # Construct the end stop inversion mask
            inversion_mask = "#define INVERSION_MASK\t\t0b00"
            for name in ["Z2", "Y2", "X2", "Z1", "Y1", "X1"]:
                inversion_mask += "1" if self.config.getboolean(
                    'Endstops', 'invert_' + name) else "0"

            configFile.write(inversion_mask + "\n")

            # Construct the endstop lookup table.
            for name, endstop in self.printer.end_stops.iteritems():
                mask = 0
                # stepper name is x_cw or x_ccw
                option = 'end_stop_' + name + '_stops'
                for stepper in self.config.get('Endstops', option).split(","):
                    stepper = stepper.strip()
                    if stepper == "":
                        continue
                    m = re.search('^([xyzehabc])_(ccw|cw|pos|neg)$', stepper)
                    if (m == None):
                        raise RuntimeError("'" + stepper +
                                           "' is invalid for " + option)

                    # direction should be 1 for normal operation and -1 to invert the stepper.
                    if (m.group(2) == "pos"):
                        direction = -1
                    elif (m.group(2) == "neg"):
                        direction = 1
                    else:
                        direction = 1 if self.config.getint(
                            'Steppers', 'direction_' + stepper[0]) > 0 else -1
                        if (m.group(2) == "ccw"):
                            direction *= -1

                    cur = 1 << ("xyzehabc".index(m.group(1)))
                    if (direction == -1):
                        cur <<= 8
                    mask += cur
                bin_mask = "0b" + (bin(mask)[2:]).zfill(16)
                configFile.write("#define STEPPER_MASK_" + name + "\t\t" +
                                 bin_mask + "\n")

            configFile.write("\n")

            # Put each dir and step pin in the proper buck if they are for GPIO0 or GPIO1 bank.
            # This is a restriction due to the limited capabilities of the pasm preprocessor.
            for name, bank in banks.iteritems():
                #bank = (~bank & 0xFFFFFFFF)
                configFile.write("#define GPIO" + name + "_MASK\t\t" +
                                 bin(bank) + "\n")
            #for name, bank in step_banks.iteritems():
            #bank = (~bank & 0xFFFFFFFF)
            #    configFile.write("#define GPIO"+name+"_STEP_MASK\t\t" +bin(bank)+ "\n");
            for name, bank in dir_banks.iteritems():
                #bank = (~bank & 0xFFFFFFFF)
                configFile.write("#define GPIO" + name + "_DIR_MASK\t\t" +
                                 bin(bank) + "\n")

            configFile.write("\n")

            # Add end stop delay to the config file
            end_stop_delay = self.config.getint('Endstops',
                                                'end_stop_delay_cycles')
            configFile.write("#define END_STOP_DELAY " + str(end_stop_delay) +
                             "\n")

        return configFile_0
예제 #16
0
    def __init__(self):
        firmware_version = "1.1.8~Raw Deal"
        logging.info("Redeem initializing " + firmware_version)

        printer = Printer()
        self.printer = printer
        Path.printer = printer

        printer.firmware_version = firmware_version

        # check for config files
        if not os.path.exists("/etc/redeem/default.cfg"):
            logging.error(
                "/etc/redeem/default.cfg does not exist, this file is required for operation"
            )
            sys.exit()  # maybe use something more graceful?

        if not os.path.exists("/etc/redeem/local.cfg"):
            logging.info("/etc/redeem/local.cfg does not exist, Creating one")
            os.mknod("/etc/redeem/local.cfg")

        # Parse the config files.
        printer.config = CascadingConfigParser([
            '/etc/redeem/default.cfg', '/etc/redeem/printer.cfg',
            '/etc/redeem/local.cfg'
        ])

        # Get the revision and loglevel from the Config file
        level = self.printer.config.getint('System', 'loglevel')
        if level > 0:
            logging.getLogger().setLevel(level)

        # Set up additional logging, if present:
        if self.printer.config.getboolean('System', 'log_to_file'):
            logfile = self.printer.config.get('System', 'logfile')
            formatter = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'
            printer.redeem_logging_handler = logging.handlers.RotatingFileHandler(
                logfile, maxBytes=2 * 1024 * 1024)
            printer.redeem_logging_handler.setFormatter(
                logging.Formatter(formatter))
            printer.redeem_logging_handler.setLevel(level)
            logging.getLogger().addHandler(printer.redeem_logging_handler)
            logging.info("-- Logfile configured --")

        # Find out which capes are connected
        self.printer.config.parse_capes()
        self.revision = self.printer.config.replicape_revision
        if self.revision:
            logging.info("Found Replicape rev. " + self.revision)
        else:
            logging.warning("Oh no! No Replicape present!")
            self.revision = "00B3"
        # We set it to 5 axis by default
        Path.NUM_AXES = 5
        if self.printer.config.reach_revision:
            logging.info("Found Reach rev. " +
                         self.printer.config.reach_revision)
        if self.printer.config.reach_revision == "00A0":
            Path.NUM_AXES = 8
        elif self.printer.config.reach_revision == "00B0":
            Path.NUM_AXES = 7

        if self.revision in ["00A4", "0A4A", "00A3"]:
            PWM.set_frequency(100)
        elif self.revision in ["00B1", "00B2", "00B3"]:
            PWM.set_frequency(1000)

        # Test the alarm framework
        Alarm.printer = self.printer
        Alarm.executor = AlarmExecutor()
        alarm = Alarm(Alarm.ALARM_TEST, "Alarm framework operational")

        # Init the Watchdog timer
        printer.watchdog = Watchdog()

        # Enable PWM and steppers
        printer.enable = Enable("P9_41")
        printer.enable.set_disabled()

        # Init the Paths
        Path.axis_config = printer.config.getint('Geometry', 'axis_config')

        # Init the end stops
        EndStop.inputdev = self.printer.config.get("Endstops", "inputdev")
        # Set up key listener
        Key_pin.listener = Key_pin_listener(EndStop.inputdev)

        for es in ["Z2", "Y2", "X2", "Z1", "Y1",
                   "X1"]:  # Order matches end stop inversion mask in Firmware
            pin = self.printer.config.get("Endstops", "pin_" + es)
            keycode = self.printer.config.getint("Endstops", "keycode_" + es)
            invert = self.printer.config.getboolean("Endstops", "invert_" + es)
            self.printer.end_stops[es] = EndStop(printer, pin, keycode, es,
                                                 invert)
            self.printer.end_stops[es].stops = self.printer.config.get(
                'Endstops', 'end_stop_' + es + '_stops')

        # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
        if self.revision == "00A3":
            printer.steppers["X"] = Stepper_00A3("GPIO0_27", "GPIO1_29",
                                                 "GPIO2_4", 0, "X")
            printer.steppers["Y"] = Stepper_00A3("GPIO1_12", "GPIO0_22",
                                                 "GPIO2_5", 1, "Y")
            printer.steppers["Z"] = Stepper_00A3("GPIO0_23", "GPIO0_26",
                                                 "GPIO0_15", 2, "Z")
            printer.steppers["E"] = Stepper_00A3("GPIO1_28", "GPIO1_15",
                                                 "GPIO2_1", 3, "E")
            printer.steppers["H"] = Stepper_00A3("GPIO1_13", "GPIO1_14",
                                                 "GPIO2_3", 4, "H")
        elif self.revision == "00B1":
            printer.steppers["X"] = Stepper_00B1("GPIO0_27", "GPIO1_29",
                                                 "GPIO2_4", 11, 0, "X")
            printer.steppers["Y"] = Stepper_00B1("GPIO1_12", "GPIO0_22",
                                                 "GPIO2_5", 12, 1, "Y")
            printer.steppers["Z"] = Stepper_00B1("GPIO0_23", "GPIO0_26",
                                                 "GPIO0_15", 13, 2, "Z")
            printer.steppers["E"] = Stepper_00B1("GPIO1_28", "GPIO1_15",
                                                 "GPIO2_1", 14, 3, "E")
            printer.steppers["H"] = Stepper_00B1("GPIO1_13", "GPIO1_14",
                                                 "GPIO2_3", 15, 4, "H")
        elif self.revision == "00B2":
            printer.steppers["X"] = Stepper_00B2("GPIO0_27", "GPIO1_29",
                                                 "GPIO2_4", 11, 0, "X")
            printer.steppers["Y"] = Stepper_00B2("GPIO1_12", "GPIO0_22",
                                                 "GPIO2_5", 12, 1, "Y")
            printer.steppers["Z"] = Stepper_00B2("GPIO0_23", "GPIO0_26",
                                                 "GPIO0_15", 13, 2, "Z")
            printer.steppers["E"] = Stepper_00B2("GPIO1_28", "GPIO1_15",
                                                 "GPIO2_1", 14, 3, "E")
            printer.steppers["H"] = Stepper_00B2("GPIO1_13", "GPIO1_14",
                                                 "GPIO2_3", 15, 4, "H")
        elif self.revision == "00B3":
            printer.steppers["X"] = Stepper_00B3("GPIO0_27", "GPIO1_29", 90,
                                                 11, 0, "X")
            printer.steppers["Y"] = Stepper_00B3("GPIO1_12", "GPIO0_22", 91,
                                                 12, 1, "Y")
            printer.steppers["Z"] = Stepper_00B3("GPIO0_23", "GPIO0_26", 92,
                                                 13, 2, "Z")
            printer.steppers["E"] = Stepper_00B3("GPIO1_28", "GPIO1_15", 93,
                                                 14, 3, "E")
            printer.steppers["H"] = Stepper_00B3("GPIO1_13", "GPIO1_14", 94,
                                                 15, 4, "H")
        elif self.revision in ["00A4", "0A4A"]:
            printer.steppers["X"] = Stepper_00A4("GPIO0_27", "GPIO1_29",
                                                 "GPIO2_4", 0, 0, "X")
            printer.steppers["Y"] = Stepper_00A4("GPIO1_12", "GPIO0_22",
                                                 "GPIO2_5", 1, 1, "Y")
            printer.steppers["Z"] = Stepper_00A4("GPIO0_23", "GPIO0_26",
                                                 "GPIO0_15", 2, 2, "Z")
            printer.steppers["E"] = Stepper_00A4("GPIO1_28", "GPIO1_15",
                                                 "GPIO2_1", 3, 3, "E")
            printer.steppers["H"] = Stepper_00A4("GPIO1_13", "GPIO1_14",
                                                 "GPIO2_3", 4, 4, "H")
        # Init Reach steppers, if present.
        if printer.config.reach_revision == "00A0":
            printer.steppers["A"] = Stepper_reach_00A4("GPIO2_2", "GPIO1_18",
                                                       "GPIO0_14", 5, 5, "A")
            printer.steppers["B"] = Stepper_reach_00A4("GPIO1_16", "GPIO0_5",
                                                       "GPIO0_14", 6, 6, "B")
            printer.steppers["C"] = Stepper_reach_00A4("GPIO0_3", "GPIO3_19",
                                                       "GPIO0_14", 7, 7, "C")
        elif printer.config.reach_revision == "00B0":
            printer.steppers["A"] = Stepper_reach_00B0("GPIO1_16", "GPIO0_5",
                                                       "GPIO0_3", 5, 5, "A")
            printer.steppers["B"] = Stepper_reach_00B0("GPIO2_2", "GPIO0_14",
                                                       "GPIO0_3", 6, 6, "B")

        # Enable the steppers and set the current, steps pr mm and
        # microstepping
        for name, stepper in self.printer.steppers.iteritems():
            stepper.in_use = printer.config.getboolean('Steppers',
                                                       'in_use_' + name)
            stepper.direction = printer.config.getint('Steppers',
                                                      'direction_' + name)
            stepper.has_endstop = printer.config.getboolean(
                'Endstops', 'has_' + name)
            stepper.set_current_value(
                printer.config.getfloat('Steppers', 'current_' + name))
            stepper.set_steps_pr_mm(
                printer.config.getfloat('Steppers', 'steps_pr_mm_' + name))
            stepper.set_microstepping(
                printer.config.getint('Steppers', 'microstepping_' + name))
            stepper.set_decay(
                printer.config.getint("Steppers", "slow_decay_" + name))
            # Add soft end stops
            Path.soft_min[Path.axis_to_index(name)] = printer.config.getfloat(
                'Endstops', 'soft_end_stop_min_' + name)
            Path.soft_max[Path.axis_to_index(name)] = printer.config.getfloat(
                'Endstops', 'soft_end_stop_max_' + name)
            slave = printer.config.get('Steppers', 'slave_' + name)
            if slave:
                Path.add_slave(name, slave)
                logging.debug("Axis " + name + " has slave " + slave)

        # Commit changes for the Steppers
        #Stepper.commit()

        Stepper.printer = printer

        # Delta printer setup
        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            opts = [
                "Hez", "L", "r", "Ae", "Be", "Ce", "A_radial", "B_radial",
                "C_radial", "A_tangential", "B_tangential", "C_tangential"
            ]
            for opt in opts:
                Delta.__dict__[opt] = printer.config.getfloat('Delta', opt)

            Delta.recalculate()

        # Discover and add all DS18B20 cold ends.
        import glob
        paths = glob.glob("/sys/bus/w1/devices/28-*/w1_slave")
        logging.debug("Found cold ends: " + str(paths))
        for i, path in enumerate(paths):
            self.printer.cold_ends.append(ColdEnd(path, "ds18b20-" + str(i)))
            logging.info("Found Cold end " + str(i) + " on " + path)

        # Make Mosfets, thermistors and extruders
        heaters = ["E", "H", "HBP"]
        if self.printer.config.reach_revision:
            heaters.extend(["A", "B", "C"])
        for e in heaters:
            # Mosfets
            channel = self.printer.config.getint("Heaters", "mosfet_" + e)
            self.printer.mosfets[e] = Mosfet(channel)
            # Thermistors
            adc = self.printer.config.get("Heaters", "path_adc_" + e)
            chart = self.printer.config.get("Heaters", "temp_chart_" + e)
            resistance = self.printer.config.getfloat("Heaters",
                                                      "resistance_" + e)
            self.printer.thermistors[e] = Thermistor(adc, "MOSFET " + e, chart,
                                                     resistance)
            self.printer.thermistors[e].printer = printer

            # Extruders
            onoff = self.printer.config.getboolean('Heaters', 'onoff_' + e)
            prefix = self.printer.config.get('Heaters', 'prefix_' + e)
            if e != "HBP":
                self.printer.heaters[e] = Extruder(self.printer.steppers[e],
                                                   self.printer.thermistors[e],
                                                   self.printer.mosfets[e], e,
                                                   onoff)
            else:
                self.printer.heaters[e] = HBP(self.printer.thermistors[e],
                                              self.printer.mosfets[e], onoff)
            self.printer.heaters[e].prefix = prefix
            self.printer.heaters[e].P = self.printer.config.getfloat(
                'Heaters', 'pid_p_' + e)
            self.printer.heaters[e].I = self.printer.config.getfloat(
                'Heaters', 'pid_i_' + e)
            self.printer.heaters[e].D = self.printer.config.getfloat(
                'Heaters', 'pid_d_' + e)

            # Min/max settings
            self.printer.heaters[e].min_temp = self.printer.config.getfloat(
                'Heaters', 'min_temp_' + e)
            self.printer.heaters[e].max_temp = self.printer.config.getfloat(
                'Heaters', 'max_temp_' + e)
            self.printer.heaters[
                e].max_temp_rise = self.printer.config.getfloat(
                    'Heaters', 'max_rise_temp_' + e)
            self.printer.heaters[
                e].max_temp_fall = self.printer.config.getfloat(
                    'Heaters', 'max_fall_temp_' + e)

        # Init the three fans. Argument is PWM channel number
        self.printer.fans = []
        if self.revision == "00A3":
            self.printer.fans.append(Fan(0))
            self.printer.fans.append(Fan(1))
            self.printer.fans.append(Fan(2))
        elif self.revision == "0A4A":
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))
        elif self.revision in ["00B1", "00B2", "00B3"]:
            self.printer.fans.append(Fan(7))
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))
        if printer.config.reach_revision == "00A0":
            self.printer.fans.append(Fan(14))
            self.printer.fans.append(Fan(15))
            self.printer.fans.append(Fan(7))

        # Disable all fans
        for f in self.printer.fans:
            f.set_value(0)

        # Init the servos
        printer.servos = []
        servo_nr = 0
        while (printer.config.has_option("Servos", "servo_" + str(servo_nr) +
                                         "_enable")):
            if printer.config.getboolean("Servos",
                                         "servo_" + str(servo_nr) + "_enable"):
                channel = printer.config.get(
                    "Servos", "servo_" + str(servo_nr) + "_channel")
                pulse_min = printer.config.getfloat(
                    "Servos", "servo_" + str(servo_nr) + "_pulse_min")
                pulse_max = printer.config.getfloat(
                    "Servos", "servo_" + str(servo_nr) + "_pulse_max")
                angle_min = printer.config.getfloat(
                    "Servos", "servo_" + str(servo_nr) + "_angle_min")
                angle_max = printer.config.getfloat(
                    "Servos", "servo_" + str(servo_nr) + "_angle_max")
                angle_init = printer.config.getfloat(
                    "Servos", "servo_" + str(servo_nr) + "_angle_init")
                s = Servo(channel, pulse_min, pulse_max, angle_min, angle_max,
                          angle_init)
                printer.servos.append(s)
                logging.info("Added servo " + str(servo_nr))
            servo_nr += 1

        # Connect thermitors to fans
        for t, therm in self.printer.heaters.iteritems():
            for f, fan in enumerate(self.printer.fans):
                if not self.printer.config.has_option(
                        'Cold-ends', "connect-therm-{}-fan-{}".format(t, f)):
                    continue
                if printer.config.getboolean(
                        'Cold-ends', "connect-therm-{}-fan-{}".format(t, f)):
                    c = Cooler(therm, fan, "Cooler-{}-{}".format(t, f),
                               True)  # Use ON/OFF on these.
                    c.ok_range = 4
                    opt_temp = "therm-{}-fan-{}-target_temp".format(t, f)
                    if printer.config.has_option('Cold-ends', opt_temp):
                        target_temp = printer.config.getfloat(
                            'Cold-ends', opt_temp)
                    else:
                        target_temp = 60
                    c.set_target_temperature(target_temp)
                    c.enable()
                    printer.coolers.append(c)
                    logging.info("Cooler connects therm {} with fan {}".format(
                        t, f))

        # Connect fans to M106
        printer.controlled_fans = []
        for i, fan in enumerate(self.printer.fans):
            if not self.printer.config.has_option(
                    'Cold-ends', "add-fan-{}-to-M106".format(i)):
                continue
            if self.printer.config.getboolean('Cold-ends',
                                              "add-fan-{}-to-M106".format(i)):
                printer.controlled_fans.append(self.printer.fans[i])
                logging.info("Added fan {} to M106/M107".format(i))

        # Connect the colds to fans
        for ce, cold_end in enumerate(self.printer.cold_ends):
            for f, fan in enumerate(self.printer.fans):
                option = "connect-ds18b20-{}-fan-{}".format(ce, f)
                if self.printer.config.has_option('Cold-ends', option):
                    if self.printer.config.getboolean('Cold-ends', option):
                        c = Cooler(cold_end, fan,
                                   "Cooler-ds18b20-{}-{}".format(ce, f), False)
                        c.ok_range = 4
                        opt_temp = "cooler_{}_target_temp".format(ce)
                        if printer.config.has_option('Cold-ends', opt_temp):
                            target_temp = printer.config.getfloat(
                                'Cold-ends', opt_temp)
                        else:
                            target_temp = 60
                        c.set_target_temperature(target_temp)
                        c.enable()
                        printer.coolers.append(c)
                        logging.info(
                            "Cooler connects temp sensor ds18b20 {} with fan {}"
                            .format(ce, f))

        # Init roatray encs.
        printer.filament_sensors = []

        # Init rotary encoders
        printer.rotary_encoders = []
        for ex in ["E", "H", "A", "B", "C"]:
            if not printer.config.has_option('Rotary-encoders',
                                             "enable-{}".format(ex)):
                continue
            if printer.config.getboolean("Rotary-encoders",
                                         "enable-{}".format(ex)):
                logging.debug("Rotary encoder {} enabled".format(ex))
                event = printer.config.get("Rotary-encoders",
                                           "event-{}".format(ex))
                cpr = printer.config.getint("Rotary-encoders",
                                            "cpr-{}".format(ex))
                diameter = printer.config.getfloat("Rotary-encoders",
                                                   "diameter-{}".format(ex))
                r = RotaryEncoder(event, cpr, diameter)
                printer.rotary_encoders.append(r)
                # Append as Filament Sensor
                ext_nr = Path.axis_to_index(ex) - 3
                sensor = FilamentSensor(ex, r, ext_nr, printer)
                alarm_level = printer.config.getfloat(
                    "Filament-sensors", "alarm-level-{}".format(ex))
                logging.debug("Alarm level" + str(alarm_level))
                sensor.alarm_level = alarm_level
                printer.filament_sensors.append(sensor)

        # Make a queue of commands
        self.printer.commands = JoinableQueue(10)

        # Make a queue of commands that should not be buffered
        self.printer.sync_commands = JoinableQueue()
        self.printer.unbuffered_commands = JoinableQueue(10)

        # Bed compensation matrix
        Path.matrix_bed_comp = printer.load_bed_compensation_matrix()
        Path.matrix_bed_comp_inv = np.linalg.inv(Path.matrix_bed_comp)
        logging.debug("Loaded bed compensation matrix: \n" +
                      str(Path.matrix_bed_comp))

        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)
            Path.max_speeds[i] = printer.config.getfloat(
                'Planner', 'max_speed_' + axis.lower())
            Path.min_speeds[i] = printer.config.getfloat(
                'Planner', 'min_speed_' + axis.lower())
            Path.jerks[i] = printer.config.getfloat('Planner',
                                                    'max_jerk_' + axis.lower())
            Path.home_speed[i] = printer.config.getfloat(
                'Homing', 'home_speed_' + axis.lower())
            Path.home_backoff_speed[i] = printer.config.getfloat(
                'Homing', 'home_backoff_speed_' + axis.lower())
            Path.home_backoff_offset[i] = printer.config.getfloat(
                'Homing', 'home_backoff_offset_' + axis.lower())
            Path.steps_pr_meter[i] = printer.steppers[axis].get_steps_pr_meter(
            )
            Path.backlash_compensation[i] = printer.config.getfloat(
                'Steppers', 'backlash_' + axis.lower())

        dirname = os.path.dirname(os.path.realpath(__file__))

        # Create the firmware compiler
        pru_firmware = PruFirmware(dirname + "/firmware/firmware_runtime.p",
                                   dirname + "/firmware/firmware_runtime.bin",
                                   dirname + "/firmware/firmware_endstops.p",
                                   dirname + "/firmware/firmware_endstops.bin",
                                   self.printer, "/usr/bin/pasm")

        printer.move_cache_size = printer.config.getfloat(
            'Planner', 'move_cache_size')
        printer.print_move_buffer_wait = printer.config.getfloat(
            'Planner', 'print_move_buffer_wait')
        printer.min_buffered_move_time = printer.config.getfloat(
            'Planner', 'min_buffered_move_time')
        printer.max_buffered_move_time = printer.config.getfloat(
            'Planner', 'max_buffered_move_time')

        self.printer.processor = GCodeProcessor(self.printer)
        self.printer.plugins = PluginsController(self.printer)

        # Path planner
        travel_default = False
        center_default = False
        home_default = False

        # Setting acceleration before PathPlanner init
        for axis in printer.steppers.keys():
            Path.acceleration[Path.axis_to_index(
                axis)] = printer.config.getfloat(
                    'Planner', 'acceleration_' + axis.lower())

        self.printer.path_planner = PathPlanner(self.printer, pru_firmware)
        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)

            # Sometimes soft_end_stop aren't defined to be at the exact hardware boundary.
            # Adding 100mm for searching buffer.
            if printer.config.has_option('Geometry', 'travel_' + axis.lower()):
                printer.path_planner.travel_length[
                    axis] = printer.config.getfloat('Geometry',
                                                    'travel_' + axis.lower())
            else:
                printer.path_planner.travel_length[axis] = (
                    Path.soft_max[i] - Path.soft_min[i]) + .1
                if axis in ['X', 'Y', 'Z']:
                    travel_default = True

            if printer.config.has_option('Geometry', 'offset_' + axis.lower()):
                printer.path_planner.center_offset[
                    axis] = printer.config.getfloat('Geometry',
                                                    'offset_' + axis.lower())
            else:
                printer.path_planner.center_offset[axis] = (
                    Path.soft_min[i]
                    if Path.home_speed[i] > 0 else Path.soft_max[i])
                if axis in ['X', 'Y', 'Z']:
                    center_default = True

            if printer.config.has_option('Homing', 'home_' + axis.lower()):
                printer.path_planner.home_pos[axis] = printer.config.getfloat(
                    'Homing', 'home_' + axis.lower())
            else:
                printer.path_planner.home_pos[
                    axis] = printer.path_planner.center_offset[axis]
                if axis in ['X', 'Y', 'Z']:
                    home_default = True

        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            if travel_default:
                logging.warning(
                    "Axis travel (travel_*) set by soft limits, manual setup is recommended for a delta"
                )
            if center_default:
                logging.warning(
                    "Axis offsets (offset_*) set by soft limits, manual setup is recommended for a delta"
                )
            if home_default:
                logging.warning(
                    "Home position (home_*) set by soft limits or offset_*")
                logging.info("Home position will be recalculated...")

                # convert home_pos to effector space
                Az = printer.path_planner.home_pos['X']
                Bz = printer.path_planner.home_pos['Y']
                Cz = printer.path_planner.home_pos['Z']

                z_offset = Delta.vertical_offset(Az, Bz, Cz)  # vertical offset
                xyz = Delta.forward_kinematics2(Az, Bz,
                                                Cz)  # effector position

                # The default home_pos, provided above, is based on effector space
                # coordinates for carriage positions. We need to transform these to
                # get where the effector actually is.
                xyz[2] += z_offset
                for i, a in enumerate(['X', 'Y', 'Z']):
                    printer.path_planner.home_pos[a] = xyz[i]

                logging.info("Home position = %s" %
                             str(printer.path_planner.home_pos))

        # Enable Stepper timeout
        timeout = printer.config.getint('Steppers', 'timeout_seconds')
        printer.swd = StepperWatchdog(printer, timeout)
        if printer.config.getboolean('Steppers', 'use_timeout'):
            printer.swd.start()

        # Set up communication channels
        printer.comms["USB"] = USB(self.printer)
        printer.comms["Eth"] = Ethernet(self.printer)

        if Pipe.check_tty0tty() or Pipe.check_socat():
            printer.comms["octoprint"] = Pipe(printer, "octoprint")
            printer.comms["toggle"] = Pipe(printer, "toggle")
            printer.comms["testing"] = Pipe(printer, "testing")
            printer.comms["testing_noret"] = Pipe(printer, "testing_noret")
            # Does not send "ok"
            printer.comms["testing_noret"].send_response = False
        else:
            logging.warning(
                "Neither tty0tty or socat is installed! No virtual tty pipes enabled"
            )
예제 #17
0
    def make_config_file(self):
        
        # Create a config file
        configFile_0 = os.path.join("/tmp", 'config.h')

        with open(configFile_0, 'w') as configFile:
        
            # GPIO banks
            banks      = {"0": 0, "1": 0, "2": 0, "3": 0}
            step_banks = {"0": 0, "1": 0, "2": 0, "3": 0}
            dir_banks  = {"0": 0, "1": 0, "2": 0, "3": 0}
            direction_mask = 0

            # Define step and dir pins
            for name, stepper in self.printer.steppers.iteritems():
                step_pin  = str(stepper.get_step_pin())
                step_bank = str(stepper.get_step_bank())
                dir_pin   = str(stepper.get_dir_pin())
                dir_bank  = str(stepper.get_dir_bank())
                configFile.write('#define STEPPER_' + name + '_STEP_BANK\t\t' + "STEPPER_GPIO_"+step_bank+'\n')          
                configFile.write('#define STEPPER_' + name + '_STEP_PIN\t\t'  + step_pin+'\n')          
                configFile.write('#define STEPPER_' + name + '_DIR_BANK\t\t'  + "STEPPER_GPIO_"+dir_bank+'\n')          
                configFile.write('#define STEPPER_' + name + '_DIR_PIN\t\t'   + dir_pin+'\n')          

                # Define direction
                direction = "0" if self.config.getint('Steppers', 'direction_' + name) > 0 else "1"
                configFile.write('#define STEPPER_'+ name +'_DIRECTION\t\t'+ direction +'\n') 

                index = Path.axis_to_index(name)
                direction_mask |= (int(direction) << index)        

                # Generate the GPIO bank masks
                banks[step_bank]      |=  (1<<int(step_pin))
                banks[dir_bank]       |=  (1<<int(dir_pin))
                step_banks[step_bank] |=  (1<<int(step_pin))
                dir_banks[dir_bank]   |=  (1<<int(dir_pin))

            configFile.write('#define DIRECTION_MASK '+bin(direction_mask)+'\n')            
            configFile.write('\n')

            # Define end stop pins and banks
            for name, endstop in self.printer.end_stops.iteritems():
                bank, pin = endstop.get_gpio_bank_and_pin()
                configFile.write('#define STEPPER_'+ name +'_END_PIN\t\t'+ str(pin) +'\n')
                configFile.write('#define STEPPER_'+ name +'_END_BANK\t\t'+ "GPIO_"+str(bank) +'_IN\n')

            configFile.write('\n')

            # Construct the end stop inversion mask
            inversion_mask = "#define INVERSION_MASK\t\t0b00"
            for name in ["Z2", "Y2", "X2", "Z1", "Y1", "X1"]:
                inversion_mask += "1" if self.config.getboolean('Endstops', 'invert_' + name) else "0"

            configFile.write(inversion_mask + "\n");

            # Construct the endstop lookup table.
            for name, endstop in self.printer.end_stops.iteritems():
                mask = 0
                # stepper name is x_cw or x_ccw
                option = 'end_stop_' + name + '_stops'
                for stepper in self.config.get('Endstops', option).split(","):
                    stepper = stepper.strip()
                    if stepper == "":
                        continue
                    m = re.search('^([xyzehabc])_(ccw|cw|pos|neg)$', stepper)
                    if (m == None):
                        raise RuntimeError("'" + stepper + "' is invalid for " + option)

                    # direction should be 1 for normal operation and -1 to invert the stepper.
                    if (m.group(2) == "pos"):
                        direction = -1
                    elif (m.group(2) == "neg"):
                        direction = 1
                    else:
                        direction = 1 if self.config.getint('Steppers', 'direction_' + stepper[0]) > 0 else -1
                        if (m.group(2) == "ccw"): 
                            direction *= -1

                    cur = 1 << ("xyzehabc".index(m.group(1)))
                    if (direction == -1):
                        cur <<= 8
                    mask += cur
                bin_mask = "0b"+(bin(mask)[2:]).zfill(16)
                configFile.write("#define STEPPER_MASK_" + name + "\t\t" + bin_mask + "\n")
        
            configFile.write("\n");


            # Put each dir and step pin in the proper buck if they are for GPIO0 or GPIO1 bank. 
            # This is a restriction due to the limited capabilities of the pasm preprocessor.            
            for name, bank in banks.iteritems():
                #bank = (~bank & 0xFFFFFFFF)
                configFile.write("#define GPIO"+name+"_MASK\t\t" +bin(bank)+ "\n");
            #for name, bank in step_banks.iteritems():
                #bank = (~bank & 0xFFFFFFFF)
            #    configFile.write("#define GPIO"+name+"_STEP_MASK\t\t" +bin(bank)+ "\n");
            for name, bank in dir_banks.iteritems():
                #bank = (~bank & 0xFFFFFFFF)
                configFile.write("#define GPIO"+name+"_DIR_MASK\t\t" +bin(bank)+ "\n");

            configFile.write("\n");

            # Add end stop delay to the config file
            end_stop_delay = self.config.getint('Endstops', 'end_stop_delay_cycles')
            configFile.write("#define END_STOP_DELAY " +str(end_stop_delay)+ "\n");

        return configFile_0
예제 #18
0
    def _home_internal(self, axis):
        """ Private method for homing a set or a single axis """
        logging.debug("homing internal " + str(axis))

        path_search = {}
        path_backoff = {}
        path_fine_search = {}

        path_center = {}
        path_zero = {}

        speed = Path.home_speed[0]

        for a in axis:
            if not self.printer.steppers[a].has_endstop:
                logging.debug("Skipping homing for " + str(a))
                continue
            logging.debug("Doing homing for " + str(a))
            if Path.home_speed[Path.axis_to_index(a)] < 0:
                # Search to positive ends
                path_search[a] = self.travel_length[a]
                path_center[a] = self.center_offset[a]
            else:
                # Search to negative ends
                path_search[a] = -self.travel_length[a]
                path_center[a] = -self.center_offset[a]

            backoff_length = -np.sign(
                path_search[a]) * Path.home_backoff_offset[Path.axis_to_index(
                    a)]
            path_backoff[a] = backoff_length
            path_fine_search[a] = -backoff_length * 1.2

            speed = min(abs(speed),
                        abs(Path.home_speed[Path.axis_to_index(a)]))
            fine_search_speed = min(
                abs(speed),
                abs(Path.home_backoff_speed[Path.axis_to_index(a)]))

            logging.debug("axis: " + str(a))

        logging.debug("Search: %s" % path_search)
        logging.debug("Backoff to: %s" % path_backoff)
        logging.debug("Fine search: %s" % path_fine_search)
        logging.debug("Center: %s" % path_center)

        # Move until endstop is hit
        p = RelativePath(path_search, speed, True, False, True, False)
        self.add_path(p)
        self.wait_until_done()

        # Reset position to offset
        p = G92Path(path_center, speed)
        self.add_path(p)
        self.wait_until_done()

        # Back off a bit
        p = RelativePath(path_backoff, speed, True, False, True, False)
        self.add_path(p)

        # Hit the endstop slowly
        p = RelativePath(path_fine_search, fine_search_speed, True, False,
                         True, False)
        self.add_path(p)
        self.wait_until_done()

        # Reset (final) position to offset
        p = G92Path(path_center, speed)
        self.add_path(p)

        return path_center, speed
예제 #19
0
    def __init__(self):
        """ Init """
        logging.info("Redeem initializing " + version)

        printer = Printer()
        self.printer = printer

        # check for config files
        if not os.path.exists("/etc/redeem/default.cfg"):
            logging.error("/etc/redeem/default.cfg does not exist, this file is required for operation")
            sys.exit() # maybe use something more graceful?

        # Parse the config files.
        printer.config = CascadingConfigParser(
            ['/etc/redeem/default.cfg', '/etc/redeem/printer.cfg',
             '/etc/redeem/local.cfg'])

        # Find out which capes are connected
        self.printer.config.parse_capes()
        self.revision = self.printer.config.replicape_revision
        if self.revision:
            logging.info("Found Replicape rev. " + self.revision)
            Path.set_axes(5)
        else:
            logging.warning("Oh no! No Replicape present!")
            self.revision = "0A4A"
            # We set it to 5 axis by default
            Path.set_axes(5)
        if self.printer.config.reach_revision:
            Path.set_axes(8)
            logging.info("Found Reach rev. "+self.printer.config.reach_revision)

        # Get the revision and loglevel from the Config file
        level = self.printer.config.getint('System', 'loglevel')
        if level > 0:
            logging.getLogger().setLevel(level)

        if self.revision in ["00A4", "0A4A", "00A3"]:
            PWM.set_frequency(100)
        elif self.revision in ["00B1", "00B2"]:
            PWM.set_frequency(1000)

        # Init the Paths
        Path.axis_config = printer.config.getint('Geometry', 'axis_config')

        # Init the end stops
        EndStop.callback = self.end_stop_hit
        EndStop.inputdev = self.printer.config.get("Endstops", "inputdev")
        for es in ["X1", "X2", "Y1", "Y2", "Z1", "Z2"]:
            pin = self.printer.config.get("Endstops", "pin_"+es)
            keycode = self.printer.config.getint("Endstops", "keycode_"+es)
            invert = self.printer.config.getboolean("Endstops", "invert_"+es)
            self.printer.end_stops[es] = EndStop(pin, keycode, es, invert)

        # Backwards compatibility with A3
        if self.revision == "00A3":
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00A3("GPIO0_27", "GPIO1_29", "GPIO2_4" , 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00A3("GPIO1_12", "GPIO0_22", "GPIO2_5" , 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00A3("GPIO0_23", "GPIO0_26", "GPIO0_15", 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00A3("GPIO1_28", "GPIO1_15", "GPIO2_1" , 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00A3("GPIO1_13", "GPIO1_14", "GPIO2_3" , 4, "H", 4, 4)
        elif self.revision == "00B1":
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00B1("GPIO0_27", "GPIO1_29", "GPIO2_4" , 11, 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00B1("GPIO1_12", "GPIO0_22", "GPIO2_5" , 12, 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00B1("GPIO0_23", "GPIO0_26", "GPIO0_15", 13, 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00B1("GPIO1_28", "GPIO1_15", "GPIO2_1" , 14, 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00B1("GPIO1_13", "GPIO1_14", "GPIO2_3" , 15, 4, "H", 4, 4)
        elif self.revision == "00B2":
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00B2("GPIO0_27", "GPIO1_29", "GPIO2_4" , 11, 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00B2("GPIO1_12", "GPIO0_22", "GPIO2_5" , 12, 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00B2("GPIO0_23", "GPIO0_26", "GPIO0_15", 13, 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00B2("GPIO1_28", "GPIO1_15", "GPIO2_1" , 14, 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00B2("GPIO1_13", "GPIO1_14", "GPIO2_3" , 15, 4, "H", 4, 4)
        else:
            # Init the 5 Stepper motors (step, dir, fault, DAC channel, name)
            printer.steppers["X"] = Stepper_00A4("GPIO0_27", "GPIO1_29", "GPIO2_4" , 0, 0, "X", 0, 0)
            printer.steppers["Y"] = Stepper_00A4("GPIO1_12", "GPIO0_22", "GPIO2_5" , 1, 1, "Y", 1, 1)
            printer.steppers["Z"] = Stepper_00A4("GPIO0_23", "GPIO0_26", "GPIO0_15", 2, 2, "Z", 2, 2)
            printer.steppers["E"] = Stepper_00A4("GPIO1_28", "GPIO1_15", "GPIO2_1" , 3, 3, "E", 3, 3)
            printer.steppers["H"] = Stepper_00A4("GPIO1_13", "GPIO1_14", "GPIO2_3" , 4, 4, "H", 4, 4)

            if printer.config.reach_revision:
                printer.steppers["A"] = Stepper_00A4("GPIO2_2" , "GPIO1_18", "GPIO0_14", 5, 5, "A", 5, 5)
                printer.steppers["B"] = Stepper_00A4("GPIO1_14", "GPIO0_5" , "GPIO0_14", 6, 6, "B", 6, 6)
                printer.steppers["C"] = Stepper_00A4("GPIO0_3" , "GPIO3_19", "GPIO0_14", 7, 7, "C", 7, 7)


        # Enable the steppers and set the current, steps pr mm and
        # microstepping
        for name, stepper in self.printer.steppers.iteritems():
            stepper.in_use = printer.config.getboolean('Steppers', 'in_use_' + name)
            stepper.direction = printer.config.getint('Steppers', 'direction_' + name)
            stepper.has_endstop = printer.config.getboolean('Endstops', 'has_' + name)
            stepper.set_current_value(printer.config.getfloat('Steppers', 'current_' + name))
            stepper.set_steps_pr_mm(printer.config.getfloat('Steppers', 'steps_pr_mm_' + name))
            stepper.set_microstepping(printer.config.getint('Steppers', 'microstepping_' + name))
            stepper.set_decay(printer.config.getboolean("Steppers", "slow_decay_" + name))
            # Add soft end stops
            Path.soft_min[Path.axis_to_index(name)] = printer.config.getfloat('Endstops', 'soft_end_stop_min_' + name)
            Path.soft_max[Path.axis_to_index(name)] = printer.config.getfloat('Endstops', 'soft_end_stop_max_' + name)

        # Commit changes for the Steppers
        #Stepper.commit()
        Stepper.printer = printer

        # Delta printer setup
        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            opts = ["Hez", "L", "r", "Ae", "Be", "Ce", "A_radial", "B_radial", "C_radial", "A_tangential", "B_tangential", "C_tangential" ]
            for opt in opts:
                Delta.__dict__[opt] = printer.config.getfloat('Delta', opt)

            Delta.recalculate()

        # Discover and add all DS18B20 cold ends.
        import glob
        paths = glob.glob("/sys/bus/w1/devices/28-*/w1_slave")
        logging.debug("Found cold ends: "+str(paths))
        for i, path in enumerate(paths):
            self.printer.cold_ends.append(ColdEnd(path, "ds18b20-"+str(i)))
            logging.info("Found Cold end "+str(i)+" on " + path)

        # Make Mosfets, thermistors and extruders
        heaters = ["E", "H", "HBP"]
        if self.printer.config.reach_revision:
            heaters.extend(["A", "B", "C"])
        for e in heaters:
            # Mosfets
            channel = self.printer.config.getint("Heaters", "mosfet_"+e)
            self.printer.mosfets[e] = Mosfet(channel)
            # Thermistors
            adc = self.printer.config.get("Heaters", "path_adc_"+e)
            chart = self.printer.config.get("Heaters", "temp_chart_"+e)
            resistance = self.printer.config.getfloat("Heaters", "resistance_"+e)
            self.printer.thermistors[e] = Thermistor(adc, "MOSFET "+e, chart, resistance)
            self.printer.thermistors[e].printer = printer

            # Extruders
            onoff = self.printer.config.getboolean('Heaters', 'onoff_'+e)
            prefix =  self.printer.config.get('Heaters', 'prefix_'+e)
            if e != "HBP":
                self.printer.heaters[e] = Extruder(
                                        self.printer.steppers[e],
                                        self.printer.thermistors[e],
                                        self.printer.mosfets[e], e, onoff)
            else:
                self.printer.heaters[e] = HBP(
                                        self.printer.thermistors[e],
                                        self.printer.mosfets[e], onoff)
            self.printer.heaters[e].prefix = prefix
            self.printer.heaters[e].P = self.printer.config.getfloat('Heaters', 'pid_p_'+e)
            self.printer.heaters[e].I = self.printer.config.getfloat('Heaters', 'pid_i_'+e)
            self.printer.heaters[e].D = self.printer.config.getfloat('Heaters', 'pid_d_'+e)

        # Init the three fans. Argument is PWM channel number
        self.printer.fans = []
        if self.revision == "00A3":
            self.printer.fans.append(Fan(0))
            self.printer.fans.append(Fan(1))
            self.printer.fans.append(Fan(2))
        elif self.revision == "0A4A":
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))
        elif self.revision in ["00B1", "00B2"]:
            self.printer.fans.append(Fan(7))
            self.printer.fans.append(Fan(8))
            self.printer.fans.append(Fan(9))
            self.printer.fans.append(Fan(10))


        # Disable all fans
        for f in self.printer.fans:
            f.set_value(0)

        # Init the servos
        printer.servos = []
        servo_nr = 0
        while(printer.config.has_option("Servos", "servo_"+str(servo_nr)+"_enable")):
            if printer.config.getboolean("Servos", "servo_"+str(servo_nr)+"_enable"):
                channel = printer.config.get("Servos", "servo_"+str(servo_nr)+"_channel")
                angle_init = printer.config.getint("Servos", "servo_"+str(servo_nr)+"_angle_init")
                s = Servo(channel, 0.1, 0.2, angle_init)
                printer.servos.append(s)
                logging.info("Added servo "+str(servo_nr))
            servo_nr += 1

        # Connect thermitors to fans
        for t, therm in self.printer.heaters.iteritems():
            for f, fan in enumerate(self.printer.fans):
                if self.printer.config.getboolean('Cold-ends', "connect-therm-{}-fan-{}".format(t, f)):
                    c = Cooler(therm, fan, "Cooler-{}-{}".format(t, f), False)
                    c.ok_range = 4
                    c.set_target_temperature(60)
                    c.enable()
                    self.printer.coolers.append(c)
                    logging.info("Cooler connects therm {} with fan {}".format(t, f))

        # Connect fans to M106
        printer.controlled_fans = []
        for i, fan in enumerate(self.printer.fans):
            if self.printer.config.getboolean('Cold-ends', "add-fan-{}-to-M106".format(i)):
                printer.controlled_fans.append(self.printer.fans[i])
                logging.info("Added fan {} to M106/M107".format(i))

        # Connect the colds to fans
        for ce, cold_end in enumerate(self.printer.cold_ends):
            for f, fan in enumerate(self.printer.fans):
                option = "connect-ds18b20-{}-fan-{}".format(ce, f)
                if self.printer.config.has_option('Cold-ends', option):
                    if self.printer.config.getboolean('Cold-ends', option):
                        c = Cooler(cold_end, fan, "Cooler-ds18b20-{}-{}".format(ce, f), False)
                        c.ok_range = 4
                        c.set_target_temperature(60)
                        c.enable()
                        self.printer.coolers.append(c)
                        logging.info("Cooler connects temp sensor ds18b20 {} with fan {}".format(ce, f))

        # Make a queue of commands
        self.printer.commands = JoinableQueue(10)

        # Make a queue of commands that should not be buffered
        self.printer.sync_commands = JoinableQueue()
        self.printer.unbuffered_commands = JoinableQueue(10)

        # Bed compensation matrix
        Path.matrix_bed_comp = printer.load_bed_compensation_matrix()
        Path.matrix_bed_comp_inv = np.linalg.inv(Path.matrix_bed_comp)
        logging.debug("Loaded bed compensation matrix: \n"+str(Path.matrix_bed_comp))

        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)
            Path.max_speeds[i] = printer.config.getfloat('Planner', 'max_speed_'+axis.lower())
            Path.home_speed[i] = printer.config.getfloat('Homing', 'home_speed_'+axis.lower())
            Path.home_backoff_speed[i] = printer.config.getfloat('Homing', 'home_backoff_speed_'+axis.lower())
            Path.home_backoff_offset[i] = printer.config.getfloat('Homing', 'home_backoff_offset_'+axis.lower())
            Path.steps_pr_meter[i] = printer.steppers[axis].get_steps_pr_meter()
            Path.backlash_compensation[i] = printer.config.getfloat('Steppers', 'backlash_'+axis.lower())

        dirname = os.path.dirname(os.path.realpath(__file__))

        # Create the firmware compiler
        pru_firmware = PruFirmware(
            dirname + "/firmware/firmware_runtime.p",
            dirname + "/firmware/firmware_runtime.bin",
            dirname + "/firmware/firmware_endstops.p",
            dirname + "/firmware/firmware_endstops.bin",
            self.revision, self.printer.config, "/usr/bin/pasm")

        printer.maxJerkXY = printer.config.getfloat('Planner', 'maxJerk_xy')
        printer.maxJerkZ = printer.config.getfloat('Planner', 'maxJerk_z')
        printer.maxJerkEH = printer.config.getfloat('Planner', 'maxJerk_eh')

        printer.move_cache_size = printer.config.getfloat('Planner', 'move_cache_size')
        printer.print_move_buffer_wait = printer.config.getfloat('Planner', 'print_move_buffer_wait')
        printer.min_buffered_move_time = printer.config.getfloat('Planner', 'min_buffered_move_time')
        printer.max_buffered_move_time = printer.config.getfloat('Planner', 'max_buffered_move_time')

        self.printer.processor = GCodeProcessor(self.printer)
        self.printer.plugins = PluginsController(self.printer)

        # Path planner
        travel_default = False
        center_default = False
        home_default = False

        # Setting acceleration before PathPlanner init
        for axis in printer.steppers.keys():
            printer.acceleration[Path.axis_to_index(axis)] = printer.config.getfloat(
                                                        'Planner', 'acceleration_' + axis.lower())

        self.printer.path_planner = PathPlanner(self.printer, pru_firmware)
        for axis in printer.steppers.keys():
            i = Path.axis_to_index(axis)

            # Sometimes soft_end_stop aren't defined to be at the exact hardware boundary.
            # Adding 100mm for searching buffer.
            if printer.config.has_option('Geometry', 'travel_' + axis.lower()):
                printer.path_planner.travel_length[axis] = printer.config.getfloat('Geometry', 'travel_' + axis.lower())
            else:
                printer.path_planner.travel_length[axis] = (Path.soft_max[i] - Path.soft_min[i]) + .1
                if axis in ['X','Y','Z']:
                    travel_default = True

            if printer.config.has_option('Geometry', 'offset_' + axis.lower()):
                printer.path_planner.center_offset[axis] = printer.config.getfloat('Geometry', 'offset_' + axis.lower())
            else:
                printer.path_planner.center_offset[axis] =(Path.soft_min[i] if Path.home_speed[i] > 0 else Path.soft_max[i])
                if axis in ['X','Y','Z']:
                    center_default = True

            if printer.config.has_option('Homing', 'home_' + axis.lower()):
                printer.path_planner.home_pos[axis] = printer.config.getfloat('Homing', 'home_' + axis.lower())
            else:
                printer.path_planner.home_pos[axis] = printer.path_planner.center_offset[axis]
                if axis in ['X','Y','Z']:
                    home_default = True

        if Path.axis_config == Path.AXIS_CONFIG_DELTA:
            if travel_default:
                logging.warning("Axis travel (travel_*) set by soft limits, manual setup is recommended for a delta")
            if center_default:
                logging.warning("Axis offsets (offset_*) set by soft limits, manual setup is recommended for a delta")
            if home_default:
                logging.warning("Home position (home_*) set by soft limits or offset_*")
                logging.info("Home position will be recalculated...")

                # convert home_pos to effector space
                Az = printer.path_planner.home_pos['X']
                Bz = printer.path_planner.home_pos['Y']
                Cz = printer.path_planner.home_pos['Z']

                z_offset = Delta.vertical_offset(Az,Bz,Cz) # vertical offset
                xyz = Delta.forward_kinematics2(Az, Bz, Cz) # effector position

                # The default home_pos, provided above, is based on effector space
                # coordinates for carriage positions. We need to transform these to
                # get where the effector actually is.
                xyz[2] += z_offset
                for i, a in enumerate(['X','Y','Z']):
                    printer.path_planner.home_pos[a] = xyz[i]

                logging.info("Home position = %s"%str(printer.path_planner.home_pos))

        if Path.axis_config == Path.AXIS_CONFIG_SCARA:
            if travel_default:
                logging.warning("Axis travel (travel_*) set by soft limits, manual setup is recommended for a scara")
            if center_default:
                logging.warning("Axis offsets (offset_*) set by soft limits, manual setup is recommended for a scara")
            if home_default:
                logging.warning("Home position (home_*) set by soft limits or offset_*")
                logging.info("Home position will be recalculated...")

                # convert home_pos to effector space
                #A = printer.path_planner.home_pos['X']
                #B = printer.path_planner.home_pos['Y']
                #C = printer.path_planner.home_pos['Z']

                #z_offset = Delta.vertical_offset(Az,Bz,Cz) # vertical offset
                #xyz = Scara.forward_kinematics(A, B, C) # effector position

                # don't cpnvert home_pos to effector spac
                # home offset is defined in cartesian space

                xyz = np.array([printer.path_planner.home_pos['X'],printer.path_planner.home_pos['Y'],printer.path_planner.home_pos['Z']])

                # The default home_pos, provided above, is based on effector space
                # coordinates for carriage positions. We need to transform these to
                # get where the effector actually is.
                #xyz[2] += z_offset
                for i, a in enumerate(['X','Y','Z']):
                    printer.path_planner.home_pos[a] = xyz[i]

                logging.info("Home position = %s"%str(printer.path_planner.home_pos))

        # Enable PWM and steppers
        printer.enable = Enable("P9_41")
        printer.enable.set_enabled()

        # Set up communication channels
        printer.comms["USB"] = USB(self.printer)
        printer.comms["Eth"] = Ethernet(self.printer)

        if Pipe.check_tty0tty() or Pipe.check_socat():
            printer.comms["octoprint"] = Pipe(printer, "octoprint")
            printer.comms["toggle"] = Pipe(printer, "toggle")
            printer.comms["testing"] = Pipe(printer, "testing")
            printer.comms["testing_noret"] = Pipe(printer, "testing_noret")
            # Does not send "ok"
            printer.comms["testing_noret"].send_response = False
        else:
            logging.warning("Neither tty0tty or socat is installed! No virtual tty pipes enabled")