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仿真曲线()

  1. 假设运动无限远距离,速度一般,计算达到最大速度的理论步数与实际步数
  2. 其中速度 加速度 减速度 都是放大10倍的
  3. 问题点: 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步进电机曲线分析的更多相关文章

  1. 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 ...

  2. C#曲线分析平台的制作(六,Sqldependency+Signalr+windows 服务)

    在经过五天的学习和资料收集后,终于初步实现了利用sqldependency进行数据库变化监控,signalr进行前后台交互,数据实时更新.下面将源代码贴出进行初步分析: 1.系统整体框架构成: 2.具 ...

  3. C#曲线分析平台的制作(四,highcharts+ajax加载后台数据)

    在上一篇博客:C#曲线分析平台的制作(三,三层构架+echarts显示)中已经完成了后台的三层构架的简单搭建,为实现后面的拓展应用开发和review 改写提供了方便.而在曲线分析平台中,往往有要求时间 ...

  4. C#曲线分析平台的制作(一,ajax+json前后台数据传递)

    在最近的项目学习中,需要建立一个实时数据的曲线分析平台,这其中的关键在于前后台数据传递过程的学习,经过一天的前辈资料整理,大概有了一定的思路,现总结如下: 1.利用jquery下ajax函数实现: & ...

  5. nvidia gpu fan speed control

    nvidia在linux上控制风扇速度,需要起X,在无显示器链接的服务器上显得有点坑,这里汇总一下整个流程 1.nvidia-xconfig --cool-bits=4 生成xorg.conf 2.在 ...

  6. C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)

    在前篇博客中,利用interval()函数,进行ajax轮询初步的实现的对数据的实时显示.但是在工业级别实时显示中,这并非是一种最好的解决方案.随着Html5 websocket的发展,这种全双工的通 ...

  7. C#曲线分析平台的制作(三,三层构架+echarts显示)

    本文依据CSDN另一位网友关于三层构架的简单搭建,基于他的源码进行修改.实现了三层构架合理结构,以及从数据库中传递数值在echarts显示的实验目的. 废话不多说,show me codes: 具体构 ...

  8. C#曲线分析平台的制作(二,echarts前后台数据显示)

    在上一篇博客中,学习了使用javascript和jquery两种方法来进行前后台交互.本篇博客着重利用jquery+echarts来实现从后台取数,从前端echarts中展示. 1.html页面编写: ...

  9. 步进电机的Arduino库函数

    This library allows you to control unipolar or bipolar stepper motors. To use it you will need a ste ...

随机推荐

  1. 创建有关hbase数据库的项目时所遇到的问题

    1.在以前使用其他数据库时,经常会使用id自增来做主键,但是hbase数据库中不知道怎么来设置自增主键,所以我打算不要id自增主键.然后删除原来的表,重新创建表. 删除表语句: 用drop命令可以删除 ...

  2. inventor安装失败怎样卸载安装inventor 2015?

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  3. [转]分享20佳好玩的 jQuery 游戏

    本文转自:http://www.cnblogs.com/lhb25/archive/2011/04/17/2001089.html jQuery是时下最流行的 JavaScript 库.现在,除了HT ...

  4. 使用vue Devtools

    第一步: 在谷歌应用商店中查找 vue Devtools 并安装.安装之后,即使我们打开了vue项目发现vue标识是灰色的,说明并没有成功启动vue. 第二步: 默认安装的情况下,找到C:\Users ...

  5. ETL模型设计

    传统的关系数据库一般采用二维数表的形式来表示数据,一个维是行,另一个维是列,行和列的交叉处就是数据元素.关系数据的基础是关系数据库模型,通过标准的SQL语言来加以实现. 数据仓库是多维数据库,它扩展了 ...

  6. java学习第十五天

    1:对象数组(掌握) (1)数组既可以存储基本数据类型,也可以存储引用类型.它存储引用类型的时候的数组就叫对象数组. (2)案例: 用数组存储5个学生对象,并遍历数组. 2:集合(Collection ...

  7. 网页设计,Access入门 2010,数学

    网页设计(表格) 创建表格:插入---表格---设置表格大小---确定.(按Ctrl键可多选单元格) 插入图片在表格:光标在单元格---插入---图像---选择图像---确定. 表格属性:属性(屏幕下 ...

  8. Spring课程 Spring入门篇 1-2Spring简介

    课程链接: 1 Spring是什么? 2 为什么是Spring 3 Spring的作用: 4 适用范围 1 Spring是什么? a 开源框架 b 轻量级的控制反转(Ioc)和面向切面编程(AOP)的 ...

  9. FastDFS 搭建

    #FastDFS安装方式 安装必要插件:libevent  (此次搭建方案采用libevent 1.4.13)   wget http://fastdfs.googlecode.com/files/F ...

  10. 微信小程序电商实战-商品详情(上)

    先看一下今天要实现的小程序商品详情页吧!   商品详情.gif 本期我们要实现小程序商品详情页的头部标题.头部轮播.商品详情浮动按钮和商品内页布局. 一.设置头部标题 如上图所示,头部标题是商品详情 ...