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

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

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

### 回答1: stm32f103c8t6是一款单片机芯片,内置了丰富的外设和功能,可以用来驱动步进电机步进电机是一种特殊的电机,可以按照一定的步幅旋转,通常用于需要精确定位和控制旋转角度的场合。 在stm32f103c8t6芯片中,可以用GPIO口来控制步进电机驱动器。步进电机驱动器通常是通过串行通信协议来控制的,常见的协议有步进脉冲方向信号、步进脉冲脉宽调制信号等。 下面是一个示例代码,用于控制stm32f103c8t6芯片驱动步进电机转动: 1. 首先需要配置GPIO口的工作模式。例如,将GPIOA口的第0位配置为输出模式,用来控制步进电机的方向信号。 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); 2. 设置步进电机的旋转方向。通过设置GPIOA0口的电平状态,可以控制步进电机的旋转方向。 GPIO_SetBits(GPIOA, GPIO_Pin_0); // 设置引脚电平为高,方向标志位“1” GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 设置引脚电平为低,方向标志位“0” 3. 通过发送脉冲信号控制步进电机的旋转。 GPIO_SetBits(GPIOA, GPIO_Pin_1); // 设置引脚电平为高,发出一个脉冲 GPIO_ResetBits(GPIOA, GPIO_Pin_1); // 设置引脚电平为低,发出一个脉冲 这是一个简单的示例代码,用于驱动步进电机的旋转。通过配置GPIO口的工作模式和发送脉冲信号,可以控制步进电机的方向和旋转。根据步进电机的具体需求和电机驱动器的特性,可能还需要添加其他相关代码来完善步进电机的控制。 ### 回答2: STM32F103C8T6是一款基于ARM Cortex-M3内核的STM32系列单片机,它具有丰富的外设资源和强大的性能。步进电机驱动是STM32F103C8T6的一个重要功能,下面给出一个基于STM32Cube HAL库的步进电机驱动示例步进电机驱动的主要思路是利用GPIO控制步进电机的各个相位,从而实现电机的旋转。本示例以四相八方式驱动步进电机,即利用四个GPIO口依次控制步进电机的四个相位。以下是代码示例: 1. 配置GPIO口为输出模式,并使能相关时钟。 ```c GPIO_InitTypeDef GPIO_InitStruct; /* 初始化GPIO口时钟 */ __HAL_RCC_GPIOx_CLK_ENABLE(); /* 配置步进电机的四个相位控制引脚 */ ``` 2. 配置定时器TIM作为步进电机的时钟源。 ```c TIM_HandleTypeDef htim; /* 初始化定时器时钟 */ __HAL_RCC_TIMx_CLK_ENABLE(); /* 配置定时器TIM的时钟源 */ htim.Instance = TIMx; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = xxx; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.RepetitionCounter = 0; HAL_TIM_Base_Init(&htim); ``` 3. 编写步进电机控制函数。 ```c void motorStep(int step) { switch (step) { case 0: HAL_GPIO_WritePin(GPIOx, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_3, GPIO_PIN_RESET); break; case 1: HAL_GPIO_WritePin(GPIOx, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_1, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_3, GPIO_PIN_RESET); break; case 2: HAL_GPIO_WritePin(GPIOx, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_3, GPIO_PIN_RESET); break; case 3: HAL_GPIO_WritePin(GPIOx, GPIO_PIN_0, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOx, GPIO_PIN_3, GPIO_PIN_SET); break; default: break; } } ``` 4. 调用步进电机控制函数,实现电机的旋转。 ```c int main() { HAL_Init(); // 初始化HAL库 SystemClock_Config(); // 配置系统时钟 HAL_TIM_Base_Init(&htim); // 初始化定时器 motorStep(0); // 旋转1步 motorStep(1); // 旋转2步 motorStep(2); // 旋转3步 motorStep(3); // 旋转4步 while (1) { } } ``` 以上就是一个基于STM32F103C8T6的步进电机驱动示例。通过配置GPIO口和定时器,我们可以控制步进电机的旋转。通过在主函数中调用步进电机控制函数,可以实现不同步数的旋转,从而控制电机的运动。 ### 回答3: stm32f103c8t6是一款基于ARM Cortex-M3内核的高性能微控制器,它拥有丰富的外设和强大的处理能力。步进电机是常用的电机类型,可以通过精确的控制来驱动机械装置。下面是一个例子,展示如何使用stm32f103c8t6来驱动步进电机步进电机需要依靠一个驱动器来控制,常见的驱动器类型有L293D、ULN2003等。首先,将步进电机的控制引脚别连接到stm32f103c8t6的GPIO口,通过设置GPIO口输出电平,控制引脚的状态来控制步进电机的转动。接下来,通过编写STM32固件库函数或使用HAL库函数来控制GPIO口的电平状态,从而控制步进电机的转动。 在程序中首先需要初始化相关的GPIO引脚,设置为输出模式。接着,编写一个函数来实现步进电机正向或逆向转动。该函数可以根据所需转动的步数来控制电机的持续时间和每步的距离。我们可以使用循环结构,通过改变GPIO口输出电平的状态来控制电机步进。 在编写控制函数时,可以根据步进电机的特性来设置适当的延时时间。延时的大小将影响步进电机的转速和转动齿数。我们可以使用定时器或延时函数来实现延时的控制。 除了控制步进电机的转动,我们还可以通过编写计数器函数来记录步进电机的位置。通过增加或减少计数器的值,我们可以精确地控制步进电机的位置。 总结起来,通过初始化GPIO口,编写控制函数和计数器函数,我们可以实现步进电机驱动。我们可以根据实际需求,设置适当的参数,以实现不同的转动速度和精度。因此,stm32f103c8t6是一个很好的选择,能够灵活地控制步进电机的转动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值