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

108 lines
4.2 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/23 18:21
# @Author : reenrr
# @File : servo_motor.py
# 功能描述RK3506通过GPIO模拟PWM控制DS3235舵机模拟持续旋转
# 参考文档DS3235 Coreless datasheet.pdf、接线图.docx
'''
import time
import signal
from periphery import GPIO
# -------------------------- 1. 硬件配置(必须根据实际接线调整) --------------------------
# 1.1 舵机PWM信号输出引脚RK3506的GPIO编号需与硬件接线对应
# 例若舵机信号线接GPIO3_B2_d对应Linux GPIO编号为10参考你提供的vibration_control-test.py
SERVO_GPIO_NUM = 10 # 替换为你的实际舵机信号引脚GPIO编号
# 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 舵机角度模式选择(根据需求切换,参考接线图.docx
MODE = "180" # 180°模式500μsec=0°2500μsec=180°
# -------------------------- 2. 全局变量初始化 --------------------------
gpio = None # 舵机GPIO引脚对象
is_running = True # 程序运行标志
# -------------------------- 3. PWM信号生成函数 --------------------------
def set_servo_pulse(pulse_us):
'''
生成指定脉宽的PWM信号通过GPIO高低电平模拟
参数pulse_us - 高电平脉宽(单位:微秒)
'''
global gpio
# 脉宽范围限制(避免舵机过载,严格遵循规格书)
pulse_us = max(MIN_PULSE_US, min(MAX_PULSE_US, pulse_us))
# 1. 输出高电平持续pulse_us微秒
gpio.write(True)
time.sleep(pulse_us / 1000000) # 转换为秒单位
# 2. 输出低电平补全PWM周期20ms - 高电平时间)
low_time_ms = PWM_PERIOD_MS - (pulse_us / 1000) # 低电平时间(毫秒)
gpio.write(False)
time.sleep(low_time_ms / 1000) # 转换为秒单位
# -------------------------- 4. 模拟持续旋转函数 --------------------------
def continuous_rotate_sim():
'''
模拟持续旋转交替输出“最小脉宽”和“最大脉宽180°
'''
global is_running
print(f"DS3235舵机已启动{MODE}°模式按Ctrl+C停止...")
while is_running:
# 第一步输出最小脉宽对应0°
set_servo_pulse(MIN_PULSE_US)
print(f"当前脉宽:{MIN_PULSE_US}μsec")
time.sleep(ROTATE_DELAY)
# 第二步输出最大脉宽对应180°/270°
set_servo_pulse(MAX_PULSE_US)
if MODE == "180":
print(f"当前脉宽:{MAX_PULSE_US}μsec180°")
else:
print(f"当前脉宽:{MAX_PULSE_US}μsec270°")
time.sleep(ROTATE_DELAY)
# -------------------------- 5. 信号处理Ctrl+C优雅退出 --------------------------
def signal_handler(signum, frame):
'''捕获Ctrl+C信号设置退出标志'''
global is_running
print("\n收到停止指令,正在清理资源...")
is_running = False
# -------------------------- 6. 主函数 --------------------------
if __name__ == "__main__":
# 1. 注册信号处理确保Ctrl+C能正常退出
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
try:
# 2. 初始化舵机GPIO引脚输出模式参考你的vibration_control-test.py风格
gpio = GPIO(SERVO_GPIO_NUM, "out")
print(f"舵机GPIO引脚编号{SERVO_GPIO_NUM})初始化完成")
# 3. 启动模拟持续旋转
continuous_rotate_sim()
except Exception as e:
# 异常处理如GPIO初始化失败
print(f"程序异常:{str(e)}")
finally:
# 4. 资源清理必做避免GPIO引脚异常
if gpio is not None:
gpio.write(False) # 程序结束前拉低GPIO避免舵机持续受力
gpio.close()
print("舵机GPIO引脚已关闭")
print("程序退出完成")