Setup guide

ESP32 Sensor Thresholds and Hysteresis: Stop Rapid Toggling

Use two thresholds and remembered state in ESP32 code. Trace fixed sample values, handle invalid input and separate hysteresis from smoothing.

Learning reference · Updated 2026-10-30

ESP32 Sensor Thresholds and Hysteresis: Stop Rapid Toggling guide illustration
Jump to a section

Before you start

Hardware
Classic ESP32-WROOM DevKit, USB data cable and computer. No external sensor or output circuit for this exercise.
Software baseline
Arduino IDE 2 and Arduino-ESP32 3.3.2 for the stated classic ESP32 examples. This is an API review baseline, not a latest-version claim.
Before this lesson
Complete the first Serial-only upload. For the logic lessons, read the variables, decisions, loops and functions references first.
Your goal
Predict when a high-level flag turns on, turns off or keeps its previous state inside a threshold band.
Verification limits
Documentation/API and local content/browser review only. No sketch compilation, board upload or physical hardware test was performed for this lesson.

A single threshold can chatter

A signal close to one decision boundary can alternate above and below it. A comparison such as level >= 50 would repeatedly change a flag for values 49, 51, 49 and 51. Whether that matters depends on the application; frequent transitions can make displays or control logic unstable.

Hysteresis uses a different boundary to enter a state than to leave it. Its memory is the current flag. This demonstration uses a made-up integer level from 0 through 100, with no physical unit, sensor, GPIO or actuator. The thresholds are teaching values, not a thermostat or safety recommendation.

Give both thresholds an explicit policy

Inclusive transition boundaries: high = 55, low = 45
Previous flagValid inputNext flag
OFF55 or higherON
ON45 or lowerOFF
EitherStrictly between 45 and 55Keep the previous flag.
OFF45 or lowerStay OFF.
ON55 or higherStay ON.
EitherOutside 0–100Report invalid; do not update the remembered flag.

Decide the initial state and invalid policy

The stored flag begins OFF. A first valid sample inside the band therefore leaves it OFF. If you need a different startup rule, define it explicitly; there is no previous physical history for the program to recover automatically after reset. The code checks low < high with a compile-time assertion.

An invalid sample is reported and skipped. Retaining a software flag is only the policy of this no-output demonstration. A real actuator may need a separate fault state, timeout or independent protection. For floating-point sensor data, also reject non-finite values such as NaN before applying comparisons; the integer sample stream here cannot represent NaN.

Trace both travel directions

The fixed sequence is 49, 51, 50, 54, 55, 53, 46, 45, 44, -1, 56. Starting OFF, the flag stays OFF through 54, turns ON at 55, stays ON at 53 and 46, then turns OFF at 45. It stays OFF at 44, reports -1 as invalid, and turns ON at 56. These are source predictions, not captured sensor readings.

The function returns the next flag from a valid sample and the prior flag. It does not turn on an output or read a sensor. Its explicit input and return value make the policy easier to inspect than a collection of hidden global side effects.

Hysteresis and smoothing solve different problems

Hysteresis stabilizes a decision by keeping state inside a band. A moving average changes the values being considered and introduces a response tradeoff. You can combine them deliberately, but averaging alone does not guarantee the decision will stop toggling near a threshold.

Choose a band using the real signal range, noise, desired sensitivity and acceptable response. A narrow band may still chatter when noise crosses both thresholds; a wide one may ignore changes you care about. Respect the sensor’s valid reading interval. Reading a cached value repeatedly is not a stream of independent measurements.

Test equalities and invalid values

Practice on paper with 45, 46, 54 and 55 for both starting states. Then change the constants to low = 40 and high = 60 and predict the same sample stream again. Keep low below high. Do not silently reinterpret the arbitrary levels as degrees, humidity or ADC volts.

If a real adaptation toggles unexpectedly, log the raw value, validity and prior/next state together. Check units and boundary operators before widening the band. Before connecting hardware, use the exact sensor guide’s electrical and sampling requirements and define what a failed reading should do.

Use one complete example

Save this full sketch as hysteresis_demo.ino, select your exact ESP32 board and port, and use Verify before Upload. Open Serial Monitor at 115200 baud after upload; press EN/reset if you missed startup text. No extra library is needed. The example uses no GPIO wiring. The stated results are predictions from source, not a recorded board run.

Wiring and matching Arduino code

Complete USB and Serial-only example

USB only; no GPIO wiring. Serial Monitor: 115200 baud.

hysteresis_demo.ino
#include <Arduino.h>

constexpr int LOW_LEVEL = 45;
constexpr int HIGH_LEVEL = 55;
static_assert(LOW_LEVEL < HIGH_LEVEL, "Thresholds must be ordered");
const int samples[] = {49, 51, 50, 54, 55, 53, 46, 45, 44, -1, 56};
bool highFlag = false;

bool nextFlag(int validLevel, bool previous) {
  if (!previous && validLevel >= HIGH_LEVEL) { return true; }
  if (previous && validLevel <= LOW_LEVEL) { return false; }
  return previous;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  for (size_t i = 0; i < sizeof(samples) / sizeof(samples[0]); ++i) {
    const int value = samples[i];
    Serial.print(value); Serial.print(": ");
    if (value < 0 || value > 100) {
      Serial.println("INVALID; flag not updated");
      continue;
    }
    highFlag = nextFlag(value, highFlag);
    Serial.println(highFlag ? "ON" : "OFF");
  }
}

void loop() {
  delay(10);
}

Expected behavior in this guide is a source walkthrough. No firmware compilation or physical board upload was performed for this lesson.

Continue your learning path

Back to this Learning path · See the full ESP32 roadmap

Next steps

Check both boundaries and startup behavior before choosing a real application’s thresholds.

FAQ

Technical references