From c6c4592dfb8f5213a2668e392870011b5c2738f4 Mon Sep 17 00:00:00 2001 From: Maxim Devaev Date: Sat, 14 Aug 2021 03:08:28 +0300 Subject: [PATCH 1/3] servo template --- kvmd/plugins/ugpio/servo.py | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 kvmd/plugins/ugpio/servo.py diff --git a/kvmd/plugins/ugpio/servo.py b/kvmd/plugins/ugpio/servo.py new file mode 100644 index 00000000..5a3c9a20 --- /dev/null +++ b/kvmd/plugins/ugpio/servo.py @@ -0,0 +1,83 @@ +# ========================================================================== # +# # +# KVMD - The main Pi-KVM daemon. # +# # +# Copyright (C) 2018-2021 Maxim Devaev # +# Shantur Rathore # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +# ========================================================================== # + + +from typing import Dict + +from ... import aiotools + +from ...yamlconf import Option + +from ...validators.basic import valid_number +from ...validators.basic import valid_int_f0 + +from .pwm import Plugin as PwmPlugin + + +# ===== +class Plugin(PwmPlugin): + def __init__( # pylint: disable=super-init-not-called,too-many-arguments + self, + instance_name: str, + notifier: aiotools.AioNotifier, + + chip: int, + period: int, + duty_cycle_min: int, + duty_cycle_max: int, + angle_min: int, + angle_max: int, + angle_push: int, + angle_release: int, + ) -> None: + + duty_cycle_push = 0 # FIXME + duty_cycle_release = 0 # FIXME + + super().__init__( + instance_name=instance_name, + notifier=notifier, + + chip=chip, + period=period, + duty_cycle_push=duty_cycle_push, + duty_cycle_release=duty_cycle_release, + ) + + @classmethod + def get_plugin_options(cls) -> Dict: + valid_angle = (lambda arg: valid_number(arg, min=0, max=360)) + return { + "chip": Option(0, type=valid_int_f0), + "period": Option(20000000, type=valid_int_f0), + "duty_cycle_min": Option(0, type=valid_int_f0), # FIXME + "duty_cycle_max": Option(0, type=valid_int_f0), # FIXME + "angle_min": Option(0, type=valid_angle), # FIXME + "angle_max": Option(0, type=valid_angle), # FIXME + "angle_push": Option(0, type=valid_angle), # FIXME + "angle_release": Option(0, type=valid_angle), # FIXME + } + + def __str__(self) -> str: + return f"Servo({self._instance_name})" + + __repr__ = __str__ From c644a9f6e1be50888b5973e561c8fdce63fd2604 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Sun, 15 Aug 2021 08:15:53 +0100 Subject: [PATCH 2/3] Implement servo angles (#58) /etc/kvmd/override.yaml ``` kvmd: gpio: drivers: servo1: type: servo chip: 0 # PWM Chip Number period: 20000000 # Servo Motor SG90 Period in nano-seconds duty_cycle_min: 350000 # Servo Motor SG90 duty_cycle for -90 degrees duty_cycle_max: 2350000 # Servo Motor SG90 duty_cycle for +90 degrees angle_max: 90 # Servo Motor SG90 angle at duty_cycle_max angle_min: -90 # Servo Motor SG90 angle at duty_cycle_min angle_push: 45 # Servo Motor SG90 angle to push button angle_release: 20 # Servo Motor SG90 angle to release button scheme: short_press: driver: servo1 pin: 0 # Pin number is the PWM channel number on the PWM Chip mode: output switch: false pulse: delay: 0.5 max_delay: 2 long_press: driver: servo1 pin: 0 # Pin number is the PWM channel number on the PWM Chip mode: output switch: false pulse: delay: 2 max_delay: 2 extra_long_press: driver: servo1 pin: 0 # Pin number is the PWM channel number on the PWM Chip mode: output switch: false pulse: delay: 10 max_delay: 20 view: header: title: Controls table: - ["#Servo - Short Press", "short_press|Press"] - ["#Servo - Long Press", "long_press|Press"] - ["#Servo - Extra Long Press", "extra_long_press|Press"] ``` --- kvmd/plugins/ugpio/servo.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/kvmd/plugins/ugpio/servo.py b/kvmd/plugins/ugpio/servo.py index 5a3c9a20..daa29293 100644 --- a/kvmd/plugins/ugpio/servo.py +++ b/kvmd/plugins/ugpio/servo.py @@ -50,8 +50,14 @@ class Plugin(PwmPlugin): angle_release: int, ) -> None: - duty_cycle_push = 0 # FIXME - duty_cycle_release = 0 # FIXME + #FIXME - Should we implement check for angles to be between the rangle ranges + #FIXME - Same for duty_cycle_push and release to be in ranges (maybe in pwm.py) + + + duty_cycle_per_degree = (duty_cycle_max - duty_cycle_min) / (angle_max - angle_min) + + duty_cycle_push = int(duty_cycle_per_degree * (angle_push - angle_min) + duty_cycle_min) + duty_cycle_release = int(duty_cycle_per_degree * (angle_release - angle_min) + duty_cycle_min) super().__init__( instance_name=instance_name, @@ -65,19 +71,19 @@ class Plugin(PwmPlugin): @classmethod def get_plugin_options(cls) -> Dict: - valid_angle = (lambda arg: valid_number(arg, min=0, max=360)) + valid_angle = (lambda arg: valid_number(arg, min=-360, max=360, type=float)) return { "chip": Option(0, type=valid_int_f0), "period": Option(20000000, type=valid_int_f0), - "duty_cycle_min": Option(0, type=valid_int_f0), # FIXME - "duty_cycle_max": Option(0, type=valid_int_f0), # FIXME - "angle_min": Option(0, type=valid_angle), # FIXME - "angle_max": Option(0, type=valid_angle), # FIXME - "angle_push": Option(0, type=valid_angle), # FIXME - "angle_release": Option(0, type=valid_angle), # FIXME + "duty_cycle_min": Option(1000000, type=valid_int_f0), + "duty_cycle_max": Option(2000000, type=valid_int_f0), + "angle_min": Option(0, type=valid_angle), + "angle_max": Option(180, type=valid_angle), + "angle_push": Option(100, type=valid_angle), + "angle_release": Option(120, type=valid_angle), } def __str__(self) -> str: return f"Servo({self._instance_name})" - __repr__ = __str__ + __repr__ = __str__ \ No newline at end of file From a340fc6053b08ec9564d5834130beadc278af186 Mon Sep 17 00:00:00 2001 From: Maxim Devaev Date: Sun, 15 Aug 2021 10:23:54 +0300 Subject: [PATCH 3/3] minor servo fixes --- kvmd/plugins/ugpio/servo.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/kvmd/plugins/ugpio/servo.py b/kvmd/plugins/ugpio/servo.py index daa29293..448cfdb1 100644 --- a/kvmd/plugins/ugpio/servo.py +++ b/kvmd/plugins/ugpio/servo.py @@ -44,15 +44,14 @@ class Plugin(PwmPlugin): period: int, duty_cycle_min: int, duty_cycle_max: int, - angle_min: int, - angle_max: int, - angle_push: int, - angle_release: int, + angle_min: float, + angle_max: float, + angle_push: float, + angle_release: float, ) -> None: - #FIXME - Should we implement check for angles to be between the rangle ranges - #FIXME - Same for duty_cycle_push and release to be in ranges (maybe in pwm.py) - + angle_push = min(max(angle_push, angle_min), angle_max) + angle_release = min(max(angle_release, angle_min), angle_max) duty_cycle_per_degree = (duty_cycle_max - duty_cycle_min) / (angle_max - angle_min) @@ -71,19 +70,19 @@ class Plugin(PwmPlugin): @classmethod def get_plugin_options(cls) -> Dict: - valid_angle = (lambda arg: valid_number(arg, min=-360, max=360, type=float)) + valid_angle = (lambda arg: valid_number(arg, min=-360.0, max=360.0, type=float)) return { "chip": Option(0, type=valid_int_f0), "period": Option(20000000, type=valid_int_f0), - "duty_cycle_min": Option(1000000, type=valid_int_f0), - "duty_cycle_max": Option(2000000, type=valid_int_f0), - "angle_min": Option(0, type=valid_angle), - "angle_max": Option(180, type=valid_angle), - "angle_push": Option(100, type=valid_angle), - "angle_release": Option(120, type=valid_angle), + "duty_cycle_min": Option(1000000, type=valid_int_f0), + "duty_cycle_max": Option(2000000, type=valid_int_f0), + "angle_min": Option(0.0, type=valid_angle), + "angle_max": Option(180.0, type=valid_angle), + "angle_push": Option(100.0, type=valid_angle), + "angle_release": Option(120.0, type=valid_angle), } def __str__(self) -> str: return f"Servo({self._instance_name})" - __repr__ = __str__ \ No newline at end of file + __repr__ = __str__