1. 项目概述
这个小项目源于我去年给侄子做的生日礼物 - 一台用STM32控制的遥控小车。当时市面上现成的遥控车要么太玩具化,要么价格昂贵,于是决定自己动手做一个既能玩又能学的装置。没想到这个简单的需求让我深入研究了无线通信的底层原理,最终完成了一个稳定传输距离超过50米的遥控系统。
STM32F103C8T6作为性价比极高的Cortex-M3内核MCU,配合NRF24L01射频模块,构成了这个项目的硬件基础。整个系统分为发射端(遥控器)和接收端(小车)两部分,通过2.4GHz频段进行通信。相比市面上常见的315MHz/433MHz方案,2.4GHz提供了更好的抗干扰能力和数据传输速率。
2. 硬件设计与选型
2.1 核心控制器选型
选择STM32F103C8T6主要基于以下几点考虑:
- 72MHz主频足够处理遥控数据
- 内置硬件SPI接口,与NRF24L01通信效率高
- 丰富的GPIO资源(37个I/O口)
- 价格优势(约10元/片)
- 完善的生态系统(STM32CubeMX、标准库等)
实际使用中发现,这款MCU的ADC性能也相当不错,可以用来读取摇杆的模拟量输入。我使用的是蓝色药丸开发板(Blue Pill),其板载8MHz晶振和32.768kHz RTC晶振,省去了外部时钟电路的设计。
2.2 无线模块对比测试
测试了三种常见的无线方案:
- HC-12(433MHz):传输距离远但速率低
- ESP8266 WiFi:功耗高且延迟明显
- NRF24L01+(2.4GHz):最终选择方案
NRF24L01+的优势在于:
- 2Mbps高速传输(实际测试稳定在1Mbps)
- 125个可选频道,抗干扰能力强
- 硬件自动应答和重传机制
- 超低功耗(接收模式约12mA)
- 价格低廉(约5元/个)
特别注意要选择带"+PA+LNA"的增强版模块,实测传输距离从基础版的10米提升到了50米以上。模块与STM32通过SPI接口通信,需要5个GPIO(CE、CSN、SCK、MOSI、MISO)加上一个中断引脚(IRQ)。
2.3 电机驱动方案
接收端采用L298N双H桥驱动模块控制两个直流电机:
- 最大驱动电流2A(瞬时峰值3A)
- 内置5V稳压器可为STM32供电
- 支持PWM调速(使用TIM1和TIM4的PWM输出)
实际调试中发现,电机启动瞬间会产生较大电流冲击,需要在电源端并联大容量电解电容(我用了470μF/25V)。此外,电机运转时会产生高频干扰,建议在电机两端并联104瓷片电容。
3. 软件架构设计
3.1 通信协议设计
自定义了简单的通信协议框架:
code复制[前导码0xAA][长度][命令字][数据][校验和]
- 前导码:用于同步接收端
- 长度:后续数据的总字节数
- 命令字:区分不同控制指令
- 数据:具体控制参数(如速度、方向)
- 校验和:简单的累加和校验
每个数据包固定为8字节,包含:
- 左电机速度(-100~100)
- 右电机速度(-100~100)
- 灯光控制(bit0-左灯,bit1-右灯)
- 预留字段
3.2 发射端程序设计
发射端主流程:
- 初始化硬件(GPIO、SPI、ADC、TIM)
- 配置NRF24L01为发送模式
- 循环读取摇杆状态(ADC)
- 封装数据包
- 发送数据
- 延时10ms(100Hz刷新率)
关键代码片段:
c复制// ADC读取摇杆
uint16_t adc_x = ADC_Read(ADC_CHANNEL_0);
uint16_t adc_y = ADC_Read(ADC_CHANNEL_1);
// 转换为-100~100范围
int8_t speed_l = (adc_y - 2048) / 20;
int8_t speed_r = (adc_x - 2048) / 20;
// 填充数据包
tx_data[0] = 0xAA;
tx_data[1] = 6; // 长度
tx_data[2] = CMD_MOTOR_CTRL;
tx_data[3] = speed_l;
tx_data[4] = speed_r;
tx_data[5] = light_status;
tx_data[6] = checksum(tx_data, 6);
// 发送数据
nrf24_send(tx_data, 7);
3.3 接收端程序设计
接收端主流程:
- 初始化硬件(GPIO、SPI、TIM、PWM)
- 配置NRF24L01为接收模式
- 开启接收中断
- 在中断中解析数据包
- 根据指令控制电机和灯光
中断服务程序关键部分:
c复制void EXTI0_IRQHandler(void) {
if(nrf24_data_ready()) {
uint8_t rx_data[8];
nrf24_receive(rx_data, 8);
// 校验数据包
if(rx_data[0]==0xAA && rx_data[1]==6 &&
rx_data[6]==checksum(rx_data,6)) {
// 解析电机速度
int8_t speed_l = rx_data[3];
int8_t speed_r = rx_data[4];
// 设置PWM占空比
set_motor_speed(MOTOR_L, speed_l);
set_motor_speed(MOTOR_R, speed_r);
// 控制灯光
light_ctrl(rx_data[5]);
}
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
4. 关键问题与解决方案
4.1 通信稳定性优化
初期测试发现约5%的数据包丢失,通过以下措施改善:
- 启用NRF24L01的自动重传功能(SETUP_RETR寄存器)
- 降低数据传输速率从2Mbps到1Mbps
- 在代码中添加软件重传机制
- 为模块添加3.3V稳压电路(AMS1117)
- 在电源引脚并联100μF+0.1μF电容
优化后,在50米距离内丢包率降至0.1%以下。
4.2 电机干扰处理
电机运转时会导致以下问题:
- 电源电压波动导致MCU复位
- 高频噪声干扰无线通信
- 地线噪声影响ADC采样
解决方案:
- 电源隔离:电机电源与MCU电源分开供电
- 添加LC滤波:电机电源线串接功率电感
- 良好接地:使用星型接地,避免地环路
- 软件滤波:ADC采样采用中值平均滤波
4.3 低功耗设计
为延长遥控器电池寿命(使用2节18650),采取以下措施:
- 启用STM32的低功耗模式(STOP模式)
- 摇杆采用中断唤醒(EXTI)
- NRF24L01在空闲时进入STANDBY-I模式
- 优化发射功率(从0dBm降到-12dBm)
- 降低工作频率(从100Hz降到50Hz)
实测电流从常态30mA降至平均5mA,电池续航从8小时提升到48小时。
5. 进阶功能扩展
5.1 加入PID速度控制
为改善电机响应,增加了速度闭环控制:
- 在电机上安装霍尔编码器(500线)
- 使用TIM编码器接口模式读取转速
- 实现位置式PID算法
- 动态调整PWM占空比
PID核心代码:
c复制typedef struct {
float Kp, Ki, Kd;
float integral;
float prev_error;
} PID_Controller;
float pid_update(PID_Controller* pid, float setpoint, float measurement) {
float error = setpoint - measurement;
pid->integral += error;
if(pid->integral > 1000) pid->integral = 1000;
if(pid->integral < -1000) pid->integral = -1000;
float derivative = error - pid->prev_error;
pid->prev_error = error;
return pid->Kp*error + pid->Ki*pid->integral + pid->Kd*derivative;
}
5.2 添加OLED状态显示
使用0.96寸OLED显示:
- 实时电池电压
- 信号强度指示
- 电机转速
- 工作模式
通过I2C接口连接,使用u8g2图形库:
c复制U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
void display_init() {
u8g2.begin();
u8g2.setFont(u8g2_font_6x10_tf);
}
void show_battery(uint8_t percent) {
u8g2.drawFrame(100, 0, 20, 10);
u8g2.drawBox(102, 2, (uint16_t)(16*percent/100), 6);
}
5.3 实现手机蓝牙控制
添加HC-05蓝牙模块实现手机控制:
- 通过USART与STM32通信
- 自定义简单协议(类似无线模块)
- 开发Android控制APP(使用Android Studio)
- 支持重力感应和触控两种模式
USART接收处理:
c复制void USART1_IRQHandler(void) {
if(USART_GetITStatus(USART1, USART_IT_RXNE)) {
uint8_t ch = USART_ReceiveData(USART1);
// 解析蓝牙数据...
}
}
6. 项目总结与改进方向
经过三个版本的迭代,当前系统已经相当稳定。实测在开阔场地控制距离可达80米,室内穿墙能力约3堵墙。整套硬件成本控制在100元以内(不含电池),远低于市面上的竞品。
几个值得改进的方向:
- 改用STM32F4系列,实现更复杂的控制算法
- 加入陀螺仪实现自平衡功能
- 开发PC端配置工具(使用Qt)
- 改用LoRa模块实现千米级遥控
- 加入摄像头实现FPV功能
这个项目最让我惊喜的是STM32F103C8T6的性能表现 - 在72MHz主频下不仅能流畅处理无线通信,还能跑PID控制算法。NRF24L01+也颠覆了我对低成本射频模块的认知,其稳定性完全不输专业数传电台。