The Moving Average Trend Spotter

SS 1 Arduino Uno Simulation first Statistical Signal Filtering
Simulation lab
Board: ♾️ Arduino Uno
Open in Wokwi ↗
Simulator preview
ARDUINO UNO

Press the pushbutton to test the interactive circuit in real time.

>_ Serial monitor
Ready — press the button.
📦 Components ▴
  • Arduino Uno microcontroller board
  • LED indicator (green)
  • 220 ohm current-limiting resistor
  • Tactile pushbutton switch
  • Jumper wires (male-male)

🔧 Build Your Moving Average Filter

1 Construct a circular buffer array of length 10 in Arduino C++: 'int window[10]'.
2 Maintain a running sum variable to achieve O(1) constant-time algorithmic updates.
3 Sample analog input A0; subtract the oldest value, overwrite with new reading, and add to sum.
4 Verify on the Wokwi Serial Plotter that high-frequency ADC thermal ripple is cleanly eliminated!
🧩 Block plan / Starter code ▴
const int SENSOR_PIN = A0;
const int WINDOW_SIZE = 10;

int readings[WINDOW_SIZE];
int readIndex = 0;
long runningSum = 0;
int smoothedValue = 0;

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < WINDOW_SIZE; i++) {
    readings[i] = analogRead(SENSOR_PIN);
    runningSum += readings[i];
  }
  Serial.println("Raw,Smoothed");
}

void loop() {
  int rawReading = analogRead(SENSOR_PIN);

  // Constant-time O(1) circular buffer update
  runningSum -= readings[readIndex];
  readings[readIndex] = rawReading;
  runningSum += readings[readIndex];
  readIndex = (readIndex + 1) % WINDOW_SIZE;

  smoothedValue = runningSum / WINDOW_SIZE;

  Serial.print(rawReading);
  Serial.print(",");
  Serial.println(smoothedValue);
  delay(50);
}

Maintaining runningSum enables O(1) updates without expensive iterative array looping in embedded memory.

⚗️ Test your model

Test Condition / ActionExpected Result
Thermal ADC Noise (±15 raw counts)Smoothed output variance drops to < ±1 count
Sudden Step Input (+200 counts)Smoothed output cleanly ramps to new level over exactly 10 samples
Sustained DC InputZero steady-state error; smoothed output matches mean raw input
⚑ Try a challenge

Calculate and output the real-time sample variance in the loop to identify when the sensor has entered a turbulent state!

❓ Quick check
Why do raw analog sensor readings from an Arduino ADC fluctuate randomly by a few counts even in a stationary environment?

📖 Our Story & Concepts

Analog-to-Digital Converters (ADCs) in microcontrollers convert continuous physical voltages into discrete integer counts. In real circuits, power supply ripple, electromagnetic interference (EMI), and thermal agitation induce high-frequency white noise.

In medical electrocardiograms (ECGs) and industrial thermal kilns, calculating an N-point Simple Moving Average (SMA) acts as an optimal finite impulse response (FIR) low-pass filter. Implementing this with a circular ring buffer ensures execution time remains independent of window length.

</> Full Annotated Code Walkthrough

// Complete Circular Buffer with Real-Time Statistical Variance
const int SENSOR_PIN = A0;
const int N = 10;

int buf[N];
int idx = 0;
long sum = 0;

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < N; i++) {
    buf[i] = analogRead(SENSOR_PIN);
    sum += buf[i];
  }
}

void loop() {
  int raw = analogRead(SENSOR_PIN);
  sum -= buf[idx];
  buf[idx] = raw;
  sum += buf[idx];
  idx = (idx + 1) % N;

  float mean = (float)sum / N;

  // Compute Variance
  float varSum = 0;
  for (int i = 0; i < N; i++) {
    float diff = buf[i] - mean;
    varSum += diff * diff;
  }
  float variance = varSum / N;

  Serial.print("Raw:"); Serial.print(raw);
  Serial.print(",Mean:"); Serial.print(mean);
  Serial.print(",Variance:"); Serial.println(variance);
  delay(100);
}

Maintaining runningSum enables O(1) updates without expensive iterative array looping in embedded memory.

▷ Expected Results & Troubleshooting

Test Condition / ActionExpected Result
Thermal ADC Noise (±15 raw counts)Smoothed output variance drops to < ±1 count
Sudden Step Input (+200 counts)Smoothed output cleanly ramps to new level over exactly 10 samples
Sustained DC InputZero steady-state error; smoothed output matches mean raw input

⚑ Extension Challenges & Blueprints

⚑ Extension Challenges
  • Level 1: Implement an Exponential Moving Average (EMA) with configurable smoothing factor alpha (0.1 to 0.9).
  • Level 2: Benchmark CPU execution cycles between circular buffer O(1) and array recalculation O(N).
  • Level 3: Apply the filter to an ultrasonic rangefinder to eliminate acoustic reflection spikes.

❓ Check Your Understanding

Question 1: Why do raw analog sensor readings from an Arduino ADC fluctuate randomly by a few counts even in a stationary environment?

Question 2: How does a circular buffer array in C/C++ work when a new sensor sample arrives?

Question 3: If the window size N is chosen to be 100 samples instead of 5 samples, what is the engineering tradeoff?

Question 4: What pin on the Arduino Uno is used to read the variable analog voltage from a temperature sensor or potentiometer?

Feedback appears after you check your answer.