• stm32f103步进电机S曲线加减速计算


    S曲线主要实现低速扭力大,更快更稳
    https://zhuanlan.zhihu.com/p/396648926?utm_campaign=&utm_medium=social&utm_oi=1361101006265331712&utm_psn=1686906450235133952&utm_source=zhihu
    可点击上面链接查看啤酒杯的运动动画

    摘自一段知乎上一段关于S曲线方程的解释

    首先说一下什么是S型曲线加速,为什么要S型曲线加速。S型曲线加速是指步进电机的启动速度按照S型曲线逐渐增加,以达到设定的最大速度。具体的S型曲线方程如下:
    在这里插入图片描述

    x取值-5~5的曲线图如下:
    在这里插入图片描述

    可以看到,刚开始加速和达到最大速度时加速比较缓慢,中间加速比较快。电机的转矩和转速的乘积的k倍等于功率,也就是说,功率一定的时候,转速与转矩成反比关系。所以,转速越低,转矩越大。当电机直接高速启动时,电机可能存在震动、丢步甚至启动不起来的情况。因此需要S型曲线加速,使电机能够缓慢启动。

    程序实现控制电机的速度,其实就是控制PWM的输出频率。首先需要对S曲线方程进行一些变化,如下:

    Fcurrent = Fmin + (Fmax-Fmin)/(1+exp( -Flexible(i - num )/num) )

    Fcurrent为计算出的当前频率。
    Fmin为加速的起始频率。
    Fmax为加速的最大频率。
    -Flexible*(i - num)/num是对S型曲线进行拉伸变化,其中Flexible代表S曲线区间(越大代表压缩的最厉害,中间加速度越大;越小越接近匀加速。理想的S曲线的取值为4-6)。
    i是在循环计算过程中的索引,从0开始。
    num为 加速脉冲数/2 大小。

    S曲线加减算法计算

    /*加速曲线计算*/
    	for (i = 0; i < Motor_S_Type_ARRAY.step_accel; i++)
    	{
    		// F_current = F_min + (F_max - F_min) / (1 + exp(-flexible*(i-num)/num));
    		F_current = (float)(Motor_S_Type_ARRAY.speed_min_frq + 
    		(Motor_S_Type_ARRAY.speed_max_frq - Motor_S_Type_ARRAY.speed_min_frq) 
    		/ (1 + exp(-FLEXIBLE*(i - (float)(Motor_S_Type_ARRAY.step_accel/2)) 
    		/ (Motor_S_Type_ARRAY.step_accel/2))));
    		
    		speed_per = 1000000 / (F_current*2);//定时器分频后1M的频率,除以当前电平翻转的频率得重装载值。电平翻转的频率为电机频率的2倍
    		MotorDataAlgorithm_Struct_Array.accel_array[i] = (uint16_t)speed_per;
    	}
    	
    	/*减速曲线计算*/
        for (i = 0; i < Motor_S_Type_ARRAY.step_decel; i++)
    	{
    		// F_current = F_max - (F_max - F_min) / (1 + exp(-flexible*(i-num)/num));
    		F_current = (float)(Motor_S_Type_ARRAY.speed_max_frq - 
    		(Motor_S_Type_ARRAY.speed_max_frq - Motor_S_Type_ARRAY.speed_min_frq) 
    		/ (1 + exp(-FLEXIBLE*(i - (float)(Motor_S_Type_ARRAY.step_decel/2))
    		/ (Motor_S_Type_ARRAY.step_decel/2))));
    		
    		speed_per = 1000000 / (F_current*2);//定时器分频后1M的频率,除以当前电平翻转的频率得重装载值。电平翻转的频率为电机频率的2倍
    		MotorDataAlgorithm_Struct_Array.decel_array[i] = (uint16_t)speed_per;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    程序设定的最小频率是2000,最大脉冲翻转频率根据需要设定,由于S曲线的计算需要占用比较多的时间,需要在电机运转前计算好存放于一个数组,提供给定时器中断服务程序使用。

    void motor_prog(void)
    {
    	static uint8_t i=0,j=0;
    	MA_STEP_LEVEL = !MA_STEP_LEVEL;
    	Motor_S_Type_ARRAY.step_counter ++;
    
    	if(Motor_S_Type_ARRAY.step_counter < Motor_S_Type_ARRAY.step_num)//还没达到最大步数,即还没运行完
    	{
    		if(Motor_S_Type_ARRAY.step_counter < Motor_S_Type_ARRAY.step_accel*ACCEL_DECEL_MULTIPLE)//加速过程中
    		{
    			i++;
    			if(i==ACCEL_DECEL_MULTIPLE)
    			{
    				i=0;
    				MotorTimArrUpdate(*MA_accel_data_p++);
    			}
    		}
    		else if(Motor_S_Type_ARRAY.step_counter == Motor_S_Type_ARRAY.step_accel)//刚好加速完成
    		{
    			MotorTimArrUpdate(Motor_S_Type_ARRAY.step_per);
    		}
    		else if((Motor_S_Type_ARRAY.step_num - Motor_S_Type_ARRAY.step_counter) //减速过程中
    				< Motor_S_Type_ARRAY.step_decel*ACCEL_DECEL_MULTIPLE)
    		{
    			j++;
    			if(j==ACCEL_DECEL_MULTIPLE)
    			{
    				j=0;
    				MotorTimArrUpdate(*MA_decel_data_p++);
    			}
    		}
            
            MotorStartStopClk(ENABLE);//启动定时器
    	}
        
            if(Motor_S_Type_ARRAY.step_counter >= Motor_S_Type_ARRAY.step_num){//已达到最大步数
                
                MotorHalfCurrent(HalfEn);//半流锁开启
                MotorStartStopClk(DISABLE);//关闭定时器
                Motor_S_Type_ARRAY.run_state = STOP;//运行状态为停止
    		
                /*电机位置信息更新*/
                if(Motor_S_Type_ARRAY.motor_dir != config_get_ptr()->rst_dir)
                {
                    if( Location_Last + Motor_S_Type_ARRAY.step_counter/2 < MOTOR_LIMIT )
                        Location_Last = Location_Last + Motor_S_Type_ARRAY.step_counter/2;
                    else
                        Location_Last = MOTOR_LIMIT;
                }
                else
                {
                    if( Location_Last > Motor_S_Type_ARRAY.step_counter/2 ) 
                        Location_Last = Location_Last - Motor_S_Type_ARRAY.step_counter/2;
                    else
                        Location_Last = 0;
                }
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    计算完成后的S曲线交由给中断服务程序处理,主要实现设置定时器重载值与实现IO翻转实现产生PWM

    在这里插入图片描述
    没有S曲线的步进电机驱动启动与停止显得顿挫

    stepper

    加入S曲线的步进电机启动与停止显得平滑

    stepper s

  • 相关阅读:
    PHP:prim普里姆算法(附完整源码)
    每章一篇博客带你拿下吉林大学JAVAEE期末(一)
    Spring Data ElasticSearch(一)
    MicroSIP-3.21.3+pjproject-2.13.1+ opus-1.3.1+VS2019
    借助 Pyroscope 对 Amazon EKS 容器服务进行 Continuous Profiling 诊断应用性能
    java计算机毕业设计社团管理系统源码+系统+数据库+lw文档+mybatis+运行部署
    对比编程语言的四种错误处理方法,哪种才是最优方案?
    word文档怎么翻译成中文?不妨试试这几个方法
    大二Web课程设计期末考试——基于HTML+CSS+JavaScript+jQuery电商类化妆品购物商城
    2023上半年软考系统分析师科目一整理-02
  • 原文地址:https://blog.csdn.net/dmjkun/article/details/132959818