Smoothing

这段代码是一个Arduino示例程序,用于演示如何对从模拟输入(例如电位器)读取的值进行平滑处理。它通过计算一个滑动平均值来实现平滑效果,从而减少读取值的波动。它使用一个固定大小的数组存储最近的读取值,并通过总和除以数组大小来计算平均值。这种方法可以有效减少传感器读取值的噪声,提高系统的稳定性。

/*

  Smoothing

  Reads repeatedly from an analog input, calculating a running average
  and printing it to the computer.  Keeps ten readings in an array and
  continually averages them.

  The circuit:
    * Analog sensor (potentiometer will do) attached to analog input 0

  Created 22 April 2007
  By David A. Mellis  <dam@mellis.org>
  modified 9 Apr 2012
  by Tom Igoe
  http://www.arduino.cc/en/Tutorial/Smoothing

  This example code is in the public domain.


*/


// Define the number of samples to keep track of.  The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input.  Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;

void setup()
{
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;
}

void loop() {
  // subtract the last reading:
  total = total - readings[index];
  // read from the sensor:
  readings[index] = analogRead(inputPin);
  // add the reading to the total:
  total = total + readings[index];
  // advance to the next position in the array:
  index = index + 1;

  // if we're at the end of the array...
  if (index >= numReadings)
    // ...wrap around to the beginning:
    index = 0;

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(average);
  delay(1);        // delay in between reads for stability
}

功能概述

硬件部分

  • 使用一个电位器或其他模拟传感器连接到Arduino的模拟输入引脚A0。

软件部分

  • 通过一个数组存储最近的10次读取值。

  • 计算这些读取值的平均值,从而实现平滑效果。

  • 将平均值通过串行通信发送到计算机。

代码逐行解释

定义常量和变量

const int numReadings = 10;  // 定义存储的读取值数量
int readings[numReadings];   // 用于存储读取值的数组
int index = 0;               // 当前读取值的索引
int total = 0;               // 读取值的总和
int average = 0;             // 平均值
int inputPin = A0;           // 模拟输入引脚
  • numReadings:定义存储的读取值数量,这里为10。

  • readings:一个数组,用于存储最近的10次读取值。

  • index:当前读取值的索引。

  • total:读取值的总和。

  • average:计算得到的平均值。

  • inputPin:模拟输入引脚A0。

setup() 函数

void setup() {
  // 初始化串行通信,波特率为9600
  Serial.begin(9600);
  // 将数组中的所有读取值初始化为0
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;
}
  • Serial.begin(9600):初始化串行通信,设置波特率为9600。

  • for循环:将数组readings中的所有值初始化为0。

loop() 函数

void loop() {
  // 从总和中减去即将被替换的读取值
  total = total - readings[index];
  // 从传感器读取值
  readings[index] = analogRead(inputPin);
  // 将新的读取值加到总和中
  total = total + readings[index];
  // 移动到数组的下一个位置
  index = index + 1;

  // 如果索引超出数组范围,则回到数组开头
  if (index >= numReadings)
    index = 0;

  // 计算平均值
  average = total / numReadings;
  // 将平均值发送到计算机
  Serial.println(average);
  // 稍作延迟以提高稳定性
  delay(1);
}

更新总和

  • total = total - readings[index]:从总和中减去即将被替换的读取值。

  • readings[index] = analogRead(inputPin):从传感器读取新的值。

  • total = total + readings[index]:将新的读取值加到总和中。

更新索引

  • index = index + 1:移动到数组的下一个位置。

  • 如果index超出数组范围(即index >= numReadings),则将其重置为0,实现循环存储。

计算平均值

  • average = total / numReadings:计算所有读取值的平均值。

发送平均值

  • Serial.println(average):将平均值通过串行通信发送到计算机。

延迟

  • delay(1):稍作延迟,以提高读取的稳定性。

工作原理

滑动平均

  • 通过一个固定大小的数组存储最近的读取值。

  • 每次读取新的值时,更新数组中的值,并重新计算总和。

  • 通过总和除以数组大小,得到平均值。

循环存储

  • 使用索引index来管理数组中的位置。

  • 当索引超出数组范围时,将其重置为0,实现循环存储。

串行通信

  • 将计算得到的平均值通过串行通信发送到计算机,方便观察和调试。

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)