Skip to content

Commit

Permalink
servo: Use GCodeRequestQueue to queue updates
Browse files Browse the repository at this point in the history
Signed-off-by: Kevin O'Connor <[email protected]>
  • Loading branch information
KevinOConnor committed Sep 12, 2024
1 parent 7940a6a commit 28995a8
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
9 changes: 9 additions & 0 deletions docs/Config_Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ All dates in this document are approximate.

## Changes

20240912: `SET_PIN`, `SET_SERVO`, `SET_FAN_SPEED`, `M106`, and `M107`
commands are now collated. Previously, if many updates to the same
object were issued faster than the minimum scheduling time (typically
100ms) then actual updates could be queued far into the future. Now if
many updates are issued in rapid succession then it is possible that
only the latest request will be applied. If the previous behavior is
requried then consider adding explicit `G4` delay commands between
updates.

20240912: Support for `maximum_mcu_duration` and `static_value`
parameters in `[output_pin]` config sections have been removed. These
options have been deprecated since 20240123.
Expand Down
23 changes: 11 additions & 12 deletions klippy/extras/servo.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Support for servos
#
# Copyright (C) 2017-2020 Kevin O'Connor <[email protected]>
# Copyright (C) 2017-2024 Kevin O'Connor <[email protected]>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
from . import output_pin

SERVO_SIGNAL_PERIOD = 0.020
PIN_MIN_TIME = 0.100

class PrinterServo:
def __init__(self, config):
Expand All @@ -18,7 +18,7 @@ def __init__(self, config):
self.max_angle = config.getfloat('maximum_servo_angle', 180.)
self.angle_to_width = (self.max_width - self.min_width) / self.max_angle
self.width_to_value = 1. / SERVO_SIGNAL_PERIOD
self.last_value = self.last_value_time = 0.
self.last_value = 0.
initial_pwm = 0.
iangle = config.getfloat('initial_angle', None, minval=0., maxval=360.)
if iangle is not None:
Expand All @@ -33,6 +33,9 @@ def __init__(self, config):
self.mcu_servo.setup_max_duration(0.)
self.mcu_servo.setup_cycle_time(SERVO_SIGNAL_PERIOD)
self.mcu_servo.setup_start_value(initial_pwm, 0.)
# Create gcode request queue
self.gcrq = output_pin.GCodeRequestQueue(
config, self.mcu_servo.get_mcu(), self._set_pwm)
# Register commands
servo_name = config.get_name().split()[1]
gcode = self.printer.lookup_object('gcode')
Expand All @@ -42,12 +45,10 @@ def __init__(self, config):
def get_status(self, eventtime):
return {'value': self.last_value}
def _set_pwm(self, print_time, value):
if value == self.last_value:
return
print_time = max(print_time, self.last_value_time + PIN_MIN_TIME)
self.mcu_servo.set_pwm(print_time, value)
self.last_value = value
self.last_value_time = print_time
if value != self.last_value:
self.last_value = value
self.mcu_servo.set_pwm(print_time, value)
return (True, 0.)
def _get_pwm_from_angle(self, angle):
angle = max(0., min(self.max_angle, angle))
width = self.min_width + angle * self.angle_to_width
Expand All @@ -64,9 +65,7 @@ def cmd_SET_SERVO(self, gcmd):
else:
angle = gcmd.get_float('ANGLE')
value = self._get_pwm_from_angle(angle)
toolhead = self.printer.lookup_object('toolhead')
toolhead.register_lookahead_callback((lambda pt:
self._set_pwm(pt, value)))
self.gcrq.queue_gcode_request(value)

def load_config_prefix(config):
return PrinterServo(config)

0 comments on commit 28995a8

Please sign in to comment.