Files
wire_controlsystem/RK1106/stepper_motor_test.py
2026-01-05 18:11:56 +08:00

160 lines
6.0 KiB
Python
Raw 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 : 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()