目的:通过树莓派编写一个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
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库)。调整传入参数的顺序,可以控制步进电机的转向。这时步进电机应该已经开始低转速运转,说明驱动成功。以上代码中,如果要改变步进电机的转速,我们只需要把改变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://www.codelast.com/?p=5232