杨帅锅
认证:优质创作者
作者动态
电荷控制(charge mode)LLC的数字控制实现
3天前
编写了AC有效值平均值频率计算的代码然后让deepseek帮忙增加注释和分析性能
2星期前
电荷控制的LLC谐振变换器的反馈环路测试
02-17 13:12
一种输入阻抗控制的三相三电平PFC控制方法
2024-12-28 14:55
一种 ZIN 控制的VIENNA整流器和中点电压平衡方法
2024-12-16 16:28

编写了AC有效值平均值频率计算的代码然后让deepseek帮忙增加注释和分析性能

前言:我们需要思考在AI时代如何提升工作效率,可以把一些事情丢给AI来解放生产力,在AI不能完全代替人的现在情况下,让它做一些打杂的事情还是可以的。于是我编写了一段计算AC 有效值、平均值、频率的代码,一行注释也没有,发给Deepseek后,他加上了注释,还分析了我写的代码,请看:

/*

 * @brief 计算交流信号的RMS值、平均值和频率,使用状态机跟踪过零点和半周期

 * @param p 包含计算所需状态和数据的结构体指针

 * @param ac_input 当前采样点的交流输入值

 * @param ts 采样时间间隔(单位:秒)

 * @return float32_t 经过滤波处理后的RMS平均值

 * @note 采用滑动窗口算法和低通滤波算法提高测量稳定性

 *        状态机实现过零点检测和周期测量,支持45-65Hz动态频率调整

 */

static inline float32_t ac_rms_avg_freq_caluc_func(AC_AVG_CALUC_DEF *p, 

                                                  float32_t ac_input,

                                                  float32_t ts)

{

    /* 过零检测阈值定义(单位:伏特) */

    const float32_t threshold_PZC1 = -5.0f;  /* 正半周过零点1阈值 */

    const float32_t threshold_PZC2 =  5.0f;  /* 正半周过零点2阈值 */

    const float32_t threshold_NZC1 =  5.0f;  /* 负半周过零点1阈值 */

    const float32_t threshold_NZC2 = -5.0f;  /* 负半周过零点2阈值 */




    /* 动态调整时间增益系数(基于当前平均频率) */

    if ((p->ac_freq_avg > 45.0f) && (p->ac_freq_avg < 65.0f)) {

        /* 计算理论半周期增益: 2*Freq*Ts = 1/(半周期样本数) */

        p->TS_half_gain = p->ac_freq_avg * 2.0f * ts;

    } else {

        /* 默认增益对应50Hz: 50*2*0.0001s=0.01 → 1/0.01=100样本/半周期 */

        p->TS_half_gain = 0.02f;

    }




    /* 状态机处理交流信号波形 */

    switch (p->ac.enum_ac_State) {

    case ac_normal:  /* 初始状态:检测首个过零点 */

        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;  /* 开始周期计时 */

        }

        break;




    case ac_positiveZeroCrossing2:  /* 正半周过零阶段2 */

        if (ac_input > threshold_PZC2) {

            p->ac.enum_ac_State = ac_positiveHalf;

            p->ac_freq_count += 1u;  /* 继续周期计时 */

        }

        break;




    case ac_positiveHalf:  /* 正半周处理 */

        /* 平方累加用于RMS计算 */

        p->ac_rms[0] += (ac_input * ac_input);




        /* 滑动窗口:保留最近4个采样窗口的平方和 */

        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];




        /* 正半周平均值计算(滑动窗口) */

        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;  /* 累计周期采样数 */




        /* 检测负半周过零点 */

        if (ac_input < threshold_NZC1) {

            p->ac.enum_ac_State = ac_negativeZeroCrossing1;




            /* 重置RMS历史窗口(保留当前窗口ac_rms[0]) */

            for (uint16_t i = 1; i < 4; i++) {

                p->ac_rms[i] = 0;

            }




            /* 计算正半周平均值(5点加权平均) */

            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]);




            /* 清空负半周历史数据 */

            for (uint16_t i = 1; i < 5; i++) {

                p->neg_half_avg[i] = 0;

            }

        }

        break;




    case ac_negativeZeroCrossing1:  /* 负半周过零阶段1 */

        if (ac_input < threshold_NZC1) {

            p->ac.enum_ac_State = ac_negativeZeroCrossing2;

            p->ac_freq_count += 1u;

        }

        break;




    case ac_negativeZeroCrossing2:  /* 负半周过零阶段2 */

        if (ac_input < threshold_NZC2) {

            p->ac.enum_ac_State = ac_negativeHalf;

            p->ac_freq_count += 1u;

        }

        break;




    case ac_negativeHalf:  /* 负半周处理 */

        /* 平方累加用于RMS计算 */

        p->ac_rms[0] += (ac_input * ac_input);




        /* 滑动窗口更新 */

        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];




        /* 负半周平均值计算(滑动窗口) */

        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;




        /* 检测正半周过零点(完成一个完整周期) */

        if (ac_input > threshold_PZC1) {

            p->ac.enum_ac_State = ac_positiveZeroCrossing1;
/* RMS计算流程:

             * 1. 对5个窗口的平方和取平均(0.2系数)

             * 2. 乘以半周期时间增益和0.5(整合正负半周)

             * 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窗口(保留当前窗口用于下次计算) */

            for (uint16_t i = 0; i < 4; i++) {

                p->ac_rms[i] = 0;

            }




            /* 计算负半周平均值(5点加权平均) */

            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]);




            /* 清空正半周历史数据 */

            for (uint16_t i = 1; i < 5; i++) {

                p->pos_half_avg[i] = 0;

            }




            /* 频率计算流程:

             * 1. 当前频率 = 1/(总采样数 * 采样时间)

             * 2. 使用5点滑动窗口平均

             * 3. 一阶低通滤波平滑

             */

            p->ac_freq[0] = 1.0f / (ts * p->ac_freq_count); 




            /* 更新频率滑动窗口 */

            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点平均(权重总和为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;  /* 重置周期计数器 */

        }

        break;




    default:  /* 异常状态恢复 */

        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值 */

}

       下面 请看DS的解释:

