ULN2003的工作原理。

 

1;这里图2步进电机的A端流入+5V ,如果图1输入的是高电平的话。两个三极管导通,于是步进电机的那一相就导通了。低电平,就断开了。
2;这里如果电机突然停止产生很大的电流;这时由于COM端接了二极管则限制在+5.7V左右

以前一直不理解,为什么会没供电的端口。原来ULN2003只是一个开关,供电的是在外围上。

 

最近做项目用到了ULN2003,上网查资料挺多,挺杂,这里将自己的经验作为总结,以便查阅。

ULN2003是高压大电流达林顿晶体管阵列系列产品。

ULN2003具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统,所以ULN2003作为驱动大电流负载芯片使用。

ULN2003有16个引脚,7个in,7个out,1个GND,1个COM。

输入端可以直接接MCu的引脚使用TTL电平控制,输出端接驱动电路(如可以接步进电机,直流电机等大功率电路)。COM引脚使用时可以接VCC,作为驱动电流。

 

 

 

ULN2003内部逻辑如下图

由上图可知ULN2003其实主要有7个反相器组成,其中反相器OC门,也就是集电极开路。

用NPN型三极管解释集电极开路就是集电极作为输出,基极作为输入,发射极接地。其中集电极在这里对应COM端,可以接VCC,这样当基极接低电平时三极管截止集电极输出高电平;基极接高电平时三极管导通集电极输出低电平。如此形成了MCU电平反相输出,但反相不是重点,大电流才是重点(反相是副产品大笑)。

 

ULN2003的COM端接继电器的电源正防止击穿器件。

ULN2003集电极开路输出,只能接收灌入电流。驱动负载电流最大为500mA,驱动电压最大为50V.

 

 

概述

演示单极步进电机的控制。没有现成的 H 桥模块,双极步进电机就不做实验啦。

这里没有使用 stepper 库,用 IO 粗糙地原始地驱动,以加深对步进电机驱动的理解,实际使用的时候当然有库就用库啦。

 

示例程序

整步驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// ----------------------------------------------------------------------------
// unipolarStepperTest_fullStep.ino
//
// Created 2015-06-27
// By seesea <seesea2517#gmail#com>
//
// 单极步进电机单相励磁整步驱动方式测试
//
// 通过 uln2003 来控制,arduino 每一个 IO 口接一个输入,对应输出分别接到电机上,因 uln2003 是集电极开路输出,所以电机公共端接高电平
// ----------------------------------------------------------------------------
 
const unsigned char pins[]  = { 8, 9, 10, 11 };
const unsigned char pinNum  = sizeof(pins) / sizeof(pins[0]);
const unsigned char delayMs = 10;   // 每步动作间隔,控制速度
const char dir = 1;                 // 正负一用来控制转动方向
 
void setup()
{
    for (unsigned char i = 0; i < pinNum; ++i)
    {
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i], LOW);
    }
}
 
// 每次进入函数时轮换引脚,在轮换到的引脚上发出高电平后经 uln2003 反相成低电平给电机上电
void loop()
{
    static unsigned char pulsePin = 0;
 
    digitalWrite(pins[pulsePin], HIGH);
    delay(delayMs);
 
    digitalWrite(pins[pulsePin], LOW);
    pulsePin = (pulsePin + dir + pinNum) % pinNum;
}

 

半步驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// ----------------------------------------------------------------------------
// unipolarStepperTest_halfStep.ino
//
// Created 2015-06-28
// By seesea <seesea2517#gmail#com>
//
// 单极步进电机单相励磁半步驱动方式测试
// 使用两种方式来实现,一种使用数组做控制序列的,一种使用算法来实现
//
// 通过 uln2003 来控制,arduino 每一个 IO 口接一个输入,对应输出分别接到电机上,因 uln2003 是集电极开路输出,所以电机公共端接高电平
// ----------------------------------------------------------------------------
 
const unsigned char pins[]  = { 8, 9, 10, 11 };
const unsigned char pinNum  = sizeof(pins) / sizeof(pins[0]);
const unsigned char delayMs = 10;   // 每次动作间隔,控制速度
const char dir = 1;                 // 正负一用来控制转动方向
 
const unsigned char controlSeq[] = { 0x08, 0x0C, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09 };    // 控制序列:以低四位来表示 pins 里的 4 个引脚某一次动作时需要通电的两引脚
const unsigned char pinMask[]    = { 0x01, 0x02, 0x04, 0x08 };                            // 引脚对应掩码
const unsigned char seqNum = sizeof(controlSeq) / sizeof(controlSeq[0]);
// 如果把控制序列改成这样,就变成原来的单相励磁整步前进的方式:const unsigned char controlSeq[] = { 0x08, 0x04, 0x02, 0x01 };
// 如果把控制序列改成这样,就变成双相励磁整步前进的方式:const unsigned char controlSeq[] = { 0x0C, 0x06, 0x03, 0x09 };
 
// 使用控制序列的方式来实现的半步驱动
// 对于复杂的没有什么规律的方式可以选用
void halfStep_controlSeq()
{
    static unsigned char seqIndex = 0; // 当前序列
 
    // 发出高电平后经 uln2003 反相成低电平给电机上电
    for (unsigned char i = 0; i < pinNum; ++i)
    {
        digitalWrite(pins[i], (controlSeq[seqIndex] & pinMask[i]) ? HIGH : LOW);
    }
     
    seqIndex = (seqIndex + dir + seqNum) % seqNum;
    delay(delayMs);
}
 
// 用算法来实现的半步驱动
// 半步驱动的操作其实也是有一定规律的,所以也可以用一定的算法来实现
void halfStep_algrothm()
{
    static unsigned char pulsePin1 = 0;
    static unsigned char pulsePin2 = 0;
 
    digitalWrite(pins[pulsePin1], HIGH);
    digitalWrite(pins[pulsePin2], HIGH);
    delay(delayMs);
 
    digitalWrite(pins[pulsePin1], LOW);
    digitalWrite(pins[pulsePin2], LOW);
     
    // 算法实现
    // 两个引脚的索引按规律前进(这里的前进是以 dir 为标准,如果 dir 是负数,把后退方向当成前进):
    // - 当两个引脚一样的时候,pin1 前进
    // - 当两个引脚不一样的时候,pin2 前进
    if (pulsePin1 == pulsePin2)
        pulsePin1 = (pulsePin1 + dir + pinNum) % pinNum;
    else
        pulsePin2 = (pulsePin2 + dir + pinNum) % pinNum;
}
 
void setup()
{
  Serial.begin(9600);
    for (unsigned char i = 0; i < pinNum; ++i)
    {
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i], LOW);
    }
}
 
void loop()
{
    halfStep_controlSeq();
    // halfStep_algrothm();
}

 

实验照片

posted @ 2018-05-22 07:22  chenlife  阅读(9576)  评论(0)    收藏  举报