用 L293D 电机驱动板来做一个小车

用 L293D 电机驱动板来做一个小车

介绍

在使用 Arduino 开发的过程中,我们会碰到使用直流电机的场景,但是直流电机一般不是开发板直接驱动的,需要一个辅助开发板来帮助运作,所以今天这篇文章就是介绍基于 L293D 的驱动板。

老样子,本文案例还是基于 platformIO + vscode 的开发模式,如果还不太了解的可以看之前的文章。

前期准备

  1. Arduino uno X 1
  2. L2930D 驱动板 X 1
  3. 马达 x 1(最多支持 4 个)

板子原理

按照板子上的接口来看,这个驱动可以同时驱动 4 个直流电机(或者 2 个步进电机)。还可以驱动两个舵机。

l293d 支持

l293d电机驱动板芯片组

主要起作用的就是中间的三个小方块,#1 和 #2 是电机驱动模块,74HC595是整个驱动板的核心驱动。

供电模块

板子支持Arduino 供电,也支持外置电源供电,外置电源的供电电压在 4.5 - 25V 之间。这里需要特别注意的是,如果外接电源超过了 12v,一定要断开 Power Supply,不然会烧毁。低于这个电压则无所谓。

外接电源超过 12V,断开 Power supply。

L293D电机驱动屏蔽电源

电机驱动接口

如下图所示的就是四个直流电机的接口,在直流电机的模式下,介于两个电机中间的GND接口不需要连接。

对于直流和步进电机控制,扩展板使用引脚 D3、D4、D5、D6、D7、D8、D11 和 D12。

D9和D10用于控制伺服电机。D10 连接到舵机 1,而 D9 连接到舵机 2。

l293d 电机驱动器屏蔽直流电机连接

下图就是两个步进电机的接口。

l293d电机驱动器屏蔽步进电机连接

下图是两个舵机的接口,注意使用这个功能的时候,只能使用像 SG90 这样的小型舵机。太大的功率带不动。

当然这两个接口如果不接舵机也可以自己自定义去连接一些其它的外设,比如我就是一个拿来接红外线接收器,另一个来接超声波避障。

l293d电机驱动器屏蔽伺服电机连接

其它接口

下图所示的A0-A5接口对应的是原Arduino uno开发板上的模拟引脚。另外开发板上也额外提供了6组 5V输出口,这个就看自己的需要了,当然外设接的多,电就消耗的更多。

还有 D0、D1、D2、D13 这几个引脚在这个板子上也是不用的,如果需要的话也可以利用起来。

目前这些额外的引脚比较麻烦的点就是,需要额外的焊接。

l293d 电机驱动器屏蔽复位 LED 电阻阵列原型

代码参考

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <Arduino.h>
#include <IRremote.hpp>
#include <AFMotor.h>

AF_DCMotor motorRight(3);
AF_DCMotor motorLeft(4);
#define IR_RECEIVE_PIN 10

int ledPin = A5;
int LED_CODE = 12;
bool ledState = false;

int currentDirection = FORWARD; // 记录一个当前全局的方向
int speed = 0;
const int LEFT = 8;
const int RIGHT = 90;
const int STOP = 28;
const int speedStep = 50; // 每次增加的速度
const int maxSpeed = 250;

void handleCar(int code) {
// 当当前点击的按钮与当前方向不一致时,停止当前方向的转动
if (currentDirection != code) {
motorLeft.run(RELEASE); // 这四条语句作用是使用关键字RELEASE作为run函数的参数。
motorRight.run(RELEASE); // 在这种情况下,AFMotor扩展板将会停止为电机旋转提供动力。
} else {
if (speed < maxSpeed) {
speed += speedStep;
}
}

switch (code)
{
case FORWARD:
currentDirection = FORWARD;
motorLeft.run(FORWARD);
motorRight.run(FORWARD);
motorLeft.setSpeed(speed);
motorRight.setSpeed(speed);
delay(10);
break;
case BACKWARD:
currentDirection = BACKWARD;
motorLeft.run(BACKWARD); /
motorRight.run(BACKWARD);
motorLeft.setSpeed(speed);
motorRight.setSpeed(speed);
delay(10);
case LEFT:
currentDirection = LEFT;
motorRight.setSpeed(speed);
motorLeft.setSpeed(speed);
motorLeft.run(FORWARD);
motorRight.run(BACKWARD);
case RIGHT:
currentDirection = RIGHT;
motorRight.setSpeed(speed);
motorLeft.setSpeed(speed);
motorLeft.run(BACKWARD);
motorRight.run(FORWARD);
break;
case STOP:
currentDirection = STOP;
motorLeft.run(RELEASE);
motorRight.run(RELEASE);
break;
default:
break;
}
delay(1000);
}

String rx_data;
// 串口中断函数
void Serial_callback()
{
if (!Serial.available()) {
rx_data = "";
}
Serial.println(Serial.available());
while (Serial.available())
{
rx_data += char(Serial.read());
delay(5); //这里不能去掉,要给串口处理数据的时间
}

if (rx_data != "")
{
Serial.println(rx_data);
if (rx_data == "code=8") {
digitalWrite(ledPin, LOW); // 设置LED的状态
} else if (rx_data == "code=7") {
digitalWrite(ledPin, HIGH); // 设置LED的状态
} else if (rx_data == "code=24") {
handleCar(FORWARD);
} else if (rx_data == "code=82") {
handleCar(BACKWARD);
} else if (rx_data == "code=28") {
handleCar(STOP);
}
}
}

void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
// 小车初始化
motorRight.setSpeed(speed);
motorLeft.setSpeed(speed);
motorRight.run(RELEASE);
motorLeft.run(RELEASE);
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
if (IrReceiver.decode()) {
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
IrReceiver.printIRResultRawFormatted(&Serial, true);
IrReceiver.resume();
}
else {
switch (IrReceiver.decodedIRData.command) {
case 24:
handleCar(FORWARD);
break;
case 82:
handleCar(BACKWARD);
break;
case 8:
handleCar(LEFT);
break;
case 90:
handleCar(RIGHT);
break;
case 28:
handleCar(STOP);
break;
case 12:
ledState = !ledState; // 切换LED的状态
digitalWrite(ledPin, ledState ? HIGH : LOW); // 设置LED的状态
break;
default:
break;
}
IrReceiver.resume();
}
}
Serial_callback();
delay(100); // 延迟一段时间,以避免频繁触发
}

小结

整体来说这个驱动板还是挺简单使用的,但是主要的问题是由于这个板子是外置的,在使用的时候会覆盖原来开发板的所有接口,导致有部分接口直接废弃了,但是又想加入一些新功能的场景就很操蛋。

比如我想加个红外线传感器,再加个 esp8266 开发板连接 wifi 实现无线控制,这种情况串口接口就不太够用了。属实有点操蛋。

另外由于这个板子可以同时驱动 4 个马达,但是我的小车是双轮的,这就导致我另外两个端口一直用不上,也很浪费,所以建议如果和我一样使用的是双马达的话,还是建议用另外一款驱动板 L298N,最大程度的利用端口。

img

参考文章

dev 的艺术空间

用 L293D 电机驱动板来做一个小车

http://blog.jzxer.cn/20241110/20241110_arduino_with_ L293D/

作者

dev

发布于

2024-11-10

更新于

2025-01-13

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×