def __init__(self, channel, offset=-19, lock=True, bus_number=None, address=0x40): ''' Init a servo on specific channel, this offset ''' if channel < 0 or channel > 16: raise ValueError( "Servo channel \"{0}\" is not in (0, 15).".format(channel)) if self._DEBUG: print(self._DEBUG_INFO, "Debug on") self.channel = channel self.offset = offset self.lock = lock self.pwm = PWM(bus_number=bus_number, address=address) self.frequency = self._FREQUENCY self.write(90)
def __init__(self, debug=False, bus_number=1, db="config"): ''' Init the direction channel and pwm channel ''' self.forward_A = True self.forward_B = True self.db = fileDB(db=db) self.forward_A = int(self.db.get('forward_A', default_value=1)) self.forward_B = int(self.db.get('forward_B', default_value=1)) self.left_wheel = Motor(self.Motor_A, offset=self.forward_A) self.right_wheel = Motor(self.Motor_B, offset=self.forward_B) self.pwm = PWM(bus_number=bus_number) def _set_a_pwm(value): pulse_wide = self.pwm.map(value, 0, 100, 0, 4095) self.pwm.write(self.PWM_A, 0, pulse_wide) def _set_b_pwm(value): pulse_wide = self.pwm.map(value, 0, 100, 0, 4095) self.pwm.write(self.PWM_B, 0, pulse_wide) self.left_wheel.pwm = _set_a_pwm self.right_wheel.pwm = _set_b_pwm self._speed = 0 self.debug = debug if self._DEBUG: print( self._DEBUG_INFO, 'Set left wheel to #%d, PWM channel to %d' % (self.Motor_A, self.PWM_A)) print( self._DEBUG_INFO, 'Set right wheel to #%d, PWM channel to %d' % (self.Motor_B, self.PWM_B))
def set_PWM_frequency(self, value): """ Set the amount of on-time from 0..1 """ self.pwm_frequency = int(value) PWM.set_frequency(value)
def __init__(self, fwd, bwd, pwm): self.fwd_pin = fwd self.bwd_pin = bwd self.pwm_pin = PWM(pwm, blocking=False) GPIO.setup(self.fwd_pin, GPIO.OUT) GPIO.setup(self.bwd_pin, GPIO.OUT)
class Motor(object): def __init__(self, fwd, bwd, pwm): self.fwd_pin = fwd self.bwd_pin = bwd self.pwm_pin = PWM(pwm, blocking=False) GPIO.setup(self.fwd_pin, GPIO.OUT) GPIO.setup(self.bwd_pin, GPIO.OUT) def set_forward(self): GPIO.output(self.fwd_pin, 1) GPIO.output(self.bwd_pin, 0) def set_backward(self): GPIO.output(self.fwd_pin, 0) GPIO.output(self.bwd_pin, 1) def stop(): self.pwm_pin.stop() def forward(self, speed): self.set_forward() self.pwm_pin.set_duty_cycle(speed) self.pwm_pin.run() def forward_for(self, speed, time): self.set_forward() self.pwm_pin.set_duty_cycle(speed) self.pwm_pin.runFor(time) def backward(self, speed): self.set_backward() self.pwm_pin.set_duty_cycle(speed) self.pwm_pin.run() def backward_for(self, speed, time): self.set_backward() self.pwm_pin.set_duty_cycle(speed) self.pwm_pin.runFor(time)
class Back_Wheels(object): ''' Back wheels control class ''' Motor_A = 17 Motor_B = 27 PWM_A = 4 PWM_B = 5 _DEBUG = False _DEBUG_INFO = 'DEBUG "back_wheels.py":' def __init__(self, debug=False, bus_number=1, db="config"): ''' Init the direction channel and pwm channel ''' self.forward_A = True self.forward_B = True self.db = fileDB(db=db) self.forward_A = int(self.db.get('forward_A', default_value=1)) self.forward_B = int(self.db.get('forward_B', default_value=1)) self.left_wheel = Motor(self.Motor_A, offset=self.forward_A) self.right_wheel = Motor(self.Motor_B, offset=self.forward_B) self.pwm = PWM(bus_number=bus_number) def _set_a_pwm(value): pulse_wide = self.pwm.map(value, 0, 100, 0, 4095) self.pwm.write(self.PWM_A, 0, pulse_wide) def _set_b_pwm(value): pulse_wide = self.pwm.map(value, 0, 100, 0, 4095) self.pwm.write(self.PWM_B, 0, pulse_wide) self.left_wheel.pwm = _set_a_pwm self.right_wheel.pwm = _set_b_pwm self._speed = 0 self.debug = debug if self._DEBUG: print( self._DEBUG_INFO, 'Set left wheel to #%d, PWM channel to %d' % (self.Motor_A, self.PWM_A)) print( self._DEBUG_INFO, 'Set right wheel to #%d, PWM channel to %d' % (self.Motor_B, self.PWM_B)) def forward(self): ''' Move both wheels forward ''' self.left_wheel.forward() self.right_wheel.forward() if self._DEBUG: print(self._DEBUG_INFO, 'Running forward') def backward(self): ''' Move both wheels backward ''' self.left_wheel.backward() self.right_wheel.backward() if self._DEBUG: print(self._DEBUG_INFO, 'Running backward') def stop(self): ''' Stop both wheels ''' self.left_wheel.stop() self.right_wheel.stop() if self._DEBUG: print(self._DEBUG_INFO, 'Stop') @property def speed(self, speed): return self._speed @speed.setter def speed(self, speed): self._speed = speed ''' Set moving speeds ''' self.left_wheel.speed = self._speed self.right_wheel.speed = self._speed if self._DEBUG: print(self._DEBUG_INFO, 'Set speed to', self._speed) @property def debug(self): return self._DEBUG @debug.setter def debug(self, debug): ''' Set if debug information shows ''' if debug in (True, False): self._DEBUG = debug else: raise ValueError( 'debug must be "True" (Set debug on) or "False" (Set debug off), not "{0}"' .format(debug)) if self._DEBUG: print(self._DEBUG_INFO, "Set debug on") self.left_wheel.debug = True self.right_wheel.debug = True self.pwm.debug = True else: print(self._DEBUG_INFO, "Set debug off") self.left_wheel.debug = False self.right_wheel.debug = False self.pwm.debug = False def ready(self): ''' Get the back wheels to the ready position. (stop) ''' if self._DEBUG: print(self._DEBUG_INFO, 'Turn to "Ready" position') self.left_wheel.offset = self.forward_A self.right_wheel.offset = self.forward_B self.stop() def calibration(self): ''' Get the front wheels to the calibration position. ''' if self._DEBUG: print(self._DEBUG_INFO, 'Turn to "Calibration" position') self.speed = 50 self.forward() self.cali_forward_A = self.forward_A self.cali_forward_B = self.forward_B def cali_left(self): ''' Reverse the left wheels forward direction in calibration ''' self.cali_forward_A = (1 + self.cali_forward_A) & 1 self.left_wheel.offset = self.cali_forward_A self.forward() def cali_right(self): ''' Reverse the right wheels forward direction in calibration ''' self.cali_forward_B = (1 + self.cali_forward_B) & 1 self.right_wheel.offset = self.cali_forward_B self.forward() def cali_ok(self): ''' Save the calibration value ''' self.forward_A = self.cali_forward_A self.forward_B = self.cali_forward_B self.db.set('forward_A', self.forward_A) self.db.set('forward_B', self.forward_B) self.stop() def test(self): import time back_wheels = Back_Wheels() DELAY = 0.01 try: back_wheels.forward() for i in range(0, 100): back_wheels.speed = i print("Forward, speed =", i) time.sleep(DELAY) for i in range(100, 0, -1): back_wheels.speed = i print("Forward, speed =", i) time.sleep(DELAY) back_wheels.backward() for i in range(0, 100): back_wheels.speed = i print("Backward, speed =", i) time.sleep(DELAY) for i in range(100, 0, -1): back_wheels.speed = i print("Backward, speed =", i) time.sleep(DELAY) except KeyboardInterrupt: print("KeyboardInterrupt, motor stop") back_wheels.stop() finally: print("Finished, motor stop") back_wheels.stop()
from PWM import PWM import time CUPHOLDER_PWM = 12 CUPHOLDER_2_PWM = 13 UNDER_SEAT_PWM = 0 UPPER_SHELL_RED = 8 UPPER_SHELL_GREEN = 9 UPPER_SHELL_BLUE = 10 # Initialise the PWM device using the default address pwm = PWM(0x42) # Note if you'd like more debug output you can instead run: #pwm = PWM(0x42) freq = 0 pwm.setPWMFreq(500) # Set frequency to 60 Hz while (True): if freq > 4095: freq = 0 else: freq = freq + 10 pwm.setPWM(UNDER_SEAT_PWM, 4095 - freq, freq) pwm.setPWM(CUPHOLDER_PWM, 4095 - freq, freq) pwm.setPWM(UPPER_SHELL_GREEN, 4095 - freq, freq) pwm.setPWM(UPPER_SHELL_BLUE, 4095 - freq, freq) pwm.setPWM(UPPER_SHELL_RED, 2048, 2048) pwm.setPWM(CUPHOLDER_2_PWM, 4095 - freq, freq)
def set_value(self, value): """ Set the amount of on-time from 0..1 """ self.value = value PWM.set_value(value, self.channel)
def set_voltage(self, voltage): """ Set the amount of on-time from 0..1 """ # The VCC on the PWM chip is 5.0V on Replicape Rev B1 PWM.set_value((voltage / 5.0) + self.offset, self.channel)
def ramp_to(self, value, delay=0.01): ''' Set the fan/light value to the given value, in degree, with the given speed in deg / sec ''' for w in xrange(int(self.value*255.0), int(value*255.0), (1 if value>=self.value else -1)): logging.debug("Fan value: "+str(w)) self.set_value(w/255.0) time.sleep(delay) if __name__ == '__main__': import os import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M') PWM.set_frequency(100) fan7 = Fan(7) fan8 = Fan(8) fan9 = Fan(9) fan10 = Fan(10) while 1: for i in xrange(1,100): fan7.set_value(i/100.0) fan8.set_value(i/100.0) fan9.set_value(i/100.0) fan10.set_value(i/100.0) time.sleep(0.01) for i in xrange(100,1,-1):
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")
def initialiseLists(self): db = sqlite3.connect("./test2.sql") gpio = db.execute(""" SELECT * FROM Gpio """) for row in gpio: gpioType = row[2] pinNumber = row[0] gpioNumber = row[1] label = row[3] if gpioType == 'out': # create a switch switch = Switch(pinNumber, gpioNumber, label, self) #self.gpioList.append(switch) self.gpioLabelMapping[label] = gpioNumber self.gpioMap[gpioNumber] = switch elif gpioType == 'in': # create a contact contact = Contact(pinNumber, gpioNumber, label, self) #self.gpioList.append(contact) self.gpioLabelMapping[label] = gpioNumber self.gpioMap[gpioNumber] = contact elif gpioType == 'PWM': # create a pwm pwm = PWM(pinNumber, gpioNumber, label, self) #self.gpioList.append(pwm) self.gpioLabelMapping[label] = gpioNumber self.gpioMap[gpioNumber] = pwm # else: # print("Skipped pin for now") for gpio in self.gpioMap.values(): if gpio.threadBehavior != None: gpio.threadBehavior.start() table = db.execute(""" SELECT * FROM Alias""") self.gpioAliasMapping = {} for row in table: alias = row[1] gpio = row[2] self.gpioAliasMapping[alias] = gpio self.gpioAliasMapping = { **self.gpioLabelMapping, **self.gpioAliasMapping } print("---------------") print("GPIO Map:") print("---------------") print(self.gpioMap) print("---------------") print("Alias Map:") print("---------------") print(self.gpioAliasMapping) db = sqlite3.connect("./test2.sql") rules = db.execute(""" SELECT * FROM Rules """) for row in rules: ruleGpioTrigger = row[1] ruleGpioNewValue = row[2] ruleTriggeredScript = row[3] if ruleGpioTrigger not in self.ruleTableSwitchType: self.ruleTableSwitchType[ruleGpioTrigger] = [] self.ruleTableSwitchType[ruleGpioTrigger].append( [ruleGpioNewValue, ruleTriggeredScript]) cronJobs = db.execute(""" SELECT * FROM CronJobs """) for row in cronJobs: ruleCronStatement = row[1] ruleTriggeredScript = row[2] if ruleCronStatement not in self.ruleTableCronType: self.ruleTableCronType[ruleCronStatement] = [] self.ruleTableCronType[ruleCronStatement].append( ruleTriggeredScript)
def set_power(self, value): self.power = value """Set duty cycle between 0 and 1""" PWM.set_value(value, self.channel)
UPPER_SHELL_RED = 8 UPPER_SHELL_GREEN = 9 UPPER_SHELL_BLUE = 10 ############################################################ # i2c ############################################################ # prox detection address GP2Y0E02B = 0x40 proxSensor1 = Adafruit_I2C(GP2Y0E02B) #proxSensor2 = Adafruit_I2C(VCNL4010_I2CADDR_DEFAULT) #PWM driver connected on i2c ledDriver = PWM(0x42) ######################################################################## # websocket ######################################################################## amcServerIP = '192.168.42.1' def on_show_video_1(message): if (message['id'] == ID): global player if (player): player.quit() player = OMXPlayer("path/to/file.mp4", args=['--no-osd', '--no-keys', '-b'])
def set_voltage(self, voltage): """ Set the amount of on-time from 0..1 """ # The VCC on the PWM chip is 5.0V on Replicape Rev B1 PWM.set_value((voltage/5.0)+self.offset, self.channel)
class Servo(object): '''Servo driver class''' _MIN_PULSE_WIDTH = 600 _MAX_PULSE_WIDTH = 2400 _DEFAULT_PULSE_WIDTH = 1500 _FREQUENCY = 60 _DEBUG = False _DEBUG_INFO = 'DEBUG "Servo.py":' def __init__(self, channel, offset=-19, lock=True, bus_number=None, address=0x40): ''' Init a servo on specific channel, this offset ''' if channel < 0 or channel > 16: raise ValueError( "Servo channel \"{0}\" is not in (0, 15).".format(channel)) if self._DEBUG: print(self._DEBUG_INFO, "Debug on") self.channel = channel self.offset = offset self.lock = lock self.pwm = PWM(bus_number=bus_number, address=address) self.frequency = self._FREQUENCY self.write(90) def setup(self): self.pwm.setup() def _angle_to_analog(self, angle): ''' Calculate 12-bit analog value from giving angle ''' pulse_wide = self.pwm.map(angle, 0, 180, self._MIN_PULSE_WIDTH, self._MAX_PULSE_WIDTH) analog_value = int(float(pulse_wide) / 1000000 * self.frequency * 4096) if self._DEBUG: print(self._DEBUG_INFO, 'Angle %d equals Analog_value %d' % (angle, analog_value)) return analog_value @property def frequency(self): return self._frequency @frequency.setter def frequency(self, value): self._frequency = value self.pwm.frequency = value @property def offset(self): return self._offset @offset.setter def offset(self, value): ''' Set offset for much user-friendly ''' self._offset = value if self._DEBUG: print(self._DEBUG_INFO, 'Set offset to %d' % self.offset) def write(self, angle): ''' Turn the servo with giving angle. ''' if self.lock: if angle > 180: angle = 180 if angle < 0: angle = 0 else: if angle < 0 or angle > 180: raise ValueError( "Servo \"{0}\" turn angle \"{1}\" is not in (0, 180).". format(self.channel, angle)) val = self._angle_to_analog(angle) val += self.offset self.pwm.write(self.channel, 0, val) if self._DEBUG: print(self._DEBUG_INFO, 'Turn angle = %d' % angle) @property def debug(self): return self._DEBUG @debug.setter def debug(self, debug): ''' Set if debug information shows ''' if debug in (True, False): self._DEBUG = debug else: raise ValueError( 'debug must be "True" (Set debug on) or "False" (Set debug off), not "{0}"' .format(debug)) if self._DEBUG: print(self._DEBUG_INFO, "Set debug on") else: print(self._DEBUG_INFO, "Set debug off")
logging.debug("Fan value: " + str(w)) self.set_value(w / 255.0) time.sleep(delay) self.set_value(value) if __name__ == '__main__': import os import logging logging.basicConfig( level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M') PWM.set_frequency(100) fan7 = Fan(7) fan8 = Fan(8) fan9 = Fan(9) fan10 = Fan(10) while 1: for i in xrange(1, 100): fan7.set_value(i / 100.0) fan8.set_value(i / 100.0) fan9.set_value(i / 100.0) fan10.set_value(i / 100.0) time.sleep(0.01) for i in xrange(100, 1, -1): fan7.set_value(i / 100.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"]: 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")
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" )
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")