mirror of https://github.com/Desuuuu/klipper.git
gcode: Support parsing of "extended" gcode commands
Support human readable commands (eg, "help"). Add a "help" command to list these extended commands. Also, add support for declaring command aliases, command help, and command availability next to the handlers themselves. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
35719e665c
commit
a6055ce069
|
@ -28,11 +28,6 @@ Host user interaction
|
||||||
|
|
||||||
* Improve gcode interface:
|
* Improve gcode interface:
|
||||||
|
|
||||||
* Support ASCII based commands in addition to common gcode
|
|
||||||
commands. It would be useful to support high-level commands such as
|
|
||||||
"query_endstops", "pid_autotune", and "help" instead of having to
|
|
||||||
invent cryptic gcode commands (eg, "M119" and "M303").
|
|
||||||
|
|
||||||
* Provide a better way to handle print nozzle z offsets. The M206
|
* Provide a better way to handle print nozzle z offsets. The M206
|
||||||
command is cryptic to use and it is too easy to set the value
|
command is cryptic to use and it is too easy to set the value
|
||||||
incorrectly or to forget to set it.
|
incorrectly or to forget to set it.
|
||||||
|
|
|
@ -45,20 +45,23 @@ class GCodeParser:
|
||||||
self.heater_bed = self.printer.objects.get('heater_bed')
|
self.heater_bed = self.printer.objects.get('heater_bed')
|
||||||
self.fan = self.printer.objects.get('fan')
|
self.fan = self.printer.objects.get('fan')
|
||||||
def build_handlers(self):
|
def build_handlers(self):
|
||||||
shutdown_handlers = ['M105', 'M110', 'M114']
|
handlers = ['G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92',
|
||||||
handlers = ['G0', 'G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92',
|
'M18', 'M82', 'M83', 'M105', 'M110', 'M114', 'M206',
|
||||||
'M18', 'M82', 'M83', 'M84',
|
'HELP', 'QUERY_ENDSTOPS']
|
||||||
'M105', 'M110', 'M114', 'M119', 'M206']
|
|
||||||
if self.heater_nozzle is not None:
|
if self.heater_nozzle is not None:
|
||||||
handlers.extend(['M104', 'M109', 'M303'])
|
handlers.extend(['M104', 'M109', 'PID_TUNE'])
|
||||||
if self.heater_bed is not None:
|
if self.heater_bed is not None:
|
||||||
handlers.extend(['M140', 'M190'])
|
handlers.extend(['M140', 'M190'])
|
||||||
if self.fan is not None:
|
if self.fan is not None:
|
||||||
handlers.extend(['M106', 'M107'])
|
handlers.extend(['M106', 'M107'])
|
||||||
if not self.is_printer_ready:
|
if not self.is_printer_ready:
|
||||||
handlers = [h for h in handlers if h in shutdown_handlers]
|
handlers = [h for h in handlers
|
||||||
|
if getattr(self, 'cmd_'+h+'_when_not_ready', False)]
|
||||||
self.gcode_handlers = dict((h, getattr(self, 'cmd_'+h))
|
self.gcode_handlers = dict((h, getattr(self, 'cmd_'+h))
|
||||||
for h in handlers)
|
for h in handlers)
|
||||||
|
for h, f in self.gcode_handlers.items():
|
||||||
|
aliases = getattr(self, 'cmd_'+h+'_aliases', [])
|
||||||
|
self.gcode_handlers.update(dict([(a, f) for a in aliases]))
|
||||||
def finish(self):
|
def finish(self):
|
||||||
self.reactor.end()
|
self.reactor.end()
|
||||||
self.toolhead.motor_off()
|
self.toolhead.motor_off()
|
||||||
|
@ -85,7 +88,7 @@ class GCodeParser:
|
||||||
for eventtime, data in self.input_log:
|
for eventtime, data in self.input_log:
|
||||||
logging.info("Read %f: %s" % (eventtime, repr(data)))
|
logging.info("Read %f: %s" % (eventtime, repr(data)))
|
||||||
# Parse input into commands
|
# Parse input into commands
|
||||||
args_r = re.compile('([a-zA-Z*])')
|
args_r = re.compile('([a-zA-Z_]+|[a-zA-Z*])')
|
||||||
def process_commands(self, eventtime):
|
def process_commands(self, eventtime):
|
||||||
i = -1
|
i = -1
|
||||||
for i in range(len(self.input_commands)-1):
|
for i in range(len(self.input_commands)-1):
|
||||||
|
@ -106,7 +109,7 @@ class GCodeParser:
|
||||||
if not parts:
|
if not parts:
|
||||||
self.cmd_default(params)
|
self.cmd_default(params)
|
||||||
continue
|
continue
|
||||||
params['#command'] = cmd = parts[0] + parts[1].strip()
|
params['#command'] = cmd = parts[0].upper() + parts[1].strip()
|
||||||
# Invoke handler for command
|
# Invoke handler for command
|
||||||
self.need_ack = True
|
self.need_ack = True
|
||||||
handler = self.gcode_handlers.get(cmd, self.cmd_default)
|
handler = self.gcode_handlers.get(cmd, self.cmd_default)
|
||||||
|
@ -226,9 +229,8 @@ class GCodeParser:
|
||||||
logging.debug(params['#original'])
|
logging.debug(params['#original'])
|
||||||
return
|
return
|
||||||
self.respond('echo:Unknown command:"%s"' % (cmd,))
|
self.respond('echo:Unknown command:"%s"' % (cmd,))
|
||||||
def cmd_G0(self, params):
|
cmd_G1_aliases = ['G0']
|
||||||
self.cmd_G1(params, sloppy=True)
|
def cmd_G1(self, params):
|
||||||
def cmd_G1(self, params, sloppy=False):
|
|
||||||
# Move
|
# Move
|
||||||
for a, p in self.axis2pos.items():
|
for a, p in self.axis2pos.items():
|
||||||
if a in params:
|
if a in params:
|
||||||
|
@ -242,7 +244,7 @@ class GCodeParser:
|
||||||
if 'F' in params:
|
if 'F' in params:
|
||||||
self.speed = float(params['F']) / 60.
|
self.speed = float(params['F']) / 60.
|
||||||
try:
|
try:
|
||||||
self.toolhead.move(self.last_position, self.speed, sloppy)
|
self.toolhead.move(self.last_position, self.speed)
|
||||||
except homing.EndstopError, e:
|
except homing.EndstopError, e:
|
||||||
self.respond_error(str(e))
|
self.respond_error(str(e))
|
||||||
self.last_position = self.toolhead.get_position()
|
self.last_position = self.toolhead.get_position()
|
||||||
|
@ -299,12 +301,11 @@ class GCodeParser:
|
||||||
def cmd_M83(self, params):
|
def cmd_M83(self, params):
|
||||||
# Use relative distances for extrusion
|
# Use relative distances for extrusion
|
||||||
self.absoluteextrude = False
|
self.absoluteextrude = False
|
||||||
|
cmd_M18_aliases = ["M84"]
|
||||||
def cmd_M18(self, params):
|
def cmd_M18(self, params):
|
||||||
# Turn off motors
|
# Turn off motors
|
||||||
self.toolhead.motor_off()
|
self.toolhead.motor_off()
|
||||||
def cmd_M84(self, params):
|
cmd_M105_when_not_ready = True
|
||||||
# Stop idle hold
|
|
||||||
self.toolhead.motor_off()
|
|
||||||
def cmd_M105(self, params):
|
def cmd_M105(self, params):
|
||||||
# Get Extruder Temperature
|
# Get Extruder Temperature
|
||||||
self.ack(self.get_temp())
|
self.ack(self.get_temp())
|
||||||
|
@ -314,9 +315,11 @@ class GCodeParser:
|
||||||
def cmd_M109(self, params):
|
def cmd_M109(self, params):
|
||||||
# Set Extruder Temperature and Wait
|
# Set Extruder Temperature and Wait
|
||||||
self.set_temp(self.heater_nozzle, params, wait=True)
|
self.set_temp(self.heater_nozzle, params, wait=True)
|
||||||
|
cmd_M110_when_not_ready = True
|
||||||
def cmd_M110(self, params):
|
def cmd_M110(self, params):
|
||||||
# Set Current Line Number
|
# Set Current Line Number
|
||||||
pass
|
pass
|
||||||
|
cmd_M114_when_not_ready = True
|
||||||
def cmd_M114(self, params):
|
def cmd_M114(self, params):
|
||||||
# Get Current Position
|
# Get Current Position
|
||||||
if self.toolhead is None:
|
if self.toolhead is None:
|
||||||
|
@ -327,14 +330,6 @@ class GCodeParser:
|
||||||
self.last_position[0], self.last_position[1],
|
self.last_position[0], self.last_position[1],
|
||||||
self.last_position[2], self.last_position[3],
|
self.last_position[2], self.last_position[3],
|
||||||
kinpos[0], kinpos[1], kinpos[2]))
|
kinpos[0], kinpos[1], kinpos[2]))
|
||||||
def cmd_M119(self, params):
|
|
||||||
# Get Endstop Status
|
|
||||||
if self.is_fileinput:
|
|
||||||
return
|
|
||||||
print_time = self.toolhead.get_last_move_time()
|
|
||||||
query_state = homing.QueryEndstops(print_time, self.respond)
|
|
||||||
self.toolhead.query_endstops(query_state)
|
|
||||||
self.set_busy(query_state)
|
|
||||||
def cmd_M140(self, params):
|
def cmd_M140(self, params):
|
||||||
# Set Bed Temperature
|
# Set Bed Temperature
|
||||||
self.set_temp(self.heater_bed, params)
|
self.set_temp(self.heater_bed, params)
|
||||||
|
@ -356,10 +351,29 @@ class GCodeParser:
|
||||||
v = float(params[a])
|
v = float(params[a])
|
||||||
self.base_position[p] += self.homing_add[p] - v
|
self.base_position[p] += self.homing_add[p] - v
|
||||||
self.homing_add[p] = v
|
self.homing_add[p] = v
|
||||||
def cmd_M303(self, params):
|
cmd_QUERY_ENDSTOPS_help = "Report on the status of each endstop"
|
||||||
|
cmd_QUERY_ENDSTOPS_aliases = ["M119"]
|
||||||
|
def cmd_QUERY_ENDSTOPS(self, params):
|
||||||
|
# Get Endstop Status
|
||||||
|
if self.is_fileinput:
|
||||||
|
return
|
||||||
|
print_time = self.toolhead.get_last_move_time()
|
||||||
|
query_state = homing.QueryEndstops(print_time, self.respond)
|
||||||
|
self.toolhead.query_endstops(query_state)
|
||||||
|
self.set_busy(query_state)
|
||||||
|
cmd_PID_TUNE_help = "Run PID Tuning"
|
||||||
|
cmd_PID_TUNE_aliases = ["M303"]
|
||||||
|
def cmd_PID_TUNE(self, params):
|
||||||
# Run PID tuning
|
# Run PID tuning
|
||||||
heater = int(params.get('E', '0'))
|
heater = int(params.get('E', '0'))
|
||||||
heater = {0: self.heater_nozzle, -1: self.heater_bed}[heater]
|
heater = {0: self.heater_nozzle, -1: self.heater_bed}[heater]
|
||||||
temp = float(params.get('S', '60'))
|
temp = float(params.get('S', '60'))
|
||||||
heater.start_auto_tune(temp)
|
heater.start_auto_tune(temp)
|
||||||
self.bg_temp(heater)
|
self.bg_temp(heater)
|
||||||
|
def cmd_HELP(self, params):
|
||||||
|
cmdhelp = ["// Available extended commands:"]
|
||||||
|
for cmd in self.gcode_handlers:
|
||||||
|
desc = getattr(self, 'cmd_'+cmd+'_help', None)
|
||||||
|
if desc is not None:
|
||||||
|
cmdhelp.append("%-10s: %s" % (cmd, desc))
|
||||||
|
self.respond("\n// ".join(cmdhelp))
|
||||||
|
|
|
@ -248,7 +248,7 @@ class ToolHead:
|
||||||
self.move_queue.flush()
|
self.move_queue.flush()
|
||||||
self.commanded_pos[:] = newpos
|
self.commanded_pos[:] = newpos
|
||||||
self.kin.set_position(newpos)
|
self.kin.set_position(newpos)
|
||||||
def move(self, newpos, speed, sloppy=False):
|
def move(self, newpos, speed):
|
||||||
speed = min(speed, self.max_speed)
|
speed = min(speed, self.max_speed)
|
||||||
move = Move(self, self.commanded_pos, newpos, speed, self.max_accel)
|
move = Move(self, self.commanded_pos, newpos, speed, self.max_accel)
|
||||||
if not move.move_d:
|
if not move.move_d:
|
||||||
|
|
Loading…
Reference in New Issue