def position(self): """ Return current machine position (after the latest command) Note that hal might still be moving motors and in this case function will block until motors stops. This function for tests only. :return current position. """ hal.join() return self._position
def _spindle(self, spindle_speed): hal.join() hal.spindle_control(100.0 * spindle_speed / SPINDLE_MAX_RPM)
def do_command(self, gcode): """ Perform action. :param gcode: GCode object which represent one gcode line :return String if any answer require, None otherwise. """ if gcode is None: return None answer = None logging.debug("got command " + str(gcode.params)) # read command c = gcode.command() if c is None and gcode.has_coordinates(): c = 'G1' # read parameters if self._absoluteCoordinates: coord = gcode.coordinates(self._position - self._local, self._convertCoordinates) coord = coord + self._local delta = coord - self._position else: delta = gcode.coordinates(Coordinates(0.0, 0.0, 0.0, 0.0), self._convertCoordinates) # coord = self._position + delta velocity = gcode.get('F', self._velocity) radius = gcode.radius(Coordinates(0.0, 0.0, 0.0, 0.0), self._convertCoordinates) # check parameters if velocity < MIN_VELOCITY_MM_PER_MIN: raise GMachineException("feed speed too low") # select command and run it if c == 'G0': # rapid move vl = max(MAX_VELOCITY_MM_PER_MIN_X, MAX_VELOCITY_MM_PER_MIN_Y, MAX_VELOCITY_MM_PER_MIN_Z, MAX_VELOCITY_MM_PER_MIN_E) l = delta.length() if l > 0: proportion = abs(delta) / l if proportion.x > 0: v = int(MAX_VELOCITY_MM_PER_MIN_X / proportion.x) if v < vl: vl = v if proportion.y > 0: v = int(MAX_VELOCITY_MM_PER_MIN_Y / proportion.y) if v < vl: vl = v if proportion.z > 0: v = int(MAX_VELOCITY_MM_PER_MIN_Z / proportion.z) if v < vl: vl = v if proportion.e > 0: v = int(MAX_VELOCITY_MM_PER_MIN_E / proportion.e) if v < vl: vl = v self._move_linear(delta, vl) elif c == 'G1': # linear interpolation self._move_linear(delta, velocity) elif c == 'G2': # circular interpolation, clockwise self._move_circular(delta, radius, velocity, CW) elif c == 'G3': # circular interpolation, counterclockwise self._move_circular(delta, radius, velocity, CCW) elif c == 'G4': # delay in s if not gcode.has('P'): raise GMachineException("P is not specified") pause = gcode.get('P', 0) if pause < 0: raise GMachineException("bad delay") hal.join() time.sleep(pause) elif c == 'G17': # XY plane select self._plane = PLANE_XY elif c == 'G18': # ZX plane select self._plane = PLANE_ZX elif c == 'G19': # YZ plane select self._plane = PLANE_YZ elif c == 'G20': # switch to inches self._convertCoordinates = 25.4 elif c == 'G21': # switch to mm self._convertCoordinates = 1.0 elif c == 'G28': # home axises = gcode.has('X'), gcode.has('Y'), gcode.has('Z') if axises == (False, False, False): axises = True, True, True self.safe_zero(*axises) hal.join() if not hal.calibrate(*axises): raise GMachineException("failed to calibrate") elif c == 'G53': # switch to machine coords self._local = Coordinates(0.0, 0.0, 0.0, 0.0) elif c == 'G90': # switch to absolute coords self._absoluteCoordinates = True elif c == 'G91': # switch to relative coords self._absoluteCoordinates = False elif c == 'G92': # switch to local coords if gcode.has_coordinates(): self._local = self._position - gcode.coordinates( Coordinates(self._position.x - self._local.x, self._position.y - self._local.y, self._position.z - self._local.z, self._position.e - self._local.e), self._convertCoordinates) else: self._local = self._position elif c == 'M3': # spindle on spindle_rpm = gcode.get('S', self._spindle_rpm) if spindle_rpm < 0 or spindle_rpm > SPINDLE_MAX_RPM: raise GMachineException("bad spindle speed") self._spindle(spindle_rpm) self._spindle_rpm = spindle_rpm elif c == 'M5': # spindle off self._spindle(0) elif c == 'M2' or c == 'M30': # program finish, reset everything. self.reset() elif c == 'M84': # disable motors hal.disable_steppers() # extruder and bed heaters control elif c == 'M104' or c == 'M109' or c == 'M140' or c == 'M190': if c == 'M104' or c == 'M109': heater = HEATER_EXTRUDER elif c == 'M140' or c == 'M190': heater = HEATER_BED else: raise Exception("Unexpected heater command") wait = c == 'M109' or c == 'M190' if not gcode.has("S"): raise GMachineException("temperature is not specified") t = gcode.get('S', 0) if ((heater == HEATER_EXTRUDER and t > EXTRUDER_MAX_TEMPERATURE) or (heater == HEATER_BED and t > BED_MAX_TEMPERATURE) or t < MIN_TEMPERATURE) and t != 0: raise GMachineException("bad temperature") self._heat(heater, t, wait) elif c == 'M105': # get temperature try: et = hal.get_extruder_temperature() except (IOError, OSError): et = None try: bt = hal.get_bed_temperature() except (IOError, OSError): bt = None if et is None and bt is None: raise GMachineException("can not measure temperature") answer = "E:{} B:{}".format(et, bt) elif c == 'M106': # fan control if gcode.get('S', 1) != 0: self._fan(True) else: self._fan(False) elif c == 'M107': # turn off fan self._fan(False) elif c == 'M111': # enable debug logging_config.debug_enable() elif c == 'M114': # get current position hal.join() p = self.position() answer = "X:{} Y:{} Z:{} E:{}".format(p.x, p.y, p.z, p.e) elif c is None: # command not specified(ie just F was passed) pass # commands below are added just for compatibility elif c == 'M82': # absolute mode for extruder if not self._absoluteCoordinates: raise GMachineException("Not supported, use G90/G91") elif c == 'M83': # relative mode for extruder if self._absoluteCoordinates: raise GMachineException("Not supported, use G90/G91") else: raise GMachineException("unknown command") # save parameters on success self._velocity = velocity logging.debug("position {}".format(self._position)) return answer
def do_command(self, gcode): """ Perform action. :param gcode: GCode object which represent one gcode line """ if gcode is None: return logging.debug("got command " + str(gcode.params)) # read command c = gcode.command() if c is None and gcode.has_coordinates(): c = 'G1' # read parameters if self._absoluteCoordinates: coord = gcode.coordinates(self._position, self._convertCoordinates) coord = coord + self._local delta = coord - self._position else: delta = gcode.coordinates(Coordinates(0.0, 0.0, 0.0, 0.0), self._convertCoordinates) coord = self._position + delta velocity = gcode.get('F', self._velocity) spindle_rpm = gcode.get('S', self._spindle_rpm) pause = gcode.get('P', self._pause) radius = gcode.radius(self._radius, self._convertCoordinates) # check parameters if velocity <= 0 or velocity > STEPPER_MAX_VELOCITY_MM_PER_MIN: raise GMachineException("bad feed speed") if spindle_rpm < 0 or spindle_rpm > SPINDLE_MAX_RPM: raise GMachineException("bad spindle speed") if pause < 0: raise GMachineException("bad delay") # select command and run it if c == 'G0': # rapid move self._move_linear(delta, STEPPER_MAX_VELOCITY_MM_PER_MIN) elif c == 'G1': # linear interpolation self._move_linear(delta, velocity) elif c == 'G2': # circular interpolation, clockwise self._circular(delta, radius, velocity, CW) elif c == 'G3': # circular interpolation, counterclockwise self._circular(delta, radius, velocity, CCW) elif c == 'G4': # delay in s hal.join() time.sleep(pause) elif c == 'G17': # XY plane select self._plane = PLANE_XY elif c == 'G18': # ZX plane select self._plane = PLANE_ZX elif c == 'G19': # YZ plane select self._plane = PLANE_YZ elif c == 'G20': # switch to inches self._convertCoordinates = 25.4 elif c == 'G21': # switch to mm self._convertCoordinates = 1.0 elif c == 'G28': # home self.home() elif c == 'G53': # switch to machine coords self._local = Coordinates(0.0, 0.0, 0.0, 0.0) elif c == 'G90': # switch to absolute coords self._absoluteCoordinates = True elif c == 'G91': # switch to relative coords self._absoluteCoordinates = False elif c == 'G92': # switch to local coords self._local = self._position - \ gcode.coordinates(Coordinates(0.0, 0.0, 0.0, 0.0), self._convertCoordinates) elif c == 'M3': # spinle on self._spindle(spindle_rpm) elif c == 'M5': # spindle off self._spindle(0) elif c == 'M2' or c == 'M30': # program finish, reset everything. self.reset() elif c == 'M111': # enable debug logging.getLogger().setLevel(logging.DEBUG) elif c is None: # command not specified(for example, just F was passed) pass else: raise GMachineException("unknown command") # save parameters on success self._velocity = velocity self._spindle_rpm = spindle_rpm self._pause = pause self._radius = radius logging.debug("position {}".format(self._position))
def do_command(self, gcode): """ Perform action. :param gcode: GCode object which represent one gcode line :return String if any answer require, None otherwise. """ if gcode is None: return None answer = None logging.debug("got command " + str(gcode.params)) # read command c = gcode.command() if c is None and gcode.has_coordinates(): c = 'G1' # read parameters if self._absoluteCoordinates: coord = gcode.coordinates(self._position - self._local, self._convertCoordinates) coord = coord + self._local delta = coord - self._position else: delta = gcode.coordinates(Coordinates(0.0, 0.0, 0.0, 0.0), self._convertCoordinates) # coord = self._position + delta velocity = gcode.get('F', self._velocity) radius = gcode.radius(Coordinates(0.0, 0.0, 0.0, 0.0), self._convertCoordinates) # check parameters if velocity < MIN_VELOCITY_MM_PER_MIN: raise GMachineException("feed speed too low") # select command and run it if c == 'G0': # rapid move vl = max(MAX_VELOCITY_MM_PER_MIN_X, MAX_VELOCITY_MM_PER_MIN_Y, MAX_VELOCITY_MM_PER_MIN_Z, self._get_extruder_max_speed()) l = delta.length() if l > 0: proportion = abs(delta) / l if proportion.x > 0: v = int(MAX_VELOCITY_MM_PER_MIN_X / proportion.x) if v < vl: vl = v if proportion.y > 0: v = int(MAX_VELOCITY_MM_PER_MIN_Y / proportion.y) if v < vl: vl = v if proportion.z > 0: v = int(MAX_VELOCITY_MM_PER_MIN_Z / proportion.z) if v < vl: vl = v if proportion.e > 0: v = int(self._get_extruder_max_speed() / proportion.e) if v < vl: vl = v self._move_linear(delta, vl) elif c == 'G1': # linear interpolation self._move_linear(delta, velocity) elif c == 'G2': # circular interpolation, clockwise self._move_circular(delta, radius, velocity, CW) elif c == 'G3': # circular interpolation, counterclockwise self._move_circular(delta, radius, velocity, CCW) elif c == 'G4': # delay in s if not gcode.has('P'): raise GMachineException("P is not specified") pause = gcode.get('P', 0) if pause < 0: raise GMachineException("bad delay") hal.join() time.sleep(pause) elif c == 'G17': # XY plane select self._plane = PLANE_XY elif c == 'G18': # ZX plane select self._plane = PLANE_ZX elif c == 'G19': # YZ plane select self._plane = PLANE_YZ elif c == 'G20': # switch to inches self._convertCoordinates = 25.4 elif c == 'G21': # switch to mm self._convertCoordinates = 1.0 elif c == 'G28': # home axises = gcode.has('X'), gcode.has('Y'), gcode.has('Z') if axises == (False, False, False): axises = True, True, True self.safe_zero(*axises) hal.join() if not hal.calibrate(*axises): raise GMachineException("failed to calibrate") elif c == 'G53': # switch to machine coords raise GMachineException('Not supported') # TODO not sure what local/machine coordinates mean and how to handle this with multiple extruders # self._local = Coordinates(0.0, 0.0, 0.0, 0.0) elif c == 'G90': # switch to absolute coords self._absoluteCoordinates = True elif c == 'G91': # switch to relative coords self._absoluteCoordinates = False elif c == 'G92': # switch to local coords raise GMachineException('Not supported') # if gcode.has_coordinates(): # self._local = self._position - gcode.coordinates( # Coordinates(self._position.x - self._local.x, # self._position.y - self._local.y, # self._position.z - self._local.z, # self._position.e - self._local.e), # self._convertCoordinates) # else: # self._local = self._position elif c == 'M2' or c == 'M30': # program finish, reset everything. self.reset() elif c == 'M72': audio_id = int(gcode.get('P', 0)) if audio_id not in AUDIO_FILES: raise GMachineException('Audio ID not recognized') audio_filepath = AUDIO_BASE_FILEPATH + AUDIO_FILES[audio_id] logging.info('playing audio from {}'.format(audio_filepath)) AudioPlayer.play(audio_filepath) elif c == 'M84': # disable motors hal.disable_steppers() elif c == 'M111': # enable debug logging_config.debug_enable() elif c == 'M114': # get current position hal.join() p = self.position() answer = "X:{} Y:{} Z:{} E:{}".format(p.x, p.y, p.z, p.e) elif c == 'T': # select tool (extruder) self._set_extruder(int(gcode.get('T'))) elif c is None: # command not specified(ie just F was passed) pass # commands below are added just for compatibility elif c == 'M82': # absolute mode for extruder if not self._absoluteCoordinates: raise GMachineException("Not supported, use G90/G91") elif c == 'M83': # relative mode for extruder if self._absoluteCoordinates: raise GMachineException("Not supported, use G90/G91") else: raise GMachineException("unknown command") # save parameters on success self._velocity = velocity logging.debug("position {}".format(self._position)) return answer