DIY 多功能 Arduino 遥控发射器:分步制作指南
本教程将指导你如何制作一款 DIY Arduino 遥控发射器。由于我的项目经常需要无线控制,因此我设计了这款多功能无线电控制器,几乎可适用于所有场景。 你可以观看以下视频,或阅读下方的图文教程。 只需在接收端做少量调整,这款发射器即可无线控制任何 Arduino 项目。它也可作为商业级遥控器,用于控制遥控玩具、赛车、无人机等。为此只需搭配一个简单的 Arduino 接收机,即可生成控制这些商业设备所需的信号。 我将通过几个实例讲解其工作原理:控制 Arduino 机器人小车、控制我上期视频中的 Arduino 蚂蚁机器人,以及通过 ESC 和舵机控制无刷直流电机。 本控制器的无线通信基于 NRF24L01 收发模块,若配合放大天线,在开阔地带可实现高达 700 米的稳定通信距离。控制器共提供 14 个通道,其中 6 个为模拟输入,8 个为数字输入。 硬件配置包括:两个摇杆、两个电位器、两个拨码开关、六个按钮,以及一个由加速度计和陀螺仪组成的内部测量单元(IMU),可通过倾斜或移动控制器来操控设备。 首先来看电路图。这款 RC 控制器的核心是 Arduino Pro Mini,由两节锂聚合物电池串联供电(约 7.4V)。可直接接入 Pro Mini 的 RAW 引脚,其板载稳压器会将电压降至 5V。注意:Arduino Pro Mini 有 5V 和 3.3V 两个版本,本项目使用 5V 版本。 NRF24L01 模块必须使用 3.3V 供电,且建议使用独立电源。因此需用一颗 3.3V 稳压器(如 HT7333 或 AMS1117)将 7.4V 降至 3.3V,并在模块旁并联去耦电容以稳定电压,从而提高无线通信稳定性。NRF24L01 通过 SPI 协议与 Arduino 通信,MPU6050 加速度计/陀螺仪模块则使用 I2C 协议。 所需元件购买链接如下: 本项目占用了 Arduino Pro Mini 所有模拟和数字引脚,若用杜邦线连接会非常混乱。因此我使用 EasyEDA 免费在线工具设计了专用 PCB。 设计时充分考虑了人体工学,使控制器易于双手握持,所有控件均在手指可及范围内。板边采用圆角设计,并预留 3mm 安装孔以便后续固定。Arduino 编程引脚引出至板子顶部,方便随时重新烧录。注意:RX 和 TX 引脚用于摇杆按钮,上传代码时必须将其与外部电路断开,因此设计了两排排针配合跳线帽实现快速断连。 重要提示: 请确认手中的 Arduino Pro Mini 版本与 PCB 匹配,或自行修改 PCB 设计。下图对比了三种不同版本(取决于你的 Arduino 板和稳压器型号)。 PCB 设计工程文件链接(包含三个版本,可按需选择)。 设计完成后生成 Gerber 文件,委托 JLCPCB(本视频赞助商)制板。 上传 Gerber 文件后可在查看器中核对,选择板子颜色(我选了黑色)等参数即可下单。首单可享 10 片仅 $2 的优惠。 成品质量优秀,完全符合设计预期。 先焊接 Arduino Pro Mini 排针。将排针插在面包板上固定,焊接更稳妥。 Pro Mini 两侧也有排针,位置可能因厂家而异。我用的型号每侧需 5 个引脚,其中一个 GND 引脚留空(PCB 下层走线占用)。将 Pro Mini 直接焊在 PCB 上并剪去多余引脚,旁边焊接 MPU6050 模块。 焊接 3.3V 稳压器及其旁路电容,并在 NRF24L01 模块旁再加一颗电容。该模块有三个版本均兼容。 依次焊接编程排针、RX/TX 排针、电源输入排针和电源开关。 电位器引脚过短,需用排针延长。旋钮杆也已剪短以便安装旋钮帽,电位器稍后焊接。 焊接两个拨码开关和两个摇杆。 最后焊接四个轻触按键,同样用排针垫高引脚。 PCB 焊接完成。为展示电路之美,我选择透明亚克力制作外壳。 使用 4mm 厚透明亚克力(带蓝色保护膜),制作上下两块与 PCB 同形的板,通过螺栓固定在 PCB 两面。 按 PCB 轮廓锯切亚克力,用锉刀微调,两块板完美贴合。 标记开孔位置:3mm 钻头钻 4 个安装孔并沉头;6mm 钻头开拨码开关和电位器孔;25mm 福斯纳钻头开摇杆孔,再用锉刀修整。 注:电源排针故意反向焊接,以便从背面(电池侧)插拔。 撕去保护膜,开始组装外壳。先将两个电位器固定在上盖,装入 3mm 螺栓和 11mm 隔离柱。 合合上盖与 PCB,拧紧螺栓。此时再焊接电位器引脚(此前不确定确切高度)。 背板安装电池盒(2 颗螺栓),再用 4 颗螺栓将背板锁在 PCB 背面。 接上电池线,装上电位器旋钮、摇杆帽和 NRF24L01 天线。DIY Arduino 遥控发射器硬件部分大功告成! 接下来烧录程序。Pro Mini 需 USB 转串口模块,连接控制器顶部的编程排针。 Arduino IDE 中选择:开发板 "Arduino Pro or Pro Mini",处理器型号对应选择(5V/16MHz),端口选择对应 COM 口,烧录器选 "USBasp"。 即可上传代码。 发射端代码核心逻辑如下: 首先引入库文件: 定义数据结构体存储 14 通道数据。结构体最大 32 字节(NRF24L01 单包缓冲区上限)。 当拨码开关 1 闭合(读为 LOW)时,改用 IMU 姿态角控制:调用 完整发射端代码(含 IMU 读取、互补滤波融合算法)见下方。 接收端原理图如下(可用任意 Arduino 板)。 接收端代码结构与发射端对应:相同的结构体、相同的无线参数,调用 接收端读取摇杆 1 数值驱动电机,实现小车前后左右移动。 读取发射器数据,根据指令执行前进、转向、咬合、攻击等动作。 商业 RC 设备通常通过 PWM/PPM 控制舵机或无刷电机(ESC)。接收端用 Arduino 注意: NRF24L01 2.4GHz 体制无法与标准 RC 接收机配对,必须自制接收端(Arduino + NRF24L01)再输出 PWM/PPM 信号。 教程到此结束。希望你喜欢并有所收获。欢迎在评论区提问,别忘了关注我的 Arduino 项目合集!概述


