基于STM32F103与ACS712的交流电流测量实战:从硬件连接到Python可视化

张开发
2026/4/16 7:23:30 15 分钟阅读

分享文章

基于STM32F103与ACS712的交流电流测量实战:从硬件连接到Python可视化
1. 硬件选型与连接从零搭建测量系统第一次用STM32F103配ACS712测交流电流时我对着淘宝五花八门的电流互感器发了半小时呆。后来实测发现硬件选型不当会导致测量误差直接翻倍。先说核心配置我用的正点原子MiniSTM32开发板MCU为STM32F103RCT6搭配ACS712-30A模块量程±30A。这里有个坑——ACS712分5A/20A/30A三个版本30A版本的灵敏度最低66mV/A但测量笔记本充电这种场景完全够用。电流互感器选型更有讲究。我买的10A/5A穿心式互感器关键参数是匝数比。包装上标着10A:5A 3匝意思是火线绕3圈时10A初级电流对应5A次级电流。实际接线时要把插座线剥开注意安全单独让火线穿过互感器中心孔绕3圈。有次偷懒只绕了1圈测得电流值直接缩水三分之二。硬件连接示意图ACS712的VCC接5VGND接地OUT引脚接STM32的PA1ADC1通道1电流互感器次级两根线随便接ACS712的输入端子不分极性务必在ACS712输出端加0.1μF滤波电容这个细节能减少50%以上的高频噪声2. STM32CubeMX配置ADCDMATIM三重奏用STM32CubeMX配置时这三个外设的联动就像交响乐配合。TIM定时触发ADC采样DMA负责搬运数据到内存CPU全程不参与实测采样率轻松跑到10kHz。具体操作打开CubeMX后先设置时钟树HCLK设为72MHzSTM32F103的满血状态APB2时钟设为72MHzADC所在总线接着配置ADC1选择通道1对应PA1分辨率设为12位4096级扫描模式禁用单通道连续转换模式禁用由TIM触发DMA设置成Circular模式循环缓冲TIM3的配置最易出错时钟源选内部时钟分频系数设为7200-172MHz/(7200*1Hz)10kHz计数模式Up在Trigger Output里把TRGO选为Update Event最后生成代码时记得勾选Generate peripheral initialization as a pair of .c/.h files。这样ADC、DMA、TIM的配置代码会分开后期调试更方便。3. 代码实战从采集到校准生成的代码需要三处关键修改。首先在main.c定义全局变量uint16_t adc_buff[1000]; // 存放1000个采样点 volatile uint8_t AdcConvEnd 0; // DMA完成标志然后在main()函数启动ADCHAL_ADC_Start_DMA(hadc1, (uint32_t*)adc_buff, 1000);重点来了——校准公式。ACS712空载时输出2.5V但实际测量我的模块是2.48V个体差异。转换公式要这样写float current (adc_buff[i] * 3.3f / 4095 - 2.48f) / 0.066f;其中0.066是30A版本的灵敏度66mV/A。打印数据时建议用科学格式printf(%.3e %.3e\n, i*0.0001f, current);遇到过最头疼的问题是零点漂移。解决方法是在设备断电时采集100次ADC值取平均作为动态零点补偿。实测可将静态误差从±0.3A降到±0.05A。4. Python可视化让数据会说话串口数据用Python处理时pySerialMatplotlib组合比LabVIEW更轻量。先安装依赖pip install pyserial matplotlib numpy完整的Python脚本示例import serial import matplotlib.pyplot as plt import numpy as np ser serial.Serial(COM3, 115200, timeout1) data [] for _ in range(1000): line ser.readline().decode().strip() if line: t, i map(float, line.split()) data.append([t, i]) data np.array(data) plt.figure(figsize(12, 4)) plt.plot(data[:,0], data[:,1], lw1) plt.title(Laptop Charging Current (10kHz Sampling)) plt.xlabel(Time (s)) plt.ylabel(Current (A)) plt.grid(True) plt.tight_layout() plt.show()进阶技巧添加移动平均滤波window_size 50 weights np.ones(window_size) / window_size smoothed np.convolve(data[:,1], weights, modevalid)5. 避坑指南血泪经验总结电源隔离问题有次测量电钻电流时STM32突然重启。后来发现是电机启停导致地线干扰用光耦隔离后解决。采样率陷阱最初设1kHz采样率测充电器完全看不到高频纹波。后来改到10kHz才发现电流波形有100us级的尖峰。量程选择测小电流1A建议换ACS712-5A版本灵敏度185mV/A30A版本测0.1A以下基本没精度。导线发热连续测10A以上电流时电流互感器次级导线会明显发热建议换AWG18以上线径。Python内存泄漏长时间连续采集时记得定期清空serial缓冲区否则内存会缓慢增长直到崩溃。

更多文章