修改步进电机接口、通讯方式和EMV的接口

This commit is contained in:
2026-02-06 15:16:17 +08:00
parent 17df13c08e
commit 5c9946dfc7
7 changed files with 432 additions and 1111 deletions

View File

@ -1,15 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
# @Time : 2026/1/5 15:50
"""
# @Time : 2026/1/4 19:13
# @Author : reenrr
# @File : stepper_motor.py
# @Desc : 控制步进电机从初始位置移动10cm,移动后回到初始位置
'''
# @File : stepper_motor_test1.py
# @Desc : 线条厂控制步进电机测试 应该不会丢步
"""
import time
from periphery import GPIO
import logging
import os
# ------------参数配置-------------
# 1. 脉冲PUL引脚配置 → GPIO32
@ -20,33 +19,15 @@ DIR_Pin = 33
# 3. 驱动器参数(根据拨码调整,默认不变)
PULSES_PER_ROUND = 400 # 每圈脉冲数SW5~SW8拨码默认400
PULSE_FREQUENCY = 2500 # 脉冲频率Hz
PULSE_FREQUENCY = 2500 # 脉冲频率Hz新手建议500~2000最大200KHz
# ------------ 日志+参数配置 ------------
script_dir = os.path.dirname(os.path.abspath(__file__))
log_file_path = os.path.join(script_dir, "stepper_motor.log")
logging.basicConfig(
level=logging.INFO,
format='[%(asctime)s.%(msecs)03d] [%(levelname)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
handlers=[
logging.StreamHandler(),
logging.FileHandler(log_file_path, encoding='utf-8')
]
)
class StepperMotor:
"""新力川MA860H驱动器步进电机控制类"""
# 方向常量定义
CLOCKWISE = "clockwise" # 顺时针
COUNTER_CLOCKWISE = "counterclockwise" # 逆时针
def __init__(self,
pul_pin: int = PUL_Pin,
dir_pin: int = DIR_Pin,
pulses_per_round: int = PULSES_PER_ROUND,
pulse_frequency: int = PULSE_FREQUENCY,
clockwise_level: bool = True,
counter_clockwise_level: bool = False):
"""
@ -54,7 +35,6 @@ class StepperMotor:
:param pul_pin: 脉冲引脚
:param dir_pin: 方向引脚
:param pulses_per_round: 每圈脉冲数SW5~SW8拨码默认400
:param pulse_frequency: 脉冲频率Hz
:param clockwise_level: 顺时针对应的DIR电平
:param counter_clockwise_level: 逆时针对应的DIR电平
"""
@ -64,7 +44,6 @@ class StepperMotor:
# 驱动器参数
self.pulses_per_round = pulses_per_round
self.pulse_frequency = pulse_frequency
self.clockwise_level = clockwise_level
self.counter_clockwise_level = counter_clockwise_level
@ -76,7 +55,7 @@ class StepperMotor:
self._init_gpio()
def _init_gpio(self):
"""初始化PUL和DIR引脚"""
"""初始化PUL和DIR引脚(内部方法)"""
try:
# 初始化脉冲引脚(输出模式)
self.pul_gpio = GPIO(self.pul_pin, "out")
@ -87,52 +66,48 @@ class StepperMotor:
self.pul_gpio.write(False)
self.dir_gpio.write(False)
logging.info(f"PUL引脚初始化完成{self.pul_pin} 引脚")
logging.info(f"DIR引脚初始化完成{self.dir_pin} 引脚")
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_rounds(self, rounds: float) -> bool:
"""验证圈数是否合法(内部方法)"""
def _validate_params(self, rounds: float, direction: int) -> bool:
if rounds <= 0:
logging.info("圈数必须为正数")
print("圈数必须为正数")
return False
if direction not in (0, 1):
print("方向必须为0逆时针或1顺时针")
return False
return True
def _validate_direction(self, direction: str) -> bool:
"""验证方向参数是否合法(内部方法)"""
if direction not in [self.CLOCKWISE, self.COUNTER_CLOCKWISE]:
logging.info(f"方向参数错误:仅支持 {self.CLOCKWISE}/{self.COUNTER_CLOCKWISE}")
return False
return True
def rotate(self, rounds: float, direction: str = CLOCKWISE):
def rotate(self, pulse_frequency: int, rounds: float, direction: int):
"""
控制电机旋转(支持正反转)
:param pulse_frequency: 脉冲频率hz)
:param rounds: 旋转圈数可小数如0.5=半圈)
:param direction: 方向(clockwise=顺时针counterclockwise=逆时针)
:param direction: 方向(1=顺时针0=逆时针)
"""
# 参数验证
if not self._validate_rounds(rounds) or not self._validate_direction(direction):
if not self._validate_params(rounds, direction):
return
# 设置旋转方向DIR电平
if direction == self.CLOCKWISE: # 顺时针
if direction == 1: # 顺时针
self.dir_gpio.write(self.clockwise_level)
logging.info(f"\n=== 顺时针旋转 {rounds} 圈 ===")
print(f"\n=== 顺时针旋转 {rounds} 圈 ===")
else: # 逆时针
self.dir_gpio.write(self.counter_clockwise_level)
logging.info(f"\n=== 逆时针旋转 {rounds} 圈 ===")
print(f"\n=== 逆时针旋转 {rounds} 圈 ===")
# 计算总脉冲数和时序(精准控制,避免丢步)
total_pulses = int(rounds * self.pulses_per_round)
pulse_period = 1.0 / self.pulse_frequency # 脉冲周期(秒)
pulse_period = 1.0 / pulse_frequency # 脉冲周期(秒)
half_period = pulse_period / 2 # 占空比50%MA860H最优
logging.info(f"总脉冲数:{total_pulses} | 频率:{self.pulse_frequency}Hz | 周期:{pulse_period * 1000:.2f}ms")
print(f"总脉冲数:{total_pulses} | 频率:{pulse_frequency}Hz | 周期:{pulse_period * 1000:.2f}ms")
start_time = time.perf_counter() # 高精度计时(避免丢步)
# 发送脉冲序列核心占空比50%的方波)
@ -147,13 +122,13 @@ class StepperMotor:
# 更新下一个脉冲的起始时间
start_time += pulse_period
logging.info("旋转完成")
print("旋转完成")
def stop(self):
"""紧急停止(置低脉冲引脚)"""
if self.pul_gpio:
self.pul_gpio.write(False)
logging.info("电机已停止")
print("🛑 电机已停止")
def close(self):
"""释放GPIO资源"""
@ -161,12 +136,12 @@ class StepperMotor:
if self.pul_gpio:
self.pul_gpio.write(False) # 脉冲引脚置低
self.pul_gpio.close()
logging.info("\n PUL引脚已关闭电平置低")
print("\n PUL引脚已关闭电平置低")
if self.dir_gpio:
self.dir_gpio.write(False) # 方向引脚置低
self.dir_gpio.close()
logging.info("DIR引脚已关闭电平置低")
print("DIR引脚已关闭电平置低")
# 重置GPIO对象
self.pul_gpio = None
@ -176,36 +151,65 @@ class StepperMotor:
"""析构函数:确保资源释放"""
self.close()
# ------全局实例-------
GLOBAL_MOTOR = StepperMotor()
#---------控制步进电机外部接口--------------
def stepper_motor_control():
motor = None
# -------对外接口----------
def motor_start(speed: int, cycle: float, direction: int):
"""
开启电机,用于断电时电机恢复到起始位置
:param speed: 脉冲频率hz)
:param cycle: 旋转圈数
:param direction: 0=负向逆时针1=正向(顺时针)
"""
try:
# 创建电机实例(使用默认配置)
motor = StepperMotor()
logging.info("\n=== 步进电机控制程序启动 ===")
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=== 启动线条对齐 ===")
# 靠近电机方向 逆时针
motor.rotate(rounds=10.0, direction=motor.COUNTER_CLOCKWISE)
GLOBAL_MOTOR.rotate(pulse_frequency=speed, rounds=cycle, direction=0)
time.sleep(5) # 暂停5秒
# 远离电机方向 顺时针
motor.rotate(rounds=10.0, direction=motor.CLOCKWISE)
GLOBAL_MOTOR.rotate(pulse_frequency=speed,rounds=10.0, direction=1)
time.sleep(5) # 暂停5秒
except PermissionError:
logging.info("\n 权限不足:请用 sudo 运行!")
logging.info("命令sudo python3 double_direction_motor.py")
except ImportError:
logging.info("\n 缺少依赖请安装python-periphery")
logging.info("命令pip install python-periphery")
print("\n 缺少依赖请安装python-periphery")
print("命令pip install python-periphery")
except Exception as e:
logging.info(f"\n 程序异常:{str(e)}")
finally:
if motor:
motor.close()
logging.info("程序退出完成")
print(f"\n 程序异常:{str(e)}")
def cleanup():
"""程序退出时统一清理"""
if GLOBAL_MOTOR:
GLOBAL_MOTOR.close()
if __name__ == '__main__':
stepper_motor_control()
motor_start(2500, 10.0, 1)