Arduino驱动 步进电机-Arduino中文社区 - Powered by Discuz! Archiver

希岩 发表于 2018-3-25 17:39

Arduino驱动 步进电机

本帖最后由 希岩 于 2020-5-28 13:05 编辑

    知识点:
    步进电机是一种将电脉冲转化为角位移的执行机构。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。您可以通过控制脉冲个来控制角位移量,从而达到准确定位的目的;同时您可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

    步进电机28BYJ48型四相八拍电机,电压为DC5V—DC12V。当对步进电机施加一系列连续不断的控制脉冲时,它可以连续不断地转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单(单相绕组通电)四拍(A-B-C-D-A。。。),双(双相绕组通电)四拍(AB-BC-CD-DA-AB-。。。),八拍(A-AB-B-BC-C-CD-D-DA-A。。。)

   正文:
   本文用Arduino 驱动步进电机28BYJ48,没有使用库文件,编写的程序简捷高效。注意,连接成组,在端口4 5 6 7,之后就可以测试了。程序测试通过,没有问题,供学习Arduino和步进电机用。


/*********************************
功能:驱动28BYJ-48步进电机
设计:凌晨七點半
日期:2018.3.25
连接引脚:分别将28BYJ-48驱动器的IN1 IN2 IN3 IN4连接到
            Arduino Uno R3 4 5 6 7引脚 也就是PORTD 4 5 6 7
*********************************/
//定义连接为PD4 PD5 PD6 PD7

#define ROTATE(x) {PORTD|=x; PORTD&=(x|0x0F);}

//四相单四拍
const char SinBeat={0x80,0x40,0x20,0x10};
//四相双四拍
const char DulBeat1={0xc0,0x60,0x30,0x90};
//四相双八拍
const char DulBeat2={0x80,0xc0,0x40,0x60,0x20,0x30,0x10,0x90};

//节拍模式选择
#define MODE DulBeat2
void setup() {
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
Serial.begin(9600);
}
//逆时针旋转
void Anti_Clockwise(int Speed)
{
for(int i=0;i<sizeof(MODE);i++)
{
ROTATE(MODE);
delay(Speed);
}
}
//顺时针旋转
void Clockwise(int Speed)
{
for(int i=sizeof(MODE);i>=0;i--)
{
ROTATE(MODE);
delay(Speed);
}
}
void loop() {


Clockwise(50);
delay(500);
//Serial.println("OK...");

}

李逍遥 发表于 2019-6-3 22:59

本帖最后由 李逍遥 于 2019-6-3 23:16 编辑

首先,感谢作者的分享,认真读完代码,学到了很多知识,但在其中发现一些错误,可能是我的拙见,如果理解错误请指出。


[*]问题:在运行原代码时,电机总是转动一个角度,然后来回晃一晃,再转动一个角度,再晃一晃,起初以为是电机质量问题。在读到#define ROTATE(x) {PORTD|=x; PORTD&=(x|0x0F);} 时产生疑惑,之后仔细分析,发现错误。


[*]错误:以四相单四拍为例const char SinBeat={0x80,0x40,0x20,0x10}; 四相单四拍的本意是给PORTD依次赋值0x80 0x40 0x20 0x10从而实现单四拍的目的。而根据ROTATE(x)的定义,PORTD的赋值依次为0x80 0xc0 0x40 0x60 0x20 0x30 0x10 0x90这就变成四相双八拍的了 。显然,对于四相双八拍,就大错特错了,由于原代码初始使用的是四相双八拍,所以出现了晃动的现象。(同时,对于(x|0x0F) 尚有不解,因为全程没有涉及到3号脚,而且这样对3号脚也没有影响)



[*]猜想:估计#define ROTATE(x) {PORTD|=x; PORTD&=(x|0x0F);} 这一条代码是专门为四相双八拍设计的,这样在定义时,只用定义四个数值即可。



