基于PIC MCU的车速里程表开发:里程计算方案问询
基于PIC系列MCU开发车速里程表,模拟速度输入对应关系为0V→0km/h、25V→25km/h,可通过ADC正常获取速度值。当前采用100ms固定延迟轮询,用瞬时速度乘以时间间隔累加里程(其他函数执行时间1-5ms可忽略),但里程计算精度不足,寻求更优方案。
现有基础代码:
// need to multiply with the reference voltage as well (value*5/4096) currentSpeedVoltage = ADC_Read(9); //(0.001220703125 = 5/4096) currentSpeedVoltage = (currentSpeedVoltage * 0.001220703125); // assumed here that at 18 Volts, we show the speed as 25 Km/hr. currentSpeed = (currentSpeedVoltage*25)/18; // converting km/hr to m/s and adding the distance travelled in 100mS. distance += (currentSpeed*100*5*(pow(10,-5))/18)/1000;
注:代码中速度-电压对应关系(18V→25km/h)与描述的(25V→25km/h)不一致,需先统一需求。
1. 替换轮询为定时器中断采样,缩短间隔
放弃固定100ms延迟的轮询模式,利用PIC的定时器生成1ms/10ms级别的固定间隔中断,在中断服务函数中完成速度采样与里程累加。更密集的采样能大幅降低瞬时速度突变带来的里程误差,同时避免轮询延迟占用主程序资源。
以1ms间隔为例,里程累加公式可简化为:
// currentSpeed单位:km/h;distance单位:米 distance += currentSpeed * 1e-3 / 3.6;
推导:1km/h = 1000m/3600s = 1/3.6 m/s,1ms内行驶距离为 (currentSpeed/3.6) * 0.001 米。
2. 全整数运算替代浮点计算
PIC MCU的浮点运算效率低且易引入精度损失,将所有转换逻辑改为整数比例运算:
假设采用12位ADC(4096刻度)、5V参考电压,按描述的0V→0km/h、25V→25km/h对应关系:
// 读取ADC值 uint16_t adc_val = ADC_Read(9); // 计算速度(放大1000倍,单位:0.001km/h,避免小数) uint32_t current_speed_milli = (uint32_t)adc_val * 1000 / 4096;
里程累加(1ms间隔,distance_milli单位:0.001米):
// 1ms内行驶的0.001米数 = (0.001km/h) * (1ms/3600000ms每小时) * 1000000米每km distance_milli += current_speed_milli / 3600;
最终显示时,distance_milli / 1000 即为米数,distance_milli / 1000000 即为公里数。
3. 加入速度滤波抑制噪声
模拟输入的噪声会导致速度跳变,进而影响里程精度,可采用以下滤波方式:
- 滑动窗口滤波:保存最近8~16次ADC采样值,取平均值作为当前速度的计算依据,适合平稳变化的速度信号。
- 一阶低通滤波:用整数比例实现,例如:
用滤波后的速度值参与里程累加,能有效平滑误差。// filtered_speed_milli为上一次滤波后的速度值,alpha取1/10 filtered_speed_milli = (current_speed_milli + 9 * filtered_speed_milli) / 10;
4. 校准采样间隔误差
定时器的实际触发间隔可能因MCU振荡器精度、中断响应延迟存在微小偏差,可通过以下方式校准:
- 使用PIC内部高精度振荡器(如HS模式)作为定时器时钟源。
- 用已知距离的测试路段(比如1km)运行设备,对比实际里程与计算值,调整里程累加的系数。
内容的提问来源于stack exchange,提问作者Siddharth Goel

