Files
wire_controlsystem/RK1106/stepper_motor.py

216 lines
7.2 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 19:13
# @Author : reenrr
# @File : stepper_motor_test1.py
# @Desc : 线条厂控制步进电机测试 应该不会丢步
"""
import time
from periphery import GPIO
# ------------参数配置-------------
# 1. 脉冲PUL引脚配置 → GPIO32
PUL_Pin = 32
# 2. 方向DIR引脚配置 → GPIO33
DIR_Pin = 33
# 3. 驱动器参数(根据拨码调整,默认不变)
PULSES_PER_ROUND = 400 # 每圈脉冲数SW5~SW8拨码默认400
PULSE_FREQUENCY = 2500 # 脉冲频率Hz新手建议500~2000最大200KHz
class StepperMotor:
"""新力川MA860H驱动器步进电机控制类"""
def __init__(self,
pul_pin: int = PUL_Pin,
dir_pin: int = DIR_Pin,
pulses_per_round: int = PULSES_PER_ROUND,
clockwise_level: bool = True,
counter_clockwise_level: bool = False):
"""
初始化步进电机控制器
:param pul_pin: 脉冲引脚
:param dir_pin: 方向引脚
:param pulses_per_round: 每圈脉冲数SW5~SW8拨码默认400
:param clockwise_level: 顺时针对应的DIR电平
:param counter_clockwise_level: 逆时针对应的DIR电平
"""
# 硬件配置参数
self.pul_pin = pul_pin
self.dir_pin = dir_pin
# 驱动器参数
self.pulses_per_round = pulses_per_round
self.clockwise_level = clockwise_level
self.counter_clockwise_level = counter_clockwise_level
# GPIO对象初始化
self.pul_gpio = None
self.dir_gpio = None
# 初始化GPIO
self._init_gpio()
def _init_gpio(self):
"""初始化PUL和DIR引脚内部方法"""
try:
# 初始化脉冲引脚(输出模式)
self.pul_gpio = GPIO(self.pul_pin, "out")
# 初始化方向引脚(输出模式)
self.dir_gpio = GPIO(self.dir_pin, "out")
# 初始电平置低(避免电机误动作)
self.pul_gpio.write(False)
self.dir_gpio.write(False)
print(f"✅ PUL引脚初始化完成{self.pul_pin} 引脚")
print(f"✅ DIR引脚初始化完成{self.dir_pin} 引脚")
except PermissionError:
raise RuntimeError("权限不足请用sudo运行程序sudo python xxx.py")
except Exception as e:
raise RuntimeError(f"GPIO初始化失败{str(e)}") from e
def _validate_params(self, rounds: float, direction: int) -> bool:
if rounds <= 0:
print("圈数必须为正数")
return False
if direction not in (0, 1):
print("方向必须为0逆时针或1顺时针")
return False
return True
def rotate(self, pulse_frequency: int, rounds: float, direction: int):
"""
控制电机旋转(支持正反转)
:param pulse_frequency: 脉冲频率hz)
:param rounds: 旋转圈数可小数如0.5=半圈)
:param direction: 方向1=顺时针0=逆时针)
"""
# 参数验证
if not self._validate_params(rounds, direction):
return
# 设置旋转方向DIR电平
if direction == 1: # 顺时针
self.dir_gpio.write(self.clockwise_level)
print(f"\n=== 顺时针旋转 {rounds} 圈 ===")
else: # 逆时针
self.dir_gpio.write(self.counter_clockwise_level)
print(f"\n=== 逆时针旋转 {rounds} 圈 ===")
# 计算总脉冲数和时序(精准控制,避免丢步)
total_pulses = int(rounds * self.pulses_per_round)
pulse_period = 1.0 / pulse_frequency # 脉冲周期(秒)
half_period = pulse_period / 2 # 占空比50%MA860H最优
print(f"总脉冲数:{total_pulses} | 频率:{pulse_frequency}Hz | 周期:{pulse_period * 1000:.2f}ms")
start_time = time.perf_counter() # 高精度计时(避免丢步)
# 发送脉冲序列核心占空比50%的方波)
for _ in range(total_pulses):
# 高电平
self.pul_gpio.write(True)
# 精准延时比time.sleep稳定适配高频脉冲
while time.perf_counter() - start_time < half_period:
pass
# 低电平
self.pul_gpio.write(False)
# 更新下一个脉冲的起始时间
start_time += pulse_period
print("✅ 旋转完成")
def stop(self):
"""紧急停止(置低脉冲引脚)"""
if self.pul_gpio:
self.pul_gpio.write(False)
print("🛑 电机已停止")
def close(self):
"""释放GPIO资源"""
# 安全释放GPIO资源关键避免引脚电平残留
if self.pul_gpio:
self.pul_gpio.write(False) # 脉冲引脚置低
self.pul_gpio.close()
print("\n✅ PUL引脚已关闭电平置低")
if self.dir_gpio:
self.dir_gpio.write(False) # 方向引脚置低
self.dir_gpio.close()
print("✅ DIR引脚已关闭电平置低")
# 重置GPIO对象
self.pul_gpio = None
self.dir_gpio = None
def __del__(self):
"""析构函数:确保资源释放"""
self.close()
# ------全局实例-------
GLOBAL_MOTOR = StepperMotor()
# -------对外接口----------
def motor_start(speed: int, cycle: float, direction: int):
"""
开启电机,用于断电时电机恢复到起始位置
:param speed: 脉冲频率hz)
:param cycle: 旋转圈数
:param direction: 0=负向逆时针1=正向(顺时针)
"""
try:
print("\n=== 启动步进电机 ===")
GLOBAL_MOTOR.rotate(pulse_frequency=speed, rounds=cycle, direction=direction)
time.sleep(5) # 暂停5秒
except ImportError:
print("\n❌ 缺少依赖请安装python-periphery")
print("命令pip install python-periphery")
except Exception as e:
print(f"\n❌ 程序异常:{str(e)}")
def motor_stop():
"""紧急停止(仅停止脉冲,保留实例)"""
try:
if GLOBAL_MOTOR:
GLOBAL_MOTOR.stop()
except Exception as e:
print("停止失败:{e}")
def align_wire(speed: int, cycle: float):
"""
使线条对齐
:param speed: 脉冲频率hz)
:param cycle: 旋转圈数
"""
try:
print("\n=== 启动线条对齐 ===")
# 靠近电机方向 逆时针
GLOBAL_MOTOR.rotate(pulse_frequency=speed, rounds=cycle, direction=0)
time.sleep(5) # 暂停5秒
# 远离电机方向 顺时针
GLOBAL_MOTOR.rotate(pulse_frequency=speed,rounds=cycle, direction=1)
time.sleep(5) # 暂停5秒
except ImportError:
print("\n❌ 缺少依赖请安装python-periphery")
print("命令pip install python-periphery")
except Exception as e:
print(f"\n❌ 程序异常:{str(e)}")
def cleanup():
"""程序退出时统一清理"""
if GLOBAL_MOTOR:
GLOBAL_MOTOR.close()
if __name__ == '__main__':
motor_start(2500, 10.0, 1)