树莓派GPIO驱动步进电机

目的:通过树莓派编写一个C程序,通过其GPIO接口控制步进电机的运转速度和运转方向。

材料:正常工作并联网的树莓派、5V步进电机+ULN2003驱动板

方案:

先将5V步进电机和ULN2003驱动板连接好,可以看到驱动板上有IN1~IN4 4各输入口,这4个输入口分别对接树莓派的GPIO口。同时,需要利用树莓派的5V GPIO口为步进电机供电(5V GPIO口接驱动板正级,0V GPIO接驱动板负级)。

将树莓派上GPIO 17、18、21、22分别对应步进电机驱动板的IN1、IN2、IN3、IN4口。

接下来需要编程,将IN1~IN4口依次传入高电平(步进电机运行原理)即可驱动步进电机。

利用WiringPi(安装教程)的库来写如下代码:

touch motor.c
nano motor.c

粘贴如下代码:

/* moto.c
* A program to control a stepper motor through the GPIO on Raspberry Pi
*
* Author: Darran Zhang (http://www.codelast.com)
*/

#include <wiringPi.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define CLOCKWISE 1
#define COUNTER_CLOCKWISE 2
voiddelayMS(intx);
voidrotate(int* pins, intdirection);
intmain(intargc,char* argv[]) {
  if(argc < 4) {
    printf("Usage example: ./motor 0 1 2 3 n");
    return1;
  }
  /* number of the pins which connected to the stepper motor driver board */
  intpinA = atoi(argv[1]);
  intpinB = atoi(argv[2]);
  intpinC = atoi(argv[3]);
  intpinD = atoi(argv[4]);
  intpins[4] = {pinA, pinB, pinC, pinD};
  if(-1 == wiringPiSetup()) {
    printf("Setup wiringPi failed!");
    return1;
  }
  /* set mode to output */
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
  delayMS(50);    // wait for a stable status 
  for(inti = 0; i < 500; i++) {
    rotate(pins, CLOCKWISE);
  }
  return0;
}
/* Suspend execution for x milliseconds intervals.
 *  @param ms Milliseconds to sleep.
 */
voiddelayMS(intx) {
  usleep(x * 1000);
}
/* Rotate the motor.
 *  @param pins     A pointer which points to the pins number array.
 *  @param direction  CLOCKWISE for clockwise rotation, COUNTER_CLOCKWISE for counter clockwise rotation.
 */
voidrotate(int* pins, intdirection) {
  for(inti = 0; i < 4; i++) {
    if(CLOCKWISE == direction) {
      for(intj = 0; j < 4; j++) {
        if(j == i) {
          digitalWrite(pins[3 - j], 1); // output a high level
        else{
          digitalWrite(pins[3 - j], 0); // output a low level
        }
      }
    elseif(COUNTER_CLOCKWISE == direction) {
      for(intj = 0; j < 4; j++) {
        if(j == i) {
          digitalWrite(pins[j], 1); // output a high level
        else{
          digitalWrite(pins[j], 0); // output a low level
        }
      }
    }
    delayMS(4);
  }
}
g++ motor.c -o motor -lwiringPi //编译程序
./motor 0 1 2 3 //运行程序,向程序传入4个参数分别代表要控制的树莓派的GPIO口编号(由于使用的时WiringPi库)。调整传入参数的顺序,可以控制步进电机的转向。这时步进电机应该已经开始低转速运转,说明驱动成功。以上代码中,如果要改变步进电机的转速,我们只需要把改变rotate()函数中每次delay的时间即可。如果我们把delay的时间逐渐由大变小,步进电机就会呈加速状态。让步进电机周期性加速的完整代码如下:

/* motor_speed_up.c

* A program to control a stepper motor(speed up) through the GPIO on Raspberry Pi.
*
* Author: Darran Zhang (http://www.codelast.com)
*/
#include <wiringPi.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define CLOCKWISE 1
#define COUNTER_CLOCKWISE 2
voiddelayMS(intx);
voidrotate(int* pins, intdirection, intdelay);
voidstop(int* pins);
intmain(intargc,char* argv[]) {
  if(argc < 4) {
    printf("Usage example: ./motor 0 1 2 3 n");
    return1;
  }
  /* number of the pins which connected to the stepper motor driver board */
  intpinA = atoi(argv[1]);
  intpinB = atoi(argv[2]);
  intpinC = atoi(argv[3]);
  intpinD = atoi(argv[4]);
  intpins[4] = {pinA, pinB, pinC, pinD};
  if(-1 == wiringPiSetup()) {
    printf("Setup wiringPi failed!");
    return1;
  }
  /* set mode to output */
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
  delayMS(50);    // wait for a stable status
  intdelay = 25;
  while(true) {
    for(inti = 0; i < 10; i++) {
      rotate(pins, CLOCKWISE, delay);
    }
    delay--;
    if(delay < 4) {
      delay = 25;
      stop(pins);
      delayMS(500);
    }
  }
  return0;
}
/* Suspend execution for x milliseconds intervals.
 *  @param ms Milliseconds to sleep.
 */
voiddelayMS(intx) {
  usleep(x * 1000);
}
/* Rotate the motor.
 *  @param pins     A pointer which points to the pins number array.
 *  @param direction  CLOCKWISE for clockwise rotation, COUNTER_CLOCKWISE for counter clockwise rotation.
 *  @param delay    The time intervals(in ms) to delay, and if the value is smaller, the motor rotates faster.
 */
voidrotate(int* pins, intdirection, intdelay) {
  for(inti = 0; i < 4; i++) {
    if(CLOCKWISE == direction) {
      for(intj = 0; j < 4; j++) {
        if(j == i) {
          digitalWrite(pins[3 - j], 1); // output a high level
        else{
          digitalWrite(pins[3 - j], 0); // output a low level
        }
      }
    elseif(COUNTER_CLOCKWISE == direction) {
      for(intj = 0; j < 4; j++) {
        if(j == i) {
          digitalWrite(pins[j], 1); // output a high level
        else{
          digitalWrite(pins[j], 0); // output a low level
        }
      }
    }
    delayMS(delay);
  }
}
/* Stop the motor.
 *  @param pins     A pointer which points to the pins number array.
 */
voidstop(int* pins) {
  for(inti = 0; i < 4; i++) {
    digitalWrite(pins[i], 0); // output a low level
  }
}

修改完程序再试试看?
参考文章:http://www.codelast.com/?p=5232