Node.js 实时控制的蓝牙机器人小车:物联网实战项目
组件与物料
| 组件 | 数量 | 备注 |
|---|---|---|
| Arduino UNO | 1 | |
| L298N 双 H 桥驱动板 | 1 | SparkFun Dual H-Bridge |
| HC-05 蓝牙模块 | 1 | |
| 跳线 | 若干 | |
| 9V 电池 | 2 | 分别供电 Arduino 与电机驱动 |
| 12V 直流减速电机 | 2 | 配合车轮 |
项目简介
项目构想
Node.js 擅长实时应用,我曾用 Socket.io 做过实时 Web 应用,决定将同理念用于物联网:Node.js 服务器经蓝牙与小车通信,前端网页通过 Socket 发送控制指令。
项目目标
研究并实现 Node 服务器与硬件的无线通信,通过手机网页远程控制小车。
前置知识
基础 Node.js、Socket 编程、L298N 驱动原理。
所需材料清单
- Arduino Uno ×1
- L298N 电机驱动 ×1
- HC-05 蓝牙模块 ×1
- 跳线若干
- 9V 电池 ×2
- 6-9V 减速电机 ×2 + 配套车轮
- 二轮底盘套件
- 安装 Node.js 的电脑作为服务器
步骤 1:组装小车

推荐购买"二轮底盘套件",含所有结构件。Arduino 与 L298N 固定在底盘上,分别由一节 9V 电池供电。Arduino 为 HC-05 供电。
电路原理图

- L298N 由 9V 电池供电,两路电机输出接 Motor A/B(极性任意,但需保证两轮同向)。勿移除 5V 稳压跳线。
- 警告:L298N 输入电压勿超 12V,否则板载 5V 稳压器会损坏。
- Arduino 由另一节 9V 电池供电 (Vin 接正极,GND 接负极)。
- HC-05:VCC 接 Arduino 5V,GND 接地;TXD 接 Arduino RX (引脚 0),RXD 接 Arduino TX (引脚 1)。
- L298N 控制引脚:EN1/EN2 接 Arduino PWM 引脚,IN1-IN4 接任意数字引脚。
数据传输流程

- 用户访问 Node 服务网页 (如
192.168.x.x:8080) - 点击按钮触发 Socket 事件,服务器接收指令
- 服务器经蓝牙向 HC-05 发送数据
- HC-05 串口透传给 Arduino
- Arduino 驱动 L298N 控制电机
步骤 2:搭建 Node.js 服务器
安装 Node.js (推荐 v11.15.0,兼容 node-gyp)。需安装包:
- node-gyp
- express
- node-bluetooth
- socket.io
- ejs
用 Express + EJS 搭建网页与 Socket 服务;用 node-bluetooth 连接 HC-05。网页按钮点击 → Socket 发送指令 → 服务器转发蓝牙数据。示例网页:

步骤 3:Arduino 代码逻辑
蓝牙串口发送字符串命令,以 T 为结束符。如 forwardT 表示前进。Arduino 收到 T 解析命令,控制 L298N 实现前进、后退、左转、右转、变速、停止等。完整代码见下方。
步骤 4:最终效果与展望
后续计划:语音控制、避障、数据库记录里程/速度、扩展温湿度光照传感器并入库。
下一版本:"手机语音控制小车"
代码
Arduino 端代码
const int en1 = 9, en2 = 3;
const int inp1 = 2, inp2 = 4, inp3 = 7, inp4 = 8;
char charRead;
String inputString = "";
void setup() {
Serial.begin(9600);
pinMode(en1, OUTPUT); pinMode(en2, OUTPUT);
pinMode(inp1, OUTPUT); pinMode(inp2, OUTPUT);
pinMode(inp3, OUTPUT); pinMode(inp4, OUTPUT);
}
void loop() {
if (Serial.available()) {
charRead = Serial.read();
if (charRead != 'T') {
inputString += charRead;
} else {
if (inputString == "forward") { // 前进
digitalWrite(inp1, HIGH); digitalWrite(inp2, LOW);
digitalWrite(inp3, HIGH); digitalWrite(inp4, LOW);
} else if (inputString == "backward") { // 后退
digitalWrite(inp1, LOW); digitalWrite(inp2, HIGH);
digitalWrite(inp3, LOW); digitalWrite(inp4, HIGH);
} else if (inputString == "fleft") { // 前左
digitalWrite(inp1, HIGH); digitalWrite(inp2, LOW);
digitalWrite(inp3, LOW); digitalWrite(inp4, LOW);
} else if (inputString == "fright") { // 前右
digitalWrite(inp1, LOW); digitalWrite(inp2, LOW);
digitalWrite(inp3, HIGH); digitalWrite(inp4, LOW);
} else if (inputString == "bleft") { // 后左
digitalWrite(inp1, LOW); digitalWrite(inp2, LOW);
digitalWrite(inp3, LOW); digitalWrite(inp4, HIGH);
} else if (inputString == "bright") { // 后右
digitalWrite(inp1, LOW); digitalWrite(inp2, HIGH);
digitalWrite(inp3, LOW); digitalWrite(inp4, LOW);
} else if (inputString == "break") { // 刹车停车
analogWrite(en1, 50); analogWrite(en2, 50);
delay(550);
digitalWrite(inp1, LOW); digitalWrite(inp2, LOW);
digitalWrite(inp3, LOW); digitalWrite(inp4, LOW);
analogWrite(en1, 150); analogWrite(en2, 150);
} else if (inputString == "maxspeed") { // 最高速
analogWrite(en1, 250); analogWrite(en2, 250);
} else if (inputString == "medspeed") { // 中速
analogWrite(en1, 180); analogWrite(en2, 180);
} else if (inputString == "lowspeed") { // 低速
analogWrite(en1, 90); analogWrite(en2, 90);
} else { // 停止
digitalWrite(inp1, LOW); digitalWrite(inp2, LOW);
digitalWrite(inp3, LOW); digitalWrite(inp4, LOW);
}
inputString = "";
}
}
}
原理图
Fritzing 文件及导出图片:soundspectrumvisualizer_qLzRsVPVlc.fzz 等
制造工艺
- 树莓派4搭建Web实时温湿度监测系统
- 温控风扇DIY:媒体柜散热的继电器驱动方案
- 4 美元太阳能庭院灯改造:MSP430 + nRF24L01+ 打造花园无线传感器节点
- 将树莓派 4 打造成 Web 服务器并搭建个人网站
- DIY改装:将遥控车升级为蓝牙手机控车辆
- 废旧遥控车改装:Arduino + USB Host Shield 实现 Xbox 手柄无线控制
- Qi 无线充电 Wi-Fi 遥控小车:Arduino MKR1000 + IDT Qi 套件
- Arduino Mega 驱动 Wii Nunchuk 控制 6 自由度机械臂
- 无线红外测温枪:Arduino Nano + HC-06蓝牙 + MLX90614
- 构建无线红外传感器驱动的机器人小车
- 资源受限单片机的高效Web服务器方案:WebSocket+TLS的Minnow Server实践
- 30分钟在3美元ESP8266上部署TLS加密Web服务器:Minnow Server实战指南