Files
ElecScalesMeasur/servo_motor_PWM.py
2025-09-30 14:57:14 +08:00

139 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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")
time.sleep(ROTATE_DELAY)
# 输出最大脉宽对应180°
set_servo_angle(MAX_PULSE_US)
if MODE == "180":
print(f"当前脉宽:{MAX_PULSE_US}ns180°")
else:
print(f"当前脉宽:{MAX_PULSE_US}ns270°")
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("程序退出完成")