Interruptible feedback is a closed-loop control architecture where sensor readings and actuator updates are bound to hardware interrupts, allowing the system to instantly preempt normal operation for safety faults or limit triggers without waiting for the main polling loop. If you are building a CNC router, a balancing robot, or a high-speed pick-and-place machine, relying on delay() or millis() polling for your encoder feedback will eventually result in crashed gantries or oscillating motors. Moving from software polling to hardware-driven interruptible feedback is the single most effective upgrade you can make to an embedded control system.

The Core Concept: What It Changes and What It Isn't

In a standard polling architecture, your microcontroller checks the state of a sensor (like a limit switch or an encoder pin) sequentially inside the main loop(). The fatal flaw here is latency jitter. If a WiFi stack event, an SD card write, or a complex floating-point calculation blocks the main loop for 3 milliseconds, your controller is entirely blind to the physical world during that window.

Interruptible feedback changes this by shifting the sensor-read responsibility to the silicon level. When a physical event occurs (a voltage edge on a GPIO pin), the microcontroller's Nested Vectored Interrupt Controller (NVIC) immediately pauses the main program, jumps to an Interrupt Service Routine (ISR), records the data, and resumes.

Common Confusion: RTOS Tasks vs. Hardware Interrupts

Many makers confuse interruptible feedback with asynchronous polling using an RTOS (like FreeRTOS on the ESP32). While an RTOS task running at high priority is faster than a bare-metal loop(), it still suffers from context-switching overhead—typically 10µs to 50µs. True interruptible feedback happens via hardware interrupts, executing in under 2µs. Think of an RTOS task as a manager who checks your desk every 20 microseconds, while a hardware interrupt is a spinal reflex that pulls your hand away from a hot stove before your brain even processes the heat.

The Math in Motion: A Worked Numeric Example

To understand why interruptible feedback is non-negotiable for motion control, let us look at the math of reading a quadrature encoder on an ESP32-WROOM-32.

The Setup: You are driving a DC motor with a 600 PPR (pulses per revolution) optical encoder. Using 4x quadrature decoding, that yields 2,400 counts per revolution. The motor is spinning at 3,000 RPM (50 revolutions per second).

  • Total edges per second: 50 RPS × 2,400 counts = 120,000 edges/second.
  • Time between edges: 1 / 120,000 = 8.33 µs per edge.

Scenario A: Polling in the Main Loop
Your main loop, burdened by WiFi telemetry and LCD updates, runs at roughly 1 kHz (1 poll every 1,000 µs). Because your poll interval (1,000 µs) is vastly longer than the edge interval (8.33 µs), you will miss approximately 119 out of every 120 edges. If a limit switch triggers, your motor will travel 17.8 degrees of mechanical rotation before the controller even realizes it needs to stop. In a CNC machine, that is enough to snap a 3mm end mill.

Scenario B: Interruptible Feedback (Hardware ISR)
You attach the encoder pins to hardware interrupts. The ESP32's GPIO interrupt latency is roughly 1.5 µs to 2.5 µs. Because the ISR executes faster than the 8.33 µs edge interval, you catch 100% of the pulses. If a fault occurs, the mechanical overshoot is reduced to less than 0.01 degrees.

Where You Meet This in Practice

You will encounter the absolute requirement for interruptible feedback in three specific embedded domains:

  1. Field Oriented Control (FOC) Motor Drives: Libraries like SimpleFOC rely on hardware timer interrupts to trigger ADC (Analog-to-Digital Converter) readings for phase currents exactly at the center of the PWM cycle. Polling the ADC results in noisy current readings and violent motor cogging.
  2. CNC and 3D Printer Homing: When a high-speed gantry hits a limit switch or a BLTouch probe triggers, that signal must immediately halt the step-pulse generator. Wiring E-stops and limit switches to interrupt pins ensures the stepper drivers are disabled in microseconds, regardless of what the G-code parser is doing.
  3. High-Speed Tachometers and Flow Meters: Measuring the RPM of a turbocharger or the flow rate of a chemical dosing pump generates pulse trains in the 10kHz–50kHz range. Only hardware counters driven by interruptible feedback can track these without dropping pulses.
Safety Caveat: Never rely solely on software interruptible feedback for human safety E-stops on machinery operating above 50V or with high kinetic energy. Always wire physical E-stop buttons in series with the hardware enable (EN) pins of your motor drivers or main contactors to physically cut power, using the microcontroller interrupt only as a secondary state-logger.

Decision Path: Choosing Your Feedback Architecture

Do not default to hardware interrupts for everything; they carry overhead and can starve your main CPU if misused. Use this decision matrix to select the right architecture for your sensor.

Signal Frequency Safety / Precision Criticality Recommended Architecture Concrete Implementation Pick
< 100 Hz Low (e.g., UI buttons, slow temp sensors) Main Loop Polling digitalRead() with software debouncing in loop()
100 Hz - 5 kHz Medium (e.g., PID control loop updates) Hardware Timer Interrupt ESP32 hw_timer_t set to 1kHz to trigger PID math
> 5 kHz OR Asynchronous Faults High (e.g., Encoders, Limit Switches, E-Stops) Hardware GPIO Interrupt attachInterrupt() with IRAM_ATTR on ESP32

The Default Recommendation: If you are building a closed-loop motor controller on an ESP32 or STM32, your final architecture should be a hybrid. Use Hardware GPIO Interrupts (attachInterrupt) strictly for counting encoder edges and catching limit switches. Use a Hardware Timer Interrupt running at exactly 1 kHz to read those counts, calculate the PID error, and update the PWM duty cycle. Leave the main loop() exclusively for WiFi, MQTT, and display updates.

Implementation Gotchas on the ESP32

When implementing interruptible feedback on the ESP32, ignoring memory architecture will lead to random crashes. According to the Espressif Interrupt Allocation documentation, ISRs must be placed in specific memory regions.

  • The IRAM_ATTR Mandate: You must tag your ISR function with IRAM_ATTR. If you do not, the code resides in SPI Flash. If a flash write operation (like logging to an SD card or SPIFFS) occurs, the flash cache is disabled, and your ISR will trigger a fatal Cache Disabled exception, bricking the control loop and crashing the motor.
  • Volatile and Atomic Variables: Any variable shared between the ISR and the main loop must be declared volatile to prevent the compiler from caching it in a register. For 32-bit integers on a dual-core ESP32, prefer std::atomic<int32_t> to prevent torn reads if the main loop reads the variable exactly as the ISR is updating it.
  • Keep it Under 5µs: Never put Serial.print(), delay(), or I2C/SPI transactions inside an ISR. If your interruptible feedback routine takes longer than 5 microseconds, you will block the WiFi/Bluetooth stack (which relies on its own high-priority interrupts), causing silent network drops.

Frequently Asked Questions

Can I just use a dedicated hardware counter chip instead of microcontroller interrupts?
Yes. For extremely high-speed encoders (e.g., 10,000 PPR at 6,000 RPM), the interrupt load can overwhelm even an STM32. In these cases, offload the interruptible feedback to a dedicated quadrature counter IC like the LS7366R, which handles the edge counting in silicon and lets the microcontroller poll the total count via SPI at a leisurely 100 Hz.

What happens if my limit switch bounces and triggers the interrupt 50 times in a millisecond?
Hardware interrupts do not have built-in debouncing. If a mechanical limit switch bounces, your ISR will fire repeatedly. You must implement a software timestamp check inside the ISR (e.g., if(micros() - last_trigger > 5000)) to ignore subsequent edges within a 5-millisecond window, ensuring the feedback loop registers only the initial physical contact.