The most useful fact about modern electronics is that almost nothing is one chip. Look inside a quadcopter and you'll find a flight controller talking to four electronic speed controllers over UART, talking to a GPS module over UART, talking to a telemetry radio over UART. Look inside a 3D printer and the main board uses UART to drive each stepper motor's driver chip. Your phone talks to the SIM card over UART. Your laptop's keyboard talks to its embedded controller over UART. UART is everywhere because composing small chips is cheaper than designing one big one.

The smallest possible model

Two Arduino Unos, one wire from D1 (TX) on the first to D0 (RX) on the second, a common ground tied between them. That's a complete UART link. The sending chip writes a byte to its UDR register; its USART peripheral shifts the byte out as voltage transitions on TX; the receiving chip's USART samples the transitions, reassembles the byte, and makes it available through Serial.read(). Same protocol that drove teletypes in 1962; same wires.

In SimDuino, when the multi-runner finds a wire connecting Uno A's D1 to Uno B's D0, it installs runnerA.usart.onByteTransmit → runnerB.usart.writeByte. The byte's protocol-level journey matches real silicon: A's program writes to UDR; the byte appears in B's UDR; B's USART_RX ISR fires; the Arduino library pushes the byte into B's software ring buffer; B's loop() reads it with Serial.read(). Every register-level step matches the datasheet — what the simulator idealizes is timing: in the sim the byte crosses the wire in one CPU cycle (~62 ns simulated); in real hardware it takes one bit-time per bit, about 1.04 ms total at 9600 baud. Protocol behavior is faithful; sub-millisecond UART timing isn't.

Why this composition is everywhere

One reason is cost. A specialised motor driver chip can include features (current sensing, microstepping, thermal protection) that would crowd a general-purpose microcontroller. Let the main chip do the high-level control and offload the time-critical pulse generation to a dedicated driver. Each chip is cheap because each is mass-produced for its niche.

Another reason is robustness. If the GPS module crashes, your flight controller still flies — it just stops trusting GPS data until the module reboots. If the keyboard controller hangs, your laptop's main CPU keeps running. Decoupling subsystems means failure stays local.

A third reason is concurrency. Each chip runs its own loop at its own rate. The motor driver might toggle pins at 50 kHz while the main chip is computing trajectory at 100 Hz. Trying to do both on one CPU means hand-coding tight interrupt service routines and worrying about whether the slow loop blocks the fast one. Splitting the work gives each chip its own dedicated mainloop.

The serial monitor is the protocol analyzer

What makes the demo powerful as a teaching tool is that you can see both sides at once. Serial A shows the bytes A sent. Serial B shows the bytes B received plus B's own log of what it decided to do. If A is sending characters and B is reading garbage, the two monitors immediately reveal whether the bug is in the sender, the receiver, or the wire. You can replace either sketch and watch how the other reacts. Once you've debugged your first UART link this way, you've debugged every UART link you'll ever build.