ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用STM32自制PowerGrid Analyzer:从硬件到FFT谐波分析全解析

用STM32自制PowerGrid Analyzer:从硬件到FFT谐波分析全解析 最近用一个周末做了台基于STM32F103的Wattmeter/PowerGrid Analyzer也就是一台能测电压、电流、功率、功率因数还能看谐波和波形实时数据的电网分析仪。做完之后顺手测了家里几个电器发现冰箱启动瞬间的电流畸变比我预想的严重得多也第一次看清变频空调待机时的功率因数有多低。这篇文章把整个项目的设计思路、硬件电路、软件流程、校准方法和踩过的坑完整过一遍适合有一定单片机基础、想自己动手做电能测量设备的朋友参考。1. 为什么自己造一台电网分析仪而不是直接买先说结论不是所有需求都能靠成品解决。市面上几十块钱的功率计插座能显示当前功率但它在内部只采样电压和电流的少量点然后套一个近似公式算功率。对于纯阻性负载这没什么问题一旦碰到开关电源、变频电机这类非线性负载误差能到百分之二三十。而专业电能质量分析仪动辄上万功能确实全但我是想在实验室和家里长期挂着看数据还得能自己改算法、加传感器成品设备根本不给这个自由度。PowerGrid Analyzer这个名字听起来高大上拆开看就是把电网电压和负载电流通过采样电路送入MCU在数字域做RMS计算、有功功率计算、FFT谐波分析再把结果显示出来。我给自己定的功能目标很简单功能项目标指标电压测量10V~300V AC RMS电流测量0.1A~50A AC RMS频率测量45Hz~65Hz功率测量有功功率P、视在功率S、功率因数PF谐波分析基波到21次谐波THD显示OLED屏幕实时刷新数据接口串口输出留作二次开发1.1 成品功率计查不到的背后数据普通功率计插座只能给你一个累计电费数字但很多问题恰恰需要看电压电流的波形细节才能定位。比如我遇到过的案例一台上位机莫名其妙重启用示波器看电源输入端发现电压波形在每次电机启动时被拉低了一个明显的凹坑普通功率计完全看不出这个瞬态。再比如很多开关电源输入端会有很大的3次谐波电流导致中线过流。单看功率数值你只会觉得这个设备耗电不高但实际上它给电网注入了不少谐波污染。要看到这些就需要采集完整波形并做频谱分析这正是PowerGrid Analyzer的核心价值。1.2 功能定级这台分析仪能测什么项目不能一口吃成胖子我给第一版定义了几个核心指标电压和电流采用隔离采样MCU内部ADC以固定采样率连续采集一个周期内至少采128个点这样能保证基波和谐波分析的精度。显示界面做了三页第一页显示电压、电流、频率第二页显示有功功率、视在功率、功率因数第三页显示THD和2~21次谐波的柱状图。这三个页面已经能覆盖绝大多数家用和实验室测试场景。串口输出采用简单的文本格式后面接树莓派做远程监控也方便。2. 硬件方案选型采样与主控怎么搭硬件架构其实非常简单电压互感器加运放调理、电流互感器加采样电阻、MCU的ADC负责数字化OLED负责显示。整体框图不复杂但每一步都有讲究。2.1 电压采样优先用互感器别用纯电阻分压有些教程会教你把220V用两个电阻分压后直接送ADC我强烈不建议这么做。第一是安全隔离问题市电地和MCU的GND直接连通一旦电脑USB串口连上来会形成一个非常危险的地环路轻则烧板子重则触电。第二是噪声问题开关电源的共模干扰会被ADC直接采进去。我选的是ZMPT101B电压互感器模块它内部是一个微型变压器初级侧串联一个100kΩ电阻后接到被测电压次级输出电流信号模块上自带运放调理电路和偏置电压。这样市电和MCU之间通过磁路隔离非常安全。模块输出是0~3.3V1.65V对应零电压交流信号在这个偏置上下摆动。注意ZMPT101B模块本身适合220V左右测量但不同批次的输出幅度差异较大后面校准时必须逐台标定不能直接拿理论值当准。2.2 电流采样SCT013互感器与偏置电路电流侧我用的是SCT013-100A穿心式电流互感器它输出的是电流信号额定100A对应50mA。互感器次级我并联了20Ω采样电阻这样100A对应1V有效值。如果被测电流主要在10A以下可以加大采样电阻来提高小电流分辨率但要注意不能超过互感器次级的最大输出电压限制否则波形会削顶。SCT013输出是交流电流信号需要叠加一个1.65V的直流偏置才能送ADC。我直接用两个10kΩ电阻分压从3.3V得到1.65V再经过一个电压跟随器给信号叠加偏置。运放选的是 LMV358它是轨到轨输出适合3.3V供电的单电源系统。2.3 主控选型STM32F103怎么够用主控选了STM32F103C8T6原因是它性价比高、资料多而且内部自带两个ADC模块可以做双ADC同步采样。这里有个关键点测量有功功率需要电压和电流的瞬时值相乘再求平均如果电压电流不是同一时刻采到的会有相位差直接导致功率因数计算错误。STM32F103的ADC1和ADC2可以配置成同步采样模式实现真正的同时刻采样。顺便说一句ESP32我试过但它的ADC线性度太差做简单传感器还行做电能测量这种对精度有要求的场合不合适。STM32自带的12位ADC虽然也不算顶级但配合过采样和校准做到1%以内的功率测量精度没有问题。供电方面我用了一个隔离DC-DC模块把220V转换为5V给核心板供电再经过LDO降到3.3V。隔离电源的好处是让测量前端和显示端之间减少地环路干扰虽然ZMPT101B和SCT013已经把电压电流采样隔离了但供电端再隔一道更稳。3. 核心原理与关键参数先把公式和电路算明白软件部分绕不开两个基础概念真有效值和瞬时功率积分。如果不把原理吃透后面写代码就是瞎试。3.1 真有效值为什么普通万用表会骗你交流信号的RMS有效值严格定义是Vrms sqrt( (1/T) * ∫ v(t)^2 dt )数字实现是离散化的Vrms sqrt( (1/N) * Σ v[n]^2 )普通万用表的交流档为了省钱内部先做整流然后测平均值再乘一个1.11的系数。这个系数只对标准正弦波有效。一旦波形是变频器输出或者开关电源输入那种尖顶波平均值和真有效值的偏差会很大。所以这台分析仪用的是真RMS算法直接对采样点平方求和开根号对任意波形都成立。同样的道理有功功率也不是电压乘电流那么简单。有功功率的定义是P (1/T) * ∫ v(t)*i(t) dt在数字域就是P (1/N) * Σ v[n]*i[n]只有纯阻性负载的时候P才等于VrmsIrms。带电机的设备会在电压和电流之间引入相位差或者产生谐波这两者都会让P小于VI多出来的那部分就是无功功率或谐波功率。3.2 电压通道参数计算实例ZMPT101B模块的输出幅度我可以根据采样电阻推算。ZMPT101B额定变比是1:1初级串联100kΩ电阻220V输入时初级电流约为2.2mA次级输出同样2.2mA电流。如果模块上采样电阻是100Ω得到220mV再经过运放放大到合适的幅度。不同模块的增益差异很大我的模块实测输出约1.85Vpp对应220V RMS也就是327V峰值时输出大约±0.9V的变化。这一步只需要关心量程匹配ADC输入范围0~3.3V偏置1.65V那么最大交流摆幅不能超过±1.65V换算成电压大约是400V RMS。这个设计留了足够余量实测250V市电也不会饱和。电流通道的参数更直接SCT013-100A的输出是50mA100A采样电阻20Ω得到1V RMS。偏置1.65V最大摆幅允许±1.65V对应165A RMS。这个量程对家用场景绰绰有余而且留了很大的削顶余量。3.3 频率与过零检测别让干扰让计数乱跳电网频率虽然标称50Hz但实际会在49.9到50.1之间浮动。测频率的常见做法是过零检测。我没用专门的比较器芯片直接复用软件对采样到的电压波形做符号判断从负到正就是一次过零计算两次过零的时间差就是周期。但电网波形不是完美的正弦波畸变波形可能在零点附近来回穿越导致误判。我的解决办法是加滞回区间只有电压从低于0.5V变化到高于0.5V才认为真正过零低于-0.5V才算负半周中间区域忽略。这个0.5V阈值相当于大约95V的电网电压保证了只有主波过零才被计数。频率测量用定时器计数来做不需要占用额外的硬件捕获通道软件逻辑二十行以内搞定。实测频率读数稳定到小数点后一位完全够用。4. 软件实现从ADC采样到谐波分析一套走通软件部分是这台分析仪的核心也可以说是最花时间的地方。整个流程分采样、计算、显示三个环节我用一个简单的循环结构跑起来没有上RTOS因为逻辑足够简单。4.1 采样策略定时器触发加DMAADC采样必须等间隔否则算出来的频谱全是错乱的。我用了定时器TIM2产生一个40kHz的触发信号每次触发同时启动ADC1和ADC2分别采集电压和电流通道。40kHz对应每周期800个采样点足以分析到20次谐波20次谐波是1000Hz40kHz采样率是它的40倍完全满足奈奎斯特条件。关键代码逻辑如下// ADC1采样电压通道ADC2采样电流通道 // 双ADC同步模式定时器触发 HAL_TIM_Base_Start(htim2); HAL_ADCEx_MultiModeStart_DMA(hadc1, (uint32_t*)adc_buffer, 2 * SAMPLE_COUNT); // DMA双缓冲模式一个缓冲在采另一个缓冲在算 // SAMPLE_COUNT取800代表40kHz采样率下20ms的一个完整工频周期DMA双缓冲是这个项目一个很重要的点ADC不断往缓冲区A写数据同时CPU在计算缓冲区B的上一轮数据。采集和计算重叠进行不会因为FFT计算时间过长丢失采样点。4.2 功率与功率因数的代码实现每次拿到800个点的电压和电流数组后第一件事是去掉直流偏置。ADC读到的数值减去204812位ADC中值再乘以3.3/4096换算成实际电压再用标定系数转换成真实的电压电流值。接下来就是核心计算代码量不大float v[N], i[N]; // 已经转为实际电压电流值的数组 float sum_v2 0, sum_i2 0, sum_p 0; for (int n 0; n N; n) { sum_v2 v[n] * v[n]; sum_i2 i[n] * i[n]; sum_p v[n] * i[n]; } float Vrms sqrtf(sum_v2 / N); float Irms sqrtf(sum_i2 / N); float P sum_p / N; // 有功功率 float S Vrms * Irms; // 视在功率 float PF P / S; // 功率因数这段代码就是整个功率计的核心没什么神秘的地方。PF值是瞬时值它会不断跳动我在显示端做了滑动平均大概1秒更新一次这样读数比较稳定。4.3 谐波分析FFT和THD的落地细节谐波分析用STM32的DSP库里的arm_rfft_fast_f32函数它要求输入长度必须是2的幂。我的方案是取FFT点数为1024但实际采样一个完整周期是800点怎么对齐我先用上面算出来的频率值动态调整采样窗口比如检测到频率是50.1Hz就调整定时器的自动重装载值让采样窗口恰好覆盖完整的10个周期然后在这个窗口内均匀采2048个点。这里有一个非常容易踩的坑直接对800点做FFT而不加窗频谱会因为栅栏泄漏出现一堆旁瓣看起来像是谐波其实全是假的。我选择加汉宁窗代码如下for (int n 0; n FFT_SIZE; n) { float w 0.5f * (1 - arm_cos_f32(2 * PI * n / (FFT_SIZE - 1))); fft_input[n] (v[n] - v_offset) * w; } arm_rfft_fast_f32(S, fft_input, fft_output, 0);FFT输出的频点间隔等于采样率除以FFT点数我用的是动态采样率每个周期512点FFT_SIZE取1024也就是对两个周期做FFT。基波落在第2个频点第k次谐波落在第2k个频点。取对应频点的幅值THD的计算公式是THD sqrt( f2^2 f3^2 ... f21^2 ) / f1这个值能直观反映负载对电网的污染程度。工业标准是THD小于5%算合格家里很多劣质开关电源都能到10%以上。5. 校准与误差补偿让测量数据真正可信硬件做完能出数但这台设备到底准不准得靠校准。所有用ADC做测量的项目都绕不开这一步因为电阻有误差、互感器有离散性、ADC本身也有增益误差。5.1 电压校准两步走电压校准的基准是手头的Fluke万用表。接上被测电压后让设备读出一个原始值然后用基准表测真实值求出比例系数。校准公式很简单K_v V_real / V_measured这个系数直接乘到软件里的电压换算系数上。我做了两点校准分别在110V和220V左右测两次取平均值作为最终系数能覆盖更宽的量程。提示校准前先让设备预热至少20分钟因为运放和基准源的温漂在冷启动时变化最大。我用的是静态校准如果你追求更高精度可以做一个两点温补表但家用场景没必要。5.2 电流校准与相位补偿电流校准我使用一个纯阻性负载一台1200W的取暖器用热成像确认它确实没有明显感抗后再把它接入电路。这时功率因数理论上是1.0如果设备显示的PF不是接近1说明电压和电流两个通道之间存在相位延迟。相位延迟的来源主要是电流互感器的初相位SCT013在低频率下几乎没有相移但ZMPT101B模块内部的运放会引入一点点延迟。解决方法是软件相位补偿直接对电流采样数组做一个时域移位移动的点数在小数位用插值实现。补偿值通过观察PF读数调整目标是让纯阻性负载的PF读数在0.999以上。5.3 温漂处理与长期稳定性校准完了不代表一劳永逸。SCT013的磁芯会受温度影响ZMPT101B内部的采样电阻也有温漂设备长时间运行后读数会缓慢漂移。我的处理办法比较暴力做一次长时间老化测试通电10小时每10分钟记录一次电压电流读数观察漂移趋势。实测下来我这对互感器在环境温度稳定后漂移量大约在0.3%以内对这台分析仪的定位来说完全可以接受。如果你需要更高稳定性可以在电路板上加一个温度传感器做软件温度补偿系数表。我这次没做但在设计上留了I2C接口后续想加随时能加。6. 实战踩坑记录与安全提示做这个项目时踩了不少坑有些是原理性错误有些是低级失误。整理出来给后来人少走弯路。6.1 高频踩坑从电压跳变到FFT杂峰我先说几个典型的排查问题写成表格方便对照现象可能原因解决方法电压读数明显偏高校准系数错误或ZMPT101B模块批次差异太大用万用表重新校准不要相信模块说明书上的固定变比电流读数跳动剧烈SCT013接到负载线上但没有卡紧或采样电阻虚焊重新卡紧互感器检查焊接点PF显示0.99但负载是电机电压电流采样不同步存在固定相位差检查双ADC配置是否真的同步尝试软件相移补偿FFT频谱图基波旁边一片杂峰采样窗口不是整数周期或没有加窗函数加汉宁窗或者锁定采样率做同步采样OLED显示花屏主控3.3V供电电压被电流互感器采样电阻干扰增加100nF和10uF去耦电容电源走线加粗ADC读满量程4095值采样信号实际超出3.3V范围检查运算放大器输出波形是否削顶减小采样电阻最让我印象深刻的一个坑是我第一次接上SCT013后电流读数一直是0.2A左右拔掉负载也是0.2A。折腾半天发现是互感器穿线方向反了本来应该只感应差模电流结果变成了共模天线把周围环境的磁场也采样了。重新调整穿线方向后零电流时读数降到0.01A以下。6.2 市电安全绝缘、隔离和习惯我不建议没有任何电工基础的初学者直接上手做这个项目因为涉及220V交流电。几个安全习惯必须养成第一调试时全程使用隔离变压器供电这样即使操作失误触碰到单根导线也不会和大地形成回路第二所有裸露的电路板放进绝缘外壳固定好测试时不要用手去碰任何金属部位第三电流互感器是穿心式的不需要断开负载线但穿线时一定要确认负载线已经断电。另外千万不要把电脑USB串口直接连到未隔离的设备上。我一开始偷懒没用隔离DC-DC结果每次USB一插上ADC读数就像心电图一样跳动。后来加了隔离电源模块再把USB转TTL的GND不连只连TX和RX问题彻底消失。贴几个实测结果和后续打算这台分析仪做出来之后我测了手头几个设备。家里那台变频空调待机时功率因数是0.47有功功率3.5W视在功率却有7.4VA这个数据让我对待机功耗有了新的理解。台式电脑的电源在运行时THD是13.7%主要集中在3次和5次谐波这也解释了为什么UPS的说明书总是强调谐波会导致设备容量下降。原计划里还留了一个扩展功能通过串口把数据发给树莓派在树莓派上做一个简单的HTTP服务就能在手机浏览器里远程看实时功率和谐波柱状图。这个部分我还没做完目前串口文本输出已经调通格式是V:226.5,I:1.23,P:278.3,PF:0.98,THD:3.2%后面接什么平台都方便。如果你也打算复刻这个项目我建议先把主体跑通再考虑远程毕竟一台能放在桌面上稳定显示数据的基础版比一个半吊子的物联网电力监测中心有用得多。
返回列表