393 lines
10 KiB
C
393 lines
10 KiB
C
/* 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 */
|