139 lines
4.5 KiB
Python
139 lines
4.5 KiB
Python
|
|
#!/usr/bin/env python
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
'''
|
|||
|
|
# @Time : 2025/9/24 16:55
|
|||
|
|
# @Author : reenrr
|
|||
|
|
# @File : servo_motor_PWM.py
|
|||
|
|
'''
|
|||
|
|
#!/usr/bin/env python
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
'''
|
|||
|
|
# @Time : 2025/9/24 10:30
|
|||
|
|
# @Author : reenrr
|
|||
|
|
# @File : servo_motor_pwm.py
|
|||
|
|
# 功能描述:RK3506通过硬件PWM控制DS3235舵机(模拟持续旋转)
|
|||
|
|
# 参考文档:DS3235 Coreless datasheet.pdf、瑞芯微RK3506 PWM控制器文档
|
|||
|
|
'''
|
|||
|
|
import time
|
|||
|
|
import signal
|
|||
|
|
import os
|
|||
|
|
|
|||
|
|
# -------------------------- 1. 硬件配置(必须根据实际接线调整) --------------------------
|
|||
|
|
# 1.1 舵机PWM通道(RK3506的PWM通道,需与硬件接线对应)
|
|||
|
|
# 瑞芯微RK3506通常有多个PWM通道,如pwm0, pwm1等,根据实际使用的通道修改
|
|||
|
|
PWM_CHIP = 0 # PWM芯片编号
|
|||
|
|
PWM_CHANNEL = 0 # PWM通道编号
|
|||
|
|
PWM_PATH = f"/sys/class/pwm/pwmchip{PWM_CHIP}/pwm{PWM_CHANNEL}" # 已经通过设备树绑定到了相关的引脚上了
|
|||
|
|
|
|||
|
|
# 1.2 DS3235舵机核心参数(来自DS3235规格书)
|
|||
|
|
PWM_PERIOD_MS = 20 # PWM周期:20ms(规格书4-6条“控制频率50Hz”,1/50Hz=20ms)
|
|||
|
|
MIN_PULSE_US = 500 # 最小脉宽:500μsec(对应0°,规格书4-2条)
|
|||
|
|
MAX_PULSE_US = 2500 # 最大脉宽:2500μsec(对应180°,规格书4-2条)
|
|||
|
|
ROTATE_DELAY = 0.1 # 角度切换间隔(越小转动越“连续”,建议0.1-0.5秒)
|
|||
|
|
|
|||
|
|
# 1.3 舵机角度模式选择
|
|||
|
|
MODE = "180" # 180°模式
|
|||
|
|
|
|||
|
|
# -------------------------- 2. 全局变量初始化 --------------------------
|
|||
|
|
is_running = True # 程序运行标志
|
|||
|
|
|
|||
|
|
|
|||
|
|
# -------------------------- 3. 硬件PWM控制函数 --------------------------
|
|||
|
|
def export_pwm():
|
|||
|
|
"""导出PWM通道(使能PWM功能)"""
|
|||
|
|
if not os.path.exists(PWM_PATH):
|
|||
|
|
with open(f"/sys/class/pwm/pwmchip{PWM_CHIP}/export", "w") as f:
|
|||
|
|
f.write(str(PWM_CHANNEL))
|
|||
|
|
# 等待文件系统创建完成
|
|||
|
|
time.sleep(0.1)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def unexport_pwm():
|
|||
|
|
"""取消导出PWM通道(禁用PWM功能)"""
|
|||
|
|
if os.path.exists(PWM_PATH):
|
|||
|
|
with open(f"/sys/class/pwm/pwmchip{PWM_CHIP}/unexport", "w") as f:
|
|||
|
|
f.write(str(PWM_CHANNEL))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def set_pwm_period(period_ns):
|
|||
|
|
"""设置PWM周期(单位:纳秒)"""
|
|||
|
|
with open(f"{PWM_PATH}/period", "w") as f:
|
|||
|
|
f.write(str(period_ns))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def set_pwm_duty_cycle(duty_ns):
|
|||
|
|
"""设置PWM占空比(单位:纳秒)"""
|
|||
|
|
# 确保占空比在有效范围内
|
|||
|
|
duty_ns = max(MIN_PULSE_US, min(MAX_PULSE_US, duty_ns))
|
|||
|
|
with open(f"{PWM_PATH}/duty_cycle", "w") as f:
|
|||
|
|
f.write(str(duty_ns))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def enable_pwm(enable=True):
|
|||
|
|
"""启用或禁用PWM输出"""
|
|||
|
|
with open(f"{PWM_PATH}/enable", "w") as f:
|
|||
|
|
f.write("1" if enable else "0")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def set_servo_angle(pulse_ns):
|
|||
|
|
"""通过设置脉宽控制舵机角度"""
|
|||
|
|
set_pwm_duty_cycle(pulse_ns)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# -------------------------- 4. 模拟持续旋转函数 --------------------------
|
|||
|
|
def continuous_rotate_sim():
|
|||
|
|
"""模拟持续旋转:在最小和最大脉宽之间交替切换"""
|
|||
|
|
global is_running
|
|||
|
|
print(f"DS3235舵机已启动({MODE}°模式,硬件PWM控制,按Ctrl+C停止)...")
|
|||
|
|
|
|||
|
|
# 初始化PWM
|
|||
|
|
export_pwm()
|
|||
|
|
set_pwm_period(PWM_PERIOD_MS)
|
|||
|
|
enable_pwm(True)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
while is_running:
|
|||
|
|
# 输出最小脉宽(对应0°)
|
|||
|
|
set_servo_angle(MIN_PULSE_US)
|
|||
|
|
print(f"当前脉宽:{MIN_PULSE_US}ns(0°)")
|
|||
|
|
time.sleep(ROTATE_DELAY)
|
|||
|
|
|
|||
|
|
# 输出最大脉宽(对应180°)
|
|||
|
|
set_servo_angle(MAX_PULSE_US)
|
|||
|
|
if MODE == "180":
|
|||
|
|
print(f"当前脉宽:{MAX_PULSE_US}ns(180°)")
|
|||
|
|
else:
|
|||
|
|
print(f"当前脉宽:{MAX_PULSE_US}ns(270°)")
|
|||
|
|
time.sleep(ROTATE_DELAY)
|
|||
|
|
finally:
|
|||
|
|
# 关闭PWM输出
|
|||
|
|
enable_pwm(False)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# -------------------------- 5. 信号处理(Ctrl+C优雅退出) --------------------------
|
|||
|
|
def signal_handler(signum, frame):
|
|||
|
|
"""捕获Ctrl+C信号,设置退出标志"""
|
|||
|
|
global is_running
|
|||
|
|
print("\n收到停止指令,正在清理资源...")
|
|||
|
|
is_running = False
|
|||
|
|
|
|||
|
|
|
|||
|
|
# -------------------------- 6. 主函数 --------------------------
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
# 注册信号处理
|
|||
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|||
|
|
signal.signal(signal.SIGTERM, signal_handler)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 启动模拟持续旋转
|
|||
|
|
continuous_rotate_sim()
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"程序异常:{str(e)}")
|
|||
|
|
|
|||
|
|
finally:
|
|||
|
|
# 资源清理
|
|||
|
|
unexport_pwm()
|
|||
|
|
print("舵机PWM通道已关闭")
|
|||
|
|
print("程序退出完成")
|