【问题标题】:Simple signal processing in C#C#中的简单信号处理
【发布时间】:2009-08-29 15:19:20
【问题描述】:

我正在对真实世界的传感器进行采样,我需要显示其过滤值。信号以 10 Hz 的速率进行采样,在此期间它可能会上升到最大范围的 80%。

之前我使用均方根作为过滤器,并将其应用于我记录的最后五个值。对于这个应用程序,这并不好,因为我不存储未更改的值。换句话说,我需要在过滤器中考虑时间...

我在DSP Guide 上阅读过,但我并没有从中得到什么。是否有专门针对程序员而非Mathcad 工程师的教程?是否有一些简单的代码 sn-ps 可以提供帮助?

更新:经过几次电子表格测试后,我决定记录所有样本,并申请 Butterworth filter

【问题讨论】:

  • 所以只计算最后五个值的问题是它们不能反映实时,因为未记录未更改的数据?我理解正确吗?

标签: c# signal-processing


【解决方案1】:

你总是需要存储一些值(但不一定 所有输入值)。滤波器的电流输出取决于 输入值的数量,可能还有一些过去的输出值。

最简单的滤波器是一阶巴特沃斯低通滤波器 筛选。这只需要您存储一个过去的输出 价值。滤波器的(当前)输出 y(n) 为:

y(n) = x(n) - a1 * y(n-1)

其中 x(n) 是当前输入,y(n-1) 是前一个 滤波器的输出。 a1 取决于截止频率 和采样频率。截止频率频率 必须小于 5 Hz(采样频率的一半), 足够低以滤除噪声,但不是那么低 输出将相对于输入延迟。和的 当然不能低到过滤掉真实信号!

在代码中(主要是 C#):

double a1 = 0.57; //0.57 is just an example value.
double lastY = 0.0;
while (true)
{
    double x = <get an input value>;

    double y = x - a1 * lastY;

    <Use y somehow>

    lastY = y;
}

一阶过滤器是否足够取决于您的 要求和输入信号的特性(一 高阶滤波器可能能够抑制更多的 噪声的代价是输出信号的延迟更高)。

对于更高阶的过滤器,需要存储更多的值 并且代码变得有点复杂。通常 这些值需要在数组中向下移动;在一个数组中 过去的 y 值和过去 x 值的数组。

【讨论】:

  • 是过滤器吗?结果数据 (y) 将与 x 相同,但 a1*lastY 更少。此处未过滤任何内容。
【解决方案2】:

在 DSP 中,术语“滤波器”通常是指放大或衰减(即“降低”)连续信号中的频率分量。这通常使用快速傅里叶变换 (FFT) 来完成。 FFT 从在给定时间长度内记录的信号开始(数据在所谓的“时域”中)并将这些值转换为所谓的“频域”,其中结果表示一系列信号的强度频率“箱”的范围从 0 Hz 到采样率(在您的情况下为 10 Hz)。因此,作为一个粗略的例子,一秒钟的数据(10 个样本)的 FFT 将告诉您信号在 0-2 Hz、2-4 Hz、4-6 Hz、6-8 Hz 和8-10 赫兹。

要“过滤”这些数据,您需要增加或减少任何或所有这些信号强度值,然后执行反向 FFT 以将这些值转换回时域信号。因此,例如,假设您想对转换后的数据进行低通滤波器,其中截止频率为 6 Hz(换句话说,您想去除信号中高于 6 Hz 的任何频率分量)。您将以编程方式将 6-8 Hz 值设置为零并将 8-10 Hz 值设置为 0,然后执行反向 FFT。

我之所以提到这一切,是因为听起来“过滤”并不是您真正想要在这里做的。我认为您只想显示传感器的当前值,但您希望平滑结果,使其不会过度响应传感器测量值的瞬态波动。做到这一点的最佳方法是使用简单的移动平均值,可能较新的值比旧值的权重更大。

通过存储最新测量值的集合,运行平均值非常容易编程(比 FFT 容易得多,相信我)。您提到您的应用仅存储与先前值不同的值。假设您还存储了记录每个值的时间,那么您的运行平均代码应该很容易通过使用记录的先前值来填充“缺失值”。

【讨论】:

  • 你说得对,我不想搞乱 FFT。我不介意数学或其他任何东西,但是当我看到 FFT 实现(或函数)时,我感到后背不寒而栗。
  • 这真的很有趣,一旦你克服了最初的痛苦,就信号处理而言,它打开了许多大门。
  • 运行平均值一个过滤器。这是一个简单的过滤器,但仍然是一个过滤器。 “平滑结果”与去除或降低高频分量完全相同。
  • @rorold:同意你的前两句话,但不同意第三句话。时域中的平滑会影响所有频率(尽管不均等),并且不会产生与频域中的高频衰减完全相同相同的结果。
  • @MusiGenesis 实际上,它可以产生相同的结果。频域中的乘法(这是您在衰减频率时所做的)与时域中的卷积(即加权移动平均)完全相同。要获得完全相同的结果,我猜您必须采用衰减函数的逆 DFT 并将其用作移动平均线的权重,这可能是一个相当长的移动平均线。但我(诚然有些迂腐)的原点是,您的回答暗示只有频域处理是过滤,事实并非如此。
【解决方案3】:

我没有可以帮助您的教程,但在 C# 中您可能需要考虑使用 Reactive LINQ - 请参阅博文 Reactive programming (II.) - Introducing Reactive LINQ

作为获取事件的一种方式,您可以在不必存储所有值的情况下进行处理,它只会在您获取下一个事件时进行处理。

要考虑时间,您可以只使用带有负指数的指数来减少过去测量的影响。

【讨论】:

  • +1 链接,似乎是一个非常好的主意。但是,对于他的实际问题来说,这似乎有点断章取义......对我来说,他的主要问题似乎是他只存储变化,而不是随时间变化的信号,而他的计算需要后者。存储时间或更改日志本身可能就足够了。
  • 他似乎想保留一个值,但要增加时间,该值需要在添加新值之前减少。随着时间的推移,这将更多地减少旧值,并且通过使用响应式 linq,他可以更好地拥有一种算法来满足他的需求。
【解决方案4】:

是的,对于采样多个数据流的复杂实时系统,数据处理(数据的计算和存储)和数据一致性可能存在问题。

【讨论】:

    猜你喜欢
    • 2013-07-30
    • 2011-09-23
    • 2011-01-29
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多