最大电流采样500A,主要应用在电力上的对某个电网进行瞬时功率,平均功率,总功率采集
通过STM32微控制器,对电网信号进行采样处理
设计参数
(1) 电压参数 0-105V
(2)电流参数 0-500mA,0-5A,0-500A
(3) 最大频率成分 <25kHz
(4) AD采样率600kHz(方便处理),功率采样率300kHz
结果输出:每秒通过串口将p、P、W发送到PC端
这是整体电路
我们主要分析电流采样这块
电流采样这块采用精密零漂移电流检测放大器U3 LTC6102,VIN输入最高为105V(电网的电压经过变压器整流降压的),通过外部检测电阻RoutX和RoutX_ADJ (分流 电阻) 两端的电压来监测电流(0-500ma,0-5A,0-500A)。内部电路将输入 电压转换为输出电流,使得大共模电压上的小检 测信号可以转换为以地为基准的信号。低直流失 调电压支持使用非常小的分流电阻值和较大的 增益设置电阻。电流精度可以达到10ma,电流采样电阻采用大功率Rsense 1mR,最大检测电流达到电网的500A。下图最右边是对电流采样原理和计算公式。
对电流采样采用二阶低通滤波器,这个是一个有源滤波器,用工作在线性区的集成运放和 RC 网络组称,实际上是一种具有特定频 率响应的放大器,主要滤除电网负载的波动
具体原理如下:
U3的输出经过PR2、CC2、PR1、CC1构成二阶低通滤波电路,R1、Rf1、Rf1_ADJ构成同相比例放大电路,Rf1_ADJ可以调节电路的放大倍数,这是计算公式
在集成运放U2输出到集成运放同相输入之间并联电容CC2引入一个负反馈,主要作用是,在不同的频段,反馈的极性不相同,当信号频率f>>f0时(f0 为截止频率),电路的每级RC 电路的相移趋于-90º,两级RC 电路的移相到-180º,电路的输出电压Vout与输入电压Vin的相位相反,故此时通过电容CC2引到集成运放同相端的反馈是负反馈,反馈信号将起着削弱输入信号的作用,使电压放大倍数减小,所以该反馈将使二阶有源低通滤波器的幅频特性高频端迅速衰减,只允许低频端信号通过。其特点是输入阻抗高,输出阻抗低。
下图是低通滤波器的频率特性曲线
我们对电流采样的同时也对电网负载的电压进行实时采集,就是说电压和电流是同步采集。
具体原理如下
电网负载电压LOAD_VCC经过电阻VR2、VR1、VR1_ADJ分压,把电网的高电压变成低电压给运放U4滤波采集,和上面的电流采样原理一样
下图是电压采样频率特性图
最后是功率数据处理
我们采用DMA采样并传输数据
通过调整缓冲区大小,可调整DMA中断周期
具体的功率计算如下
瞬时功率
平均功率
总功率
源码分析,ADC初始化
void ADC1_Mode_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
//DMA1 通道1
/* DMA1 channel1 configuration */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_VAL;//
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//从外设读取数据
DMA_InitStructure.DMA_BufferSize = (CHANNEL*BUFFER_SIZE);//3KB (HW)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//DMA地址增加
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16bit
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_ClearITPendingBit(DMA1_IT_TC1);
DMA_ITConfig(DMA1_Channel1,DMA1_IT_TC1,ENABLE);//DMA1传输完成中断
/* Enable DMA channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC1 configuration */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC独立转换模式,相对于双重模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 2;
ADC_Init(ADC1, &ADC_InitStructure);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5);
// ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_28Cycles5);
/* ADC1 regular channel configuration */
//AD采样率为12000K/(7.5+12.5)=600K
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_7Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
上面也说了我们采用DMA中断来采集
//DMA1中断优先级最高(约5.3ms)
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//DMA1 中断服务程序
void DMA1_Channel1_IRQHandler()
{
if(DMA_GetITStatus(DMA1_IT_TC1))
{
DMA_ClearITPendingBit(DMA1_IT_TC1);
//CALIBRATE_U_I();//校准模式
CALCULATE_POWER();//计算功率模式
}
}
计算功率
//瞬时功率
INSTANT_POWER_W = (double)INSTANT_POWER*CONVERT_FACTOR_P_5_A;
//平均功率
AVE_POWER = INSTANT_POWER_SUM/CYCLE_COUNT;
AVE_POWER_W = (double)AVE_POWER*CONVERT_FACTOR_P_5_A;
SUM_OF_POWER += AVE_POWER;
//总功率
SUM_OF_POWER_WH = (double)SUM_OF_POWER*CONVERT_FACTOR_P_5_A*CONVERT_FACTOR_WH;
// printf("INSTANT_POWER_W: %f\r\n",INSTANT_POWER_W);
// printf("AVE_POWER_W: %f\r\n",AVE_POWER_W);
// printf("SUM_OF_POWER_WH: %.10f\r\n",SUM_OF_POWER_WH);
printf("p: %.3fw P: %.3fw W: %.3fwh\r\n",INSTANT_POWER_W,AVE_POWER_W,SUM_OF_POWER_WH);