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

news2024/11/25 3:05:09

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;
	}

程序设定的最小频率是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;
            }
	}
	
}

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1021618.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#,数值计算——Logisticdev的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Structure for logistic deviates. /// </summary> public class Logisticdev : Ran { private double mu { get; set; } private double sig {…

PaddlePaddle Hackathon 飞桨黑客马拉松热身赛上线!

挑战自我 拓展技能 激发创新 挑战极限 再次相遇黑客松 我们期待你的加入&#xff01; 第五期 PaddlePaddle Hackathon 飞桨黑客马拉松热身赛上线&#xff0c;本次活动是面向全球开发者的深度学习领域编程活动&#xff0c;鼓励开发者了解和参与飞桨深度学习开源项目与文心大…

基于海康Ehome/ISUP接入到LiveNVR实现海康摄像头、录像机视频统一汇聚,做到物联网无插件直播回放和控制

LiveNVR支持海康NVR摄像头通EHOME接入ISUP接入LiveNVR分发视频流或是转GB28181 1、海康 ISUP 接入配置2、海康设备接入2.1、海康EHOME接入配置示例2.2、海康ISUP接入配置示例 3、通道配置3.1、直播流接入类型 海康ISUP3.2、海康 ISUP 设备ID3.3、启用保存3.4、接入成功 4、相关…

TC397 IfxAsclin串口收发分析

TC397 IfxAsclin串口收发分析 硬件FIFO 16 bytes TxFIFO 16 bytes RxFIFO 软件操作: 通过以上函数调用分析,可知: 1:初始化串口时,指定的FIFO为S/W 缓冲FIFO 2:ILLD提供的ISR操作函数: IfxAsclin_Asc_isrTransmit(&gstAsc2); IfxAsclin_Asc_isrReceive(&gs…

VMware虚拟机如何设置网络

一直没弄明白怎么能让虚拟机正常上网和访问&#xff0c;最近总结一个小经验 要在宿主机访问虚拟机电脑服务器&#xff0c;要设置成nat格式&#xff0c;虚拟机可以上网&#xff0c;宿主机访问虚拟机上的ip即可访问虚拟机里的服务器&#xff0c;也就是这样设置就行。 这时候ip不…

计算机网络层(2)

1.动态路由协议&#xff1a; 内部网关协议&#xff1a;用于一个自治系统的内部 外部网关协议&#xff1a;用于不同自治系统 RIP协议&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;&#xff1a;路由信息协议是一种内部网关协议&#xff0c;是一…

【洛谷算法题】P5706-再分肥宅水【入门1顺序结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5706-再分肥宅水【入门1顺序结构】&#x1f30f;题目描述&#x1f30f;输入格式…

Python爬虫基础(五):使用scrapy框架

文章目录 系列文章索引一、scrapy简介1、什么是scrapy2、scrapy安装3、scrapy架构组成4、scrapy工作原理 二、scrapy基本使用1、创建项目2、创建爬虫文件3、&#xff08;附&#xff09;项目组成4、运行爬虫代码&#xff08;1&#xff09;修改baidu.py&#xff08;2&#xff09;…

css自学框架之平滑滚动

今天添加的功能是平滑滚动到指定位置&#xff0c;就是单击页面的按钮&#xff0c;平滑滚动页面到对应的元素&#xff0c;可添加偏移值。 示例&#xff1a;单击ID为gundongBTN 元素&#xff0c;页面平滑滚动到其指定的ID为#topdiv对应内容&#xff0c;同时保留 5px 的偏移间距。…

Java计算机毕业设计 基于SSM+Vue医药进出口交易系统的设计与实现 Java课程设计 实战项目

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

八、实时时钟

八、实时时钟 简介时钟芯片模块代码可调时钟 简介 引脚定义和应用电路 我们的开发板没有备用电池 寄存器定义 时序定义 在时钟的上升沿&#xff0c;IO口的数据被写入到芯片中&#xff0c;在下降沿&#xff0c;芯片就会将数据输出。如果是写入&#xff0c;那么在整个过程中&…

MySQL查询表结构方法

MySQL查询数据库单个表结构代码 – 查询数据库表信息 SELECT​ COLUMN_NAME 列名,​ DATA_TYPE 字段类型,​ CHARACTER_MAXIMUM_LENGTH 长度,​ IS_NULLABLE 是否为空,​ IF(column_key PRI,Y,) 是否为主键,​ COLUMN_DEFAULT 默认值,​ COLUMN_COMMENT 备注FROM​ INFORMAT…

c++ reference_wrapper源码注释

并给出图片&#xff0c;这样就不用下载了 谢谢

实现安全的服务通信:探索如何使用服务网格来确保服务间的安全通信

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

C++,基础函数、string、引用型变量reference

9月18日 C标准库。 一、C入门基础 1、基础 入口函数与C语言相同 后缀名使用cpp 注释与c语言相同 导入c标准库无需后缀 自定义头文件与c语言相同 using namespace std; std&#xff1a;名称空间&#xff08;全局区&#xff09; cout、endl属性名称空间“std” C输出没有格式…

linux入门到精通-第三章-vi(vim)编辑器

目录 文本编辑器gedit介绍vi(vim)命令模式命令模式编辑模式末行模式 帮助教程保存文件切换到编辑模式光标移动(命令模式下)复制粘贴删除撤销恢复保存退出查找替换可视模式替换模式分屏其他用法配置文件 文本编辑器 gedit介绍 gedit是一个GNOME桌面环境下兼容UTF-8的文本编辑器…

SpringCLoud——Docker的基本介绍

什么是Docker 项目部署问题 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会碰到一些问题&#xff1a; 依赖关系复杂&#xff0c;容易出现兼容性问题开发、测试、生产环境有差异。 Docker Docker如何解决依赖的兼容问题的&#xff1f; 将应用的LIbs&…

GDPU 数据结构 天码行空2

实验内容 用顺序表实现病历信息的管理与查询功能。具体要求如下: 利用教材中定义顺序表类型存储病人病历信息(病历号,姓名&#xff0c;症状)&#xff1b;要求使用头文件。 设计顺序表定位查找算法&#xff0c;写成一个函数&#xff0c;完成的功能为:在线性表L中查找数据元素x…

CSS 链接:Link

文章目录 CSS 链接链接样式常见的链接样式文本修饰背景颜色案例1&#xff0c;添加不同样式的超链接2&#xff0c;高级 - 创建链接框 CSS 链接 CSS可以用来设置链接的样式&#xff0c;包括未访问的链接&#xff08;a:link&#xff09;、已访问的链接&#xff08;a:visited&…

【Linux 应用】 kworker 进程

1.简介 “kworker” 是 Linux 内核的工作线程&#xff0c;用于异步处理工作队列中的任务。这些任务包括处理硬件中断、文件系统事件、管理系统内存等。你可能会看到多个 kworker 进程&#xff0c;每个进程的名称后面都有一个数字&#xff0c;如 “kworker/0:1”、“kworker/1:…