Embedded Microcontroller I/O Lab — Interactive Sensor-to-Actuator Simulator

Interactive embedded control-bench simulator — run a potentiometer-to-PWM, temperature-to-fan, or encoder PI speed-control application on a 3.3 V MCU, inject 11 electrical faults, inspect ADC math and logic-analyzer timing, and run a 16-check I/O verification bench.

← Computer Science Labs
About this tool — how it works & FAQOpen ▾Close ▴

About the Embedded Microcontroller I/O Lab

This simulator models an STM32F401-style embedded control bench — a 3.3 V microcontroller reading a potentiometer and a TMP36-style temperature sensor, running a timer-driven firmware scheduler, and driving a 12 V brushed DC motor with encoder feedback and a 5 V hobby servo — so you can see exactly how sampling, timing, control logic and real-world electrical faults interact.

What the simulator shows

• A live 3D control-bench diagram (drag to orbit, pinch to zoom; Board view / Actuator view / Auto orbit / Expand controls) with selectable components and a component-info callout. • Four control applications — Potentiometer → motor PWM, Manual motor duty, Temperature → cooling fan, and Encoder → PI speed control — each with its own sliders (potentiometer, temperature, manual duty, speed target, mechanical load), Arm/Disarm outputs, Run/​+20 ms/​+1 second/​Reset controls, and a 1×/5×/20× time scale. • Live sensor-to-control readouts with ADC math shown explicitly, command-vs-physical-response comparisons, and a debounced push-button with independently modeled 10 ms contact bounce. • Eleven injectable faults — analog noise/aliasing, an open or shorted temperature sensor, a missing button pull-up, an open or shorted motor MOSFET driver, a disconnected motor wire, a jammed motor shaft, missing encoder feedback, a jammed servo, and a hung firmware loop — plus adjustable MCU/ADC reference and motor supply voltages, an independent motor-isolation E-stop, and a protection-latch reset. • A signals & timing tab: a logic analyzer reconstructing PWM edges at three time windows, a live history chart (true/measured motor speed, current, duty, ADC code, or raw/debounced GPIO), and a UART 8-N-1 terminal with history export. • A firmware & pins tab exposing ADC bit depth, sample/release period, control-job time, debounce time, PWM frequency, UART baud, an independent 500 ms watchdog toggle, and PI gains (Kp/Ki), alongside a functional pin map, a plain-language firmware sequence, and the governing timer/PWM/ADC formulas. • A tests tab with a 16-check isolated verification bench, and a How it works tab documenting the represented hardware and explicit model boundaries.

How the sample-decide-actuate loop works

A hardware timer periodically releases an ADC scan of the potentiometer and temperature inputs; if the previous control job is still executing when a new release arrives, that release is dropped and counted as an overrun rather than queued. The ADC codes are latched and handed to a control task that runs for its configured execution time, validates the inputs, computes a duty cycle or PI correction, and writes new timer compare values — after which it feeds an independent watchdog and can enqueue telemetry. Hardware timers and the UART continue operating on their own between control-task completions, which is why a hung firmware loop and a stopped watchdog feed are two separately observable failure modes.

The governing relationships are explicit: timer_hz = 84 MHz / (PSC + 1), PWM_hz = timer_hz / (ARR + 1), duty = CCR / (ARR + 1), and the ADC code = floor(Vin / Vref × 2ᴺ), clamped to the configured bit depth. Because the motor uses an active-low GPIO with a pull-up and a MOSFET driver with a flyback diode, several faults — a shorted MOSFET in particular — can energize the motor even while firmware reports Disarm, which is exactly why an independent series isolation path exists outside firmware's control.

What this model is and isn't

Representative hardware includes a Cortex-M-style 3.3 V MCU, a 10 kΩ potentiometer, a TMP36-style analog temperature sensor, a pull-up button, a status LED, a timer-driven MOSFET motor driver with flyback protection, a brushed DC motor with encoder, and a separately powered hobby servo — all following an averaged electrical/mechanical model. PWM edges are reconstructed exactly from timer settings, but switching ripple, flyback transients, electromagnetic interference, thermal damage, and MCU instruction-level timing are not solved. This is a teaching pin map and functional model, not a register-level MCU emulator, a vendor board pinout, an electrical safety approval, or a flashable firmware project, and the protection logic is explicitly a teaching model rather than a certified safety circuit.

Frequently asked questions

Why can a shorted motor MOSFET energize the motor even after Disarm?

Firmware's Disarm command only controls the MOSFET's gate signal — it cannot open a MOSFET that has failed shorted. That is exactly why the lab includes an independent series isolation/protection path: it can interrupt the current physically, whereas firmware-level Disarm or even an MCU reset cannot stop current already flowing through a failed shorted switch.

What happens if a control-task release overlaps with the previous one still running?

The scheduler model permits only one active control job at a time. If a new timer release arrives before the previous job finishes, that release is dropped and counted as an overrun rather than being queued or interrupting the running job.

Why is the watchdog fed only after successful control-task completion?

Feeding the watchdog from an unrelated, always-running source (like a separate timer interrupt) could keep resetting it even while the control task itself has hung, hiding a real firmware fault. Feeding it specifically after the control task completes successfully means a hung loop will let the watchdog expire and reveal the fault.

How does increasing PWM frequency affect available duty-cycle resolution at a fixed timer clock?

PWM period in timer counts is timer_hz / PWM_hz, so a higher PWM frequency means fewer timer counts fit in each period. Since duty cycle is set as CCR / (ARR + 1), fewer available counts per period means fewer distinct duty-cycle steps are achievable at that frequency.

Related tools & guides