160 lines
6.0 KiB
Python
160 lines
6.0 KiB
Python
#!/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()
|
||
|