/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : machine.c * @brief : LK540 Machine Stepper Motor Control Implementation * 步进电机控制模块实现 ****************************************************************************** * @attention * * Copyright (c) 2026 STMicroelectronics. * All rights reserved. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "machine.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* 步进脉冲时序参数(微秒) */ #define STEP_PULSE_HIGH_TIME_US 10 /* 脉冲高电平时间 */ #define STEP_PULSE_LOW_TIME_US 10 /* 脉冲低电平时间 */ /* 移动相关参数 */ #define MAX_STEPS_TO_ORIGIN 50000 /* 移动到原点的最大步数(防止无限循环) */ #define STEP_DELAY_US 100 /* 每步之间的延时(微秒) */ /* 各料位相对于中心点的距离(mm) */ #define DISTANCE_TO_MATERIAL1 192.4f /* 从中心点向左移动192.4mm */ #define DISTANCE_TO_MATERIAL2 65.4f /* 从中心点向左移动65.4mm */ #define DISTANCE_TO_MATERIAL3 61.6f /* 从中心点向右移动61.6mm */ #define DISTANCE_TO_MATERIAL4 188.6f /* 从中心点向右移动188.6mm */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ static void DelayUs(uint32_t us); static uint32_t Machine_MmToSteps(float mm); static uint8_t Machine_MoveSteps(Motor_DirectionTypeDef dir, uint32_t steps); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /** * @brief 微秒级延时函数 * @param us: 延时时间(微秒) * @note 基于系统时钟的简单延时,72MHz系统时钟下 * 考虑循环开销,使用约60个周期/微秒 * @retval None */ static void DelayUs(uint32_t us) { uint32_t i; /* 72MHz时钟,考虑循环开销,约60个周期/微秒 */ for (i = 0; i < us * 60; i++) { __NOP(); } } /** * @brief 将毫米距离转换为步数 * @param mm: 距离(毫米) * @retval 步数 */ static uint32_t Machine_MmToSteps(float mm) { /* 每毫米5.33个脉冲,向上取整 */ return (uint32_t)(mm * MOTOR_PULSE_PER_MM + 0.5f); } /** * @brief 步进电机移动指定步数 * @param dir: 移动方向 * @param steps: 移动步数 * @retval 0: 成功, 1: 失败(到达限位点) */ static uint8_t Machine_MoveSteps(Motor_DirectionTypeDef dir, uint32_t steps) { uint32_t i; /* 设置方向 */ Machine_SetDirection(dir); DelayUs(STEP_DELAY_US); /* 移动指定步数 */ for (i = 0; i < steps; i++) { /* 检查限位传感器 */ if (Machine_IsAtLimit()) { return 1; /* 到达限位点,返回错误 */ } /* 移动一步 */ Machine_Step(); DelayUs(STEP_DELAY_US); } return 0; /* 成功 */ } /* USER CODE END 0 */ /* Exported functions --------------------------------------------------------*/ /** * @brief 检测步进电机是否在原点 * @note PB3状态为0表示检测到步进电机在原点 * @retval 1: 在原点, 0: 不在原点 */ uint8_t Machine_IsAtOrigin(void) { GPIO_PinState pinState; /* 读取PB3引脚状态 */ pinState = HAL_GPIO_ReadPin(MOTOR_ORIGIN_PIN_PORT, MOTOR_ORIGIN_PIN); /* PB3为0表示在原点 */ return (pinState == GPIO_PIN_RESET) ? 1 : 0; } /** * @brief 检测步进电机是否在临界点(限位传感器) * @note PG15状态为0表示检测到步进电机到达临界点,不能再前进了 * @retval 1: 在临界点, 0: 不在临界点 */ uint8_t Machine_IsAtLimit(void) { GPIO_PinState pinState; /* 读取PG15引脚状态 */ pinState = HAL_GPIO_ReadPin(MOTOR_LIMIT_PIN_PORT, MOTOR_LIMIT_PIN); /* PG15为0表示在临界点 */ return (pinState == GPIO_PIN_RESET) ? 1 : 0; } /** * @brief 设置步进电机方向 * @param dir: 方向 * MOTOR_DIR_CW (0): 向左移动 (CW - Clockwise) * MOTOR_DIR_CCW (1): 向右移动 (CCW - Counter Clockwise) * @note PD7为0表示向左,1表示向右 * @retval None */ void Machine_SetDirection(Motor_DirectionTypeDef dir) { GPIO_PinState pinState; /* 根据方向设置PD7引脚状态 */ /* CW(0) = 向左 = GPIO_PIN_RESET, CCW(1) = 向右 = GPIO_PIN_SET */ pinState = (dir == MOTOR_DIR_CW) ? GPIO_PIN_RESET : GPIO_PIN_SET; /* 设置方向引脚 */ HAL_GPIO_WritePin(MOTOR_DIR_PIN_PORT, MOTOR_DIR_PIN, pinState); } /** * @brief 控制气缸状态 * @param state: 状态 (0: 张开, 1: 闭合) * @note PG8为0表示张开,1表示闭合 * @retval None */ void Machine_SetCylinder(uint8_t state) { GPIO_PinState pinState; /* 根据状态设置PG8引脚状态 */ /* 0 = 张开 = GPIO_PIN_RESET, 1 = 闭合 = GPIO_PIN_SET */ pinState = (state == 0) ? GPIO_PIN_RESET : GPIO_PIN_SET; /* 设置气缸控制引脚 */ HAL_GPIO_WritePin(CYLINDER_PIN_PORT, CYLINDER_PIN, pinState); } /** * @brief 步进电机移动一步 * @note 产生一个脉冲信号,电机移动一步 * 移动1mm需要5.33个脉冲,所以一步约等于1/5.33 mm * 脉冲时序:低->高->低 * @retval None */ void Machine_Step(void) { /* 确保步进引脚初始为低电平 */ HAL_GPIO_WritePin(MOTOR_STEP_PIN_PORT, MOTOR_STEP_PIN, GPIO_PIN_RESET); DelayUs(STEP_PULSE_LOW_TIME_US); /* 产生高电平脉冲 */ HAL_GPIO_WritePin(MOTOR_STEP_PIN_PORT, MOTOR_STEP_PIN, GPIO_PIN_SET); DelayUs(STEP_PULSE_HIGH_TIME_US); /* 恢复低电平 */ HAL_GPIO_WritePin(MOTOR_STEP_PIN_PORT, MOTOR_STEP_PIN, GPIO_PIN_RESET); DelayUs(STEP_PULSE_LOW_TIME_US); } /** * @brief 步进电机移动到原点 * @note 一直向左移动直到检测到原点传感器(PB3为0) * 如果检测到限位传感器(PG15为0),则停止并返回错误 * @retval 0: 成功到达原点, 1: 到达限位点(错误) */ uint8_t Machine_MoveToOrigin(void) { uint32_t stepCount = 0; /* 设置方向为向左(CW) */ Machine_SetDirection(MOTOR_DIR_CW); DelayUs(STEP_DELAY_US); /* 如果已经在原点,直接返回 */ if (Machine_IsAtOrigin()) { return 0; } /* 一直向左移动直到检测到原点 */ while (!Machine_IsAtOrigin()) { /* 检查限位传感器 */ if (Machine_IsAtLimit()) { return 1; /* 到达限位点,返回错误 */ } /* 防止无限循环 */ if (stepCount++ > MAX_STEPS_TO_ORIGIN) { return 1; /* 超时,返回错误 */ } /* 移动一步 */ Machine_Step(); DelayUs(STEP_DELAY_US); } return 0; /* 成功到达原点 */ } /** * @brief 步进电机从原点移动到中心点 * @note 从原点(传感器位置)向右移动215.0mm到达中心点 * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToCenter(void) { uint32_t steps; /* 计算需要的步数:215.0mm */ steps = Machine_MmToSteps(MOTOR_ORIGIN_DISTANCE); /* 向右移动 */ return Machine_MoveSteps(MOTOR_DIR_CCW, steps); } /** * @brief 步进电机从中心点移动到1#料位置 * @note 从中心点向左移动192.4mm到达1#料 * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial1(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL1); /* 向左移动 */ return Machine_MoveSteps(MOTOR_DIR_CW, steps); } /** * @brief 步进电机从中心点移动到2#料位置 * @note 从中心点向左移动65.4mm到达2#料 * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial2(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL2); /* 向左移动 */ return Machine_MoveSteps(MOTOR_DIR_CW, steps); } /** * @brief 步进电机从中心点移动到3#料位置 * @note 从中心点向右移动61.6mm到达3#料 * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial3(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL3); /* 向右移动 */ return Machine_MoveSteps(MOTOR_DIR_CCW, steps); } /** * @brief 步进电机从中心点移动到4#料位置 * @note 从中心点向右移动188.6mm到达4#料 * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial4(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL4); /* 向右移动 */ return Machine_MoveSteps(MOTOR_DIR_CCW, steps); } /** * @brief 从中心点移动到1#料位置并取料,然后返回中心点放料 * @note 1. 从中心点移动到1#料位置 * 2. 闭合气缸取料 * 3. 返回中心点 * 4. 张开气缸放料 * @retval 0: 成功, 1: 失败(移动失败) */ uint8_t Machine_PickMaterial1(void) { /* 从中心点移动到1#料位置 */ if (Machine_MoveToMaterial1() != 0) { return 1; /* 移动失败 */ } /* 延时,确保到位 */ DelayUs(10000); /* 10ms延时 */ /* 闭合气缸取料 */ Machine_SetCylinder(1); DelayUs(100000); /* 100ms延时,确保气缸闭合完成 */ /* 从1#料位置返回中心点(向左移动192.4mm,返回需要向右移动) */ { uint32_t steps; steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL1); if (Machine_MoveSteps(MOTOR_DIR_CCW, steps) != 0) { return 1; /* 返回失败 */ } } /* 延时,确保到位 */ DelayUs(10000); /* 10ms延时 */ /* 张开气缸放料 */ Machine_SetCylinder(0); DelayUs(100000); /* 100ms延时,确保气缸张开完成 */ return 0; /* 成功 */ } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */