1. 项目概述
这个高精度电压电流表项目是我在实验室折腾了半个月的成果,核心目标是用低成本方案实现0.5%以内的测量精度。整套系统基于单片机开发,包含硬件电路设计和嵌入式软件编程两个主要部分。实测下来,3.3V供电时整机功耗不到20mA,用旧手机电池就能续航8小时以上。
作为电子工程师,我们经常需要测量各种电压电流参数。市面上专业仪器动辄上千元,而用单片机+常见元器件自制的方案,成本可以控制在百元以内。这个项目的独特之处在于:
- 采用TL431基准电压源魔改方案,比普通分压电阻稳定得多
- 并联电阻阵列实现高精度电流采样
- 软件算法上采用滑动均值滤波+异常值剔除
- 整套系统功耗极低,适合便携式应用
2. 硬件设计详解
2.1 基准电压电路设计
基准电压是整个测量系统的"尺子",其精度直接影响最终测量结果。我选择了TL431可调基准源,相比普通齐纳二极管,它具有更好的温度稳定性和初始精度。
关键计算公式:
code复制Vref = 2.5 * (1 + R1/R2)
实际设计时要注意:
- 电阻R1、R2建议使用1%精度的0805封装电阻,实测温漂比0603小30%
- 需要预留调校余量,建议设计输出电压比需求值高5%
- 输出端要并联0.1μF和10μF电容滤波
注意:TL431的最小工作电流是1mA,设计分压电阻时要确保满足这个条件。
2.2 电流采样电阻设计
电流采样采用10个1Ω的0603电阻并联,等效电阻0.1Ω。这种设计有几个优势:
- 分散功率,避免单个电阻过热
- 通过数量优势抵消个体误差
- 便于PCB布局布线
计算采样电阻功率的公式:
code复制P = I² × R
例如测量2A电流时,单个电阻功耗为(2A/10)² × 1Ω = 0.04W,远低于0603电阻的1/8W额定功率。
2.3 ADC电路设计
选用XPT2046这款四通道12位ADC芯片,性价比很高。布线时有几个关键点:
- 模拟地要单独拉线到接地点,避免数字噪声干扰
- 基准电压引脚要并联0.1μF+10μF电容
- 使用双面PCB时,底层建议铺铜做屏蔽
- 信号线尽量短,避免平行走线
3. 软件算法实现
3.1 ADC驱动编程
XPT2046通过SPI接口通信,时序控制很关键。以下是经过实测稳定的驱动代码:
c复制uint16_t XPT_Read(uint8_t cmd)
{
CLK = 1;
DCLK_LOW(); // 时钟线拉低准备
CS_LOW(); // 片选使能
uint16_t value = 0;
for(uint8_t i=0; i<12; i++){ // 12位精度
DCLK_HIGH();
if(cmd & (1<<(11-i))) DIN_HIGH();
else DIN_LOW();
DCLK_LOW();
delay_us(1);
if(DOUT) value |= (1<<(11-i));
}
CS_HIGH();
return value;
}
3.2 数字滤波算法
为了提高测量稳定性,我采用了滑动均值滤波+异常值剔除的组合算法:
c复制#define FILTER_SIZE 8
uint32_t adc_filter[FILTER_SIZE];
uint16_t Get_Valid_ADC(){
static uint8_t index = 0;
adc_filter[index++] = XPT_Read(0x94); // 通道1
// 冒泡排序去极值
for(uint8_t i=0; i<FILTER_SIZE-1; i++){
for(uint8_t j=i+1; j<FILTER_SIZE; j++){
if(adc_filter[i] > adc_filter[j]){
uint32_t temp = adc_filter[i];
adc_filter[i] = adc_filter[j];
adc_filter[j] = temp;
}
}
}
// 取中间4个值平均
uint32_t sum = 0;
for(uint8_t i=2; i<FILTER_SIZE-2; i++){
sum += adc_filter[i];
}
return sum/(FILTER_SIZE-4);
}
这种算法能有效抑制突发干扰,同时保持较好的实时性。
3.3 校准算法实现
校准是保证精度的关键环节,需要准备一个五位半万用表作为基准。代码中采用两点校准法:
c复制float voltage_calibrate(uint16_t raw){
// 两个校准点:(raw1,实际值1),(raw2,实际值2)
static float k = (VAL2 - VAL1)/(RAW2 - RAW1);
return VAL1 + k*(raw - RAW1);
}
实际操作时:
- 先测量零点(如0V输入)
- 再测量一个接近满量程的值(如3V)
- 将这两个点的ADC原始值和实际值填入代码
4. 显示界面设计
OLED显示部分我设计了两种显示模式:
- 数值模式:直接显示电压电流数值
- 波形模式:实时显示变化曲线
波形显示的实现代码:
c复制void Draw_Wave(uint8_t *buf){
static uint8_t pos = 0;
buf[pos] = current_voltage * 64 / 3.3; // 映射到64像素高度
pos = (pos+1)%128;
for(uint8_t x=0; x<128; x++){
oled_draw_line(x,63,x,63-buf[(pos+x)%128]);
}
}
还隐藏了一个彩蛋功能:长按按键屏幕会倒转显示,这是为了适应不同的安装方向。
5. 常见问题与解决方案
5.1 测量值跳动大
可能原因:
- 电源噪声大 → 加强电源滤波
- 接地不良 → 检查地线连接
- 软件滤波参数不合适 → 调整滤波窗口大小
5.2 ADC读数不稳定
解决方案:
- 检查基准电压是否稳定
- 确认SPI时序是否符合芯片要求
- 尝试降低采样速率
5.3 电流测量误差大
排查步骤:
- 检查采样电阻阻值是否准确
- 测量运放输出电压是否正常
- 确认校准过程操作正确
6. PCB设计经验分享
- 布局要分区:模拟电路和数字电路分开布局
- 地线处理:模拟地和数字地单点连接
- 铺铜技巧:避免把散热焊盘连死
- 生产细节:一定要做泪滴,我因为偷懒没做,结果运输后芯片引脚虚焊
这个项目后续还可以做很多改进:
- 改用STM32主控,提高刷新率到30fps
- 增加蓝牙/WiFi无线传输功能
- 设计3D打印外壳
- 开发PC端数据分析软件
整个工程包含Altium设计文件和完整源码,代码注释非常详细,特别适合想要学习单片机开发的工程师。通过这个项目,你不仅能掌握高精度测量技术,还能学到很多实用的电子设计技巧。