高斯库 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 仓库自述文件,以了解此库中可用的其他函数。

更新于:2021年7月26日

895 次浏览

启动您的 职业生涯

完成课程获得认证

开始学习
广告