步进电机的8拍驱动函数示例

来源:互联网 发布:剑三 知其不可为任务 编辑:程序博客网 时间:2024/05/16 16:15

http://www.arduino.cn/thread-16151-1-1.html


在做arduino的步进电机实验时,很多人都是直接用IDE自带的stepper库来驱动步进电机。但是这个库只封装了2拍和4拍的步进电机驱动,而很多步进电机(如常见的28BYJ-48)是8拍驱动的。当然4拍也可以转起来,不过精度、平稳性和力矩都没有8拍好。

其实,驱动步进电机是个很简单的事情。在每种电机的资料中,都有驱动表格,如果有一定的编程能力,最好自己写个函数来驱动,可以做到最简洁而优雅,且占用最少的资源。这种简单的驱动,没有必要封装成库。

作为例子,针对上述28BYJ-48步进电机(5V,步进角度5.625,5线4相,8拍驱动,机械减速1:64),做了两个驱动函数。第一个示例函数用传统的方式,代码使用switch case结构,看起来比较清晰,可以作为思路的参考。第二个示例函数用了单片机口的概念,体现了单片机的特点,简洁而优雅。
这两个示例函数可以在1.0版以上的IDE中调用,都已测试通过。测试的最新版本是1.6.3。

只要有步进电机的驱动数据表格,这两个函数稍作修改就可以用于各种步进电机。


下面是28BYJ-48步进电机的驱动表格。


函数一测试代码:


int p = 0;    //  拍计数,顺时针7-0,逆时针0-7。int t=24;          //  每拍延时,控制速度,1ms对应最高速。                  //  负值为逆时针方向。 void setup() {  Serial.begin(9600);  //初始化串口,作为监视。  pinMode(4,OUTPUT);  //设置D4-D7脚为步进电机控制脚。  pinMode(5,OUTPUT);  pinMode(6,OUTPUT);  pinMode(7,OUTPUT);} void loop() {//  Serial.println(p);   //  串口输出拍数,调试用。  t = 1;                //  每拍延时24ms,设置转速和方向。负值逆时针转。  one_step(t);          //  驱动一拍。} //  此函数驱动一拍,参数控制速度与旋转方向。void one_step(int t) {    switch(p) {    case 0:                        //  (0001)  对应8拍不同的输出值。      digitalWrite(4,LOW);      digitalWrite(5,LOW);      digitalWrite(6,LOW);      digitalWrite(7,HIGH);      break;    case 1:                       //  (0011)      digitalWrite(4,LOW);      digitalWrite(5,LOW);      digitalWrite(6,HIGH);      digitalWrite(7,HIGH);      break;    case 2:                       //  (0010)      digitalWrite(4,LOW);      digitalWrite(5,LOW);      digitalWrite(6,HIGH);      digitalWrite(7,LOW);      break;    case 3:                       //  (0110)      digitalWrite(4,LOW);      digitalWrite(5,HIGH);      digitalWrite(6,HIGH);      digitalWrite(7,LOW);      break;    case 4:                       //  (0100)      digitalWrite(4,LOW);      digitalWrite(5,HIGH);      digitalWrite(6,LOW);      digitalWrite(7,LOW);      break;    case 5:                        //  (1100)      digitalWrite(4,HIGH);      digitalWrite(5,HIGH);      digitalWrite(6,LOW);      digitalWrite(7,LOW);      break;    case 6:                       //  (1000)      digitalWrite(4,HIGH);      digitalWrite(5,LOW);      digitalWrite(6,LOW);      digitalWrite(7,LOW);      break;    case 7:                       //  (1001)      digitalWrite(4,HIGH);      digitalWrite(5,LOW);      digitalWrite(6,LOW);      digitalWrite(7,HIGH);      break;  }  if (t < 0) {                  // t为负值,正向计数0-7。      p ++;      if (p > 7 ) {        p = 0;                 // 计数到7重新开始。      }    } else {                    // t为正值,逆向计数7-0。      p --;      if ( p < 0 ) {          // 计数到零重新开始。        p = 7;      }    }  Serial.println(abs(t));  delay(abs(t));            // 延时,短则转速高。}


  

函数one_step()可以驱动一拍,使用方法在注释中都有。速度用延时函数控制,延时越少,速度越快。延时1ms可以轻松启动。注意,使用串口调试时,每发送一条串口数据,会有5ms左右的延时(在我自己的计算机上测试的数据)。这个延时也会包括在每一拍的驱动延时中。

函数二测试代码:
[C] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
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
/* 步进电机8拍驱动,对应28BYJ-48,每圈64步,减速比64,
   输出轴每圈4096步。使用二进制掩码直接置位输出口。
*/
int p = 0;         // 拍计数,顺时针0-7,逆时针7-0。
int t;                // 每拍延时,控制速度,1ms对应最高速。负值为逆时针方向。
byte b[] = {B00010000,B00110000,B00100000,B01100000,
                 B01000000,B11000000,B10000000,B10010000};
                      // 对应每拍的D4-D7脚输出掩码。高4位有效。
                            
void setup() {
//  Serial.begin(9600);  // 初始化串口,作为监视。
  DDRD = DDRD | B11110000; // 置D4-D7脚为步进输出,其它脚不变。 
}
 
void loop() {
//  Serial.println(p);  // 串口输出拍数,调试用。
  t = -24;               // 每拍延时24ms,设置转速和方向。负值逆时针转。
  one_step(t);         // 驱动一拍。
}
 
//  此函数驱动一拍,参数控制速度与旋转方向。
void one_step(int t) {
  PORTD = PORTD & B00001111; // 清除D4-D7脚,D0-D3脚不变。
  PORTD = PORTD | b[p];               // 置位D4-D7脚,D0-D3脚不变。
//  Serial.println(PORTD,BIN);           //  串口输出掩码,调试用。
  if(t < 0) {                                    // t为负值,逆向计数0-7。
      p --;
      if(p < 0 ) {
        p = 7;                                   // 计数到0重新开始。
      }
    }else{                                      // t为正值,逆正向计数7-0。
      p ++;
      if( p > 7 ) {                             // 计数到7重新开始。
        p = 0;
      }
    }
  delay(abs(t));                              // 延时,短则转速高。
}

函数one_step()可以驱动一拍,使用方法在注释中都有。DDRD和PORTD是IDE的内置常数,分别表示arduino板上D0-D7脚的输出方向和输出状态,用二进制数直接可以定义。具体可查阅http://wiki.geek-workshop.com/doku.php?id=arduino:arduino_language_reference。


在arduino的学习和实验中,建议还是要学一点单片机的编程知识,最好不要照搬教程或者别人的代码,至少要问一个问什么。可以打开看看自己用到的官方库或第三方库,是不是适合自己的硬件。

代码的简洁和优雅,体现了编程的教养。

0 0