#!/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__': align_wire(speed=2500, cycle=10.0) time.sleep(10) # 电机运动需要的时间