加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C中任何更快的RMS值计算?

发布时间:2020-12-16 04:57:13 所属栏目:百科 来源:网络整理
导读:我正在用C编写一个小型8位微控制器的软件.部分代码是读取电流互感器(ZCT)的ADC值,然后计算RMS值.流过ZCT的电流是正弦曲线但可能会失真.我的代码如下: float adc_value,inst_current;float acc_load_current; // accumulator = (I1*I1 + I2*I2 + ... + In*In
我正在用C编写一个小型8位微控制器的软件.部分代码是读取电流互感器(ZCT)的ADC值,然后计算RMS值.流过ZCT的电流是正弦曲线但可能会失真.我的代码如下:
float       adc_value,inst_current;
float       acc_load_current;           // accumulator = (I1*I1 + I2*I2 + ... + In*In)
double      rms_current;

// Calculate the real instantanous value from the ADC reading
inst_current = (adc_value/1024)*2.5;    // 10bit ADC,Voltage ref. 2.5V,so formula is: x=(adc/1024)*2.5V                           

// Update the RMS value with the new instananous value:
// Substract 1 sample from the accumulator (sample size is 512,so divide accumulator by 512 and substract it from the accumulator)
acc_load_current -= (acc_load_current / 512);       
inst_current *= inst_current;          // square the instantanous current
acc_load_current += inst_current;      // Add it to the accumulator

rms_current = (acc_load_current / 512);  // Get the mean square value. (sample size is 512)
rms_current = sqrt(rms_current);         // Get RMS value

// Now the < rms_current > is the real RMS current

但是,它有许多浮点计算.这给我的小型MCU增加了很大的负担.我发现sqrt()函数在我的编译器中不起作用.

有没有可以运行得更快的代码?

解决方法

如果您需要在缺少FPU的处理器上加快速度,那就最好了
赌注是用固定点替换浮点计算.结合
这与joop的建议(一个Newton-Raphson sqrt)你得到了
像这样的东西:
#define INITIAL 512  /* Initial value of the filter memory. */
#define SAMPLES 512

uint16_t rms_filter(uint16_t sample)
{
    static uint16_t rms = INITIAL;
    static uint32_t sum_squares = 1UL * SAMPLES * INITIAL * INITIAL;

    sum_squares -= sum_squares / SAMPLES;
    sum_squares += (uint32_t) sample * sample;
    if (rms == 0) rms = 1;    /* do not divide by zero */
    rms = (rms + sum_squares / SAMPLES / rms) / 2;
    return rms;
}

只需通过此过滤器运行原始ADC样本即可.你可以添加一些
在这里和那里进行位移以获得更高的分辨率,但你必须这样做
小心不要溢出你的变量.我怀疑你真的需要
额外的决议.

滤波器的输出与其输入的单位相同.在这种情况下,
它是你的ADC的单位:
2.5 V / 1024≈2.44毫伏.如果你能保持
在后续计算中,您将通过避免来节省周期
不必要的转换.如果你真的需要以伏特为单位的值(它
可能是I / O要求),那么你将不得不转换为浮动
点.如果你想要毫伏,你可以保持整数范围:

uint16_t rms_in_mV = rms_filter(raw_sample) * 160000UL >> 16;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读