-
Notifications
You must be signed in to change notification settings - Fork 40
Check fraction range; add post-constructor access to actuation_range and pulse widths. #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
4168b4e
d214497
e6f8b4e
f0589ba
38a9b60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,10 +41,14 @@ class _BaseServo: # pylint: disable-msg=too-few-public-methods | |
:param int min_pulse: The minimum pulse length of the servo in microseconds. | ||
:param int max_pulse: The maximum pulse length of the servo in microseconds.""" | ||
def __init__(self, pwm_out, *, min_pulse=750, max_pulse=2250): | ||
self._min_duty = int((min_pulse * pwm_out.frequency) / 1000000 * 0xffff) | ||
max_duty = (max_pulse * pwm_out.frequency) / 1000000 * 0xffff | ||
self._duty_range = int(max_duty - self._min_duty) | ||
self._pwm_out = pwm_out | ||
self.set_pulse_widths(min_pulse, max_pulse) | ||
|
||
def set_pulse_widths(self, min_pulse=750, max_pulse=2250): | ||
"""Change pulse widths.""" | ||
self._min_duty = int((min_pulse * self._pwm_out.frequency) / 1000000 * 0xffff) | ||
max_duty = (max_pulse * self._pwm_out.frequency) / 1000000 * 0xffff | ||
self._duty_range = int(max_duty - self._min_duty) | ||
|
||
@property | ||
def fraction(self): | ||
|
@@ -56,6 +60,8 @@ def fraction(self): | |
|
||
@fraction.setter | ||
def fraction(self, value): | ||
if not 0.0 <= value <= 1.0: | ||
raise ValueError("Must be 0.0 to 1.0") | ||
duty_cycle = self._min_duty + int(value * self._duty_range) | ||
self._pwm_out.duty_cycle = duty_cycle | ||
|
||
|
@@ -68,6 +74,13 @@ class Servo(_BaseServo): | |
:param int min_pulse: The minimum pulse width of the servo in microseconds. | ||
:param int max_pulse: The maximum pulse width of the servo in microseconds. | ||
|
||
``actuation_range`` is an exposed property and can be changed at any time: | ||
|
||
.. code-block:: python | ||
|
||
servo = Servo(pwm) | ||
servo.actuation_range = 135 | ||
|
||
The specified pulse width range of a servo has historically been 1000-2000us, | ||
for a 90 degree range of motion. But nearly all modern servos have a 170-180 | ||
degree range, and the pulse widths can go well out of the range to achieve this | ||
|
@@ -83,19 +96,19 @@ class Servo(_BaseServo): | |
""" | ||
def __init__(self, pwm_out, *, actuation_range=180, min_pulse=750, max_pulse=2250): | ||
super().__init__(pwm_out, min_pulse=min_pulse, max_pulse=max_pulse) | ||
self._actuation_range = actuation_range | ||
self.actuation_range = actuation_range | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a triple quoted doc string here so it is included in RTD. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the Alphabetically There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does for the argument but not the object attribute (like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused. Here is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was impressively difficult to do this. I can add a docstring after the The other alternative is to document |
||
self._pwm = pwm_out | ||
|
||
@property | ||
def angle(self): | ||
"""The servo angle in degrees. Must be in the range ``0`` to ``actuation_range``.""" | ||
return self._actuation_range * self.fraction | ||
return self.actuation_range * self.fraction | ||
|
||
@angle.setter | ||
def angle(self, new_angle): | ||
if new_angle < 0 or new_angle > self._actuation_range: | ||
if new_angle < 0 or new_angle > self.actuation_range: | ||
raise ValueError("Angle out of range") | ||
self.fraction = new_angle / self._actuation_range | ||
self.fraction = new_angle / self.actuation_range | ||
|
||
class ContinuousServo(_BaseServo): | ||
"""Control a continuous rotation servo. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like
set_pulse_width_range
more.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dropped the
s
too.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it shouldn't have default values for the args, so you have to give both? I'm vacillating on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having default values was what motivated the original choice of name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like defaults because it allows one to use the name in the call. aka
servo.set_pulse_width_range(min_pulse=700, max_pulse=2000)
You could even force it with:def set_pulse_widths(self, *, min_pulse=750, max_pulse=2250):