为什么你需要掌握直流电机调速?
玩过小车的同学都知道,电机转得快不难,难的是转得刚刚好。太快容易翻车,太慢又没动力。这时候就需要 PWM 调速技术。
今天咱们用 L298N 这个经典的电机驱动模块,手把手教你如何实现直流电机的精准调速。不管你是要做智能小车、机器人底盘,还是简单的风扇控制,这套方案都能用得上。
硬件清单
| 配件 | 型号 | 价格 | 备注 |
|---|---|---|---|
| L298N 电机驱动模块 | 双 H 桥 | ¥15-25 | 某宝常见款 |
| 直流电机 | TT 马达/370 电机 | ¥8-15/个 | 3-6V 或 6-12V |
| Arduino Uno | R3 兼容板 | ¥25-35 | 或其他 5V 单片机 |
| 18650 电池 | 3.7V 2600mAh | ¥15-20 | 电机供电 |
| 杜邦线 | 公对公/母对母 | ¥5 | 若干 |
| 面包板 | 830 孔 | ¥8 | 可选 |
总成本: 约 ¥70-100(不含电池可更低)
L298N 模块详解
接口说明
L298N 模块看起来复杂,其实就几个关键接口:
+12V ──→ 电机供电正极(5-35V)
GND ──→ 共地
+5V ──→ 逻辑供电(跳线帽连接时输出 5V)
ENA ──→ A 通道使能(PWM 调速用)
IN1 ──→ A 通道输入 1
IN2 ──→ A 通道输入 2
ENB ──→ B 通道使能(PWM 调速用)
IN3 ──→ B 通道输入 1
IN4 ──→ B 通道输入 2
OUT1/OUT2 ──→ A 通道电机输出
OUT3/OUT4 ──→ B 通道电机输出
工作原理
L298N 内部是两个 H 桥电路,可以控制两个直流电机的正转、反转、停止。通过 ENA/ENB 引脚输入 PWM 信号,就能调节电机转速。
正反转控制逻辑:
| IN1 | IN2 | 电机状态 |
|---|---|---|
| HIGH | LOW | 正转 |
| LOW | HIGH | 反转 |
| LOW | LOW | 停止 |
| HIGH | HIGH | 停止(刹车) |
接线图
Arduino Uno L298N 模块
----------- ----------
5V ──────→ +5V (跳线帽连接时)
GND ──────→ GND
D9 (PWM) ──────→ ENA
D8 ──────→ IN1
D7 ──────→ IN2
电池正极 ──────→ +12V
电池负极 ──────→ GND
电机 A ──────→ OUT1/OUT2
注意事项:
- 电机供电和 Arduino 供电要共地
- 如果电机工作电压≤5V,拔掉 L298N 上的 5V 跳线帽,用 Arduino 的 5V 供电
- 如果电机工作电压>5V,保留跳线帽,L298N 会给 Arduino 反向供电(谨慎使用)
代码示例
基础调速程序
// L298N 直流电机 PWM 调速
// 引脚定义
const int ENA = 9; // PWM 调速引脚
const int IN1 = 8; // 方向控制 1
const int IN2 = 7; // 方向控制 2
void setup() {
// 设置引脚模式
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
// 串口初始化
Serial.begin(9600);
Serial.println("L298N 直流电机 PWM 调速测试");
}
void loop() {
// 正转加速
Serial.println("正转加速...");
for (int speed = 0; speed <= 255; speed += 10) {
analogWrite(ENA, speed); // PWM 调速 (0-255)
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(200);
Serial.print("速度:");
Serial.println(speed);
}
// 全速运行 2 秒
delay(2000);
// 正转减速
Serial.println("正转减速...");
for (int speed = 255; speed >= 0; speed -= 10) {
analogWrite(ENA, speed);
delay(200);
}
// 停止 1 秒
Serial.println("停止");
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
delay(1000);
// 反转加速
Serial.println("反转加速...");
for (int speed = 0; speed <= 255; speed += 10) {
analogWrite(ENA, speed);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
delay(200);
}
// 全速反转 2 秒
delay(2000);
// 反转减速
Serial.println("反转减速...");
for (int speed = 255; speed >= 0; speed -= 10) {
analogWrite(ENA, speed);
delay(200);
}
// 停止 1 秒
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
delay(1000);
}
串口控制调速
这个版本可以通过串口输入 0-255 的值来控制电机速度:
// L298N 串口调速控制
const int ENA = 9;
const int IN1 = 8;
const int IN2 = 7;
int motorSpeed = 0;
char direction = 'f'; // f=正转,r=反转,s=停止
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
Serial.begin(9600);
Serial.println("=== L298N 串口调速控制 ===");
Serial.println("命令格式:[方向][速度]");
Serial.println("示例:f200 (正转,速度 200)");
Serial.println(" r150 (反转,速度 150)");
Serial.println(" s (停止)");
}
void loop() {
if (Serial.available() > 0) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
char dir = cmd.charAt(0);
if (dir == 's') {
// 停止
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
Serial.println("电机停止");
} else {
// 解析速度值
int speed = cmd.substring(1).toInt();
speed = constrain(speed, 0, 255);
// 设置方向
if (dir == 'f') {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
Serial.print("正转,速度:");
Serial.println(speed);
} else if (dir == 'r') {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
Serial.print("反转,速度:");
Serial.println(speed);
}
// 设置 PWM 速度
analogWrite(ENA, speed);
}
}
}
PWM 调速原理
PWM(脉冲宽度调制)是通过快速开关电源来控制平均电压的技术。
占空比 100%: ████████████████████ 平均电压 = 5V
占空比 50%: ████████████████ 平均电压 = 2.5V
占空比 25%: ████ 平均电压 = 1.25V
Arduino 的 analogWrite() 函数生成频率约 490Hz 的 PWM 信号,占空比范围 0-255:
analogWrite(ENA, 0)→ 电机停止analogWrite(ENA, 128)→ 50% 速度analogWrite(ENA, 255)→ 全速
常见问题排查
问题 1:电机不转
可能原因:
- 电机供电不足 → 检查电池电压,确保≥5V
- 接线错误 → 确认 IN1/IN2 逻辑正确
- ENA 跳线帽未拔 → 如果用电机供电>5V,需要保留跳线帽
- 电机损坏 → 直接接电池测试电机是否正常
解决方法:
// 测试代码:直接给 HIGH 看是否转动
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
// 如果接了跳线帽,ENA 默认 HIGH
}
问题 2:电机转速异常
现象: 速度调不高,或者低速时抖动
原因:
- PWM 频率不匹配 → L298N 适合 1-20kHz
- 供电电压不足 → 电机负载大时压降明显
- 电刷电机低速特性差 → 这是物理限制
优化方案:
// 提高 PWM 频率(Arduino Uno)
// 引脚 9/10 是 Timer1,默认 490Hz,可改为 31kHz
void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01; // 设置分频比=1
// 现在 analogWrite(9, xxx) 频率约 31kHz
}
问题 3:Arduino 复位或工作不稳定
原因: 电机启动电流大,导致电源电压瞬间下降
解决方法:
- 电机供电和 Arduino 供电分开(只共地)
- 在 L298N 的 +12V 和 GND 之间加 100μF 电容
- 使用更大容量的电池
问题 4:发热严重
正常现象: L298N 在大电流下会发热,这是正常的
注意:
- 持续电流不要超过 2A(峰值 3A)
- 如果烫手,加散热片或降低负载
- 考虑升级到 TB6612FNG(效率更高,发热更小)
进阶技巧
1. 软启动/软停止
避免电机突然启停造成冲击:
void softStart(int targetSpeed, int stepTime = 10) {
for (int s = 0; s <= targetSpeed; s++) {
analogWrite(ENA, s);
delay(stepTime);
}
}
void softStop(int stepTime = 10) {
for (int s = 255; s >= 0; s--) {
analogWrite(ENA, s);
delay(stepTime);
}
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
2. 速度闭环控制(需要编码器)
如果加了编码器,可以用 PID 实现精准速度控制:
// 伪代码示例
int targetSpeed = 100;
int currentSpeed = readEncoder();
int error = targetSpeed - currentSpeed;
int pwmOutput = kp * error + ki * integral + kd * derivative;
analogWrite(ENA, constrain(pwmOutput, 0, 255));
3. 双电机差速转向
智能小车转向的经典方案:
void turnLeft(int speed) {
// 左电机反转,右电机正转
setMotor(1, -speed); // 左
setMotor(2, speed); // 右
}
void setMotor(int motor, int speed) {
int in1, in2, en;
if (motor == 1) { in1 = IN1; in2 = IN2; en = ENA; }
else { in1 = IN3; in2 = IN4; en = ENB; }
if (speed > 0) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
} else {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
speed = -speed;
}
analogWrite(en, constrain(speed, 0, 255));
}
升级建议
如果你已经玩转了 L298N,可以考虑这些升级方案:
| 驱动模块 | 优点 | 缺点 | 价格 |
|---|---|---|---|
| L298N | 便宜、经典、资料多 | 发热大、效率低 | ¥15-25 |
| TB6612FNG | 效率高、发热小、体积小 | 电流较小(1.2A) | ¥20-30 |
| DRV8833 | 双通道、过流保护 | 需要 3.3V 逻辑 | ¥15-25 |
| VNH2SP30 | 大电流(30A)、保护完善 | 贵、体积大 | ¥50-80 |
总结
L298N 虽然是个老模块,但作为学习电机控制的入门选择非常合适。掌握了 PWM 调速和 H 桥控制原理,你就能控制绝大多数直流电机应用。
关键知识点回顾:
- PWM 占空比控制平均电压,实现调速
- H 桥电路控制电流方向,实现正反转
- 电机供电和控制供电要共地
- 大电流应用注意散热和电源稳定性
下一步可以试试加个编码器做闭环控制,或者用蓝牙/WiFi 实现无线遥控小车。
希望这篇博客文章对您有所帮助!