树莓派物联网-WiringPi GPIO接口控制步进电机
WiringPi GPIO接口控制步进电机
说明
- 在树莓派上编写一个C程序,通过其GPIO口控制步进电机的转动方向以及速度
准备
- 树莓派
- 电机驱动板
- 步进电机
步骤
步进电机和驱动板图
步进电机和驱动板的接线
驱动板配有一个原理图,根据它我们可以知道如何把整个系统连接起来
驱动板上有4个输入口:IN1~IN4,这4个口用来接树莓派的4个GPIO口。同时,我们需要为驱动板提供5V的供电,这从哪里来?当然是从树莓派引出来。从下面的GPIO口分布图可以得知,“2”口就是+5V,正好就利用它。
将树莓派上的GPIO 17、18、21、22口(用树莓派的命名方式就是0、1、2、3口)分别接到步进电机驱动板上的IN1、IN2、IN3、IN4口,最后接好线的效果如下:
编写代码
- 依次把驱动板的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。
/* 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
void delayMS(int x);
void rotate(int* pins, int direction);
int main(int argc,char* argv[]) {
if (argc < 4) {
printf("Usage example: ./motor 0 1 2 3 \n");
return 1;
}
/* number of the pins which connected to the stepper motor driver board */
int pinA = atoi(argv[1]);
int pinB = atoi(argv[2]);
int pinC = atoi(argv[3]);
int pinD = atoi(argv[4]);
int pins[4] = {pinA, pinB, pinC, pinD};
if (-1 == wiringPiSetup()) {
printf("Setup wiringPi failed!");
return 1;
}
/* set mode to output */
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
pinMode(pinD, OUTPUT);
delayMS(50); // wait for a stable status
for (int i = 0; i < 500; i++) {
rotate(pins, CLOCKWISE);
}
return 0;
}
/* Suspend execution for x milliseconds intervals.
* @param ms Milliseconds to sleep.
*/
void delayMS(int x) {
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.
*/
void rotate(int* pins, int direction) {
for (int i = 0; i < 4; i++) {
if (CLOCKWISE == direction) {
for (int j = 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
}
}
} else if (COUNTER_CLOCKWISE == direction) {
for (int j = 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库,所以要参考上面的GPIO分布图的左边那部分来确定这些数字。
可以看到步进电机已经转动了。如果你发现转动方向(顺/逆时针)反了,你可以把传入的参数顺序调整一下,就可以让它转对方向。
- 控制转速
如果要改变步进电机的转速,只需要改变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
void delayMS(int x);
void rotate(int* pins, int direction, int delay);
void stop(int* pins);
int main(int argc,char* argv[]) {
if (argc < 4) {
printf("Usage example: ./motor 0 1 2 3 \n");
return 1;
}
/* number of the pins which connected to the stepper motor driver board */
int pinA = atoi(argv[1]);
int pinB = atoi(argv[2]);
int pinC = atoi(argv[3]);
int pinD = atoi(argv[4]);
int pins[4] = {pinA, pinB, pinC, pinD};
if (-1 == wiringPiSetup()) {
printf("Setup wiringPi failed!");
return 1;
}
/* set mode to output */
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
pinMode(pinD, OUTPUT);
delayMS(50); // wait for a stable status
int delay = 25;
while (true) {
for (int i = 0; i < 10; i++) {
rotate(pins, CLOCKWISE, delay);
}
delay--;
if (delay < 4) {
delay = 25;
stop(pins);
delayMS(500);
}
}
return 0;
}
/* Suspend execution for x milliseconds intervals.
* @param ms Milliseconds to sleep.
*/
void delayMS(int x) {
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.
*/
void rotate(int* pins, int direction, int delay) {
for (int i = 0; i < 4; i++) {
if (CLOCKWISE == direction) {
for (int j = 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
}
}
} else if (COUNTER_CLOCKWISE == direction) {
for (int j = 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.
*/
void stop(int* pins) {
for (int i = 0; i < 4; i++) {
digitalWrite(pins[i], 0); // output a low level
}
}
参考:
- http://bbs.elecfans.com/jishu_439995_1_1.html
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号