1. 电磁智能车信号处理系统概述
在智能车竞赛的电磁组比赛中,信号处理系统是整个车辆控制的核心。与摄像头组不同,电磁组需要处理的是看不见摸不着的磁场信号,这使得信号处理的质量直接决定了车辆的稳定性和速度表现。经过多次比赛实践,我们发现90%的失控情况并非源于控制算法本身,而是由于信号采集和处理环节的缺陷导致的。
电磁信号处理系统主要包含五个关键环节:信号采集、滤波处理、归一化转换、循迹算法计算和丢线保护。每个环节都需要精心设计和调试,才能确保车辆在各种赛道条件下都能稳定运行。我们的RT1064主控芯片搭载了12位ADC采样模块,理论上可以获得0-4095的原始数据范围,但实际赛道环境中有效信号通常集中在1000-3500之间。
2. 信号采集与预处理
2.1 多通道同步采样策略
电磁智能车通常需要同时采集多个电感传感器的数据。我们采用四路电感布局:左右两侧各一个横向电感(用于检测左右偏差),以及两个纵向电感(用于检测前瞻距离)。在每一个控制周期内,我们对这四路信号进行连续采样:
c复制#define SAMPLE_TIMES 5
uint16_t filter_buf_L[SAMPLE_TIMES]; // 左侧横向电感
uint16_t filter_buf_LS[SAMPLE_TIMES]; // 左侧纵向电感
uint16_t filter_buf_RS[SAMPLE_TIMES]; // 右侧纵向电感
uint16_t filter_buf_R[SAMPLE_TIMES]; // 右侧横向电感
void sample_sensors() {
for(int i=0; i<SAMPLE_TIMES; i++) {
filter_buf_L[i] = adc_read(LEFT_ADC_PIN);
filter_buf_LS[i] = adc_read(LEFT_SHU_PIN);
filter_buf_RS[i] = adc_read(RIGHT_SHU_PIN);
filter_buf_R[i] = adc_read(RIGHT_ADC_PIN);
delay_us(50); // 适当间隔防止信号干扰
}
}
采样次数的选择需要权衡信号平滑度和系统实时性。经过实测,5-7次采样能在保证足够平滑度的同时,将处理延迟控制在可接受范围内。值得注意的是,采样间隔不宜过短,否则可能因电感充放电不充分而影响数据准确性。
2.2 死区处理与噪声抑制
原始ADC数据中往往包含大量环境噪声和电路本身的零漂。我们发现,对于横向电感,小于240的数值基本是无效信号;而对于纵向电感,这个阈值提高到500。这是因为纵向电感通常距离导线更远,信号强度本身就较弱。
c复制void dead_zone_filter() {
for(int i=0; i<SAMPLE_TIMES; i++) {
if(filter_buf_L[i] < 240) filter_buf_L[i] = 0;
if(filter_buf_LS[i] < 500) filter_buf_LS[i] = 0;
if(filter_buf_RS[i] < 500) filter_buf_RS[i] = 0;
if(filter_buf_R[i] < 240) filter_buf_R[i] = 0;
}
}
死区处理必须在滤波计算之前进行,否则微弱的干扰信号会被带入后续计算,影响最终结果的准确性。这个步骤看似简单,却能显著提高系统的信噪比。
2.3 去极值平均滤波算法
普通的均值滤波对异常值非常敏感,一个突发的干扰脉冲就可能严重影响滤波结果。我们采用去极值平均滤波法,先去除采样数据中的最大值和最小值,再对剩余数据求平均:
c复制float advanced_filter(uint16_t *buf) {
uint16_t max = 0, min = 0xFFFF;
uint32_t sum = 0;
for(int i=0; i<SAMPLE_TIMES; i++) {
if(buf[i] > max) max = buf[i];
if(buf[i] < min) min = buf[i];
sum += buf[i];
}
return (float)(sum - max - min) / (SAMPLE_TIMES - 2);
}
这里需要特别注意数据类型的选择。虽然12位ADC的最大值为4095,5次累加最大约为20475,仍处于uint16_t范围内(0-65535),但如果增加采样次数到16次以上,就必须使用uint32_t来避免溢出。
3. 信号归一化处理
3.1 归一化的必要性
原始ADC值会受多种因素影响,如电池电压变化、赛道磁场强度差异等。为了消除这些影响,我们将12位ADC值(0-4095)映射到0-100的统一范围:
c复制void normalization() {
left_adc = 100.0 * filtered_L / 4096;
leftshu_adc = 100.0 * filtered_LS / 4096;
rightshu_adc = 100.0 * filtered_RS / 4096;
right_adc = 100.0 * filtered_R / 4096;
}
归一化处理带来三个显著优势:
- 算法逻辑与具体硬件解耦,提高代码可移植性
- 不同传感器数据具有可比性,便于参数调整
- 输出范围固定,简化后续PID参数整定
3.2 归一化参数调整
在实际应用中,我们发现完全按照理论最大值4095进行归一化并不总是最佳选择。可以根据实际赛道情况调整归一化基准:
c复制#define ADC_MAX 3500 // 根据实测最大信号强度调整
void dynamic_normalization() {
left_adc = 100.0 * filtered_L / ADC_MAX;
// 其他通道类似
}
这种动态基准方法可以更好地利用ADC的分辨率,特别是在信号强度较弱的赛道上。但需要注意定期校准,确保基准值的准确性。
4. 循迹算法实现
4.1 基础差比和算法
差比和算法是电磁组最基础的循迹算法,通过计算横向和纵向电感的差值比上和值来得到偏差:
c复制float basic_error_calc() {
float horiz_error = (left_adc - right_adc) / (left_adc + right_adc);
float vert_error = (leftshu_adc - rightshu_adc) / (leftshu_adc + rightshu_adc);
return 10.0 * (0.5 * horiz_error + 0.5 * vert_error);
}
这个算法的优势在于简单直观,且对信号强度变化具有自适应性。当所有信号同比变化时(如电池电压下降),计算结果保持不变。
然而,基础差比和算法存在一个严重缺陷:当车辆接近赛道边缘时,分母趋近于零,导致计算结果剧烈波动,容易引发车辆失控。
4.2 改进的差比和差算法
为了解决基础算法的问题,我们引入了差比和差算法,在分母中加入阻尼项:
c复制#define ALPHA 0.6f // 横向权重
#define BETA 0.3f // 纵向权重
#define OMEGA 0.1f // 阻尼系数
float advanced_error_calc() {
float numerator = ALPHA * (left_adc - right_adc) +
BETA * (leftshu_adc - rightshu_adc);
float denominator = ALPHA * (left_adc + right_adc) +
OMEGA * fabs(leftshu_adc - rightshu_adc);
return 10.0 * (numerator / denominator);
}
这个改进的关键在于分母中的fabs()项,它确保分母永远不会为零。即使横向电感信号完全丢失,纵向电感的差值也能维持分母的稳定性。
4.3 参数整定经验
差比和差算法的三个参数(ALPHA、BETA、OMEGA)需要根据实际车辆和赛道情况进行调整。我们的经验是:
- 初始值可以设为ALPHA=0.6, BETA=0.3, OMEGA=0.1
- 直道行驶时,适当增大ALPHA使车辆更稳定
- 弯道较多时,适当增大BETA提高转向灵敏度
- OMEGA不宜过大,否则会降低算法灵敏度
调试时可以借助OLED屏幕实时显示偏差值,观察不同赛道段落的算法输出特性。建议记录直道、小弯、大弯等不同情况下的数据,进行针对性优化。
5. 信号后处理与丢线保护
5.1 一阶低通滤波
即使经过前述处理,偏差信号仍可能包含高频噪声。我们采用一阶低通滤波进行平滑:
c复制float last_error = 0;
float filter_coef = 0.8f; // 滤波系数
float low_pass_filter(float current_error) {
last_error = last_error + filter_coef * (current_error - last_error);
return last_error;
}
滤波系数的选择需要权衡响应速度和平滑度:
- 系数接近1(如0.9):响应快但平滑效果差
- 系数接近0(如0.1):非常平滑但响应滞后
- 通常选择0.7-0.8能在两者间取得较好平衡
5.2 丢线检测与保护
丢线是电磁车最常见的问题之一,必须实现可靠的保护机制:
c复制bool check_signal_lost() {
float total = left_adc + leftshu_adc + rightshu_adc + right_adc;
return (total <= 15); // 阈值根据实际情况调整
}
void safety_control() {
if(check_signal_lost()) {
set_motor_pwm(-200); // 反向制动
set_servo_pwm(SERVO_MID); // 舵机回正
delay_ms(100);
set_motor_pwm(0); // 完全停止
}
}
丢线保护的关键点:
- 阈值设置要合理,既要能及时检测丢线,又要避免误触发
- 保护动作应包括减速、舵机回正等
- 可以增加声音或灯光提示,方便调试人员识别
6. 硬件优化与调试技巧
6.1 电感安装与支架设计
硬件安装对信号质量影响极大,我们的经验教训包括:
- 电感支架必须足够坚固,避免振动引入噪声
- 电感安装位置要合理,前瞻距离影响信号强度
- 使用热熔胶固定电感和线缆,防止松动
- 定期检查电感角度,碰撞后需要重新校准
6.2 数据采集与分析方法
建立系统的调试方法可以事半功倍:
- 使用OLED/TFT屏幕实时显示关键数据
- 通过串口将数据发送到上位机进行分析
- 记录不同赛道段落的典型数据特征
- 使用Excel或MATLAB进行离线分析和算法验证
6.3 开发流程建议
电磁车的开发应该分阶段进行:
- 初期:确保基础功能正常,车辆能完成赛道
- 中期:优化算法和参数,提高行驶稳定性
- 后期:精细调参和速度优化,追求极限性能
每个阶段都要有明确的目标和评估标准,避免过早优化。记住,一个稳定完成赛车的方案,远优于一个速度快但不可靠的方案。
