球探彩票开奖

发 帖  

如何通过树莓派的GPIO接口控制步进电机

2014-6-30 22:55:37  53414 树莓派 GPIO 步进电机
分享
7
如何通过的GPIO控制

1、实验目的
在树莓派上编写一个C程序,通过其GPIO口控制步进电机的转动方向以及速度。

2、为什么要用树莓派来控制步进电机
在我的概念中,无论是控制接在树莓派上的摄像头来拍照,还是通过树莓派控制发光,我都还是在“虚拟世界”中折腾树莓派,因为它没有向外界输出任何动作。而在构建一个稍微复杂的系统时,这种能力可能是很重要的,于是,用树莓派来控制步进电机是我必须要做的事情。

3、实现方案
怎样通过Raspberry Pi的GPIO口来控制步进电机?已经有很多人这样做了。由于步进电机通常需要一块驱动板,而这样的产品已经很容易买到并且极其廉价(肯定比你自己做要便宜),因此,我们没有必要自己去做。我在淘宝上不断地查啊查,终于找到了白菜价的步进电机和配套驱动板,加起来才一共8块多钱。

下面来看看我买的步进电机和驱动板的样子:


步进电机和驱动板的接线:


该驱动板配有一个原理图,根据它我们可以知道如何把整个系统连接起来:


可见,驱动板上有4个输入口:IN1~IN4,这4个口用来接树莓派的4个GPIO口。同时,我们需要为驱动板提供5V的供电,这从哪里来?当然是从树莓派引出来。从下面的GPIO口分布图可以得知,“2”口就是+5V,正好就利用它。


我将树莓派上的GPIO 17、18、21、22口(用树莓派的命名方式就是0、1、2、3口)分别接到步进电机驱动板上的IN1、IN2、IN3、IN4口,最后接好线的效果如下:


4、编写程序
在参考了这款步进电机配套的51的示例代码后,我知道了依次把驱动板的IN1~IN4置为高电平,就可以驱动步进电机,也就是说,要把树莓派的4个GPIO输出口依次置为高电平。例如,假设用0代表低电平,1代表高电平的话,GPIO 17、18、21、22口的电平第一次被置为1、0、0、0,第二次被置为0、1、0、0,第三次被置为0、0、1、0,第四次被置为0、0、0、1。

于是我写出了下面的代码(仍然使用WiringPi这个库来操作GPIO):
  1. /* moto.c
  2. * A program to control a stepper motor through the GPIO on Raspberry Pi.
  3. *
  4. * Author: Darran Zhang (http://www.codelast.com)
  5. */

  6. #include <wiringPi.h>
  7. #include <stdio.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>

  10. #define clockWISE 1
  11. #define COUNTER_CLOCKWISE 2

  12. void delayMS(int x);
  13. void rotate(int* pins, int direcon);

  14. int main(int argc,char* argv[]) {
  15.    (argc < 4) {
  16.     printf("Usage example: ./motor 0 1 2 3 \n");
  17.     return 1;
  18.   }

  19.   /* number of the pins which connected to the stepper motor driver board */
  20.   int pinA = atoi(argv[1]);
  21.   int pinB = atoi(argv[2]);
  22.   int pinC = atoi(argv[3]);
  23.   int pinD = atoi(argv[4]);

  24.   int pins[4] = {pinA, pinB, pinC, pinD};

  25.   if (-1 == wiringPiSetup()) {
  26.     printf("Setup wiringPi failed!");
  27.     return 1;
  28.   }

  29.   /* set mode to output */
  30.   pinMode(pinA, OUTPUT);
  31.   pinMode(pinB, OUTPUT);
  32.   pinMode(pinC, OUTPUT);
  33.   pinMode(pinD, OUTPUT);

  34.   delayMS(50);    // wait for a stable status
  35.   for (int i = 0; i < 500; i++) {
  36.     rotate(pins, CLOCKWISE);
  37.   }

  38.   return 0;
  39. }

  40. /* Suspend execution for x milliseconds intervals.
  41. *  @param ms Milliseconds to sleep.
  42. */
  43. void delayMS(int x) {
  44.   usleep(x * 1000);
  45. }

  46. /* Rotate the motor.
  47. *  @param pins     A pointer which points to the pins number array.
  48. *  @param direction  CLOCKWISE for clockwise rotation, COUNTER_CLOCKWISE for counter clockwise rotation.
  49. */
  50. void rotate(int* pins, int direction) {
  51.   for (int i = 0; i < 4; i++) {
  52.     if (CLOCKWISE == direction) {
  53.       for (int j = 0; j < 4; j++) {
  54.         if (j == i) {
  55.           digitalWrite(pins[3 - j], 1); // output a high level
  56.         } else {
  57.           digitalWrite(pins[3 - j], 0); // output a low level
  58.         }
  59.       }
  60.     } else if (COUNTER_CLOCKWISE == direction) {
  61.       for (int j = 0; j < 4; j++) {
  62.         if (j == i) {
  63.           digitalWrite(pins[j], 1); // output a high level
  64.         } else {
  65.           digitalWrite(pins[j], 0); // output a low level
  66.         }
  67.       }
  68.     }
  69.     delayMS(4);
  70.   }
  71. }
