C#中的简单信号处理

时间:2009-08-29 15:19:20

标签: c# signal-processing

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

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

我已经在DSP Guide阅读了,但我并没有从中得到很多。是否有专门针对程序员的教程,而不是Mathcad工程师?是否有一些简单的代码片段可以提供帮助?

更新:经过多次电子表格测试后,我已采取行政决定记录所有样本,并应用Butterworth filter

4 个答案:

答案 0 :(得分:6)

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

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

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

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

在代码中(主要是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;
}

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

对于高阶滤镜,必须存储更多的值 并且代码变得有点复杂。平时 值需要在数组中向下移动;在数组中 过去的y值和过去的x值的数组。

答案 1 :(得分:5)

在DSP中,术语“滤波器”通常是指连续信号内的频率分量的放大或衰减(即“降低”)。这通常使用快速傅里叶变换(FFT)来完成。 FFT以在给定时间长度内记录的信号开始(数据在所谓的“时域”内)并将这些值转换为所谓的“频域”,其中结果表明信号的强度在一系列中频率“箱”的范围从0 Hz到采样率(在您的情况下为10 Hz)。因此,作为一个粗略的例子,一秒钟的数据FFT(10个样本)将告诉您信号在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更容易,相信我)。您提到您的应用仅存储与先前值不同的值。假设您还存储了记录每个值的时间,您的运行平均代码应该很容易通过使用记录的先前值填充“缺失值”。

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:-1)

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