Arduino 遥控发射器电路图

PCB 设计





PCB 组装焊接



















DIY Arduino 遥控发射器代码详解
SPI.h、nRF24L01.h、RF24.h 用于无线通信,Wire.h 用于 I2C 设备(MPU6050)。定义数字输入引脚、变量、射频对象及通信地址。#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
// 数字输入引脚定义
#define jB1 1 // 摇杆1按钮
#define jB2 0 // 摇杆2按钮
#define t1 7 // 拨码开关1
#define t2 4 // 拨码开关2
#define b1 8 // 按钮1
#define b2 9 // 按钮2
#define b3 2 // 按钮3
#define b4 3 // 按钮4
const int MPU = 0x68; // MPU6050 I2C 地址
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY;
float angleX, angleY;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY;
float elapsedTime, currentTime, previousTime;
int c = 0;
RF24 radio(5, 6); // NRF24L01 (CE, CSN)
const byte address[6] = "00001"; // 通信地址// 结构体最大 32 字节 - NRF24L01 缓冲区限制
struct Data_Package {
byte j1PotX; // 摇杆1 X轴
byte j1PotY; // 摇杆1 Y轴
byte j1Button; // 摇杆1按钮
byte j2PotX; // 摇杆2 X轴
byte j2PotY; // 摇杆2 Y轴
byte j2Button; // 摇杆2按钮
byte pot1; // 电位器1
byte pot2; // 电位器2
byte tSwitch1; // 拨码开关1
byte tSwitch2; // 拨码开关2
byte button1; // 按钮1
byte button2; // 按钮2
byte button3; // 按钮3
byte button4; // 按钮4
};
Data_Package data; // 创建结构体变量setup() 中初始化 MPU6050,可选校准 IMU 误差;配置无线模块(250kbps 速率、低功率模式);启用所有数字输入的内部上拉电阻;设置所有通道默认值(摇杆中位 127,按键默认 1 即释放态)。void initialize_MPU6050() {
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); Wire.write(0x00); // 复位
Wire.endTransmission(true);
// 配置加速度计 ±8g
Wire.beginTransmission(MPU);
Wire.write(0x1C); Wire.write(0x10);
Wire.endTransmission(true);
// 配置陀螺仪 1000dps
Wire.beginTransmission(MPU);
Wire.write(0x1B); Wire.write(0x10);
Wire.endTransmission(true);
}
// 无线电配置
radio.begin();
radio.openWritingPipe(address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
// 启用内部上拉
pinMode(jB1, INPUT_PULLUP); pinMode(jB2, INPUT_PULLUP);
pinMode(t1, INPUT_PULLUP); pinMode(t2, INPUT_PULLUP);
pinMode(b1, INPUT_PULLUP); pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP); pinMode(b4, INPUT_PULLUP);loop() 中读取 6 路模拟量(A0-A3, A6-A7),用 map() 将 0-1023 映射为 0-255 存入结构体;读取 8 路数字量(摇杆按钮、拨码、按键);最后用 radio.write() 发送整个结构体。// 读取模拟输入并映射为 0-255
data.j1PotX = map(analogRead(A1), 0, 1023, 0, 255);
data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);
data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255);
data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);
// 读取数字输入(上拉模式下按下为 LOW)
data.j1Button = digitalRead(jB1);
data.j2Button = digitalRead(jB2);
data.tSwitch2 = digitalRead(t2);
data.button1 = digitalRead(b1);
data.button2 = digitalRead(b2);
data.button3 = digitalRead(b3);
data.button4 = digitalRead(b4);
// 发送数据包
radio.write(&data, sizeof(Data_Package));read_IMU() 计算俯仰/横滚角(-90°~+90°),再映射为 0-255 覆盖 j1PotX 和 j1PotY。if (digitalRead(t1) == 0) {
read_IMU(); // 使用 MPU6050 替代摇杆1控制
// 将角度 -90~+90 映射为 0~255
data.j1PotX = map(angleX, -90, +90, 255, 0);
data.j1PotY = map(angleY, -90, +90, 0, 255);
}接收端代码