[*]修改:由于作者在给三种模式定义时,精确到每一步的数值,所以直接删去#define ROTATE(x) 的定义,对于逆时针旋转和顺时针旋转的函数中,将ROTATE(MODE);修改为 PORTD=MODE; 即可。


[*]修改后代码如下:

/*原作者:凌晨七點半
修改:李逍遥
时间:2019/6/3
----------------------------------------------------------------------------------------------------------------*/
//四相单四拍
const char SinBeat = {0x80, 0x40, 0x20, 0x10}; //0x80转换为二进制是1000 0000对应7号脚输出高电平,0x40即0100 0000对应6号角输出高电平
//四相双四拍
const char DulBeat1 = {0xc0, 0x60, 0x30, 0x90};
//四相双八拍
const char DulBeat2 = {0x80, 0xc0, 0x40, 0x60, 0x20, 0x30, 0x10, 0x90};

//节拍模式选择
#define MODE DulBeat2//对三种模式的选择,直接修改模式名,其他无需改动
void setup() {
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
Serial.begin(9600);
}

//逆时针旋转
void Anti_Clockwise(int Speed) {
for (int i = 0; i < sizeof(MODE); i++) { //sizeof(MODE)即取MODE的数组长度,从而实现切换模式时,自动修改for的循环次数
    PORTD = MODE;                     //给引脚赋值
    delay(Speed);                        //控制每次小角度转动停留时间,从而控制一组转动的速度
}
}

//顺时针旋转
void Clockwise(int Speed) {
for (int i = sizeof(MODE); i >= 0; i--) {
    PORTD = MODE;
    delay(Speed);
}
}

//循环工作区
void loop() {
for (int i = 0; i <= 128; i++) {//i为单次转动组数,使效果更明显(控制单次角度)
    Anti_Clockwise(1);            //小角度停留1ms,使效果更明显(控制转动速度)
}
delay(200);                     //完成一次for后停留的时间
}

以上内容全为个人理解,如果错误,希望指出,立马修改             2019/6/323:16 于重庆理工大学

ClearingSky 发表于 2018-4-2 22:54

我也说一句不错

happyer 发表于 2018-3-27 01:29

上传的时候有提示“xORTD”没有被定义,是不是代码还少了一些东西?

希岩 发表于 2018-3-27 10:56

本帖最后由 希岩 于 2018-3-27 10:58 编辑

happyer 发表于 2018-3-27 01:29
上传的时候有提示“xORTD”没有被定义,是不是代码还少了一些东西?
谢谢,是的,上传啃罗布时丢了几行东西,现在编辑好了。我加个了空格,不知道为啥不加那个“P”丢掉了

odinliu88 发表于 2018-3-27 14:45

学习了,谢谢分享!

cxk1314 发表于 2018-3-27 23:01

:)学习了,,小白强烈建议作者带点注释。。。。谢谢

happyer 发表于 2018-3-28 00:25

希岩 发表于 2018-3-27 10:56
谢谢,是的,上传啃罗布时丢了几行东西,现在编辑好了。我加个了空格,不知道为啥不加那个“P”丢掉了 ...
我上传后报了新的数组的问题
invalid use of non-lvalue array
能否传个.ino文件?

希岩 发表于 2018-4-13 21:04

happyer 发表于 2018-3-28 00:25
我上传后报了新的数组的问题
invalid use of non-lvalue array
能否传个.ino文件?


已经发了。。。。。。

木头人嘟噜噜 发表于 2018-6-1 13:02

小白一个,如何提高转速呢?还有就是这五根线分别控制什么呢?

tonyness 发表于 2018-6-7 16:26

warning: narrowing conversion of '128' from 'int' to 'const char' inside { } [-Wnarrowing]

const char SinBeat={0x80,0x40,0x20,0x10};
In function 'void Anti_Clockwise(int)':

sketch_jun07a:10: error: invalid use of non-lvalue array

#define ROTATE(x) {PORTD|=x; PORTD&=(x|0x0F);}
这个是要怎么弄啊
页: [1] 2 3
查看完整版本: Arduino驱动 步进电机