首页 > 解决方案 > 消除传感器测量中的尖峰

问题描述

我正在测量 pwm 信号。有两种状态。测量值要么非常接近 1000,要么接近 2000;我不想平均这些值以消除测量噪声。我只是为了摆脱一两个非常不精确的值。

举个例子,这是预期(准确)的数据图:

在此处输入图像描述

这是真实的测量数据图:

在此处输入图像描述

我想消除仅由 3 或 4 次测量引起的中间尖峰。我想忽略这些测量。

我实际上认为我会创建一个包含 10 个元素的队列并将测量结果推送到其中。如果新测量值比队列中值的平均值少或多 500,则它不会添加到实际数据数组中。每当队列的平均值与新测量值之间的差异小于 500(即 10 个元素队列中的 5 个测量值)时,我将开始添加到实际数据数组并重置队列。

但这似乎不是一种有效的方法。我是一个数学菜鸟,但是。所以我不知道如何更有效地编写它,我需要效率,因为代码将在 Arduino 上运行。

谢谢

编辑:

我尝试按照建议使用中值过滤

这是我的实际测量图: 在此处输入图像描述

这是中值滤波器应用图:

在此处输入图像描述

如您所见,它运行良好。但是,我必须使用长度为 20 的过滤器。这是要缓存并推送到队列的大量数据。尤其是在只有 16 兆赫处理能力的 Ardunio,c++ 中。我的情况有更有效的方法吗?

标签: algorithmarduino

解决方案


我将假设现在的问题是如何加快 Arduino 的中值滤波器。我对 Arduino 的体验仅限于抱怨它产生的数据没有定期采样。显然,当他们转向 Raspberry Pi 时,这种情况就消失了,因为 Raspberry Pi 功能强大得多,所以这可能是一种选择。

我不知道您是如何计算中值过滤器的,但网络搜索表明您可以尝试一些实现。如果从 C++ STL 开始,您可以使用允许插入、删除和查找最大或最小项的数据结构来计算运行中位数。将 N/2 个项目的池保持在中位数以上,将 N/2 个项目池保持在中位数以下。当您获得一个新数据点时,删除最旧的值并将新值与中值进行比较,然后将其放入指向的任何池中。现在您可能在一侧有 N/2+1 个项目,在另一侧有 N/2-1 个项目。如果是这样,例如,从顶部池中删除最小的项目并将其插入底部池中。将中值重新计算为现在在顶部的最小项目和现在在底部的最大项目的平均值(如果 N 是奇数,那么您在池外有一个中值项目,而簿记只是稍微复杂一点)。接受新数据点的成本现在是 O(log N) 而不是 O(N) 或更糟,所以这可能会有所帮助。

(FWIW 我认识的最令人印象深刻的程序员也是专业的数学家,所以我会跟上数学)。

想一想,如果每个值真的是 1000 或 2000,你就不需要花哨的数据结构:你所需要的只是一个循环缓冲区和缓冲区中值的数量 >= 2000 的运行计数,你可以删除最旧的值并添加最新的值时更新。这将花费您 20 个整数,但如果您的值确实是 1000 或 2000,则每个值都可以用一个位表示,因此您可以将整个队列保存在一个 32 位字中,并使用POPCNT,如果 arduino C/C++ 提供它


推荐阅读