Arduino + 蓝牙掌控乐高 Power Functions 电机与舵机
项目简介
利用 Arduino UNO、L293D 双 H 桥驱动芯片与 HC-05 蓝牙模块,配合 MIT App Inventor 开发的安卓手柄 App,实现对乐高 Power Functions (PF) 电机与舵机的无线比例控制。以乐高 9398 4×4 爬行车为例(双 L 电机驱动 + 1 舵机转向),零剪切原厂线缆,适合亲子制作与机器人入门。
核心原理
PF 线缆接口定义 (Extension Wire 8886)
剪开延长线制作“断出线”,保留乐高插头一端,另一端焊排针:
- 深灰插头 (电池盒输出):仅需 C1 (9V+) 与 GND,接面包板供电总线
- 浅灰插头 (电机/舵机输入):C1、C2 两根控制线,极性反转即换向
- 舵机专用:需 4 线全接 (C1、C2、9V+、GND),内部含位置反馈电位器
L293D 双 H 桥驱动拓扑
单片 L293D 内含两路 H 桥:
- 左半桥 (EN1,2 / 1A / 2A):并联驱动两个 L 电机 (同向/同速)
- 右半桥 (EN3,4 / 3A / 4A):驱动舵机电机 (正反转控制转向角度)
- 关键隔离:L293D 内部逻辑侧 (5V) 与负载侧 (9V) 电源完全隔离,仅共地!严禁 5V 与 9V 相连
硬件清单
| 组件 | 数量 | 关键规格 |
|---|---|---|
| Arduino UNO | 1 | |
| L293D (DIP-16, 长引脚版) | 1 | 非贴片版,便于插面包板 |
| 面包板 | 1 | |
| 9V 电池盒转 DC 插头 | 1 | 给 Arduino 供电 (Vin) |
| 乐高 PF 延长线 (8886) | 3 | 剪开做断出线 |
| HC-05 蓝牙模块 | 1 | 主从一体,3.3V 电平 |
| 1kΩ 电阻 | 3 | 蓝牙 RX 分压用 |
引脚分配表
| 功能 | Arduino 引脚 | L293D 引脚 | 备注 |
|---|---|---|---|
| 电机方向 1A | D2 | 1A (Pin 2) | |
| 电机方向 2A | D5 | 2A (Pin 7) | |
| 电机使能 EN1,2 (PWM) | D9 ~ | EN1,2 (Pin 1) | PWM 调速 |
| 舵机方向 3A | D6 | 3A (Pin 10) | |
| 舵机方向 4A | D8 | 4A (Pin 15) | |
| 舵机使能 EN3,4 (PWM) | D3 ~ | EN3,4 (Pin 9) | PWM 控制转向角度 |
| 蓝牙 TXD | D0 (RX) | — | 硬件串口,上传代码时须断开 |
| 蓝牙 RXD | D1 (TX) → 分压 → 蓝牙 | — | 3.3V 电平需分压 (3×1kΩ) |
Arduino 固件核心逻辑
全局变量与初始化
// 电机控制引脚
const int controlPin1A = 2, controlPin2A = 5, ENablePin = 9;
// 舵机控制引脚
const int controlPin3A = 6, controlPin4A = 8, servoENablePin = 3;
// 运行时变量
int motorSpeed = 0; // 0-255
int motorDirection = 1; // 1=前进, 0=后退
int steering = 0; // 0-255
int steeringDirection = 0;// 0=左, 1=右
void setup() {
Serial.begin(9600);
pinMode(controlPin1A, OUTPUT); pinMode(controlPin2A, OUTPUT); pinMode(ENablePin, OUTPUT);
pinMode(controlPin3A, OUTPUT); pinMode(controlPin4A, OUTPUT); pinMode(servoENablePin, OUTPUT);
digitalWrite(ENablePin, LOW); digitalWrite(servoENablePin, LOW);
}
电机/舵机控制子程序
void SetMotorControl() {
// 电机方向
if (motorDirection == 1) { digitalWrite(controlPin1A, HIGH); digitalWrite(controlPin2A, LOW); }
else { digitalWrite(controlPin1A, LOW); digitalWrite(controlPin2A, HIGH); }
analogWrite(ENablePin, motorSpeed);
// 舵机方向
if (steeringDirection == 0) { digitalWrite(controlPin3A, HIGH); digitalWrite(controlPin4A, LOW); }
else { digitalWrite(controlPin3A, LOW); digitalWrite(controlPin4A, HIGH); }
analogWrite(servoENablePin, steering);
}
蓝牙指令解析主循环
#define INPUT_SIZE 30
void loop() {
char input[INPUT_SIZE + 1];
byte size = Serial.readBytesUntil('\n', input, INPUT_SIZE);
input[size] = 0; // C 字符串终止
// 协议格式: "RC,steering,speed\n" steering/speed: -100..100
char* cmd = strtok(input, ",");
char* RCsteering = strtok(NULL, ",");
char* RCspeed = strtok(NULL, ",");
int iRCsteering = atoi(RCsteering);
int iRCspeed = atoi(RCspeed);
// 映射到硬件变量
steeringDirection = (iRCsteering > 0) ? 1 : 0;
steering = int(2.55 * abs(iRCsteering)); // 100 → 255
motorDirection = (iRCspeed > 0) ? 1 : 0;
motorSpeed = int(2.55 * abs(iRCspeed));
SetMotorControl();
}
MIT App Inventor 手柄 App 开发
设计器界面
- 底部橙色触控区 (Pad) + 蓝色摇杆球 (Ball)
- 蓝牙连接按钮、状态标签、指令显示框
核心逻辑 (Blocks 视图)
Ball.Dragged事件持续触发,获取手指坐标currentX,currentY- 限制在圆形触控区内,计算
steering(X 轴) 与speed(Y 轴),范围 -100..100 - 拼接指令字符串:
"RC," & steering & "," & speed & "\n" BluetoothClient.SendText发送,同步显示在屏幕上
蓝牙配对步骤
- 手机开启蓝牙,搜索 "HC-05",配对码
1234 - App 中点击 "Bluetooth connect" 选择已配对设备
- 状态显示 "connected" 绿色即可操控
进阶与安全建议
- 通讯丢包保护:Arduino 端设置超时 (如 500ms 未收指令) 自动停车
- 电源管理:面包板杜邦线易松动,建议改用 Adafruit Motor Shield (大接线柱) 或自制 PCB
- 传感器扩展:加装超声波/红外避障,编写自主导航逻辑,变身火星车
- 多电机独立控制:第二个 L293D 驱动左右电机差速转向
- 电池监测:分压读取 9V 电池电量,低电量报警
资源链接
- GitHub 完整工程:源码 + Fritzing 图 + App Inventor .aia 源文件
- Google Play 现成 App:Arduino RC car bluetooth
- PF 线缆详解视频:TechnicRobot YouTube 频道
制造工艺