3. 传感器选型与接口
在STM32机器人实战项目中,传感器是机器人感知物理世界的“感官器官”。无论是避障、测距、姿态解算、轮速反馈还是视觉识别,传感器选型与接口设计直接决定了系统的鲁棒性、实时性和可维护性。本章将围绕五种最常用的机器人传感器——超声波、红外、IMU(惯性测量单元)、编码器、摄像头,从工作原理、关键参数、STM32接口方式、选型对比到实战案例进行系统拆解,帮助你在项目初期做出正确的硬件决策。
3.1 超声波传感器:原理、选型与STM32接口
核心原理
超声波测距基于声波在空气中的传播速度(约340m/s)与往返时间差。典型模块HC-SR04由发射探头、接收探头和控制电路组成。MCU向Trig引脚发送至少10μs的高电平脉冲,模块内部自动发出8个40kHz方波,并等待回波;Echo引脚输出高电平持续时间即为声波往返时间。距离计算公式为:距离(cm) = 高电平时间(μs) / 58。该公式源于声速340m/s,往返距离除以2后换算为厘米。
选型关键参数
| 参数 | HC-SR04 | US-100 | JSN-SR04T(防水) |
|---|---|---|---|
| 工作电压 | 5V | 3.3-5V | 3.3-5V |
| 量程 | 2cm-400cm | 2cm-450cm | 25cm-600cm |
| 精度 | ±3mm | ±1mm | ±5mm |
| 接口方式 | GPIO电平 | UART/GPIO | GPIO/UART |
| 适用场景 | 室内避障 | 高精度测距 | 户外/潮湿环境 |
STM32接口与实现
推荐使用定时器输入捕获方式测量Echo高电平时间,而非阻塞式延时轮询。以STM32F103为例,可将Echo引脚连接到TIM2_CH1,配置为上升沿+下降沿捕获,利用DMA或中断记录两次捕获的CNT差值。Trig引脚使用普通GPIO输出。关键代码片段如下:
// 定时器输入捕获初始化(TIM2_CH1 - PA0)
TIM_ICInitTypeDef icInit;
icInit.TIM_Channel = TIM_Channel_1;
icInit.TIM_ICPolarity = TIM_ICPolarity_Rising;
icInit.TIM_ICSelection = TIM_ICSelection_DirectTI;
icInit.TIM_ICPrescaler = TIM_ICPSC_DIV1;
icInit.TIM_ICFilter = 0x0F; // 滤波,防止噪声
TIM_ICInit(TIM2, &icInit);
// 中断中记录两次捕获值
uint32_t rise_time, fall_time;
if (TIM_GetITStatus(TIM2, TIM_IT_CC1)) {
if (capture_index == 0) {
rise_time = TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Falling);
capture_index = 1;
} else {
fall_time = TIM_GetCapture1(TIM2);
TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising);
capture_index = 0;
distance_cm = (fall_time - rise_time) / 58.0;
}
}
常见误区
- 误区1:使用delay_us()阻塞等待Echo,导致MCU无法处理其他任务。应使用中断或DMA。
- 误区2:忽略声速随温度变化。温度每升高1℃,声速增加约0.6m/s,在精密测距中需加温度补偿。
- 误区3:多路超声波同时触发会互相串扰。应分时触发,间隔至少50ms。
3.2 红外传感器:近距检测与循迹应用
核心原理
红外传感器(如TCRT5000)基于红外LED发射光,经物体反射后被光电晶体管接收。反射光强度与距离成反比。TCRT5000内部集成了发射管和接收管,输出模拟电压(通过分压电阻)或数字信号(通过比较器)。其有效检测距离通常在0.5cm-3cm,非常适合循迹、壁障和边缘检测。
选型对比
| 型号 | 输出类型 | 检测距离 | 特点 |
|---|---|---|---|
| TCRT5000 | 模拟+数字 | 0.5-3cm | 性价比高,循迹首选 |
| GP2Y0A21 | 模拟电压 | 10-80cm | 三角测量法,线性度好 |
| E18-D80NK | 数字开关量 | 3-80cm可调 | 工业级,抗干扰强 |
STM32接口设计
对于TCRT5000的模拟输出,直接连接STM32的ADC引脚(如PA1),配置为12位分辨率,采样时间设为239.5周期以降低噪声。数字输出则连接GPIO并配置为外部中断,用于快速响应。循迹场景中,通常使用4-8路红外阵列,通过ADC多通道扫描或并行GPIO读取。
// ADC单通道采集示例(PA1 - ADC1_IN1)
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
uint16_t adc_val = ADC_GetConversionValue(ADC1);
// 阈值判断:adc_val > 2000 认为检测到黑线
实战案例:循迹小车阈值自适应
某竞赛机器人使用6路TCRT5000循迹,初始固定阈值导致在不同地面(浅色木地板vs深色地毯)上误判。解决方案:上电时执行校准程序——机器人原地旋转360°,采集每路传感器的最大值和最小值,动态计算阈值为(max+min)/2。同时加入滑动滤波(取5次采样中位数),最终循迹成功率从82%提升至97%。
3.3 IMU惯性测量单元:姿态解算与数据融合
核心原理
IMU(Inertial Measurement Unit)集成了三轴加速度计和三轴陀螺仪。加速度计测量物体受到的比力(包括重力),陀螺仪测量角速度。MPU6050是机器人领域最常用的6轴IMU,内置16位ADC和DMP(数字运动处理器),可直接输出四元数,减轻MCU计算负担。姿态解算的核心是互补滤波或卡尔曼滤波:加速度计在静态时准确但动态噪声大,陀螺仪动态响应快但存在积分漂移,两者融合可获得稳定姿态角。
选型要点
- 量程:加速度计±2g/±4g/±8g/±16g可选,陀螺仪±250/±500/±1000/±2000°/s。机器人平衡车建议加速度±4g、陀螺±1000°/s。
- 输出频率:MPU6050最高1kHz,STM32通过I2C读取时建议400kHz快速模式。
- 噪声密度:单位√Hz,越低越好。高精度应用可选用BMI088或ICM-20602。
STM32接口与数据处理
MPU6050通过I2C连接STM32(默认地址0x68)。初始化流程:唤醒芯片→设置时钟源→配置量程→使能传感器→配置数字低通滤波。读取数据时,建议使用DMA+I2C中断,避免阻塞。以下为关键初始化代码:
// MPU6050初始化
void MPU6050_Init(void) {
I2C_WriteByte(MPU6050_ADDR, PWR_MGMT_1, 0x00); // 唤醒
I2C_WriteByte(MPU6050_ADDR, SMPLRT_DIV, 0x07); // 采样率1kHz
I2C_WriteByte(MPU6050_ADDR, CONFIG, 0x06); // DLPF 5Hz
I2C_WriteByte(MPU6050_ADDR, GYRO_CONFIG, 0x08); // ±500°/s
I2C_WriteByte(MPU6050_ADDR, ACCEL_CONFIG, 0x08);// ±4g
}
常见误区
- 误区1:直接使用加速度计计算倾角而不滤波,导致动态抖动严重。
- 误区2:忽略陀螺仪零偏。上电后应静止2秒,取前200个样本均值作为零偏补偿。
- 误区3:I2C总线过长(超过20cm)且无上拉电阻,导致通信不稳定。建议使用4.7kΩ上拉,线长控制在10cm内。
3.4 编码器:轮速反馈与里程计
核心原理
编码器将旋转位移转换为电脉冲信号。机器人电机常用的有霍尔编码器和光电编码器。霍尔编码器利用磁铁旋转触发霍尔元件输出方波;光电编码器通过码盘遮挡红外光产生脉冲。增量式编码器输出A/B两相信号,相位差90°,通过判断相位关系可识别旋转方向。STM32定时器的编码器模式可自动处理A/B相计数,无需外部逻辑电路。
选型参数
| 参数 | 典型值 | 说明 |
|---|---|---|
| 分辨率(线数) | 500-2000 PPR | 每转脉冲数,4倍频后×4 |
| 输出类型 | 开漏/推挽 | 开漏需上拉,推挽直接接MCU |
| 供电电压 | 3.3V/5V | 注意电平匹配 |
| 最高响应频率 | 100kHz-1MHz | 与电机最高转速匹配 |
STM32编码器模式配置
// TIM3编码器模式 - PA6(TIM3_CH1), PA7(TIM3_CH2)
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_SetCounter(TIM3, 32768); // 设置初始值,便于判断正反转
TIM_Cmd(TIM3, ENABLE);
// 读取速度:每10ms读取一次计数值
int16_t count = (int16_t)TIM_GetCounter(TIM3) - 32768;
TIM_SetCounter(TIM3, 32768);
float speed_rpm = (float)count * 60000.0f / (10 * 4 * PPR);
实战案例:双轮差速里程计
某巡检机器人使用两个500线编码器,轮径65mm,轮距160mm。通过编码器计算左右轮速度,进而推算机器人线速度和角速度:v = (vL+vR)/2,ω = (vR-vL)/L。在10ms控制周期内,通过PID闭环控制电机转速,实测里程计累计误差小于2%(10米直线行走偏差0.18米)。误差主要来源于轮子打滑和编码器安装偏心,可通过定期校准轮径系数来修正。
3.5 摄像头:视觉感知与DCMI接口
核心原理
摄像头传感器将光信号转换为数字图像数据。OV2640是STM32机器人常用的200万像素摄像头,支持RGB565/YUV422/JPEG输出。STM32通过DCMI(数字摄像头接口)接收并行数据,配合DMA实现图像数据的高速传输,无需CPU逐像素搬运。SCCB协议(兼容I2C)用于配置摄像头寄存器。
选型对比
| 型号 | 分辨率 | 输出格式 | 接口 | 适用场景 |
|---|---|---|---|---|
| OV7670 | 30万像素 | RGB565/YUV | DCMI | 入门学习 |
| OV2640 | 200万像素 | RGB565/JPEG | DCMI | 中等性能视觉 |
| OV5640 | 500万像素 | RGB565/JPEG | DCMI | 高分辨率识别 |
STM32 DCMI配置要点
// DCMI初始化 - 8位数据模式,HSYNC/VSYNC
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_SnapShot;
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);
// DMA双缓冲配置
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_BufferSize = 320*240*2; // RGB565
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)frame_buffer1;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
常见误区与优化
- 误区1:忽略DCMI的像素时钟极性设置,导致图像错位。应根据摄像头数据手册仔细配置PCLK极性。
- 误区2:DMA缓冲区未对齐到4字节边界,导致HardFault。应使用__attribute__((aligned(4)))。
- 优化建议:使用DMA双缓冲,一帧采集时另一帧处理,避免帧丢失。
3.6 传感器选型综合对比与决策框架
在实际项目中,传感器选型需要综合考量以下维度:量程与精度、响应速度、功耗、接口资源占用、成本和环境适应性。以下为综合对比表:
| 传感器 | 量程 | 精度 | 响应频率 | 接口 | 典型功耗 | 成本 |
|---|---|---|---|---|---|---|
| 超声波 | 2-400cm | ±3mm | 20Hz | GPIO/TIM | 20mA@5V | 低 |
| 红外 | 0-3cm | ±1mm | 1kHz | ADC/GPIO | 10mA@5V | 极低 |
| IMU | ±16g/±2000°/s | 0.01° | 1kHz | I2C/SPI | 3.9mA@3.3V | 中 |
| 编码器 | 无限 | 0.1mm | 100kHz | TIM | 5mA@5V | 低 |
| 摄像头 | 视场角 | 像素级 | 30fps | DCMI | 150mA@3.3V | 中高 |
决策建议
- 避障场景:超声波(远距离)+红外(近距离盲区补偿)组合。
- 平衡/姿态控制:IMU必须,编码器用于轮速反馈。
- 循迹/巡线:红外阵列性价比最高,摄像头适合复杂路径识别。
- SLAM建图:激光雷达(未在本章范围)+IMU+编码器融合。
3.7 接口设计通用原则与抗干扰措施
无论选择哪种传感器,STM32接口设计都应遵循以下原则:
- 电平匹配:5V传感器输出需经电平转换(如74LVC245或分压电阻)再接入3.3V STM32。
- 电源去耦:每个传感器模块附近放置100nF+10μF去耦电容,避免电机启停造成电压跌落。
- 信号滤波:GPIO输入配置为上下拉+施密特触发,ADC采样加RC低通滤波(截止频率=1/(2πRC))。
- 地线处理:模拟地和数字地单点连接,避免地环路干扰。
- 线缆屏蔽:编码器、IMU等高频信号线使用双绞线或屏蔽线,屏蔽层单端接地。
// GPIO输入滤波配置示例(PA0外部中断)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // 降低翻转速率,抑制噪声
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
// 在中断服务函数中加软件消抖
if (++debounce_count > 5) { // 连续5次确认
process_signal();
debounce_count = 0;
}