AVR446_Linear speed control of stepper motor步进电机曲线分析
1.1. 单片机代码处理
// 定义定时器预分频,定时器实际时钟频率为:72MHz/(STEPMOTOR_TIMx_PRESCALER+1)
#define STEPMOTOR_TIM_PRESCALER 3 // 步进电机驱动器细分设置为: 32 细
// 定义定时器周期,输出比较模式周期设置为0xFFFF
#define STEPMOTOR_TIM_PERIOD 0xFFFF
#define FALSE 0
#define TRUE 1
#define CW 0 // 顺时针
#define CCW 1 // 逆时针
#define STOP 0 // 加减速曲线状态:停止
#define ACCEL 1 // 加减速曲线状态:加速阶段
#define DECEL 2 // 加减速曲线状态:减速阶段
#define RUN 3 // 加减速曲线状态:匀速阶段
#define T1_FREQ (SystemCoreClock/(STEPMOTOR_TIM_PRESCALER+1)) // 频率ft值
#define FSPR 200 //步进电机单圈步数
#define MICRO_STEP 32 // 步进电机驱动器细分数
#define SPR (FSPR*MICRO_STEP) // 旋转一圈需要的脉冲数
// 数学常数
#define ALPHA ((float)(2*3.14159/SPR)) // α= 2*pi/spr//
#define A_T_x10 ((float)(10*ALPHA*T1_FREQ))
#define T1_FREQ_148 ((float)((T1_FREQ*0.676)/10)) // 0.676为误差修正值
#define A_SQ ((float)(2*100000*ALPHA))
#define A_x200 ((float)(200*ALPHA))
/**
* 函数功能: 相对位置运动:运动给定的步数
* 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
accel 加速度,实际值为accel*0.1*rad/sec^2
decel 减速度,实际值为decel*0.1*rad/sec^2
speed 最大速度,实际值为speed*0.1*rad/sec
* 返 回 值: 无
* 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
* 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且
* 速度很慢,那还没达到最大速度就要开始减速
*/
void STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
{
__IO uint16_t tim_count;
// 达到最大速度时的步数
__IO uint32_t max_s_lim;
// 必须要开始减速的步数(如果加速没有达到最大速度)
__IO uint32_t accel_lim;
if(step < 0) // 步数为负数
{
srd.dir = CCW; // 逆时针方向旋转
STEPMOTOR_DIR_REVERSAL();
step =-step; // 获取步数绝对值
}
else
{
srd.dir = CW; // 顺时针方向旋转
STEPMOTOR_DIR_FORWARD();
}
if(step == 1) // 步数为1
{
srd.accel_count = -1; // 只移动一步
srd.run_state = DECEL; // 减速状态.
srd.step_delay = 1000; // 短延时
}
else if(step != 0) // 如果目标运动步数不为0
{
// 我们的驱动器用户手册有详细的计算及推导过程
// 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
// min_delay = (alpha / tt)/ w
srd.min_delay = (int32_t)(A_T_x10/speed);
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
// step_delay = 1/tt * sqrt(2*alpha/accel)
// step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
// 计算多少步之后达到最大速度的限制
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
// 如果达到最大速度小于0.5步,我们将四舍五入为0
// 但实际我们必须移动至少一步才能达到想要的速度
if(max_s_lim == 0){
max_s_lim = 1;
}
// 计算多少步之后我们必须开始减速
// n1 = (n1+n2)decel / (accel + decel)
accel_lim = (uint32_t)(step*decel/(accel+decel));
// 我们必须加速至少1步才能才能开始减速.
if(accel_lim == 0){
accel_lim = 1;
}
// 使用限制条件我们可以计算出减速阶段步数
if(accel_lim <= max_s_lim){
srd.decel_val = accel_lim - step;
}
else{
srd.decel_val = -(max_s_lim*accel/decel);
}
// 当只剩下一步我们必须减速
if(srd.decel_val == 0){
srd.decel_val = -1;
}
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;
// 如果最大速度很慢,我们就不需要进行加速运动
if(srd.step_delay <= srd.min_delay){
srd.step_delay = srd.min_delay;
srd.run_state = RUN;
}
else{
srd.run_state = ACCEL;
}
// 复位加速度计数值
srd.accel_count = 0;
}
MotionStatus = 1; // 电机为运动状态
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR); __HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE);// 使能定时器通道
STEPMOTOR_OUTPUT_ENABLE();
}
1.2. VS2008仿真曲线()
- 假设运动无限远距离,速度一般,计算达到最大速度的理论步数与实际步数
- 其中速度 加速度 减速度 都是放大10倍的
- 问题点: max_s_lim为理论加速步数,accel为实际加速步数,
/* 类型定义------------------------------------------------------------------*/
typedef struct {
uint8 run_state ; // 电机旋转状态
uint8 dir ; // 电机旋转方向
int32 step_delay; // 下个脉冲周期(时间间隔),启动时为加速度
uint32 decel_start; // 启动减速位置
int32 decel_val; // 减速阶段步数
int32 min_delay; // 最小脉冲周期(最大速度,即匀速段速度)
int32 accel_count; // 加减速阶段计数值
}speedRampData;
// 定义定时器预分频,定时器实际时钟频率为:MHz/(STEPMOTOR_TIMx_PRESCALER+1)
#define STEPMOTOR_TIM_PRESCALER 3 // 步进电机驱动器细分设置为: 32 细分
//#define STEPMOTOR_TIM_PRESCALER 7 // 步进电机驱动器细分设置为: 16 细分
//#define STEPMOTOR_TIM_PRESCALER 15 // 步进电机驱动器细分设置为: 8 细分
//#define STEPMOTOR_TIM_PRESCALER 31 // 步进电机驱动器细分设置为: 4 细分
//#define STEPMOTOR_TIM_PRESCALER 63 // 步进电机驱动器细分设置为: 2 细分
//#define STEPMOTOR_TIM_PRESCALER 127 // 步进电机驱动器细分设置为: 1 细分
// 定义定时器周期,输出比较模式周期设置为xFFFF
#define STEPMOTOR_TIM_PERIOD 0xFFFF
#define FALSE 0
#define TRUE 1
#define CW 0 // 顺时针
#define CCW 1 // 逆时针
#define STOP 0 // 加减速曲线状态:停止
#define ACCEL 1 // 加减速曲线状态:加速阶段
#define DECEL 2 // 加减速曲线状态:减速阶段
#define RUN 3 // 加减速曲线状态:匀速阶段
#define T1_FREQ (72000000/(STEPMOTOR_TIM_PRESCALER+1)) // 频率ft值
#define FSPR 200 //步进电机单圈步数
#define MICRO_STEP 32 // 步进电机驱动器细分数
#define SPR (FSPR*MICRO_STEP) // 旋转一圈需要的脉冲数
// 数学常数
#define ALPHA ((float)(2*3.14159/SPR)) // α= 2*pi/spr
#define A_T_x10 ((float)(10*ALPHA*T1_FREQ))
#define T1_FREQ_148 ((float)((T1_FREQ*0.676)/10)) // 0.676为误差修正值
#define A_SQ ((float)(2*100000*ALPHA))
#define A_x200 ((float)(200*ALPHA))
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "motor.h"
#include "math.h"
MOTOR_DATA MotorData;
int32 step=20000000;
uint32 accel=15000;//rad/s
uint32 decel=15000;//rad/s
uint32 speed=1200;//rad/s
char buff[30];
char buff1[30];
speedRampData srd;
//假设距离无限远,那么肯定可以达到最大速度,计算加速到最大速度的步数
void MotorInit(FILE *fp)
{
//uint16 tim_count;
//达到最大速度时的步数
uint32 max_s_lim;
//必须要开始减速的步数
uint32 accel_lim;
float step_delay;
//float min_delay;
// min_delay = (alpha / tt)/ w
srd.min_delay = (int32_t)(A_T_x10/speed);
//min_delay=(A_T_x10/speed);
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
// step_delay = 1/tt * sqrt(2*alpha/accel)
// step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
step_delay = ((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
// 计算多少步之后达到最大速度的限制
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
accel_lim = (uint32_t)(step*decel/(accel+decel));
sprintf(buff,"max_s_lim=%d accel_lim=%d\r",max_s_lim,accel_lim);
fwrite(buff,sizeof(buff),1,fp);
srd.accel_count = 0;
}
void Timer_Scan(FILE *fp)
{
uint16_t tim_count=0;
// 保存新(下)一个延时周期
uint16_t new_step_delay=0;
// 加速过程中最后一次延时(脉冲周期).
static uint16_t last_accel_delay=0;
// 总移动步数计数器
static uint32_t step_count = 0;
// 记录new_step_delay中的余数,提高下一步计算的精度
static int32_t rest = 0;
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
static uint8_t i=0;
srd.accel_count++;// 加速计数值加1
////计算新(下)一步脉冲周期(时间间隔)
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));
// 计算余数,下次计算补上余数,减少误差
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);
srd.step_delay=new_step_delay;
while(new_step_delay >= srd.min_delay)//超过当前速度时退出计算
{
srd.accel_count++;
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);
srd.step_delay = new_step_delay;
sprintf(buff,"new_step_delay=%d count=%d\r",new_step_delay,srd.accel_count);
fwrite(buff,sizeof(buff),1,fp);
printf("%s %s \r",buff,buff1);
memset(buff,0x00,sizeof(buff));
}
}
int main()
{
FILE *fp;
fp=fopen("Timer.txt","w");
MotorInit(fp);//参数初始化
Timer_Scan(fp);
fclose(fp);
system("pause");
return 0;
}
void Timer_Scan(FILE *fp)
{
uint16_t tim_count=0;
// 保存新(下)一个延时周期
uint16_t new_step_delay=0;
// 加速过程中最后一次延时(脉冲周期).
static uint16_t last_accel_delay=0;
// 总移动步数计数器
static uint32_t step_count = 0;
// 记录new_step_delay中的余数,提高下一步计算的精度
static int32_t rest = 0;
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
static uint8_t i=0;
double a;
//srd.accel_count++;// 加速计数值加1
new_step_delay=srd.min_delay;//
while(new_step_delay >= srd.min_delay)//超过当前速度时退出计算
{
srd.accel_count++;
//new_step_delay=(int32)(srd.step_delay*sqrt((double)(srd.accel_count+1));
new_step_delay=(int32)(srd.step_delay*(sqrt((double)(srd.accel_count+1))-sqrt((double)(srd.accel_count))));
sprintf(buff,"new_step_delay=%d count=%d\r",new_step_delay,srd.accel_count);
fwrite(buff,sizeof(buff),1,fp);
printf("%s %s \r",buff,buff1);
memset(buff,0x00,sizeof(buff));
}
}
AVR446_Linear speed control of stepper motor步进电机曲线分析的更多相关文章
- Low Speed High Torque Hydraulic Motor: Motion Performance
Crank connecting rod type low speed high torque hydraulic motor is used earlier, which is called Sta ...
- C#曲线分析平台的制作(六,Sqldependency+Signalr+windows 服务)
在经过五天的学习和资料收集后,终于初步实现了利用sqldependency进行数据库变化监控,signalr进行前后台交互,数据实时更新.下面将源代码贴出进行初步分析: 1.系统整体框架构成: 2.具 ...
- C#曲线分析平台的制作(四,highcharts+ajax加载后台数据)
在上一篇博客:C#曲线分析平台的制作(三,三层构架+echarts显示)中已经完成了后台的三层构架的简单搭建,为实现后面的拓展应用开发和review 改写提供了方便.而在曲线分析平台中,往往有要求时间 ...
- C#曲线分析平台的制作(一,ajax+json前后台数据传递)
在最近的项目学习中,需要建立一个实时数据的曲线分析平台,这其中的关键在于前后台数据传递过程的学习,经过一天的前辈资料整理,大概有了一定的思路,现总结如下: 1.利用jquery下ajax函数实现: & ...
- nvidia gpu fan speed control
nvidia在linux上控制风扇速度,需要起X,在无显示器链接的服务器上显得有点坑,这里汇总一下整个流程 1.nvidia-xconfig --cool-bits=4 生成xorg.conf 2.在 ...
- C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)
在前篇博客中,利用interval()函数,进行ajax轮询初步的实现的对数据的实时显示.但是在工业级别实时显示中,这并非是一种最好的解决方案.随着Html5 websocket的发展,这种全双工的通 ...
- C#曲线分析平台的制作(三,三层构架+echarts显示)
本文依据CSDN另一位网友关于三层构架的简单搭建,基于他的源码进行修改.实现了三层构架合理结构,以及从数据库中传递数值在echarts显示的实验目的. 废话不多说,show me codes: 具体构 ...
- C#曲线分析平台的制作(二,echarts前后台数据显示)
在上一篇博客中,学习了使用javascript和jquery两种方法来进行前后台交互.本篇博客着重利用jquery+echarts来实现从后台取数,从前端echarts中展示. 1.html页面编写: ...
- 步进电机的Arduino库函数
This library allows you to control unipolar or bipolar stepper motors. To use it you will need a ste ...
随机推荐
- python3 练习3
##c##写法 #include<iostream>using namespace std;class Rectangle{public: int j;void area(int X ...
- 研磨设计模式学习笔记1--简单工厂(SimpleFactory)
需求:实现一个简单工厂,客户端根据需求获取实现类. 简单工厂优点: 客户端不需要知道工厂内部实现,然组件外部实现面向接口编程. 客户端.实现类解耦. 一.接口及实现类 //接口 public inte ...
- wget访问tomcat管理界面
tomcat已经部署了管理界面,通过如下命令,将tomcat的状态信息打印到status.xml文件中,对于不方便使用浏览器访问该页面的情况,还是很有用的. wget http://localhost ...
- javascript中typeof与instanceof的区别
JavaScript 中 typeof 和 instanceof 常用来判断一个变量是否为空,或者是什么类型的.但它们之间还是有区别的: typeof typeof 是一个一元运算,放在一个运算数之前 ...
- 17965 幸运之星(优先做) 约瑟夫环问题O(n)
17965 幸运之星(优先做) 时间限制:100MS 内存限制:65535K 提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC;VC Description 每年新年派对的最后 ...
- [转]js 判断js函数、变量是否存在
本文转自:http://blog.csdn.net/liang4571231/article/details/4042519 在进行js编程时,总会出现可能一些函数或者变量未定义而被引用,导致报错的情 ...
- nexus 私服相关的配置
1 上传到nexus的配置 1 settings.xml <server> <id>releases</id> <username>admin</ ...
- php fopen()和file_get_contents() 区别介绍
本文章向码农们介绍PHP使用fopen与file_get_contents读取文件实例分享及这两个函数的区别,需要的码农可以参考一下. php中读取文件可以使用fopen和file_get_conte ...
- LinuxOS
Linux 操作系统必须完成的两个主要目的 与硬件部分交互, 为包含在硬件平台上的所有底层可编程部件提供服务 为运行在计算机系统上的应用程序(即所谓的用户空间)提供执行环境 一些操作系统运行所有的用户 ...
- intellijidea课程 intellijidea神器使用技巧1-5 idea界面介绍
菜单栏介绍: file:文件操作edit:文本操作view:视图操作navigate:跳转code:源码文件analyze:项目依赖关系分析refactor:代码重构快捷操作,如:抽取函数build: ...