STM32——步进电机梯形加速曲线

上星期写了一篇STM32——使用PWM+DMA实现脉冲发送精确控制
今天想起来了,就在之前的基础上写了步进电机的加速曲线控制,其实也没多难,如果看过上一篇的小伙伴也许会记得,代码中有一个核心数组send_buf,今天要说的梯形速度控制其实就是按照梯形加速的方式配置send_buf
send_buf中填写的是PWM的ARR值,我们知道ARR的值可以决定PWM的频率
这里写图片描述

下面这个代码是为了验证效果,在VS里写的一个demo

void config_buf(long steps, long Fpwm, int cmd)这个函数是梯形加速曲线实现的核心,输入参数stepsFpwmcmd
steps是想要发送的脉冲数
Fpwm是想要发送的脉冲频率,是加速过程的最大值,也就是匀速阶段的频率值。
cmd是一个选择加速或者不加速的参数,1为使用加速曲线;0为不采用加速曲线,则全程匀速。

#include <stdio.h>
#define default_size 10000
#define default_arr 599
#define default_psc 719
#define default_size 10000
#define init_arr 999 
#define Fmax 10000

int send_buf[default_size];

void config_buf(long steps, long Fpwm, int cmd)
{
    if (steps > 0 && steps <= default_size && Fpwm <= Fmax) /* 判断参数合法性 */
    {
        long arr_goal = (long)(100000 / Fpwm) - 1;  /* 计算arr目标值 */
        long default_a = (long)((init_arr - arr_goal) / (steps / 4));   /* 计算加速度 */
        if (cmd == 1)   /* 使用加速曲线 */
        {
            long counter;   /* 计数 */
            long flag = 0;  /* 标记分界点 */
            long arr_temp = init_arr;
            for (counter = 0; (init_arr - default_a * counter) > arr_goal; ++counter)
            {
                arr_temp = init_arr - default_a * counter;
                send_buf[counter] = arr_temp;
            }
            if ((init_arr - default_a * counter) <= arr_goal)   /* 开始匀速阶段 */
            {
                flag = counter; /* 分界点 */
                long m;
                for (m = flag; m < steps - flag; ++m)
                {
                    send_buf[m] = arr_goal;
                    counter = m;    /* 计数 */
                }
            }
            long j;
            for (j = counter + 1; arr_goal + default_a * (j - (steps - flag) + 1) < init_arr; ++j)  /* 开始减速阶段 */
            {
                send_buf[j] = arr_goal + default_a * (j - (steps - flag) + 1);
            }
            if (arr_goal + default_a * (j - (steps - flag) + 1) >= init_arr)
            {
                send_buf[j] = arr_goal + default_a * (j - (steps - flag) + 1);
            }
        }
        else if (cmd == 0)  /* 全程匀速 */
        {
            long n;
            for (n = 0; n < steps; ++n)
            {
                send_buf[n] = arr_goal;
            }
        }
    }
}

int main()
{
    config_buf(1000, 1000, 1);
    for (int a = 0; a<default_size;++a)
    {
        printf("%d \n", send_buf[a]);
        if (send_buf[a] == 0)
            break;
    }
    getchar();
    return 0;
}

在VS里跑的效果就像下面这样

这里写图片描述

为了更加直观地看出数据的特征,我把数据在Excel里做了一张图表,如下。
可以看到纵轴是ARR的值,横轴是脉冲数,一共发送1000个脉冲,第1001个位是0。所以会看到图表最后有一个巨大的跳变。由于ARR越大,PWM的频率就越低,所以图表上看见的内容就是一个PWM频率由低到高 -> 保持不变 -> 由高到低的过程。
应用到步进电机上就是一个匀加速 -> 匀速 -> 匀减速的过程

这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41995979/article/details/82714975