基于STM32平台的步进电机S型曲线加减速驱动程序

基于STM32平台的步进电机S型曲线加减速驱动程序


一、系统架构设计

graph TD
A[主控MCU] --> B[定时器1-PWM输出]
A --> C[定时器2-速度调节]
B --> D[步进电机驱动器]
C --> B
D --> E[机械负载]

二、核心代码实现

1. 硬件初始化(CubeMX配置)

// 定时器1配置(PWM输出)
TIM_HandleTypeDef htim1;
void MX_TIM1_Init(void) {
    TIM_OC_InitTypeDef sConfigOC = {0};
    
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 84-1;    // 1MHz时钟
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim1.Init.Period = 1000-1;     // 初始频率1kHz
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&htim1);
    
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 500;          // 50%占空比
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
}

// 定时器2配置(速度调节)
TIM_HandleTypeDef htim2;
void MX_TIM2_Init(void) {
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 8400-1;  // 100Hz中断
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 0xFFFF;
    HAL_TIM_Base_Init(&htim2);
    HAL_TIM_Base_Start_IT(&htim2);
}

2. S型曲线参数生成

#define ACCEL_STEPS 800    // 加速阶段步数
#define DECEL_STEPS 800    // 减速阶段步数
#define MAX_FREQ 20000     // 最大频率20kHz
#define MIN_FREQ 1000      // 最小频率1kHz

uint16_t accel_table[ACCEL_STEPS](@ref);
uint16_t decel_table[DECEL_STEPS](@ref);

// S型曲线数学变换
float sigmoid(float x) {
    return 1.0f / (1.0f + expf(-x));
}

void GenerateSCurve() {
    float flexible = 4.0f;  // 曲线陡峭度参数
    float x_scale = ACCEL_STEPS / 2.0f;
    
    // 生成加速曲线
    for(int i=0; i<ACCEL_STEPS; i++) {
        float x = flexible * (i - x_scale) / x_scale;
        float freq = MIN_FREQ + (MAX_FREQ-MIN_FREQ) * sigmoid(x);
        accel_table[i](@ref)= (uint16_t)(SystemCoreClock / (freq * 2) - 1);
    }
    
    // 生成减速曲线(反向S曲线)
    for(int i=0; i<DECEL_STEPS; i++) {
        float x = flexible * (DECEL_STEPS - i - x_scale) / x_scale;
        float freq = MIN_FREQ + (MAX_FREQ-MIN_FREQ) * sigmoid(x);
        decel_table[i](@ref)= (uint16_t)(SystemCoreClock / (freq * 2) - 1);
    }
}

3. 状态机控制

typedef enum {
    ACCELERATE,
    RUN,
    DECELERATE,
    STOPPED
} MotorState;

MotorState motor_state = STOPPED;
volatile uint32_t step_count = 0;
volatile uint16_t *current_table;
uint16_t table_index = 0;

void SetMotorState(MotorState new_state) {
    motor_state = new_state;
    table_index = 0;
    
    switch(new_state) {
        case ACCELERATE: current_table = accel_table; break;
        case DECELERATE: current_table = decel_table; break;
        default: break;
    }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if(htim->Instance == TIM2) {
        step_count++;
        
        // 状态切换逻辑
        switch(motor_state) {
            case ACCELERATE:
                if(table_index >= ACCEL_STEPS) {
                    SetMotorState(RUN);
                }
                break;
                
            case DECELERATE:
                if(table_index >= DECEL_STEPS) {
                    SetMotorState(STOPPED);
                }
                break;
        }
        
        // 更新PWM参数
        __HAL_TIM_SET_AUTORELOAD(&htim1, current_table[table_index](@ref);
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 
                             current_table[table_index](@ref)/ 2);  // 50%占空比
        
        table_index++;
    }
}

4. 运动控制接口

void StartMotion(uint32_t total_steps) {
    // 计算总步数
    step_count = 0;
    
    // 根据总步数自动计算加速/减速阶段
    if(total_steps > ACCEL_STEPS*2) {
        // 长距离运动:加速→匀速→减速
        HAL_TIM_Base_Start_IT(&htim2);
        SetMotorState(ACCELERATE);
    } else {
        // 短距离运动:直接S型加速减速
        SetMotorState(ACCELERATE);
    }
}

void StopMotion() {
    HAL_TIM_Base_Stop_IT(&htim2);
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    motor_state = STOPPED;
}

三、关键参数优化

1. 曲线参数调整

参数 计算公式 典型值
加速时间 T_acc = (ACCEL_STEPS × 100μs) 80ms
减速时间 T_dec = (DECEL_STEPS × 100μs) 80ms
最大加速度 a_max = (MAX_FREQ-MIN_FREQ)×1000 19kHz/ms
峰值电流 I_peak = V/(Rm + Ke×a_max) 2A

2. 硬件配置建议

// 电机驱动配置(以DRV8825为例)
#define DIR_PIN  GPIO_PIN_0
#define STEP_PIN GPIO_PIN_1
#define EN_PIN   GPIO_PIN_2

void Motor_GPIO_Init() {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // 方向引脚
    GPIO_InitStruct.Pin = DIR_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 步进引脚(使用定时器通道)
    GPIO_InitStruct.Pin = STEP_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 使能引脚
    GPIO_InitStruct.Pin = EN_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void Motor_Enable() {
    HAL_GPIO_WritePin(GPIOA, EN_PIN, GPIO_PIN_RESET);  // 低电平使能
}

四、调试与验证

1. 示波器观察要点

2. 性能测试数据

测试项目 测试条件 预期结果
启动平滑度 0→20000步/秒 加速度≤5000rad/s²
停止精度 10000步停止 误差≤±2步
温升(连续运行) 25℃环境/1小时 ≤45℃

参考代码 带有S型曲线加减速的步进电机驱动程序 www.youwenfan.com/contentcnr/56714.html

五、扩展功能实现

1. 闭环控制集成

// 编码器中断处理
void Encoder_Callback() {
    static int32_t encoder_count = 0;
    encoder_count++;
    
    // 位置闭环补偿
    if(motor_state == RUN) {
        int32_t error = target_pos - encoder_count;
        if(abs(error) > 50) {
            // 触发紧急停止
            StopMotion();
        }
    }
}

2. 多轴同步控制

typedef struct {
    TIM_HandleTypeDef *htim;
    uint16_t *accel_table;
    uint32_t step_count;
} MotorHandle;

void SyncMotion(MotorHandle *motors, uint8_t num) {
    // 通过总线同步各轴时钟
    for(uint8_t i=0; i<num; i++) {
        __HAL_TIM_SET_AUTORELOAD(motors[i].htim, 
                               motors[i].accel_table[table_index]);
    }
}

六、常见问题解决方案

  1. 电机丢步

    • 检查电流是否达到额定值(使用电流检测芯片)
    • 增加细分设置(如1/16细分)
    • 优化加减速曲线参数
  2. 过热问题

    • 添加散热片
    • 降低PWM频率(如从20kHz→15kHz)
    • 增加死区时间(推荐≥2μs)
  3. 通信干扰

    • 使用屏蔽线缆
    • 添加RC滤波电路(100Ω+0.1μF)
    • 优化PCB布局(地平面分割)

 

专注于matlab/simulink,电子电路,编程