单片机 控制 步进电机


开始浏览正文之前,请大家先花几分钟看完这段视频:

步进电机是如何工作的


步进电机(stepping motor)

步进电机

步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件,是一种将电脉冲转化为角位移的执行机构。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步进角),是现代数字程序控制系统中的主要执行元件,应用极为广泛。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响。

当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为"步距角",它的旋转是以固定的角度一步一步运行的。

可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

步进电机是一种感应电机,它的工作原理是利用电子电路,将直流电变成分时供电的多相时序控制电流,用这种电流为步进电机供电,步进电机才能正常工作,驱动器就是为步进电机分时供电的多相时序控制器。

虽然步进电机已被广泛地应用,但步进电机并不能像普通的直流电机、交流电机在常规下使用。它必须由双环形脉冲信号、功率驱动电路等组成控制系统方可使用。因此用好步进电机却非易事,它涉及到机械、电机、电子及计算机等许多专业知识。

步进电机作为执行元件,是机电一体化的关键产品之一,广泛应用在各种自动化控制系统中。随着微电子和计算机技术的发展,步进电机的需求量与日俱增,在各个国民经济领域都有应用。

步进电机又称为脉冲电机,基于最基本的电磁铁原理,它是一种可以自由回转的电磁铁,其动作原理是依靠气隙磁导的变化来产生电磁转矩。

由于步进电机是一个把电脉冲转换成离散的机械运动的装置,具有很好的数据控制特性,因此,计算机成为步进电机的理想驱动源,随着微电子和计算机技术的发展,软硬件结合的控制方式成为了主流,即通过程序产生控制脉冲,驱动硬件电路。单片机通过软件来控制步进电机,更好地挖掘出了电机的潜力。因此,用单片机控制步进电机已经成为了一种必然的趋势,也符合数字化的时代趋势。


步进电机和伺服电机、舵机有何区别?

伺服电机不仅仅只包含一个电机,通常是包含电机、传感器和控制器的电机系统(具体可以参考伺服电机/舵机 控制)。
舵机是个俗称,适用于航模上,其实是一种低端的但最常见的伺服电机系统,价格低廉但精度较低。


单片机控制示例

51单片机按键控制单反转仿真

相信通过视频及文字内容,大家对步进电机相关原理已经非常熟悉。下面通过Arduino Pro MINI开发板进行一项简易的步进电机控制实验。


步进电机内部结构

步进电机(Stepper/Step/Stepping Motor),主要是依靠定子线圈序列通电,顺次在不同的角度形成磁场,推拉定子旋转。接触步进电机时会有很多容易混淆的概念。比如单极性、双极性、两相八线、四相八线等等。主要是由于线圈的接法不同,我们先简单地辩析一下:按照电机驱动架构可分为单极性 (unipolar) 和双极性 (bipolar) 步进电机。所谓的极性,就是电流通过线圈绕组产生磁场的极性,单极性就是只有一个磁极,双极就是有两个磁极。四相,八相是指步进电机的相数,即步进电机内部的线圈组数。电机的相数不同,步进电机接收到每个脉冲信号的角度也不同。通过不同的极性,不同的相数,线圈接法会得到不同的电机性能。

实验前要准备的元件

  • 28BYJ-48 五线四相步进电机
  • ULN2003驱动芯片
  • Arduino Pro MINI开发板
  • 杜邦线若干
28BYJ-48,DC5V,五线四相步进电机

示例代码一:

    可以直接在Arduino IDE的File> Examples> Stepper> MotorKnob里直接导入示例代码。

Stepper.h是Arduino IDE自带的控制步进电机的标准库。

电路原理图(电位计10K即可)

实物连接示意图
/*
 * MotorKnob
 *
 * A stepper motor follows the turns of a potentiometer
 * (or other sensor) on analog input 0.
 *
 * http://www.arduino.cc/en/Reference/Stepper
 * This example code is in the public domain.
 */
#include <Stepper.h>
// change this to the number of steps on your motor
#define STEPS 100
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 8, 9, 10, 11);
// the previous reading from the analog input
int previous = 0;
void setup() {
  // set the speed of the motor to 30 RPMs
  stepper.setSpeed(30);
}
void loop() {
  // get the sensor value
  int val = analogRead(0);

  // move a number of steps equal to the change in the
  // sensor reading
  stepper.step(val - previous);

  // remember the previous value of the sensor
  previous = val;
}

Stepper函数是用来创建步进电机实例的,共有如下两种用法:
steps代表电机转一圈所用的步数。这个一般是步进电机出厂是就固定的。

  • 也可以通过步距角计算得出:
    转一圈的步数 = 360 / 步距角
        Stepper(steps, pin1, pin2)
        Stepper(steps, pin1, pin2, pin3, pin4)

