前言:我們需要思考在AI時(shí)代如何提升工作效率,可以把一些事情丟給AI來解放生產(chǎn)力,在AI不能完全代替人的現(xiàn)在情況下,讓它做一些打雜的事情還是可以的。于是我編寫了一段計(jì)算AC 有效值、平均值、頻率的代碼,一行注釋也沒有,發(fā)給Deepseek后,他加上了注釋,還分析了我寫的代碼,請(qǐng)看:
/*
* @brief 計(jì)算交流信號(hào)的RMS值、平均值和頻率,使用狀態(tài)機(jī)跟蹤過零點(diǎn)和半周期
* @param p 包含計(jì)算所需狀態(tài)和數(shù)據(jù)的結(jié)構(gòu)體指針
* @param ac_input 當(dāng)前采樣點(diǎn)的交流輸入值
* @param ts 采樣時(shí)間間隔(單位:秒)
* @return float32_t 經(jīng)過濾波處理后的RMS平均值
* @note 采用滑動(dòng)窗口算法和低通濾波算法提高測(cè)量穩(wěn)定性
* 狀態(tài)機(jī)實(shí)現(xiàn)過零點(diǎn)檢測(cè)和周期測(cè)量,支持45-65Hz動(dòng)態(tài)頻率調(diào)整
*/
static inline float32_t ac_rms_avg_freq_caluc_func(AC_AVG_CALUC_DEF *p,
float32_t ac_input,
float32_t ts)
{
/* 過零檢測(cè)閾值定義(單位:伏特) */
const float32_t threshold_PZC1 = -5.0f; /* 正半周過零點(diǎn)1閾值 */
const float32_t threshold_PZC2 = 5.0f; /* 正半周過零點(diǎn)2閾值 */
const float32_t threshold_NZC1 = 5.0f; /* 負(fù)半周過零點(diǎn)1閾值 */
const float32_t threshold_NZC2 = -5.0f; /* 負(fù)半周過零點(diǎn)2閾值 */
/* 動(dòng)態(tài)調(diào)整時(shí)間增益系數(shù)(基于當(dāng)前平均頻率) */
if ((p->ac_freq_avg > 45.0f) && (p->ac_freq_avg < 65.0f)) {
/* 計(jì)算理論半周期增益: 2*Freq*Ts = 1/(半周期樣本數(shù)) */
p->TS_half_gain = p->ac_freq_avg * 2.0f * ts;
} else {
/* 默認(rèn)增益對(duì)應(yīng)50Hz: 50*2*0.0001s=0.01 → 1/0.01=100樣本/半周期 */
p->TS_half_gain = 0.02f;
}
/* 狀態(tài)機(jī)處理交流信號(hào)波形 */
switch (p->ac.enum_ac_State) {
case ac_normal: /* 初始狀態(tài):檢測(cè)首個(gè)過零點(diǎn) */
if (ac_input < threshold_PZC1) {
p->ac.enum_ac_State = ac_positiveZeroCrossing1;
}
break;
case ac_positiveZeroCrossing1: /* 正半周過零階段1 */
if (ac_input > threshold_PZC1) {
p->ac.enum_ac_State = ac_positiveZeroCrossing2;
p->ac_freq_count += 1u; /* 開始周期計(jì)時(shí) */
}
break;
case ac_positiveZeroCrossing2: /* 正半周過零階段2 */
if (ac_input > threshold_PZC2) {
p->ac.enum_ac_State = ac_positiveHalf;
p->ac_freq_count += 1u; /* 繼續(xù)周期計(jì)時(shí) */
}
break;
case ac_positiveHalf: /* 正半周處理 */
/* 平方累加用于RMS計(jì)算 */
p->ac_rms[0] += (ac_input * ac_input);
/* 滑動(dòng)窗口:保留最近4個(gè)采樣窗口的平方和 */
p->ac_rms[4] = p->ac_rms[3];
p->ac_rms[3] = p->ac_rms[2];
p->ac_rms[2] = p->ac_rms[1];
p->ac_rms[1] = p->ac_rms[0];
/* 正半周平均值計(jì)算(滑動(dòng)窗口) */
p->pos_half_avg[1] += ac_input;
p->pos_half_avg[5] = p->pos_half_avg[4];
p->pos_half_avg[4] = p->pos_half_avg[3];
p->pos_half_avg[3] = p->pos_half_avg[2];
p->pos_half_avg[2] = p->pos_half_avg[1];
p->ac_freq_count += 1u; /* 累計(jì)周期采樣數(shù) */
/* 檢測(cè)負(fù)半周過零點(diǎn) */
if (ac_input < threshold_NZC1) {
p->ac.enum_ac_State = ac_negativeZeroCrossing1;
/* 重置RMS歷史窗口(保留當(dāng)前窗口ac_rms[0]) */
for (uint16_t i = 1; i < 4; i++) {
p->ac_rms[i] = 0;
}
/* 計(jì)算正半周平均值(5點(diǎn)加權(quán)平均) */
p->pos_half_avg[0] = 0.1f * p->TS_half_gain
* (p->pos_half_avg[1] + p->pos_half_avg[2]
+ p->pos_half_avg[3] + p->pos_half_avg[4]
+ p->pos_half_avg[5]);
/* 更新整體平均值 */
p->ac_avg = (p->pos_half_avg[0] + p->neg_half_avg[0]);
/* 清空負(fù)半周歷史數(shù)據(jù) */
for (uint16_t i = 1; i < 5; i++) {
p->neg_half_avg[i] = 0;
}
}
break;
case ac_negativeZeroCrossing1: /* 負(fù)半周過零階段1 */
if (ac_input < threshold_NZC1) {
p->ac.enum_ac_State = ac_negativeZeroCrossing2;
p->ac_freq_count += 1u;
}
break;
case ac_negativeZeroCrossing2: /* 負(fù)半周過零階段2 */
if (ac_input < threshold_NZC2) {
p->ac.enum_ac_State = ac_negativeHalf;
p->ac_freq_count += 1u;
}
break;
case ac_negativeHalf: /* 負(fù)半周處理 */
/* 平方累加用于RMS計(jì)算 */
p->ac_rms[0] += (ac_input * ac_input);
/* 滑動(dòng)窗口更新 */
p->ac_rms[4] = p->ac_rms[3];
p->ac_rms[3] = p->ac_rms[2];
p->ac_rms[2] = p->ac_rms[1];
p->ac_rms[1] = p->ac_rms[0];
/* 負(fù)半周平均值計(jì)算(滑動(dòng)窗口) */
p->neg_half_avg[1] += ac_input;
p->neg_half_avg[5] = p->neg_half_avg[4];
p->neg_half_avg[4] = p->neg_half_avg[3];
p->neg_half_avg[3] = p->neg_half_avg[2];
p->neg_half_avg[2] = p->neg_half_avg[1];
p->ac_freq_count += 1u;
/* 檢測(cè)正半周過零點(diǎn)(完成一個(gè)完整周期) */
if (ac_input > threshold_PZC1) {
p->ac.enum_ac_State = ac_positiveZeroCrossing1;
/* RMS計(jì)算流程:
* 1. 對(duì)5個(gè)窗口的平方和取平均(0.2系數(shù))
* 2. 乘以半周期時(shí)間增益和0.5(整合正負(fù)半周)
* 3. 取平方根得到RMS
*/
p->ac_rms_avg = sqrtf(p->TS_half_gain * 0.5f *
(0.2f * (p->ac_rms[0] + p->ac_rms[1]
+ p->ac_rms[2] + p->ac_rms[3]
+ p->ac_rms[4])));
/* 重置RMS窗口(保留當(dāng)前窗口用于下次計(jì)算) */
for (uint16_t i = 0; i < 4; i++) {
p->ac_rms[i] = 0;
}
/* 計(jì)算負(fù)半周平均值(5點(diǎn)加權(quán)平均) */
p->neg_half_avg[0] = 0.1f * p->TS_half_gain
* (p->neg_half_avg[1] + p->neg_half_avg[2]
+ p->neg_half_avg[3] + p->neg_half_avg[4]
+ p->neg_half_avg[5]);
/* 更新整體平均值 */
p->ac_avg = (p->pos_half_avg[0] + p->neg_half_avg[0]);
/* 清空正半周歷史數(shù)據(jù) */
for (uint16_t i = 1; i < 5; i++) {
p->pos_half_avg[i] = 0;
}
/* 頻率計(jì)算流程:
* 1. 當(dāng)前頻率 = 1/(總采樣數(shù) * 采樣時(shí)間)
* 2. 使用5點(diǎn)滑動(dòng)窗口平均
* 3. 一階低通濾波平滑
*/
p->ac_freq[0] = 1.0f / (ts * p->ac_freq_count);
/* 更新頻率滑動(dòng)窗口 */
p->ac_freq[4] = p->ac_freq[3];
p->ac_freq[3] = p->ac_freq[2];
p->ac_freq[2] = p->ac_freq[1];
p->ac_freq[1] = p->ac_freq[0];
/* 5點(diǎn)平均(權(quán)重總和為1) */
p->ac_freq_avg = 0.2f * (p->ac_freq[0] + p->ac_freq[1]
+ p->ac_freq[2] + p->ac_freq[3]
+ p->ac_freq[4]);
p->ac_freq_count = 0u; /* 重置周期計(jì)數(shù)器 */
}
break;
default: /* 異常狀態(tài)恢復(fù) */
p->ac.enum_ac_State = ac_normal;
break;
}
/* 低通濾波處理(截止頻率20Hz) */
p->ac_freq_avg = lpf_1order_func(p->ac_freq_avg, &(p->freq_lpf), 20.0f, ts);
p->ac_rms_avg = lpf_1order_func(p->ac_rms_avg, &(p->rms_lpf_out), 20.0f, ts);
p->ac_avg = lpf_1order_func(p->ac_avg, &(p->avg_lpf_out), 20.0f, ts);
return p->ac_rms_avg; /* 返回濾波后的RMS值 */
}
下面 請(qǐng)看DS的解釋:
交流信號(hào)RMS與平均值計(jì)算實(shí)現(xiàn)文檔
版本:1.0 | 最后更新:2023-12-15
作者:智能助手 | 關(guān)鍵詞:交流信號(hào)處理、RMS計(jì)算、滑動(dòng)窗口算法、過零檢測(cè)
目錄
-
設(shè)計(jì)目標(biāo)
-
核心算法流程
-
有效值(RMS)計(jì)算方法
-
平均值計(jì)算方法
-
頻率測(cè)量原理
-
關(guān)鍵參數(shù)說明
-
應(yīng)用示例
-
性能特性
1. 設(shè)計(jì)目標(biāo)
本算法實(shí)現(xiàn)以下功能:
- 實(shí)時(shí)計(jì)算交流信號(hào)的:
- 有效值(True RMS)
- 整流平均值(Average Value)
- 基波頻率(Fundamental Frequency)
- 支持動(dòng)態(tài)頻率跟蹤(45-65Hz自適應(yīng))
- 采用抗噪設(shè)計(jì):
- 滑動(dòng)窗口平均
- 低通濾波處理
- 滯回過零檢測(cè)
2. 核心算法流程
3. 有效值(RMS)計(jì)算方法
VRMS=1T∫0Tv(t)2dt
3.3 動(dòng)態(tài)調(diào)整機(jī)制
- 窗口長(zhǎng)度自適應(yīng):
if(freq在45-65Hz范圍){
TS_half_gain = 2 * Freq * Ts; // 動(dòng)態(tài)調(diào)整
}else{
TS_half_gain = 0.02; // 50Hz默認(rèn)值
}
確保不同頻率下積分時(shí)間恒定
4. 平均值計(jì)算方法
4.1 設(shè)計(jì)特點(diǎn)
- 分離正/負(fù)半周計(jì)算
- 采用整流平均值(Rectified Average)
- 滑動(dòng)窗口降噪
4.2 計(jì)算流程
4.3 關(guān)鍵代碼
// 正半周處理
p->pos_half_avg[1] += ac_input; // 實(shí)時(shí)累加
p->pos_half_avg[0] = 0.1f * TS_half_gain * sum(pos_half_avg[1]~[5]);
// 負(fù)半周處理
p->neg_half_avg[1] += ac_input;
p->neg_half_avg[0] = 0.1f * TS_half_gain * sum(neg_half_avg[1]~[5]);
// 合并結(jié)果
p->ac_avg = pos_half_avg[0] + neg_half_avg[0];
4.4 數(shù)學(xué)關(guān)系
Vavg=2Vpπ≈0.6366V
5.1 周期測(cè)量法
實(shí)現(xiàn)步驟:
- 過零點(diǎn)觸發(fā)計(jì)時(shí)
- 統(tǒng)計(jì)兩個(gè)過零點(diǎn)間的采樣數(shù)
- 計(jì)算 Freq = 1/(N * Ts)
5.2 抗干擾設(shè)計(jì)
6. 關(guān)鍵參數(shù)說明
6.1 閾值參數(shù)
6.2 濾波器參數(shù)
7. 應(yīng)用示例
7.1 輸入信號(hào)
- 波形:V(t) = 311 sin(2pi*50t) (220V RMS)
- 采樣率:10kHz(Ts=0.0001s)
7.2 計(jì)算過程
8. 性能特性
楊帥鍋時(shí)間:
總的來看,deepseek的理解了我的編寫的函數(shù)功能和實(shí)現(xiàn)原理,也給出了正確的分析,也幫我增加注釋。下面是仿真和測(cè)試,在PLECS 仿真軟件里面使用C腳本可以直接支持C99的C語言編碼,可見測(cè)試模型:
我使用一個(gè)帶高次諧波和直流偏置的多個(gè)正弦波疊加,用于測(cè)試RMS,直流偏置,頻率的數(shù)據(jù),下圖是在50HZ/峰峰值300.0,直流偏置0的標(biāo)準(zhǔn)正弦波的情況下測(cè)試,可見函數(shù)計(jì)算的頻率、有效值、直流分量都是正確的。
在考慮各種疊加高次諧波和直流偏置的情況下,可見:
波形:
通過測(cè)試可見,這代AC分析算法,可以很好的適用于各種正弦周期信號(hào)的分析和計(jì)算中,在PFC/逆變器的控制上有較多的可用性。為了優(yōu)化計(jì)算了,僅在狀態(tài)機(jī)的過零穿越點(diǎn)進(jìn)行了一次總體數(shù)據(jù)計(jì)算,大量的簡(jiǎn)約了CPU的時(shí)鐘開銷,對(duì)于節(jié)約成本和優(yōu)化代碼有意義。本人能力有限,如有錯(cuò)誤懇請(qǐng)幫忙指正,感謝支持感謝幫助,謝謝。C代碼和PLECS模型下載:AC_RMS_AVG_FREQ_250302