Final examination & D3: one day, two proofs
420-302-VA · WEEK 13 · FALL 2026

Stage 2 of 6 · The synthesis · read before any rereading

One system, one story

Twelve weeks taught twelve subjects, and the exam will test one system. The strongest review move is to collapse the subjects back into the thing they always were: a single causal chain you can narrate hop by hop, with the governing number at each hop. Once the story runs in your head without notes, every topic has an address in it, and recalling a fact becomes walking to where it lives.

Why one story beats twelve summaries

Memory research and bench experience agree here: isolated facts decay, and facts woven into a causal structure prop each other up, because each hop cues the next (shade the LDR and you cannot help but remember what the divider does to the voltage, which cues the ADC, which cues the averaging). The same structure is how exam questions are built: almost every question is a zoom into one or two hops of this chain, asked forward (what happens next?), backward (what caused this reading?), or broken (which hop failed?). Learn the chain once and you have pre-answered the framing of most of the paper; the Week 12 half-splitting page already taught you to navigate it under the third framing.

The journey: photon to pixel

The full system as a fourteen-hop journey in three rows. Row one, on the node, Week 8: light falls on the LDR; the divider turns resistance into voltage; the ADC on GPIO34, ADC1, turns voltage into a count among 4096 levels; read underscore avg of 16 samples tames the noise; the LightNode object converts to percent. Row two, across the network, Week 9: publish to bench slash s07 slash light; Wi-Fi carries it; the broker at port 1883 routes it to every subscriber. Row three splits: the control branch, Week 10, monitor parses, the rule computes u, publishes the command on cmd, the node's check underscore msg obeys, PWM on GPIO25 acts, and the world changes, closing the loop back to the LDR; the showing branch, Week 11, the bridge keeps latest, serves slash api slash light on port 5000, the page fetches every two seconds, and the pixel changes. On the node · Week 8 light → LDRresistance moves dividerR → voltage ADC · GPIO344096 levels · ADC1 read_avg(16)noise ÷ √16 = 4 LightNode → %dark/bright calibration Across the network · Week 9 publish bench/s07/lightabout once a second Wi-Fi · 2.4 GHzkeepalive 30 s · LWT waits broker · :1883routes to every subscriber Deciding & acting · Week 10 monitor parsesbytes → float · W6 callbacks rule computes uthreshold or PID · e = SP − PV cmd · "sp:N" "duty:N"check_msg obeys PWM · GPIO25duty = brightness …and the world changes, which the LDR sees: the loop closes Showing · Week 11 bridge keeps latestpush world → ask world /api/light · :5000fresh JSON on request fetch, every 2 sthe page asks; HTTP answers the pixel changes≤ 3 s after the photon
Fourteen hops, every number in place. Shade the sensor and this entire figure happens: the fast red dashed loop closes through the world in tenths of a second; the blue showing branch reaches a phone within about three, one publish interval plus one poll interval. Narrating this figure aloud, hop by hop, is the single highest-value rehearsal this hub offers.

Practice the narration in all three exam directions. Forward: start at the photon, speak every transformation. Backward: start at a pixel showing 62 % and account for where that number has been. Broken: pick any hop, imagine it failing, and name the symptom each later hop would show, which is Week 12's half-splitting run in reverse.

The two loops

The deepest structural fact of the course, and the one that organizes the most exam material, is that the system is two loops sharing a sensor, running at speeds roughly an order of magnitude apart:

Two concentric loops around the world and the sensor. The inner, fast control loop, drawn solid green: sensor to rule to actuator to world and back, labelled machine speed, about ten readings a second on the node, publishes about every second, MQTT push, no human needed. The outer, slow human loop, drawn copper: sensor to bridge to page to human eye, and the human's hand back through the setpoint POST to the cmd topic to the rule, labelled human speed, polls every two seconds, HTTP ask, changes the target not the action. A caption states that the two meet at exactly two places: the shared PV and the setpoint. the world+ sensor · the shared PV the control loop · machine speed ruleu = Kp·e + … actuator · PWM node reads ~10×/s · publishes ~1/s · MQTT pushes · no human in it the human loop · human speed bridge · /api page · fetch 2 s the human decides eye reads the chart · hand POSTs a new setpoint → "sp:N" on cmd → the rule's target moves meet here: the PV and here: the SP
Fast loop acts, slow loop supervises. The green loop fights disturbances by itself at machine speed over MQTT's push; the copper loop lets a human watch and move the target at human speed over HTTP's ask. They touch at exactly two points, the PV both observe and the SP the human may move, and that separation is why each protocol is where it is.

Hold this figure against any "why" question from the last five weeks and it answers: why two protocols (each loop got the pattern matching its rhythm, Week 11's two-patterns argument), why the supervisory setpoint travels over cmd while control stays local (the fast loop must survive the slow one disconnecting, Week 10's fast-local rule), why polling at 2 s is honest engineering rather than waste (the human loop needs human speed, nothing more), and why the dashboard's reading may lag ~3 s while the LED answers in a blink (count the loop each signal rides).

Where each week lives in the story

WeeksHops ownedThe one-line summary the story compresses to
8Photon → percentThe analog world enters: divider, ADC1 under Wi-Fi, averaging, and a class that speaks percent
9Percent → every subscriberThe bench becomes a network: topics, QoS, retained, LWT, and a broker with two walls
10Reading → actionThe loop closes: error, three terms, tuning, and the supervisory pattern over cmd
11Reading → pixel, hand → setpointThe human loop: Flask, the bridge between push and ask, and a dashboard that steers
12All hops, joined and kept aliveThe method: skeletons, one join at a time, half-splitting, and services that survive the night
1–6 · via W7Everything underneathGit, the Pi, the terminal, Python, GPIO and objects: the floor the story stands on

Checklist for this stage

Check yourself

The dashboard reads 62 %. Account backward for that number through four transformations, with the governing fact at each.
The pixel shows what the last fetch (within the past 2 s) got from /api/light, which returned the bridge's latest, updated at the last publish (within about 1 s), so the number is at most ~3 s old. The published 62 came from LightNode mapping a raw reading onto the dark-to-bright calibration span. That raw reading was read_avg's mean of 16 ADC samples, noise cut by √16 = 4. Each sample was the 12-bit ADC on GPIO34 (ADC1, so Wi-Fi-safe) placing the divider's voltage on one of 4096 levels; and the divider's voltage followed the LDR's resistance, which followed the light. Five sentences, the whole top half of the figure.
Why would moving the rule into the browser's JavaScript break the system's design, in two-loops terms?
It would weld the fast loop to the slow one: control would now run at the human loop's rhythm (a 2 s poll, on a page that must be open, on a device that sleeps), so disturbances between polls go unanswered, closing a laptop lid turns the actuator off in effect, and the system fails Week 10's fast-local rule, that the control loop must survive the supervisory layer disconnecting. The design keeps the rule beside the broker at machine speed and gives the human loop exactly two levers, watching the PV and moving the SP, which is the whole meaning of "supervisory".
Name the two places the loops meet, and explain why the SP meeting point travels over MQTT's cmd topic rather than being written by Flask directly into the rule program's memory.
They meet at the PV (both loops read the same sensor's value) and at the SP (the human loop may move the target the fast loop pursues). The setpoint travels as a cmd message because the bridge and the rule are separate programs, by design, since Week 10 split deciding from showing; MQTT is the course's one mechanism for programs to talk without sharing memory, and a "sp:N" message keeps the contract written, observable on the firehose, and stubbable with mosquitto_pub. Writing into shared memory would work only by merging the programs, trading away the decoupling that lets each be probed, restarted and owned separately, which Week 12 turned into services.