有时候看起来很简单的事情并不那么简单。你有一个相当复杂的测量要做,但你想要一个简单的结果。您要测量的不是恒定的,而是随时间变化的。根据您的要求级别,您可以计算当前消耗的一个或多个属性。这些属性将帮助您更好地监控系统。我向您建议 3 种不同的解决方案,其复杂性不断增加。
解决方案 1:平均
你想得到一个单值结果 -> 及时得到平均值。正如@akellyirl 已经提出的那样,使用低通滤波器。计算float y = alpha*input + (1-alpha)*y
每个样本,其中alpha
是平滑因子。有关详细信息,请参阅维基百科。
解决方案 2:最大值 + 平均值
您对获取平均值和最大值很感兴趣。例如,监视最大值对于组件尺寸标注可能很有趣。
if (y > max)
max = y;
解决方案 3:标准差 + 最大值 + 平均值
为什么?
请参见下面的图表。有3种不同形状的信号。一个三角形、一个正弦和一个尖峰信号。它们都是周期性的,具有相同的周期、相同的振幅、相同的平均值以及相同的最小值和最大值。但是,它们有不同的形状,而且确实有着完全不同的故事……

差异之一是标准偏差。这就是为什么我建议你扩展你的测量,并包括标准偏差。问题是计算它的标准方法是消耗 CPU 的。希望有一个解决方案。
如何?
使用直方图方法。构建所有测量值的直方图,并有效地提取数据集的统计信息(最小值、最大值、平均值、标准差)。直方图将具有相同值或相同值范围的值组合在一起。优点是避免存储所有样本(及时增加计数),并在有限数量的数据上进行快速计算。
在开始获取测量值之前,创建一个数组来存储直方图。它是一个一维整数数组,大小为 32,例如:
int histo[32];
根据电流表的量程,调整以下功能。例如,如果范围是 256mA,这意味着直方图的 bin 0 将增加 0 到 8 mA 之间的值,bin 1 增加 8 到 16 mA 之间的值等等......所以,你需要一个整数来表示直方图 bin 编号:
short int index;
每次得到一个样本,找到对应的bin索引:
index = (short int) floor(yi);
并增加这个 bin:
histo[index] += 1;
要计算平均值,请运行以下循环:
float mean = 0;
int N = 0;
for (i=0; i < 32 ; i++) {
mean = i * histo[i]; // sum along the histogram
N += i; // count of samples
}
mean /= N; // divide the sum by the count of samples.
mean *= 8; // multiply by the bin width, in mA: Range of 256 mA / 32 bins = 8 mA per bin.
要计算标准偏差,请运行以下循环:
float std_dev = 0;
for (i=0; i < 32 ; i++) {
std_dev = (i - mean) * (i - mean) * histo[i]; // sum along the histogram
}
std_dev /= N; // divide the sum by the count of samples.
std_dev = sqrt(std_dev); // get the root mean square to finally convert the variance to standard deviation.
直方图方法的策略是对少数几个 bin 进行慢速操作,而不是对所有获取的信号样本进行操作。样本量越长越好。如果您想了解更多详细信息,请阅读这个有趣的页面The Histogram, Pmf and Pdf。