复制代码

编译程序:
  1. Compile the code:
复制代码
  1. g++ motor.c -o motor -lwiringPi
复制代码


运行程序:
  1. ./motor 0 1 2 3
复制代码


这里向程序传入了4个参数,它们分别代表要控制的树莓派的GPIO口。切记,由于使用了WiringPi库,所以要参考上面的GPIO分布图的左边那部分来确定这些数字。
可以看到步进电机已经转动了(如下面的Youku视频所示)。如果你发现转动方向(顺/逆时针)反了,你可以把传入的参数顺序调整一下,就可以让它转对方向。
从前面的代码可见,如果要改变步进电机的转速,只需要改变rotate()函数中每次delay的时间即可。因此,如果我们把delay的时间逐渐由大变小,就会导致步进电机呈加速状态。让步进电机周期性加速的完整代码如下:
  1. /* motor_speed_up.c
  2. * A program to control a stepper motor(speed up) through the GPIO on Raspberry Pi.
  3. *
  4. * Author: Darran Zhang (http://www.codelast.com)
  5. */

  6. #include <wiringPi.h>
  7. #include <stdio.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>

  10. #define CLOCKWISE 1
  11. #define COUNTER_CLOCKWISE 2

  12. void delayMS(int x);
  13. void rotate(int* pins, int direction, int delay);
  14. void stop(int* pins);

  15. int main(int argc,char* argv[]) {
  16.   if (argc < 4) {
  17.     printf("Usage example: ./motor 0 1 2 3 \n");
  18.     return 1;
  19.   }

  20.   /* number of the pins which connected to the stepper motor driver board */
  21.   int pinA = atoi(argv[1]);
  22.   int pinB = atoi(argv[2]);
  23.   int pinC = atoi(argv[3]);
  24.   int pinD = atoi(argv[4]);

  25.   int pins[4] = {pinA, pinB, pinC, pinD};

  26.   if (-1 == wiringPiSetup()) {
  27.     printf("Setup wiringPi failed!");
  28.     return 1;
  29.   }

  30.   /* set mode to output */
  31.   pinMode(pinA, OUTPUT);
  32.   pinMode(pinB, OUTPUT);
  33.   pinMode(pinC, OUTPUT);
  34.   pinMode(pinD, OUTPUT);

  35.   delayMS(50);    // wait for a stable status
  36.   int delay = 25;
  37.   while (true) {
  38.     for (int i = 0; i < 10; i++) {
  39.       rotate(pins, CLOCKWISE, delay);
  40.     }
  41.     delay--;
  42.     if (delay < 4) {
  43.       delay = 25;
  44.       stop(pins);
  45.       delayMS(500);
  46.     }
  47.   }

  48.   return 0;
  49. }

  50. /* Suspend execution for x milliseconds intervals.
  51. *  @param ms Milliseconds to sleep.
  52. */
  53. void delayMS(int x) {
  54.   usleep(x * 1000);
  55. }

  56. /* Rotate the motor.
  57. *  @param pins     A pointer which points to the pins number array.
  58. *  @param direction  CLOCKWISE for clockwise rotation, COUNTER_CLOCKWISE for counter clockwise rotation.
  59. *  @param delay    The time intervals(in ms) to delay, and if the value is smaller, the motor rotates faster.
  60. */
  61. void rotate(int* pins, int direction, int delay) {
  62.   for (int i = 0; i < 4; i++) {
  63.     if (CLOCKWISE == direction) {
  64.       for (int j = 0; j < 4; j++) {
  65.         if (j == i) {
  66.           digitalWrite(pins[3 - j], 1); // output a high level
  67.         } else {
  68.           digitalWrite(pins[3 - j], 0); // output a low level
  69.         }
  70.       }
  71.     } else if (COUNTER_CLOCKWISE == direction) {
  72.       for (int j = 0; j < 4; j++) {
  73.         if (j == i) {
  74.           digitalWrite(pins[j], 1); // output a high level
  75.         } else {
  76.           digitalWrite(pins[j], 0); // output a low level
  77.         }
  78.       }
  79.     }
  80.     delayMS(delay);
  81.   }
  82. }

  83. /* Stop the motor.
  84. *  @param pins     A pointer which points to the pins number array.
  85. */
  86. void stop(int* pins) {
  87.   for (int i = 0; i < 4; i++) {
  88.     digitalWrite(pins[i], 0); // output a low level
  89.   }
  90. }
