Arduino 高斯库

arduinosoftware & codinghardware更新于 2026/1/12 7:07:17

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!
");

之后,计算 ma​​xHit,即包含最大点数的条形图。由于条形图的最大尺寸为 BAR_SIZE (40),因此需要确定一个缩放因子,使得具有 ma​​xHit 的条形图尺寸为 40,所有其他条形图也相应缩放。ma​​xHit 的值和缩放比例都会打印出来。

// 仅缩放序列图中的绘图,以改善可视化效果
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 文件,了解此库中可用的其他函数。


相关文章