idle_timeout: Move timeout handling from toolhead.py to new extras module

Move the "motor_off_timeout" tracking to a new module in the extras/
directory.  This makes it easier to customize the idle timeout
behavior.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2018-07-12 19:07:54 -04:00
parent 0025fbf10d
commit acefe26e0f
7 changed files with 77 additions and 32 deletions

View File

@ -165,6 +165,17 @@
# default is 120.
# Idle timeout. An idle timeout is automatically enabled - add an
# explicit idle_timeout config section to change the default settings.
#[idle_timeout]
#gcode:
# A list of G-Code commands (one per line) to execute on an idle
# timeout. The default is to run "M84".
#timeout: 600
# Idle time (in seconds) to wait before running the above G-Code
# commands. The default is 600 seconds.
# Multi-stepper axes. On a cartesian style printer, the stepper
# controlling a given axis may have additional config blocks defining
# steppers that should be stepped in concert with the primary

View File

@ -293,9 +293,6 @@ max_z_accel: 30
# mm/s^2) of movement along the z axis. It limits the acceleration
# of the z stepper motor on cartesian printers. The default is to
# use max_accel for max_z_accel.
#motor_off_time: 600
# Time (in seconds) of idle time before the printer will try to
# disable active motors. The default is 600 seconds.
#square_corner_velocity: 5.0
# The maximum velocity (in mm/s) that the toolhead may travel a 90
# degree corner at. A non-zero value can reduce changes in extruder

View File

@ -216,5 +216,7 @@ max_velocity: 500
max_accel: 3000
max_z_velocity: 100
max_z_accel: 50
[idle_timeout]
# high motor off time so I don't have to relevel gantry often
motor_off_time: 6000
timeout: 6000

View File

@ -71,9 +71,11 @@ kinematics: delta
max_velocity: 500
max_accel: 3000
max_z_velocity: 150
motor_off_time: 360
delta_radius: 99.8
[idle_timeout]
timeout: 360
#[delta_calibrate]
#radius: 50
#manual_probe:

View File

@ -80,11 +80,13 @@ kinematics: delta
max_velocity: 200
max_accel: 3000
max_z_velocity: 200
motor_off_time: 360
delta_radius: 115
# if you want to DELTA_CALIBRATE you may need that
#minimum_z_position: -5
[idle_timeout]
timeout: 360
#[delta_calibrate]
#radius: 115
#manual_probe:

View File

@ -0,0 +1,48 @@
# Support for disabling the printer on an idle timeout
#
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
DEFAULT_IDLE_GCODE = """
M84
"""
class IdleTimeout:
def __init__(self, config):
self.printer = config.get_printer()
self.toolhead = None
self.last_timeout = 0.
self.idle_timeout = config.getfloat('timeout', 600., above=0.)
self.idle_script = config.get('gcode', DEFAULT_IDLE_GCODE)
def printer_state(self, state):
if state == 'ready':
self.toolhead = self.printer.lookup_object('toolhead')
reactor = self.printer.get_reactor()
reactor.register_timer(self.timeout_handler, reactor.NOW)
def run_idle_script(self):
gcode = self.printer.lookup_object('gcode')
for line in self.idle_script.split('\n'):
try:
res = gcode.process_batch(line)
except:
break
if not res:
# Raced with incoming g-code commands
return
self.last_timeout = self.toolhead.get_last_move_time()
def timeout_handler(self, eventtime):
info = self.toolhead.get_status(eventtime)
print_time = info['print_time']
status = info['status']
if print_time <= self.last_timeout or status == 'Printing':
return eventtime + self.idle_timeout
estimated_print_time = info['estimated_print_time']
elapsed_time = estimated_print_time - print_time
if elapsed_time < self.idle_timeout:
return eventtime + self.idle_timeout - elapsed_time
self.run_idle_script()
return eventtime + 1.
def load_config(config):
return IdleTimeout(config)

View File

@ -231,11 +231,7 @@ class ToolHead:
self.idle_flush_print_time = 0.
self.flush_timer = self.reactor.register_timer(self._flush_handler)
self.move_queue.set_flush_time(self.buffer_time_high)
# Motor off tracking
self.need_motor_off = False
self.motor_off_time = config.getfloat('motor_off_time', 600., above=0.)
self.motor_off_timer = self.reactor.register_timer(
self._motor_off_handler, self.reactor.NOW)
self.printer.try_load_module(config, "idle_timeout")
# Setup iterative solver
ffi_main, ffi_lib = chelper.get_ffi()
self.cmove = ffi_main.gc(ffi_lib.move_alloc(), ffi_lib.free)
@ -266,7 +262,6 @@ class ToolHead:
if not self.sync_print_time:
return self.print_time
self.sync_print_time = False
self.need_motor_off = True
est_print_time = self.mcu.estimated_print_time(self.reactor.monotonic())
if est_print_time + self.buffer_time_start > self.print_time:
self.print_time = est_print_time + self.buffer_time_start
@ -329,19 +324,6 @@ class ToolHead:
logging.exception("Exception in flush_handler")
self.printer.invoke_shutdown("Exception in flush_handler")
return self.reactor.NEVER
# Motor off timer
def _motor_off_handler(self, eventtime):
if not self.need_motor_off or not self.sync_print_time:
return eventtime + self.motor_off_time
elapsed_time = self.mcu.estimated_print_time(eventtime) - self.print_time
if elapsed_time < self.motor_off_time:
return eventtime + self.motor_off_time - elapsed_time
try:
self.motor_off()
except:
logging.exception("Exception in motor_off_handler")
self.printer.invoke_shutdown("Exception in motor_off_handler")
return eventtime + self.motor_off_time
# Movement commands
def get_position(self):
return list(self.commanded_pos)
@ -374,7 +356,6 @@ class ToolHead:
for ext in kinematics.extruder.get_printer_extruders(self.printer):
ext.motor_off(last_move_time)
self.dwell(STALL_TIME)
self.need_motor_off = False
logging.debug('; Max time of %f', last_move_time)
def wait_moves(self):
self._flush_lookahead()
@ -402,15 +383,17 @@ class ToolHead:
return is_active, "print_time=%.3f buffer_time=%.3f print_stall=%d" % (
self.print_time, max(buffer_time, 0.), self.print_stall)
def get_status(self, eventtime):
buffer_time = self.print_time - self.mcu.estimated_print_time(eventtime)
print_time = self.print_time
estimated_print_time = self.mcu.estimated_print_time(eventtime)
last_print_start_time = self.last_print_start_time
buffer_time = print_time - estimated_print_time
if buffer_time > -1. or not self.sync_print_time:
status = "Printing"
elif self.need_motor_off:
status = "Ready"
else:
status = "Idle"
printing_time = self.print_time - self.last_print_start_time
return {'status': status, 'printing_time': printing_time}
status = "Ready"
return { 'status': status, 'print_time': print_time,
'estimated_print_time': estimated_print_time,
'printing_time': print_time - last_print_start_time }
def printer_state(self, state):
if state == 'shutdown':
try: