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 :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