radio.startListening() 进入接收模式。主循环中用 radio.available() 判断是否有数据,读取后打印串口监视器验证。若超 1 秒未收到数据,调用 resetData() 恢复默认值,防止失控(如无人机油门卡住飞走)。/* 接收端示例代码 */
#include <SPI.h> #include <nRF24L01.h> #include <RF24.h>
RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0, currentTime = 0;
struct Data_Package { /* 同发射端 */ };
Data_Package data;
void setup() {
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.startListening();
resetData();
}
void loop() {
if (radio.available()) {
radio.read(&data, sizeof(Data_Package));
lastReceiveTime = millis();
}
currentTime = millis();
if (currentTime - lastReceiveTime > 1000) resetData(); // 超时保护
// 串口打印验证
Serial.print("j1PotX: "); Serial.print(data.j1PotX);
Serial.print("; j1PotY: "); Serial.print(data.j1PotY);
Serial.print("; button1: "); Serial.print(data.button1);
Serial.print("; j2PotX: "); Serial.println(data.j2PotX);
}
void resetData() {
data.j1PotX = 127; data.j1PotY = 127;
data.j2PotX = 127; data.j2PotY = 127;
data.j1Button = 1; data.j2Button = 1;
data.pot1 = 1; data.pot2 = 1;
data.tSwitch1 = 1; data.tSwitch2 = 1;
data.button1 = 1; data.button2 = 1; data.button3 = 1; data.button4 = 1;
}应用案例 1:Arduino 机器人小车无线控制

应用案例 2:Arduino 蚂蚁机器人/六足机器人控制

应用案例 3:ESC 与舵机控制(兼容商业 RC 设备)

Servo 库生成 50Hz PWM:舵机写角度(0-180°),ESC 写微秒脉宽(1000-2000μs 对应零油门到全油门)。
/* ESC 与舵机控制接收端代码 */
#include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #include <Servo.h>
RF24 radio(10, 9); const byte address[6] = "00001";
// ... 结构体定义同前 ...
Servo esc, servo1, servo2;
int escValue, servo1Value, servo2Value;
void setup() {
Serial.begin(9600);
radio.begin(); radio.openReadingPipe(0, address);
radio.setAutoAck(false); radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW); radio.startListening();
resetData();
esc.attach(9); servo1.attach(3); servo2.attach(4);
}
void loop() {
currentTime = millis();
if (currentTime - lastReceiveTime > 1000) resetData();
if (radio.available()) {
radio.read(&data, sizeof(Data_Package));
lastReceiveTime = millis();
}
// 舵机控制:映射 0-255 到 0-180°
servo1Value = map(data.j2PotX, 0, 255, 0, 180);
servo2Value = map(data.j2PotY, 0, 255, 0, 180);
servo1.write(servo1Value); servo2.write(servo2Value);
// ESC 控制:映射 0-255 到 1000-2000μs
escValue = map(data.pot1, 0, 255, 1000, 2000);
esc.writeMicroseconds(escValue);
}
制造工艺
- 卡祖笛:从非洲米里通到现代塑料玩具——历史、制造与未来
- 自制LUMAZOID:基于Arduino的音乐可视化灯光控制器
- 自制家用作业书写机:Arduino + GRBL 控制的笔绘仪
- Arduino 与智能手机打造智能电压表——简单易做的 DIY 项目
- 紧凑型气象站:Arduino Nano + ESP8266 双核方案 (BMP280 + OLED/Nokia 双屏)
- DIY VR 滑板:用 Arduino、Google Cardboard 与蓝牙打造虚拟滑雪体验
- DIY Arduino 电子波疗设备 - 基于拉德尼克疗法的 EMR 治疗仪
- DIY二自由度竞速模拟器:Arduino Nano驱动SG90微型舵机
- 使用 Arduino 制作便携式 RFID 门锁——分步指南
- DIY三轴CNC立式加工中心:打造精密铣床
- Arduino Nano + GY-906 非接触红外测温枪制作指南
- DIY 飞行模拟器方向舵脚踏板:分步制作指南