高斯库 Arduino
Ivan Seidel 编写的 Gaussian 库帮助您在 Arduino 中实现高斯数学、卡尔曼滤波器和移动平均值。
要下载此库,请转到**库管理器**并搜索**“Gaussian”**。安装 Ivan Seidel 编写的库。
安装完成后,转到:**文件 → 示例 → Gaussian**,然后打开 GaussianRandomPlot 示例。
示例
现在,这个示例乍一看可能让人不知所措。因此,我建议您首先在 Arduino 上运行此示例,并查看串口监视器的输出。我将在这里展示它。
总而言之,此代码生成 20,000 个高斯随机数(即这些数字遵循高斯钟形曲线分布),并根据它们与平均值的距离将其分成不同的列或塔(称为命中)。然后绘制这些命中,图表显示分布确实是高斯分布。
代码详解
让我们开始代码详解。
我们从包含库开始。
#include <Gaussian.h>
在 setup 中,我们只需初始化串口,并为随机数生成器添加一个种子。
void setup() { Serial.begin(9600); Serial.println("
Starting Random Gaussian Distribuition..."); delay(20); randomSeed(analogRead(0)); }
然后我们定义几个常量。SIZE 表示我们将拥有的条形图数量。TESTS 表示我们将生成的随机数数量。**BAR_SIZE** 表示每个条形图的最大尺寸或高度(**= 字符的数量**)。
// The number of "slots" to record the hits of gaussian random #define SIZE 36 // How many tests will be performed #define TESTS 20000 // How many characters will have, in width? #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;
稍后,将进行一些串口监视器打印,从 0 到 100% 的行。
// 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 数组的值递增,表示生成的随机值最终分配给了该条形图。
// Process the gaussians and randomize 'TESTS' times 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** 和 scale 的值。
// Just to scale the plot on the Serial, to improve visualization long maxHit = 0; for(int i = 0; i < SIZE; i++){ maxHit = max(maxHit, hits[i]); // Uncomment this line if you want to see the NUMBER of hits // Serial.println(hits[i]); } // This will print the bar graphic 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("
"); } // Wait until dinosaurs come back on earth while(1); }
因此,此代码实质上表明使用 **g1.random()** 生成的随机数遵循随机分布。
您可以查看此库的 GitHub 仓库自述文件,以了解此库中可用的其他函数。