#define POT_PIN A0 // Analog pin for the potentiometer
#define OUT_PIN 9 // PWM output pin
#define NUM_READINGS 100 // Number of readings for smoothing
#define CALIBRATION_TIME 5000 // Calibration period in milliseconds (1 minute)
int calibratedMin = 1023; // To store the minimum reading during calibration
int calibratedMax = 0; // To store the maximum reading during calibration
bool calibrationDone = false; // Flag to indicate calibration is complete
unsigned long calibrationStartTime; // To mark when calibration starts
// Running average variables for normal operation
int readings[NUM_READINGS];
int index = 0;
long total = 0; // Use long to avoid overflow
float sens = 1; // Sensitivity factor
void setup() {
Serial.begin(9600);
pinMode(OUT_PIN, OUTPUT);
// Start calibration timing.
calibrationStartTime = millis();
// Do an initial reading to initialize variables.
int initial = analogRead(POT_PIN);
calibratedMin = initial;
calibratedMax = initial;
// Also initialize the running average buffer.
total = (long)initial * NUM_READINGS;
for (int i = 0; i < NUM_READINGS; i++) {
readings[i] = initial;
}
}
void loop() {
unsigned long elapsed = millis() - calibrationStartTime;
if (!calibrationDone) {
// Calibration mode: during the first minute, update calibrated min and max.
int reading = analogRead(POT_PIN);
// Update calibration bounds.
if (reading < calibratedMin) {
calibratedMin = reading;
}
if (reading > calibratedMax) {
calibratedMax = reading;
}
// Debug: print calibration progress.
Serial.print("Calibrating... ");
Serial.print("Elapsed: ");
Serial.print(elapsed);
Serial.print(" ms, Min: ");
Serial.print(calibratedMin);
Serial.print(", Max: ");
Serial.println(calibratedMax);
// Check if calibration time is complete.
if (elapsed >= CALIBRATION_TIME) {
calibrationDone = true;
Serial.println("Calibration complete!");
Serial.print("Final Calibrated Min: ");
Serial.print(calibratedMin);
Serial.print(", Max: ");
Serial.println(calibratedMax);
// Optionally, reset the running average buffer with the current reading.
int current = analogRead(POT_PIN);
total = (long)current * NUM_READINGS;
for (int i = 0; i < NUM_READINGS; i++) {
readings[i] = current;
}
}
delay(10); // Small delay for stable calibration readings
} else {
// Normal operation: use running average and sensitivity check.
int reading = analogRead(POT_PIN);
// Compute the current running average.
int avgReading = total / NUM_READINGS;
// If the new reading is significantly lower than the average (scaled by sens),
// reset the running average buffer to the new reading.
if (reading <= (avgReading * sens)) {
total = (long)reading * NUM_READINGS;
for (int i = 0; i < NUM_READINGS; i++) {
readings[i] = reading;
}
avgReading = reading;
} else {
// Update running total: subtract the oldest reading and add the new reading.
total = total - readings[index] + reading;
readings[index] = reading;
index = (index + 1) % NUM_READINGS;
avgReading = total / NUM_READINGS;
}
// Map the averaged reading from the calibrated range to a PWM value (0–255).
int pwmValue = map(avgReading, calibratedMin, calibratedMax, 0, 255);
pwmValue = constrain(pwmValue, 0, 255);
// Output the PWM signal.
analogWrite(OUT_PIN, pwmValue);
// Debug output.
Serial.print("Reading: ");
Serial.print(reading);
Serial.print(" | Avg: ");
Serial.print(avgReading);
Serial.print(" | PWM: ");
Serial.println(pwmValue);
delay(50);
}
}