Files
wire_controlsystem/RK1106/stepper_motor_test.py

160 lines
6.0 KiB
Python
Raw Normal View History

2026-01-05 18:11:56 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
# @Time : 2026/1/4 15:06
# @Author : reenrr
# @File : stepper_motor_test.py
# @Desc : 线条厂控制步进电机
"""
import time
from periphery import GPIO
import sys
sys.setswitchinterval(0.000001) # 减小线程切换间隔
# --------------
# 硬件参数配置(必须与你的设备匹配!)
# --------------
# 1. 脉冲PUL引脚配置 → GPIO32
PUL_Pin = 32
# 2. 方向DIR引脚配置 → GPIO33
DIR_Pin = 33
# 3. LCDA257C驱动器核心参数关键与拨码/软件设置一致)
PULSES_PER_ROUND = 400 # 每圈脉冲数(按驱动器细分拨码调整)
PULSE_FREQUENCY = 5000 # 初始测试频率建议从500开始逐步调高
# 4. LCDA257C时序参数遵循手册要求不可低于最小值
MIN_DIR_DELAY_US = 10 # DIR提前PUL的最小延迟>8us
PULSE_LOW_MIN_US = 2 # 脉冲低电平最小宽度≥2us
PULSE_HIGH_MIN_US = 2 # 脉冲高电平最小宽度≥2us
# 5. 方向电平定义(可根据实际测试调整)
CLOCKWISE_LEVEL = True # 顺时针→DIR高电平
COUNTER_CLOCKWISE_LEVEL = False # 逆时针→DIR低电平
def init_stepper() -> tuple[GPIO, GPIO]:
"""初始化PUL和DIR引脚输出模式适配LCDA257C"""
try:
# 初始化脉冲引脚(输出模式)
pul_gpio = GPIO(PUL_Pin, "out")
# 初始化方向引脚(输出模式)
dir_gpio = GPIO(DIR_Pin, "out")
# 初始状态:脉冲低电平,方向低电平(驱动器空闲状态)
pul_gpio.write(False)
dir_gpio.write(False)
print(f"✅ PUL引脚初始化完成{PUL_Pin}引脚")
print(f"✅ DIR引脚初始化完成{DIR_Pin}引脚")
return pul_gpio, dir_gpio
except FileNotFoundError:
raise RuntimeError(f"GPIO芯片不存在检查 {PUL_Pin} 是否存在命令ls /dev/gpiochip*")
except PermissionError:
raise RuntimeError("GPIO权限不足请用 sudo 运行程序sudo python test.py")
except Exception as e:
raise RuntimeError(f"GPIO初始化失败{str(e)}") from e
def rotate(pul_gpio: GPIO, dir_gpio: GPIO, rounds: float, direction: str = "clockwise",
test_freq: int = PULSE_FREQUENCY):
"""
控制LCDA257C驱动器旋转优化版脉冲发送解决频率不生效问题
:param pul_gpio: PUL引脚GPIO对象
:param dir_gpio: DIR引脚GPIO对象
:param rounds: 旋转圈数正数可小数
:param direction: 方向clockwise/counterclockwise
:param test_freq: 本次旋转使用的脉冲频率覆盖全局默认值
"""
# 1. 参数合法性校验
if rounds <= 0:
print("❌ 圈数必须为正数!")
return
if test_freq < 100:
print("❌ 频率过低≥100Hz请调整test_freq参数")
return
# 2. 设置旋转方向严格遵循DIR提前时序
if direction == "clockwise":
dir_gpio.write(CLOCKWISE_LEVEL)
print(f"\n=== 顺时针旋转 {rounds} 圈(目标频率:{test_freq}Hz===")
elif direction == "counterclockwise":
dir_gpio.write(COUNTER_CLOCKWISE_LEVEL)
print(f"\n=== 逆时针旋转 {rounds} 圈(目标频率:{test_freq}Hz===")
else:
print("❌ 方向参数错误!仅支持 clockwise/counterclockwise")
return
# DIR电平设置后延迟≥8us满足LCDA257C时序要求
time.sleep(MIN_DIR_DELAY_US / 1_000_000)
# 3. 计算脉冲参数(确保高低电平≥最小宽度)
total_pulses = int(rounds * PULSES_PER_ROUND)
pulse_period = 1.0 / test_freq # 脉冲周期(秒)
# 确保高低电平宽度不低于驱动器要求(避免脉冲识别失败)
high_period = max(pulse_period / 2, PULSE_HIGH_MIN_US / 1_000_000)
low_period = max(pulse_period / 2, PULSE_LOW_MIN_US / 1_000_000)
# 打印参数(便于调试)
print(f"总脉冲数:{total_pulses} | 理论高电平:{high_period * 1e6:.1f}us | 理论低电平:{low_period * 1e6:.1f}us")
# 4. 优化版脉冲发送解决Python高频延时不准问题
start_total = time.perf_counter() # 高精度计时(统计实际频率)
for _ in range(total_pulses):
# 高电平直接sleep避免while循环的调度延迟
pul_gpio.write(True)
time.sleep(high_period)
# 低电平
pul_gpio.write(False)
time.sleep(low_period)
end_total = time.perf_counter()
# 5. 计算实际频率(验证是否达到目标)
actual_duration = end_total - start_total
actual_freq = total_pulses / actual_duration if actual_duration > 0 else 0
print(f"✅ 旋转完成 | 实际频率:{actual_freq:.0f}Hz | 耗时:{actual_duration:.2f}")
def motor_test_demo():
"""电机测试示例(逐步提升频率,验证转速变化)"""
pul_gpio = None
dir_gpio = None
try:
# 初始化引脚
pul_gpio, dir_gpio = init_stepper()
print("\n=== 步进电机频率测试程序启动 ===")
while True:
print(f"\n===== 测试频率:{PULSE_FREQUENCY}Hz =====")
# 远离电机方向 顺时针
rotate(pul_gpio, dir_gpio, rounds=10.0, direction="clockwise")
time.sleep(5) #
# 靠近电机方向 逆时针
rotate(pul_gpio, dir_gpio, rounds=10.0, direction="counterclockwise")
time.sleep(5) #
except Exception as e:
print(f"\n❌ 程序异常:{str(e)}")
finally:
# 安全释放GPIO资源必须执行避免引脚电平残留
if pul_gpio:
pul_gpio.write(False)
pul_gpio.close()
print("\n✅ PUL引脚已关闭低电平")
if dir_gpio:
dir_gpio.write(False)
dir_gpio.close()
print("✅ DIR引脚已关闭低电平")
print("✅ 程序退出完成")
if __name__ == '__main__':
# 运行测试demo必须sudo执行
motor_test_demo()