【问题标题】:Calculating RMS using fixed point math (C)使用定点数学计算 RMS (C)
【发布时间】:2015-06-10 12:53:07
【问题描述】:

我正在尝试计算波形的 RMS 值,但遇到了一些问题。

我每 x 微秒采样一次,这是由中断触发的。样本存储在一个数组中,每次取一个样本时,它会将最后一个值推到数组中的下一个点并输入一个新值。当我取样本时,我将它平方并除以 20(每个样本的数量周期,假设波形固定频率)然后将其放入我的数组中,我还将它添加到一个总和值,当我达到 20 个样本时,我减去第一个样本并添加最后一个样本。

value 20 = value 19   //INT16 values
value 19 = value 18
...
value1 = (sample * sample)/20
sumvalue += value1
sumvalue -= value20

然后我调用一个 RMS 函数,它取该值,除以最后计算的 RMS 值(或者如果尚未计算,则除以 1)加上最后一个 RMS 值,然后将所有值除以 2。

CalcRMS(sumvalue)
INT32 tempsum
if(RMS)
tempsum = (sumvalue/RMS + RMS)/2
else
tempsum = (sumvalue + 1)/2
RMS = tempsum

然后我将 RMS 输出到屏幕。唯一的问题是我的 RMS 值一直在变化,即使波形是恒定的。如果我在那里运行一个直流值,我的 RMS 会保持稳定,但会以正弦波推进,它会发疯。

希望有人能指出我正确的方向。我不希望直接得到答案,只是一些轻推让我回到正轨。

【问题讨论】:

  • 我不确定最后两个 RMS 值之间的平均值,因为这会在帧之间增加额外的“平均值”计算。由于您正在处理定点数,因此您可能想测试是否出现溢出错误。为此,请尝试使用较低幅度的正弦波馈送您的算法。最后,这可能会有所帮助:stackoverflow.com/questions/1058813/… 以及:en.wikipedia.org/wiki/Algorithms_for_calculating_variance
  • 这种代码:'value 20 = value 19 //INT16 values value 19 = value 18 ...'是一个巨大的CPU周期浪费。相反,请使用循环队列。
  • 可能花费的时间太长,并且在班次中途再次调用了中断。我将尝试将值放入缓冲区并使用指针来索引值。
  • 20 个样本不足以获得准确的读数,您的描述正是我所期望的。你基本上得到了波形的随机部分。除非您的读数被计时以精确覆盖单波交流电。
  • 如果你想想收敛到一个稳定值意味着什么,它意味着你的 value1 = value20。给定 x[i] = sin(t[i]) 和 value=x*x/20,这对关于谐波函数周期的采样率提出了非常具体的要求。换言之,t[1] 和 t[20] 必须相对于正弦曲线落在同一位置。这有意义吗?

标签: c fixed-point rms


【解决方案1】:

好吧,这个函数并不真正计算 RMS。

您是否查看过 sumvalue 如何随时间变化? sumvalue 在直流和符号情况下必须保持一定的常数。如果不是,则进行求和的例程有问题。如果总和值是恒定的,那么您的 RMS 程序有问题。

【讨论】:

    【解决方案2】:

    如果代码对数据的采样频率足够高,求最小值,求最大值,求中值 = (min+max)/2,求 RMS = (max-median)*.707

    如果代码没有足够频繁地对数据进行采样,则使用快速 forier(拼写)转换来查找最小值/最大值。

    【讨论】:

    • 代码对完整波形进行采样,但由于 MCU 没有 FPU,我无法使用十进制值,因为执行时间太长。
    【解决方案3】:

    除了您没有计算 RMS(sqrt 在哪里?)以及您计算 RMS 的算法似乎不正确之外,由于采样,采样的 RMS 值预计会在一个范围内振荡.您尚未指定要采样的正弦波的频率,也没有证明 20 个值足以避免混叠。如果您知道正弦波的周期并将其除以 20,那么您的 RMS 值将不会振荡。

    此外,您的代码是高度不可扩展的 - 当您意识到需要保留 200 个值(或 2000 个)时,想象一下您的 value1、value2、...、value20 方法的痛苦!

    这是一个示例 Python 脚本,您可以使用它:

       i = 0
       x = 0
       values = []
       sampleSize = 20
       while True:
          y = math.sin(x)
          y = y*y/sampleSize
          values.append(y)
          if(len(values) > sampleSize):
             values.pop(0)
          val = sum(values)
          print(math.sqrt(val))
          x += 8*math.atan(1)/sampleSize
          i += 1
    

    【讨论】:

    • 在几个周期后,计算给出了 RMS 的近似值,该值应该是恒定的。我不能使用浮点数,因为没有 FPU 并且它引入了高开销。
    • 这取决于正弦波的周期和采样率。如果 20 个样本仅覆盖周期的一小部分 - RMS 值将不断变化。
    • 正确。我应该把它放在原始帖子中,这 20 个样本涵盖了整个波形周期。
    猜你喜欢
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    相关资源
    最近更新 更多