|
|
本帖最后由 liweisgg 于 2014-12-21 15:53 编辑
鄙人近期写了部分驱动两相步进电机的测试程序,但是经过分析与实测,发现步进电机其实并没有真正的进行匀速运动,下面附出具体代码及说明,望和大虾们交流讨论。
[pre lang="arduino" line="1" file="步进测试"]
//The program name: Stepper motor speed test v1.0
//The procedure function: 完成基本的匀速、加速、减速运动测试,转速为2.5rps
//The development board: Arduino UNO
//#define STEP 4
//#define DIR 5
//#define EN 6
int STEP_PIN = 4;
int DIR_PIN = 5;
int EN_PIN = 6;
int Microstep = 200; //驱动器细分设置值
int Cyc = 1; //电机旋转速度置值(rps)
int speed_a = 40; //电机角加速度(°/s2)
int count_s = 0;
char var;
void setup(void)
{
pinMode(STEP_PIN , OUTPUT);
pinMode(DIR_PIN , OUTPUT);
pinMode(EN_PIN , OUTPUT);
Serial.begin(115200);
}
void uniform_speed_a()
{
float time_us_old;
time_us_old = 1*100000/(2*Cyc*Microstep);
int time = time_us_old;
digitalWrite (DIR_PIN,HIGH);
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us_old);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us_old);
}
void uniform_speed_b()
{
float time_us_old;
time_us_old = 1*100000/(2*Cyc*Microstep);
int time = time_us_old;
digitalWrite (DIR_PIN,LOW);
digitalWrite (STEP_PIN,HIGH);
delay(1);
digitalWrite (STEP_PIN,LOW);
delay(1);
}
void up_speed_a()
{
float time_us_old;
float Cyc_new;
Cyc_new = Cyc +count_s*((speed_a/360)/200) ; //计算出第二步相对于上一步的新转速
time_us_old = 1/(Cyc_new*Microstep)*1000000; //time_us_old为每步的二分之一时间
int time_us = time_us_old;
digitalWrite (DIR_PIN,HIGH);
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us);
count_s=count_s+1;
}
void up_speed_b()
{
float time_us_old;
float Cyc_new;
Cyc_new = Cyc +count_s*((speed_a/360)/200) ; //计算出第二步相对于上一步的新转速
time_us_old = 1/(Cyc_new*Microstep)*1000000; //time_us_old为每步的二分之一时间
int time_us = time_us_old;
digitalWrite (DIR_PIN,LOW);
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us);
count_s=count_s+1;
}
void down_speed_a()
{
float time_us_old;
float Cyc_new;
Cyc_new = Cyc -count_s*((speed_a/360)/200) ; //计算出第二步相对于上一步的新转速
time_us_old = 1/(Cyc_new*Microstep)*1000000; //time_us_old为每步的二分之一时间
int time_us = time_us_old;
digitalWrite (DIR_PIN,HIGH);
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us);
count_s=count_s+1;
}
void down_speed_b()
{
float time_us_old;
float Cyc_new;
Cyc_new = Cyc -count_s*((speed_a/360)/200) ; //计算出第二步相对于上一步的新转速
time_us_old = 1/(Cyc_new*Microstep)*1000000; //time_us_old为每步的二分之一时间
int time_us = time_us_old;
digitalWrite (DIR_PIN,LOW);
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us);
count_s=count_s+1;
}
void loop()
{
// int number;
// number=400;
EN_PIN=0;
if(Serial.available()>0)//如果串口有数据进入的话
{
var=Serial.read();//读字符,是ASCII码的
}
if (var=='1')
{
uniform_speed_a();
}
if (var=='2')
{
uniform_speed_b();
}
if (var=='3')
{
up_speed_a();
}
if (var=='4')
{
up_speed_b();
}
if (var=='5')
{
down_speed_a();
}
if (var=='6')
{
down_speed_b();
}
}[/code]
上边的代码我大概解释下,因为我用的是混合式步进电机,所以采用了其自带的步进电机驱动,驱动器的信号输入STEP_PIN、DIR_PIN 、EN_PIN 分别为脉冲信号、方向信号和使能信号,也就是说我只要控制好STEP_PIN引脚高低电平的变化频率便可以控制步进电机的旋转速度了,那么只要我的delay(time)延时函数给定,那么这个步进电机就应该是匀速运动了。
电机驱动器可以设置步进电机的细分,我这里设置为200细分,也就是说STEP_PIN信号脚200个变化周期步进电机便旋转一圈,速度由我的delay延时函数控制。
我的步进电机后边是加装1000线的编码器的,为什么说步进电机不是匀速,便是由编码器返回的差分信号看出来的,我用示波器看到了差分信号并不是恒定周期的,而是大概若干个恒定周期之后,会出现一个周期略长的缓冲周期,然后如此往复循环。
这里我认为是每一段代码都是有机器周期的,比如匀速子函数:
void uniform_speed_a()
{
float time_us_old;
time_us_old = 1*100000/(2*Cyc*Microstep);
int time = time_us_old;
digitalWrite (DIR_PIN,HIGH);
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us_old);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us_old);
}
中,
digitalWrite (STEP_PIN,HIGH);
delayMicroseconds(time_us_old);
digitalWrite (STEP_PIN,LOW);
delayMicroseconds(time_us_old);
为脉冲信号输出代码,但是该子程序中运行脉冲信号输出之前总要先运行
float time_us_old;
time_us_old = 1*100000/(2*Cyc*Microstep);
int time = time_us_old;
这三行程序,这样,其实步进电机就无法做到真正的匀速运动了,它包含了三条代码的机器时间。
大虾们,关于这样的解释是否正确?我该如何让步进电机做到真正的匀速运动?后边我的程序还有加入编码器的闭环控制,但是关于步进加减速子函数还会有一些问题,以及编码器测速后的串口速度值输出显示也有一些问题,这个后续可以在讨论。 |
|