feat: ✨ 舵机控制模块
This commit is contained in:
parent
d96a7dc599
commit
92f40c1cf4
46
k230/02test_servo.py
Normal file
46
k230/02test_servo.py
Normal file
@ -0,0 +1,46 @@
|
||||
# 02test_servo.py
|
||||
# 舵机测试程序:最大 -> 最小 -> 中间
|
||||
# 适用于庐山派 K230-CanMV 开发板
|
||||
|
||||
from servo_module import ServoController
|
||||
import time
|
||||
import sys
|
||||
|
||||
sys.path.append("/sdcard")
|
||||
|
||||
|
||||
# 创建舵机对象 (GPIO47, 角度范围0-270度)
|
||||
servo = ServoController(gpio_pin=47, min_angle=0, max_angle=360, servo_range=360)
|
||||
|
||||
print("舵机测试开始...")
|
||||
|
||||
# try:
|
||||
# # 1. 移动到最大角度
|
||||
# print("移动到最大角度")
|
||||
# servo.set_angle(360)
|
||||
# time.sleep(1)
|
||||
|
||||
# # 2. 移动到最小角度 (0度)
|
||||
# print("移动到最小角度: 0")
|
||||
# servo.set_angle(0)
|
||||
# time.sleep(1)
|
||||
|
||||
# # 3. 回到中间位置 (135度)
|
||||
# print("回到中间位置: 135")
|
||||
# servo.center()
|
||||
# time.sleep(1)
|
||||
|
||||
# print("测试完成!")
|
||||
|
||||
|
||||
# except KeyboardInterrupt:
|
||||
# print("用户停止")
|
||||
# finally:
|
||||
# servo.deinit()
|
||||
# print("舵机资源已释放")
|
||||
|
||||
|
||||
# 360度舵机需要一直发! sg90。 0-180为顺(速度变小) 180-360为逆(速度变大)。
|
||||
while True:
|
||||
servo.set_angle(360)
|
||||
time.sleep(1)
|
||||
141
k230/servo_module.py
Normal file
141
k230/servo_module.py
Normal file
@ -0,0 +1,141 @@
|
||||
# servo_module.py
|
||||
# 舵机控制模块
|
||||
# 适用于庐山派 K230-CanMV 开发板
|
||||
|
||||
from machine import PWM, FPIOA
|
||||
|
||||
# GPIO引脚与PWM通道的固定映射 (40PIN排针可用)
|
||||
# 排针引脚号 | 芯片引脚号 | PWM通道号
|
||||
# 12 | GPIO 47 | PWM3
|
||||
# 26 | GPIO 61 | PWM1
|
||||
# 32 | GPIO 46 | PWM2
|
||||
# 33 | GPIO 52 | PWM4
|
||||
# 35 | GPIO 42 | PWM0
|
||||
GPIO_PWM_MAP = {
|
||||
42: 0, # GPIO42 -> PWM0 (排针35)
|
||||
46: 2, # GPIO46 -> PWM2 (排针32)
|
||||
47: 3, # GPIO47 -> PWM3 (排针12)
|
||||
52: 4, # GPIO52 -> PWM4 (排针33)
|
||||
61: 1, # GPIO61 -> PWM1 (排针26)
|
||||
}
|
||||
|
||||
# PWM通道对应的FPIOA功能
|
||||
PWM_FPIOA_MAP = {
|
||||
0: FPIOA.PWM0,
|
||||
1: FPIOA.PWM1,
|
||||
2: FPIOA.PWM2,
|
||||
3: FPIOA.PWM3,
|
||||
4: FPIOA.PWM4,
|
||||
}
|
||||
|
||||
|
||||
class ServoController:
|
||||
"""舵机控制类,支持角度控制和增量控制"""
|
||||
|
||||
def __init__(self, gpio_pin, min_angle=0, max_angle=270, servo_range=None):
|
||||
"""
|
||||
初始化舵机控制器
|
||||
|
||||
参数:
|
||||
gpio_pin: GPIO引脚号 (42, 46, 47, 52, 61)
|
||||
min_angle: 软件最小角度限制 (默认0)
|
||||
max_angle: 软件最大角度限制 (默认270)
|
||||
servo_range: 舵机物理最大角度范围 (默认与max_angle相同)
|
||||
用于脉宽计算,如180度舵机填180,270度舵机填270
|
||||
"""
|
||||
# 检查引脚是否支持
|
||||
if gpio_pin not in GPIO_PWM_MAP:
|
||||
raise ValueError("不支持的GPIO引脚,请使用42, 46, 47, 52, 61")
|
||||
|
||||
self._gpio_pin = gpio_pin
|
||||
self._pwm_channel = GPIO_PWM_MAP[gpio_pin]
|
||||
self._min_angle = min_angle
|
||||
self._max_angle = max_angle
|
||||
# 舵机物理角度范围,用于脉宽计算
|
||||
self._servo_range = servo_range if servo_range is not None else max_angle
|
||||
self._current_angle = (min_angle + max_angle) / 2 # 默认中间位置
|
||||
|
||||
# 配置GPIO为PWM功能
|
||||
self._fpioa = FPIOA()
|
||||
self._fpioa.set_function(gpio_pin, PWM_FPIOA_MAP[self._pwm_channel])
|
||||
|
||||
# 初始化PWM,频率50Hz
|
||||
self._pwm = PWM(self._pwm_channel)
|
||||
self._pwm.freq(50)
|
||||
|
||||
# 移动到初始位置
|
||||
self._update_pwm()
|
||||
|
||||
def _angle_to_duty(self, angle):
|
||||
"""
|
||||
将角度转换为PWM占空比值
|
||||
|
||||
舵机PWM信号: 周期20ms
|
||||
- 0.5ms脉宽 -> 0度
|
||||
- 2.5ms脉宽 -> 舵机最大角度
|
||||
根据servo_range动态计算
|
||||
"""
|
||||
# 脉宽范围: 0.5ms - 2.5ms,根据舵机物理范围计算
|
||||
pulse_ms = 0.5 + (angle / self._servo_range) * 2.0
|
||||
# 占空比: pulse_ms / 20ms * 65535
|
||||
duty = int((pulse_ms / 20.0) * 65535)
|
||||
return duty
|
||||
|
||||
def _clamp_angle(self, angle):
|
||||
"""限制角度在有效范围内"""
|
||||
if angle < self._min_angle:
|
||||
return self._min_angle
|
||||
if angle > self._max_angle:
|
||||
return self._max_angle
|
||||
return angle
|
||||
|
||||
def _update_pwm(self):
|
||||
"""更新PWM输出"""
|
||||
duty = self._angle_to_duty(self._current_angle)
|
||||
self._pwm.duty_u16(duty)
|
||||
|
||||
def set_angle(self, angle):
|
||||
"""
|
||||
设置舵机到指定角度
|
||||
|
||||
参数:
|
||||
angle: 目标角度
|
||||
"""
|
||||
self._current_angle = self._clamp_angle(angle)
|
||||
self._update_pwm()
|
||||
|
||||
def get_angle(self):
|
||||
"""
|
||||
获取当前角度
|
||||
|
||||
返回:
|
||||
当前角度值
|
||||
"""
|
||||
return self._current_angle
|
||||
|
||||
def rotate(self, direction, step):
|
||||
"""
|
||||
增量控制舵机
|
||||
|
||||
参数:
|
||||
direction: 方向,1为顺时针(角度增大),-1为逆时针(角度减小)
|
||||
step: 步进角度 (如0.1, 1, 5等)
|
||||
|
||||
返回:
|
||||
转动后的角度
|
||||
"""
|
||||
new_angle = self._current_angle + (direction * step)
|
||||
self._current_angle = self._clamp_angle(new_angle)
|
||||
self._update_pwm()
|
||||
return self._current_angle
|
||||
|
||||
def center(self):
|
||||
"""舵机归中,移动到角度范围的中间位置"""
|
||||
center_angle = (self._min_angle + self._max_angle) / 2
|
||||
self.set_angle(center_angle)
|
||||
|
||||
def deinit(self):
|
||||
"""释放PWM资源"""
|
||||
if self._pwm:
|
||||
self._pwm.deinit()
|
||||
self._pwm = None
|
||||
Loading…
x
Reference in New Issue
Block a user