pin1,pin2,pin3,pin4是连接至步进电机的引脚。
根据电机的引线数确定。pin3,pin4是可选的。

    setSpeed(rpms)函数是用来设置步进电机的速度,即每分钟该转的步数。
  • 根据实例代码,当转动电位器,步进电机也会转动一定角度。

示例代码二:

调用大神写好的库当然可以节约大量的开发时间,不过懂得原理也是非常有必要的。下面通过五线四相步进电机来进行简单说明:

五线四相步进电机的工作方式
`四相步进电机可以在:`
    - 四相单拍   : 通电顺序为 A-B-C-D
    - 四相双拍1  : 通电顺序为 AB-BC-CD-DA
    - 四相双拍2  : 通电顺序为 AC-BC-BD-DA
    - 四相八拍   : 通电顺序为 A-AB-B-BC-C-CD-D-DA-A
`四种工作方式下工作。`



下面依照8拍驱动方式编写相关代码:
/* Main.ino file 
 * by: 禾灮Studios
 * 
 * Created:   周三 6月 13 2018
 * Processor: Arduino Uno
 * Compiler:  Arduino AVR (Proteus)
 */
#define motor_pin_1 8       //A
#define motor_pin_2 9       //B
#define motor_pin_3 10      //C
#define motor_pin_4 11      //D
int shiJian =10;        //参数用于电机调速

 
void steps_to_move_N(){     //逆时针旋转 八拍方式驱动,顺序为A AB B BC C CD D DA
    //1000  
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian); 
    //1100  
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    // 0100  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    // 0110  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    //0010  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    //0011  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, HIGH);
    delay(shiJian);
    //0001  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, HIGH);
    delay(shiJian);
    //1001  
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, HIGH);
    delay(shiJian);
}
void steps_to_move_Z(){
    //1001  
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, HIGH);
    delay(shiJian);
    //0001  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, HIGH);
    delay(shiJian);
    //0011  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, HIGH);
    delay(shiJian);
    //0010  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    // 0110  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    // 0100  
    digitalWrite(motor_pin_1, LOW);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    //1100  
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian);
    //1000  
    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, LOW);
    digitalWrite(motor_pin_3, LOW);
    digitalWrite(motor_pin_4, LOW);
    delay(shiJian); 
}

void setup(){  //初始化
    // put your setup code here, to run once:
    // setup the pins on the microcontroller:
    pinMode(motor_pin_1, OUTPUT);
    pinMode(motor_pin_2, OUTPUT);
    pinMode(motor_pin_3, OUTPUT);
    pinMode(motor_pin_4, OUTPUT);

    digitalWrite(motor_pin_1, HIGH);
    digitalWrite(motor_pin_2, HIGH);
    digitalWrite(motor_pin_3, HIGH);
    digitalWrite(motor_pin_4, HIGH); 
}
void loop(){   // put your main code here, to run repeatedly:
    steps_to_move_Z();
    // steps_to_move_N();
} 

示例代码三:

下面的代码适用于Arduino系列,以及AVR单片机编程,修改后可直接用于其他单片机。
本段代码是对示例代码二中函数的简化表述方式。

/* Main.ino file 
 * by: 禾灮Studios
 * 
 * Created:   周三 6月 13 2018
 * Processor: Arduino Uno
 * Compiler:  Arduino AVR (Proteus)
 */
#define motor_pin_1 8       //A
#define motor_pin_2 9       //B
#define motor_pin_3 10      //C
#define motor_pin_4 11      //D
int shiJian =10;        //参数用于电机调速   
//定义八拍方式驱动,顺序为A-AB-B-BC-C-CD-D-DA
unsigned char clockWise[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x0d}; 

    void zzz(){    //顺时针旋转
      for(int i=0;i<8;i++){
        PORTB = clockWise[i];
        delay(shiJian);
      }
    }
    void fff(){     //逆时针旋转
      for(int i=0;i<8;i++){
        PORTB = clockWise[8-i];
        delay(shiJian);
      } 
    }

void setup(){  //初始化
    // put your setup code here, to run once:
    // setup the pins on the microcontroller:
    DDRB=0xFF;    //端口B设置为输出
    PORTB=0xFF;   //端口B初始值设置为1
}
void loop(){   // put your main code here, to run repeatedly:
    zzz();       
    fff();
}
实物连接

以上内容就是控制步进电机的几种简易方法,各有优缺点大家根据自己的喜好和需要进行选择。不足之处还请大家批评指正。


    感谢一直关注着禾灮成长进步的朋友们。你们的信任、支持和鼓励,鞭策着我们一路走到了今天。
    
    感谢所有的合作伙伴,我们相互促进,共同见证了彼此的成长。

    感谢所有曾经在禾灮彼此倚靠、相互鼓励、携手同心、砥砺同行的兄弟姐妹。这里承载了我们的青春与热血。

                禾灮,感谢有你。

    未来,我们将一如既往,砥砺前行。

                                        禾灮·小楊
                                       2018.07.05

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容