toolhead: Force a firmware shutdown on an unhandled exception

Check for unhandled exceptions and force the MCU to shutdown in that
case.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2016-09-19 13:18:55 -04:00
parent 0824d32319
commit a7b81dc05c
3 changed files with 44 additions and 21 deletions

View File

@ -101,7 +101,8 @@ class GCodeParser:
handler(params) handler(params)
except: except:
logging.exception("Exception in command handler") logging.exception("Exception in command handler")
self.respond('echo:Internal error on command:"%s"' % (cmd,)) self.toolhead.force_shutdown()
self.respond('Error: Internal error on command:"%s"' % (cmd,))
# Check if machine can process next command or must stall input # Check if machine can process next command or must stall input
if self.busy_state is not None: if self.busy_state is not None:
break break
@ -142,7 +143,13 @@ class GCodeParser:
self.busy_state = busy_handler self.busy_state = busy_handler
self.reactor.update_timer(self.busy_timer, self.reactor.NOW) self.reactor.update_timer(self.busy_timer, self.reactor.NOW)
def busy_handler(self, eventtime): def busy_handler(self, eventtime):
busy = self.busy_state.check_busy(eventtime) try:
busy = self.busy_state.check_busy(eventtime)
except:
logging.exception("Exception in busy handler")
self.toolhead.force_shutdown()
self.respond('Error: Internal error in busy handler')
busy = False
if busy: if busy:
self.toolhead.reset_motor_off_time(eventtime) self.toolhead.reset_motor_off_time(eventtime)
return eventtime + self.RETRY_TIME return eventtime + self.RETRY_TIME

View File

@ -252,6 +252,7 @@ class MCU:
self.is_shutdown = False self.is_shutdown = False
self.output_file_mode = False self.output_file_mode = False
# Config building # Config building
self._emergency_stop_cmd = None
self._num_oids = 0 self._num_oids = 0
self._config_cmds = [] self._config_cmds = []
self._config_crc = None self._config_crc = None
@ -328,6 +329,8 @@ class MCU:
if err: if err:
stats += " step_errors=%d" % (err,) stats += " step_errors=%d" % (err,)
return stats return stats
def force_shutdown(self):
self.send(self._emergency_stop_cmd.encode())
# Configuration phase # Configuration phase
def _add_custom(self): def _add_custom(self):
data = self._config.get('custom', '') data = self._config.get('custom', '')
@ -340,6 +343,7 @@ class MCU:
continue continue
self.add_config_cmd(line) self.add_config_cmd(line)
def build_config(self): def build_config(self):
self._emergency_stop_cmd = self.lookup_command("emergency_stop")
# Build config commands # Build config commands
self._add_custom() self._add_custom()
self._config_cmds.insert(0, "allocate_oids count=%d" % ( self._config_cmds.insert(0, "allocate_oids count=%d" % (
@ -504,6 +508,8 @@ class DummyMCU:
pass pass
def stats(self, eventtime): def stats(self, eventtime):
return "" return ""
def force_shutdown(self):
pass
def build_config(self): def build_config(self):
pass pass
def create_stepper(self, step_pin, dir_pin, min_stop_interval, max_error): def create_stepper(self, step_pin, dir_pin, min_stop_interval, max_error):

View File

@ -85,6 +85,9 @@ class MoveQueue:
self.queue = [] self.queue = []
self.prev_junction_max = 0. self.prev_junction_max = 0.
self.junction_flush = 0. self.junction_flush = 0.
def reset(self):
del self.queue[:]
self.prev_junction_max = self.junction_flush = 0.
def flush(self, lazy=False): def flush(self, lazy=False):
can_flush = not lazy can_flush = not lazy
flush_count = len(self.queue) flush_count = len(self.queue)
@ -186,26 +189,30 @@ class ToolHead:
eventtime, self.print_time) eventtime, self.print_time)
return buffer_time > self.buffer_time_high return buffer_time > self.buffer_time_high
def flush_handler(self, eventtime): def flush_handler(self, eventtime):
if not self.print_time: try:
self.move_queue.flush()
if not self.print_time: if not self.print_time:
if eventtime >= self.motor_off_time: self.move_queue.flush()
self.motor_off() if not self.print_time:
self.reset_print_time() if eventtime >= self.motor_off_time:
self.motor_off_time = self.reactor.NEVER self.motor_off()
return self.motor_off_time self.reset_print_time()
print_time = self.print_time self.motor_off_time = self.reactor.NEVER
buffer_time = self.printer.mcu.get_print_buffer_time( return self.motor_off_time
eventtime, print_time) print_time = self.print_time
if buffer_time > self.buffer_time_low: buffer_time = self.printer.mcu.get_print_buffer_time(
return eventtime + buffer_time - self.buffer_time_low eventtime, print_time)
self.move_queue.flush() if buffer_time > self.buffer_time_low:
if print_time != self.print_time: return eventtime + buffer_time - self.buffer_time_low
self.print_time_stall += 1 self.move_queue.flush()
self.dwell(self.buffer_time_low + STALL_TIME) if print_time != self.print_time:
return self.reactor.NOW self.print_time_stall += 1
self.reset_print_time() self.dwell(self.buffer_time_low + STALL_TIME)
return self.motor_off_time return self.reactor.NOW
self.reset_print_time()
return self.motor_off_time
except:
logging.exception("Exception in flush_handler")
self.force_shutdown()
def stats(self, eventtime): def stats(self, eventtime):
buffer_time = 0. buffer_time = 0.
if self.print_time: if self.print_time:
@ -273,3 +280,6 @@ class ToolHead:
self.extruder.motor_off(last_move_time) self.extruder.motor_off(last_move_time)
self.dwell(STALL_TIME) self.dwell(STALL_TIME)
logging.debug('; Max time of %f' % (last_move_time,)) logging.debug('; Max time of %f' % (last_move_time,))
def force_shutdown(self):
self.printer.mcu.force_shutdown()
self.move_queue.reset()