Arduino 高斯库
Ivan Seidel 开发的高斯库可帮助您在 Arduino 中实现高斯数学、卡尔曼滤波器和移动平均算法。
要下载此库,请前往库管理器并搜索"Gaussian"。安装 Ivan Seidel 开发的库。

安装完成后,前往:文件 → 示例 → Gaussian,并打开 GaussianRandomPlot 示例。
示例
这个示例乍一看可能有点复杂。因此,我建议先在你的 Arduino 上运行这个示例,并查看串口监视器的输出。我会在这里演示。

总而言之,这段代码生成了 20,000 个随机高斯数,即这些数字遵循高斯钟形曲线分布,并根据它们与平均值的距离,将它们分成不同的列或塔(称为命中)。然后绘制这些命中结果的图表,结果显示分布确实符合高斯分布。
代码演示
让我们开始代码演示。
首先从库的引入开始。
#include <Gaussian.h>
在设置过程中,我们只需初始化 Serial,并向随机数生成器添加一个种子。
void setup() {
Serial.begin(9600);
Serial.println("
Starting Random Gaussian Distribuition...");
delay(20);
randomSeed(analogRead(0));
}
然后我们定义几个常量。SIZE 表示我们将拥有的条形数量。TESTS 表示我们将生成的随机数的数量。BAR_SIZE 表示每个条形的最大大小或高度(number of = characters)。
// 用于记录高斯随机命中的"槽"数量 #define SIZE 36 // 将执行多少次测试 #define TESTS 20000 // 将包含多少个字符(宽度)? #define BAR_SIZE 40
在循环中,我们首先创建一个高斯对象,其均值为 0,方差为 10。
现在,绘制时,此均值将参考中心条形。因此,"零"值已定义(高斯峰值所在位置)。由于我们有 36 条柱状图,且均值为 0,因此峰值将位于第 18 条柱状图。
然后,我们生成一个大小等于柱状图数量的 hits 数组,并将其初始化为 0。该数组最终将存储每条柱状图内有多少个随机点。
void loop() {
Gaussian g1 = Gaussian(0, 10);
long zero = SIZE/2 - g1.mean;
long hits[SIZE] = {0};
// Zero the array
for(int i = 0; i < SIZE; i++)
hits[i] = 0;
Later, some Serial Monitor printing is done 0 to 100% line.
// Print Header (0% ------------- 100%)
Serial.print("0% ");
for(int i = 3; i < BAR_SIZE - 5; i++)
Serial.print("-");
Serial.println(" 100%");
接下来,for 循环迭代直至测试次数完成。for 循环的第一部分很简单,只需在 0 ---- 100% 线下方打印 ======== 行。重要的是后半部分。使用 g1.random() 生成一个高斯随机数。根据其值,确定其位置,即它位于哪个柱状图 (int place = (int)round(val - g1.mean + zero);)。然后将位置限制在 0 到 36 之间,即小于 0 的条目向上拉至 0,大于 36 的条目向下推至 36。最后,该位置的 hits 数组的值递增,表示生成的随机值最终分配给了该柱状图。
// 处理高斯函数并随机化"测试"次数
int lastStep = 0, step;
Serial.print("=");
for(int i = 0; i < TESTS; i++){
step = (double)i/TESTS*BAR_SIZE;
if(step > lastStep){
while(lastStep < step){
Serial.print("=");
lastStep++;
}
}
double val = g1.random();
int place = (int)round(val - g1.mean + zero);
place = constrain(place, 0, SIZE);
hits[place]++;
}
Serial.print(" END!
");
之后,计算 maxHit,即包含最大点数的条形图。由于条形图的最大尺寸为 BAR_SIZE (40),因此需要确定一个缩放因子,使得具有 maxHit 的条形图尺寸为 40,所有其他条形图也相应缩放。maxHit 的值和缩放比例都会打印出来。
// 仅缩放序列图中的绘图,以改善可视化效果
long maxHit = 0;
for(int i = 0; i < SIZE; i++){
maxHit = max(maxHit, hits[i]);
// 如果要查看命中次数,请取消注释此行
// Serial.println(hits[i]);
}
// 这将打印条形图
double scale = (double)maxHit/BAR_SIZE;
Serial.print("Scale: ");
Serial.print(scale);
Serial.print("\tMaxHit: ");
Serial.println(maxHit);
其余代码与在串行监视器上绘制值有关。
for(int i = 1; i < SIZE - 1; i++){
int len = hits[i]/scale;
for(int x = 0; x < len; x++)
Serial.print("=");
Serial.print("
");
}
// 等到恐龙重返地球
while(1);
}
因此,这段代码本质上表明使用 g1.random() 生成的随机数遵循随机分布。
您可以阅读此库的 GitHub 仓库的 ReadMe 文件,了解此库中可用的其他函数。