复制代码
    • • 316
    • • 675
    • • 56
    • • 114
    • • 492
    • • 1738
    • • 1642
    • • 1509
    • • 1333
    • • 100
    • • 620
    • • 1738
    • • 997
    • • 982
    • • 1642
    • • 1509
    • • 1333
    • • 1281
    • • 1262
    • • 1090
    • • 693
    • • 405
    • • 114
    • • 1509
    • • 620
    • • 1086
    • • 100
    • • 36
    • • 37
    • • 56
    • • 316
    • • 675
    • • 56
    • • 492
    • • 611
    • • 3
    • • 39
    • • 51
    • • 66
    • • 221
2014-9-1 12:04:31
很不错,刚好能利用上.谢谢楼主
回复

举报球探彩票开奖

2014-9-9 11:48:06
必须必给楼主顶一个 谢谢分享
回复

举报球探彩票开奖

2014-9-9 11:48:17
不错,赞一个
2014-12-25 09:14:58
问一下,驱动板型号是ULN2003吗?
2015-7-31 01:17:32
谢谢,正需要那,哈哈
2015-9-4 23:20:51
楼主利害阿66666666666666666
2016-5-23 20:40:35
请问一下,树莓派分别连接GPS模块和超声波测距模块可以时时输出,但是同时连接,在一个程序实现两功能,结果GPS输出数据具有很大的滞后性,请问为什么
回复

举报球探彩票开奖

2016-9-8 11:12:29
非常不错的文章,学习了
2016-9-26 16:26:15
主动学习,逛逛论坛,灌灌水。
回复

举报球探彩票开奖

2017-7-6 09:28:59
谢谢楼主

球探彩票开奖只有小组成员才能发言,

651个成员聚集在这个小组

最新话题

热门话题

  • 165291浏览 708评论
  • 97002浏览 374评论
  • 113477浏览 332评论
  • 119026浏览 220评论
  • 49726浏览 187评论

创建小组步骤

关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表
-

-

-

-

-

-

-

-

-

-