🚗 ESP32 L298N 电机驱动:让你的项目跑起来
📅 2026-05-25 · 📂 硬件编程 · ⏱ 阅读约 10 分钟
📺 B站推荐视频:Esp32使用L298N电机驱动模块控制电机 | 无字天书上海 · 11分钟手把手接线+代码
📦 物料清单
| 物料 | 型号/参数 | 数量 | 参考价格 |
| ESP32 开发板 | ESP32-WROOM-32 / ESP32-S3 | 1 | ¥15~25 |
| L298N 电机驱动模块 | 红色 PCB 标准版(带散热片) | 1 | ¥4~8 |
| TT 减速电机 | 1:48 减速比, 3~6V, 200RPM | 2 | ¥5~8/个 |
| 18650 锂电池 | 3.7V × 2 节串联(或 7.4V 电池组) | 2 | ¥8~15/节 |
| 18650 电池盒 | 2 节串联带 DC 插头 | 1 | ¥3~5 |
| 杜邦线 | 公母各 10 根 | 若干 | ¥2~3 |
| 小车底盘 | 2WD 亚克力底盘 + 轮胎 | 1 | ¥15~25 |
| DC 电源插头 | 5.5×2.1mm 公头转接线 | 1 | ¥1~2 |
💰 总计:约 ¥60~100(不含运费)。整套入门小车成本不到一百块。
🔌 接线图
L298N 模块有三组关键引脚:电源组、控制组、输出组。接线时务必注意:ESP32 的 GND 必须和 L298N 的 GND 共地!
┌─────────────────────────────────────────────────────────┐
│ L298N 接线图 │
├─────────────────────────────────────────────────────────┤
│ │
│ 【电源组】 │
│ L298N 12V ──── 电池正极 (7.4V) │
│ L298N GND ──── 电池负极 + ESP32 GND(共地!) │
│ L298N 5V ──── ESP32 VIN (5V) ← 模块给ESP32供电 │
│ (拔掉 5V 使能跳线帽则需外接 5V) │
│ │
│ 【控制组 — 电机A】 │
│ L298N IN1 ──── ESP32 GPIO 26 │
│ L298N IN2 ──── ESP32 GPIO 27 │
│ L298N ENA ──── ESP32 GPIO 14 (PWM调速,拔掉跳线帽) │
│ │
│ 【控制组 — 电机B】 │
│ L298N IN3 ──── ESP32 GPIO 32 │
│ L298N IN4 ──── ESP32 GPIO 33 │
│ L298N ENB ──── ESP32 GPIO 15 (PWM调速,拔掉跳线帽) │
│ │
│ 【输出组】 │
│ L298N OUT1/OUT2 ──── 电机A (左轮) │
│ L298N OUT3/OUT4 ──── 电机B (右轮) │
│ │
└─────────────────────────────────────────────────────────┘
⚠️ 跳线帽说明:L298N 模块上 ENA 和 ENB 旁边各有一个黄色跳线帽。跳线帽插上 = 使能脚接 5V = 全速运行。
如果你要用 PWM 调速,必须先拔掉跳线帽,然后用杜邦线将 ENA/ENB 分别连到 ESP32 的 PWM 引脚。不拔跳线帽直接接 GPIO 会导致 5V 灌入 ESP32 引脚——有烧板风险!
💻 基础代码:电机正反转 + PWM 调速
下面是一份完整的 Arduino 代码,实现两个电机的正转、反转、停止、PWM 调速功能。使用 analogWrite() 或 ESP32 的 ledcWrite() 来输出 PWM。
/**
* ESP32 + L298N 双电机控制
* 功能:前进 / 后退 / 左转 / 右转 / 停止 / 调速
* 引脚:IN1=26, IN2=27, ENA=14, IN3=32, IN4=33, ENB=15
*/
#define IN1 26
#define IN2 27
#define ENA 14
#define IN3 32
#define IN4 33
#define ENB 15
// PWM 参数
const int freq = 5000;
const int resolution = 8;
const int pwmChannelA = 0;
const int pwmChannelB = 1;
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
// 配置 ESP32 PWM(替代 analogWrite)
ledcSetup(pwmChannelA, freq, resolution);
ledcSetup(pwmChannelB, freq, resolution);
ledcAttachPin(ENA, pwmChannelA);
ledcAttachPin(ENB, pwmChannelB);
Serial.begin(115200);
Serial.println("🚗 L298N 双电机控制启动!");
}
// 电机A控制(左轮)
void motorA(int speed) {
if (speed > 0) {
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
} else if (speed < 0) {
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
} else {
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
ledcWrite(pwmChannelA, abs(speed));
}
// 电机B控制(右轮)
void motorB(int speed) {
if (speed > 0) {
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
} else if (speed < 0) {
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
} else {
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
ledcWrite(pwmChannelB, abs(speed));
}
// 小车动作宏
void forward(int speed) { motorA(speed); motorB(speed); }
void backward(int speed) { motorA(-speed); motorB(-speed); }
void turnLeft(int speed) { motorA(-speed); motorB(speed); }
void turnRight(int speed) { motorA(speed); motorB(-speed); }
void stopCar() { motorA(0); motorB(0); }
void loop() {
Serial.println("➡️ 前进 (150/255)");
forward(150);
delay(2000);
Serial.println(⏸️ 停止");
stopCar();
delay(1000);
Serial.println(↩️ 左转 (180/255)");
turnLeft(180);
delay(1500);
Serial.println(↪️ 右转 (180/255)");
turnRight(180);
delay(1500);
Serial.println(⬅️ 后退 (120/255)");
backward(120);
delay(2000);
stopCar();
delay(3000);
}
💡 代码解读:
• speed 范围 0~255(8 位分辨率)——正数正转,负数反转。
• ESP32 没有硬件 analogWrite(),必须用 ledcSetup + ledcAttachPin + ledcWrite 三件套输出 PWM。
• forward(150) 只开到约 60% 功率——低速先测试,避免小车冲出去!
• 左右轮的 motorA/motorB 函数中 speed 正负独立——所以 turnLeft 是左轮反转+右轮正转,实现原地转弯(差速转向)。
🚀 进阶应用
1. Web 遥控小车(结合 WiFi)
还记得 WebServer 教程吗?把 L298N 控制函数嵌入 Web 服务器,用手机浏览器遥控小车:
// 在 loop() 之前加入 WebServer(需要先连 WiFi)
#include <WiFi.h>
#include <WebServer.h>
WebServer server(80);
void handleForward() { forward(180); server.send(200, "text/plain", "前进"); }
void handleBackward() { backward(180); server.send(200, "text/plain", "后退"); }
void handleLeft() { turnLeft(200); server.send(200, "text/plain", "左转"); }
void handleRight() { turnRight(200); server.send(200, "text/plain", "右转"); }
void handleStop() { stopCar(); server.send(200, "text/plain", "停止"); }
void setup() {
// ... 电机引脚初始化同上 ...
WiFi.begin("热点名", "密码");
while (WiFi.status() != WL_CONNECTED) delay(500);
server.on("/forward", handleForward);
server.on("/backward", handleBackward);
server.on("/left", handleLeft);
server.on("/right", handleRight);
server.on("/stop", handleStop);
server.begin();
}
手机连同一 WiFi,浏览器访问 http://esp32_ip/forward 即可控制小车——这就是最简 Web 遥控车!
2. 超声波自动避障
L298N + HC-SR04 超声波 = 自动避障小车。核心逻辑:
// 避障循环(伪代码骨架)
void loop() {
long distance = readUltrasonic(); // 读取前方距离
if (distance > 30) {
forward(150); // 安全 → 直行
} else if (distance > 15) {
turnRight(180); // 靠近 → 右转避让
delay(500);
} else {
backward(150); // 太近 → 后退
delay(800);
turnLeft(200); // 左转绕开
delay(600);
}
}
🎯 实战场景
场景一:RFID 刷卡启动智能小车
场景描述:制作一台只有刷授权 IC 卡才能启动的智能小车——刷对卡启动,刷错卡报警。适合教学演示和实验室设备管理。
物料组合:ESP32 + L298N + TT 电机 + RC522 RFID + 有源蜂鸣器
工作流程:
- ESP32 上电后电机锁定(不转),等待刷卡
- RC522 读到卡 → 比对预存的白名单 UID
- UID 匹配 → 蜂鸣器短响 1 声 →
forward(180) 启动小车
- UID 不匹配 → 蜂鸣器长响报警 → 电机不启动
- 再次刷卡 → 停车,回到锁定状态
这是一个完整的状态机项目——融合了 SPI 通信(RC522)、GPIO 控制(L298N)、PWM 调速,是从「点灯」迈向「系统级」的关键一步。
场景二:MQTT 远程物流小车
场景描述:办公室/仓库场景,用 MQTT 协议远程调度一台物流小车,从工位 A 运送到工位 B。
物料组合:ESP32 + L298N + 小车底盘 + MQTT 联网
工作流程:
- ESP32 连 WiFi 后订阅
cart/control 主题
- 手机/电脑通过 MQTT 客户端发送
"forward" / "left" / "stop" 等指令
- ESP32 收到消息 → 调用对应 motor 函数 → 小车执行动作
- 每 2 秒上报一次电池电压到
cart/status 主题(ADC 读电池电压)
这个场景串联了 L298N(驱动)+ WiFi(网络)+ MQTT(协议)+ ADC(电池监测)四大模块——是 IoT 机器人项目的标准架构。
❓ 常见问题
🔴 电机不转,但代码上传成功了
最常见原因:L298N 的 ENA/ENB 跳线帽没插,又没接 PWM 信号。
跳线帽是 ENA/ENB 的使能开关——如果你既拔了跳线帽又没给 ENA 引脚接杜邦线到 ESP32 GPIO,ENA 脚相当于悬空,电机绝对不会转。
快速排查:把跳线帽插回去 → 上传一个最简单的 digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); 看电机是否转。转 = 问题在 PWM 接线;不转 = 检查电源。
🔴 ESP32 USB 供电时电机无力/重启
根本原因:电脑 USB 端口只能提供 500mA(USB 2.0)或 900mA(USB 3.0)。两个 TT 电机起步就要 300~500mA(空载),带载轻松破 1A——USB 供电瞬间被拉低,ESP32 欠压重启。
正确做法:使用 7.4V(2 节 18650)独立电池组给 L298N 12V 端子供电。L298N 上的 5V 输出可以给 ESP32 供电,但要确认模块板载 5V 稳压的散热能力。
🔴 PWM 调速无效,电机总是全速转
常见原因 1:ENA/ENB 跳线帽还插着——这会强制使能脚拉高到 5V,PWM 信号被「覆盖」。必须拔掉跳线帽。
常见原因 2:ESP32 的 PWM 通道配置有误。注意 ESP32 的 ledcAttachPin 在某些引脚上不支持,推荐用 GPIO 14/15/16/17/18/19 这些无冲突引脚。
常见原因 3:L298N 的 ENA/ENB 引脚内部有上拉——如果你在代码里设 ENA 为 INPUT,它默认读到 HIGH,所以全速。必须设为 OUTPUT。
🔴 小车左右轮转速不一致,走不直
这是 TT 减速电机的通病——两个电机制造公差导致同样 PWM 下转速不同。
解决方法:
① 软件校准:单独测试每个电机,找出使两轮转速相等时的 PWM 差值。例如左轮 150 和右轮 140 同速——在 forward() 中用不同参数。
② 加编码器:升级到带霍尔编码器的电机(如 JGB37-520),用 PID 闭环控制转速——这就是下一阶段的内容。
③ 加陀螺仪:用 MPU6050 读取偏航角,实时修正方向。