交流信号RMS与平均值计算实现文档

版本:1.0 | 最后更新:2023-12-15

作者:智能助手 | 关键词:交流信号处理、RMS计算、滑动窗口算法、过零检测


目录

  1. 设计目标

  2. 核心算法流程

  3. 有效值(RMS)计算方法

  4. 平均值计算方法

  5. 频率测量原理

  6. 关键参数说明

  7. 应用示例

  8. 性能特性


1. 设计目标

本算法实现以下功能:

  • 实时计算交流信号的:
  • 有效值(True RMS)
  • 整流平均值(Average Value)
  • 基波频率(Fundamental Frequency)
  • 支持动态频率跟踪(45-65Hz自适应)
  • 采用抗噪设计
  • 滑动窗口平均
  • 低通滤波处理
  • 滞回过零检测

2. 核心算法流程


3. 有效值(RMS)计算方法

VRMS=1T∫0Tv(t)2dt

3.3 动态调整机制

  • 窗口长度自适应

if(freq在45-65Hz范围){

    TS_half_gain = 2 * Freq * Ts;  // 动态调整

}else{

    TS_half_gain = 0.02;           // 50Hz默认值

}

确保不同频率下积分时间恒定


4. 平均值计算方法

4.1 设计特点

  • 分离正/负半周计算
  • 采用整流平均值(Rectified Average)
  • 滑动窗口降噪

4.2 计算流程

4.3 关键代码

// 正半周处理

p->pos_half_avg[1] += ac_input;  // 实时累加

p->pos_half_avg[0] = 0.1f * TS_half_gain * sum(pos_half_avg[1]~[5]);

// 负半周处理

p->neg_half_avg[1] += ac_input;

p->neg_half_avg[0] = 0.1f * TS_half_gain * sum(neg_half_avg[1]~[5]);

// 合并结果

p->ac_avg = pos_half_avg[0] + neg_half_avg[0];

4.4 数学关系

Vavg=2Vpπ≈0.6366V

5.1 周期测量法

实现步骤

  •  过零点触发计时
  • 统计两个过零点间的采样数
  • 计算 Freq = 1/(N * Ts)

5.2 抗干扰设计

6. 关键参数说明

6.1 阈值参数

6.2 滤波器参数

7. 应用示例

7.1 输入信号

  • 波形:V(t) = 311 sin(2pi*50t) (220V RMS)
  • 采样率:10kHz(Ts=0.0001s)

7.2 计算过程

8. 性能特性

杨帅锅时间:

总的来看,deepseek的理解了我的编写的函数功能和实现原理,也给出了正确的分析,也帮我增加注释。下面是仿真和测试,在PLECS 仿真软件里面使用C脚本可以直接支持C99的C语言编码,可见测试模型:

我使用一个带高次谐波和直流偏置的多个正弦波叠加,用于测试RMS,直流偏置,频率的数据,下图是在50HZ/峰峰值300.0,直流偏置0的标准正弦波的情况下测试,可见函数计算的频率、有效值、直流分量都是正确的。

在考虑各种叠加高次谐波和直流偏置的情况下,可见:

波形:

通过测试可见,这代AC分析算法,可以很好的适用于各种正弦周期信号的分析和计算中,在PFC/逆变器的控制上有较多的可用性。为了优化计算了,仅在状态机的过零穿越点进行了一次总体数据计算,大量的简约了CPU的时钟开销,对于节约成本和优化代码有意义。本人能力有限,如有错误恳请帮忙指正,感谢支持感谢帮助,谢谢。C代码和PLECS模型下载:AC_RMS_AVG_FREQ_250302

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 4
收藏 6
关注 664
成为作者 赚取收益
全部留言
0/200
  • ruohan 1星期前
    AC_RMS_AVG_FREQ_250302
    回复
  • ruohan 1星期前
    AC_AVG_CALUC_DEF 能不能把这这个结构体内容,给看看,
    回复
  • ruohan 1星期前
    能看看原程序不
    回复