Interactive course · ~6 hours

Embedded Systems and Microcontrollers

A microcontroller is a whole computer on one chip, and you can buy one for the price of a sandwich. It has a processor, a little memory and a row of metal legs called pins. Those legs are the interesting part. With them a chip can light a lamp and feel a button. It can dim a light, point an arm at an exact angle, spin a motor both ways, and walk a stepper to a tenth of a degree. It can ask a sensor how warm the room is, and restart itself when it goes wrong. One simulated board and a parts list at the end.

How this works

One simulated board runs through every step. You write the firmware yourself in an editor and press Upload and run. The board records what every pin did, with times attached, so you can play the run back and slide through it while the LED, the servo horn, the motor and the pen move. Several steps hand you a sketch that is already broken on purpose, because the fastest way to understand what pinMode is for is to watch a board ignore you without it.

What you need to know first

No electronics background, and no soldering iron. It helps to have done Build a Microprocessor, since this course starts where that one stops: the processor inside the chip is the machine you built there, and the pins are new. Every electrical word, from volt to inductance, is explained where it first appears. So is every piece of the programming language, from what a function is to what === means.

The steps

Step 1

Make a pin push 3.3 volts, and measure it

A microcontroller is a processor, some memory, and a row of metal legs. The processor part is the machine from Build a Microprocessor, doing what it did there. The legs are the new thing. They are the only way the chip can reach anything outside itself. Each leg is called a pin, and each one has a number printed next to it on the board.

A pin that the chip is driving is doing one of exactly two things. Either the chip has connected it to the supply rail, which on this board sits at 3.3 volts, or it has connected it to the ground rail, which sits at 0 volts. Writing a 1 from your program picks the first. Writing a 0 picks the second. There is no third setting and nothing in between.

What is a volt, actually?

Voltage is electrical push, measured between two points. A single AA cell pushes with 1.5 volts. Two of them in a line push with 3 volts. The board here runs on 3.3 volts, which is a small, safe push: you can hold both rails at once and feel nothing at all.

Push on its own moves nothing. Current is what flows when the push has somewhere to go, and it is measured in amps, or more usefully for small parts in milliamps, thousandths of an amp. A pin can supply roughly 20 milliamps before it complains, which is enough for an indicator lamp and nowhere near enough for a motor. That gap is the whole of Step 8.

So a bit is not an idea trapped inside the machine here. It is a voltage on a piece of metal, and you can put a meter on it. Do that first.

What is a bit, and what is a byte?

A bit is one thing that has two possible states, written 0 and 1. A light switch is a bit. A pin held low or high is a bit. One bit on its own can only ever say one of two things, so bits are used in groups.

Eight bits side by side is called a byte. Eight switches with two settings each give 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 = 256 different patterns. So a byte can hold any whole number from 0 to 255. The second lab in this step builds a byte out of eight real pins, one voltage each.

Why does the lamp need a resistor in front of it?

The lamp here is an LED, a part that gives out light when current runs through it the right way. An LED has no sense of moderation: offer it more current and it takes more, until it destroys itself. So a resistor goes in the path to limit how much current can flow. Resistance is measured in ohms, and the standard part for this job is 220 ohms.

The arithmetic is one division. An LED drops about 2 volts across itself, leaving 1.3 volts of the 3.3 to push current through the resistor. Current equals volts divided by ohms, so 1.3 divided by 220 gives about 0.006 amps, which is 6 milliamps. Comfortably bright, and comfortably inside what a pin can give. The lab shows that number as you toggle the pin.

Lab 1 · A bit, with a meter on it
Try this firstPress Toggle pin 13. The number on the voltmeter changes from 0.00 V to 3.30 V, and the LED wired to that pin lights up. Then use the Touch the probe to menu to move the probe onto pin 12, which you have not touched.
Notice the pill that says what bit the voltage would be read as. It flips at 1.65 volts, halfway up. The button labelled Wire the LED to pin 13 is a switch: press it once and the LED is unplugged, and pin 13 carries on swinging between the rails with nothing watching it. The pin does not know or care whether anything is connected.
Lab 2 · Eight pins make a byte
Try this firstClick the square on the far left. It changes from 0 to 1, and the reading under the row jumps to 128. Then press Give me a number to make and set the eight squares until the number underneath matches the one you were given.
Notice what each square is worth: 1, 2, 4, 8, 16, 32, 64, 128, doubling every step to the left. Turn them all on and they add to 255, which is why a byte stops there. This is the same counting in twos you would use to read a binary number, except that here each digit is a real piece of metal at a real voltage.
A friend measures a pin on a 3.3 volt board and finds 1.9 volts, and yet the program reads that pin as a 1. What is going on?
Above halfway counts as a 1. The chip has a threshold, around 1.65 volts here, and anything above it reads as 1 while anything below reads as 0. That tolerance is what lets a board still work when a long wire or a tired battery drags the level down a little. It is also why a pin connected to nothing at all is dangerous: it can wander across that line by accident, which is Step 4.
Step 2

Choose your first board without guessing

There is no best board, and anyone who names one without asking what you are making is guessing. There is a board that fits the thing you want to build, and finding it means saying out loud what the thing has to do and then reading numbers.

Five numbers do most of the work. The price. The clock speed in megahertz, which is millions of steps a second. The flash, which is the memory that holds your program even with the power off. The RAM, which is smaller, faster memory holding the values the program is working with right now and forgetting them the instant power is lost. And the current the chip draws while asleep, which decides on its own whether a battery lasts a week or a year.

What is a megahertz?

Hertz means once per second. A kilohertz is a thousand times a second and a megahertz is a million times a second. A board at 16 megahertz takes sixteen million small steps every second, and each step does a tiny piece of work such as adding two numbers or fetching one from memory.

Sixteen million sounds like plenty, and for blinking a lamp it is absurdly more than enough. It runs out when you ask for arithmetic on every one of a thousand sensor readings a second, or when you want a screen redrawn smoothly. Most beginner projects never notice the difference between 16 and 240.

Why does a board have two different kinds of memory?

Flash keeps what is written in it with no power, like a notebook. That is where your program lives, so the board still knows what to do when you plug it in tomorrow. Writing to flash is slow and it wears out after many thousands of rewrites, so a program is written once when you upload it and then only read.

RAM forgets everything the moment the power goes, like a whiteboard, and in exchange it is fast and can be rewritten endlessly. Every value your program keeps while it runs lives there. RAM is the number that usually runs out first: 2 kilobytes, which is 2048 bytes, disappears quickly once you want to remember a few hundred sensor readings.

How much is a microamp, and why does it decide a battery project?

A milliamp is a thousandth of an amp. A microamp is a millionth of an amp, so a thousand microamps make one milliamp. Battery size is quoted in milliamp hours: a coin cell holds about 220 milliamp hours, meaning it can give 220 milliamps for an hour, or 1 milliamp for 220 hours, and so on.

Now the arithmetic. A board that draws 30 milliamps flattens that coin cell in about seven hours. A board that sleeps at 10 microamps, which is 0.01 milliamps, would take 22000 hours, which is over two years. Same job, same cell, and the only thing that changed was one column in the table below.

Lab 3 · An honest comparator
Try this firstDrag Needs wireless all the way to the right. The table reorders itself and the line underneath names the winner and says which of your settings decided it. Now drag Runs on a battery up as well and watch the winner change again.
Notice the "asleep" column. One board sits at 30 milliamps and another at 10 microamps, three thousand times apart, and none of the other columns come close to that spread. Notice too that when you set everything to zero the ranking still moves as you nudge one slider, because the score is computed from the table rather than looked up.
Lab 4 · Match the job to the board
Try this firstRead Job 1, then press the button for the board you would actually buy. It answers straight away, and when you are wrong it names the board that fits and explains which number in the job decided it. Press Next job for the next one.
Notice how often the slow cheap board is the right answer. A faster chip is only better when something in the job needs the speed, and for a doorbell nothing does. What that job needs is the board with the most tutorials written about it, which is a real engineering property even though no datasheet lists it.
A sensor is buried in a plant pot, running from one coin cell, waking for one second every hour for a year. Which number decides whether it manages that?
The sleeping current. Add it up: one second awake per hour is one part in 3600 of its life, so whatever it draws for the other 3599 seconds is what empties the cell. Clock speed only matters during that one second and is swamped. Flash size has nothing to do with power at all, and picking it here is the mistake of choosing the number that sounds the most impressive.
Step 4

Read a button, and stop the pin from guessing

Pins go both ways. Told to be an input, a pin stops pushing and starts listening. digitalRead then hands your program a 1 if the voltage on that pin is above the halfway mark, and a 0 if it is below. That is all a chip can tell you about the outside world through one pin.

A push button is not clever. It is two pieces of metal that touch while your finger is down and spring apart when you let go. Wire one between a pin and the ground rail and the pin is dragged to 0 volts while you hold it. So far so good.

Now ask the awkward question. When the button is open, what is that pin connected to? Nothing. And a pin connected to nothing does not read 0. It reads whatever it feels like.

What does === mean, and why three of them?

A single = puts a value into a name: count = 0 means make count hold zero. Three of them is a question rather than an order. digitalRead(2) === LOW asks whether those two things are the same, and the answer is either true or false. Using one where you meant three is a classic bug, which is why the question form is deliberately different to look at.

if takes such a question and runs the block after it only when the answer is true. else supplies a block to run instead when the answer is false. So an if with an else always runs exactly one of the two blocks, never both and never neither.

What is a pull-up resistor, and how can it be overruled by a finger?

A pull-up is a resistor from the pin up to the 3.3 volt rail. While the button is open it is the only thing connected to the pin, so it holds the pin high and the reading is a steady 1. It works because nothing needs to flow: the pin is only listening, so a very weak connection is plenty.

Press the button and the pin now has two things attached: 10000 ohms up to 3.3 volts, and near zero ohms straight down to ground. The direct path wins, and the pin sits at 0 volts. A tiny current trickles down through the resistor while you hold it, about a third of a milliamp, which is why the resistor is chosen large. Most chips have such a resistor built in, switched on by asking for INPUT_PULLUP instead of INPUT. Then you need no extra part at all.

Why is a pressed button a 0? That feels backwards.

It is backwards, and it is normal. With a pull-up the resting state is high, so pressing is the thing that pulls the pin down. Open reads 1, pressed reads 0. Nothing is wrong with the wiring and nothing can be done about it except to write the code that matches.

You could wire it the other way, with a pull-down resistor to ground and the button going up to 3.3 volts, and then pressed would read 1. Almost nobody does, for one reason: the pull-up is already inside the chip and free and the pull-down is not. A whole industry reads its buttons upside down to save a part.

Lab 7 · A pin with nothing holding it
Try this firstLeave No resistor selected and press Take 60 more readings three times. Sixty readings of the same untouched pin, and they disagree with each other every time. Then press Hold the button down, and after that try Pull-up to 3.3 V.
Notice the pill counting changes between readings. With no resistor it is high and never the same twice, because the pin is floating: nothing joins it to either rail, so it drifts on whatever electrical hum is in the room. With a pull-up fitted it drops to 0 changes, and the readings become boring, which is exactly what you want from a button.
Lab 8 · Light the lamp only while it is held
Try this firstPress Upload and run and watch the trace. The LED is on while the button is open and off while the finger is down, which is exactly backwards. Change the one comparison inside loop, upload again, then press Check my answer.
Notice how the checker tests it. It samples the recorded LED state at ninety-odd moments across two seconds, including inside both presses and in the gaps between them, and it wants the lamp to match the finger at every single one. Being right during the press and wrong in the gaps does not pass.
A button is wired between pin 4 and the ground rail, and setup says pinMode(4, INPUT). The program reads the pin a hundred times while nobody touches it, and gets a mixture of 0s and 1s. Why?
The pin is floating. An open button leaves it joined to nothing, and a pin joined to nothing picks up whatever electrical noise is nearby, so the answer is a coin toss each time you look. Asking for INPUT_PULLUP gives it something weak to hold on to and the readings go still. The button is fine, and reading speed does not come into it: a pin that is being held properly reads the same value a million times in a row.
Step 5

Count one press as one press

Now count presses. Keep a counter, which is just a name holding a number, and add one to it every time the pin falls from high to low. It is three lines of program and it does not work.

Inside a push button are two springy pieces of metal. On the way together they touch, bounce apart, touch again, and do that a handful of times over a few thousandths of a second before they settle. Your finger went down once. The pin saw the level fall five or seven times.

What is a counter, in program terms?

A name that holds a number, and a line that replaces what it holds with one more than that. count = count + 1 reads the current value, adds one, and puts the result back under the same name. The name is called a variable, because what it holds varies.

A counter declared outside every function, at the top of the sketch, keeps its value between one pass through loop and the next. One declared inside loop would be created fresh each pass and would never get past 1, which is a bug worth knowing about before you write it.

Why does metal bounce at all?

Because the contacts are springs. They have to be, or they would not push back against each other hard enough to make a reliable connection. A spring that arrives at a stop does not simply stay there, it rebounds, and while it is in the air the circuit is open again.

The bouncing dies away as the energy goes, which is why the gaps in the lab below get shorter each time. Bigger switches bounce for longer, worn ones bounce worse than new ones, and no switch has a published bounce time you can rely on. That is the point: this is a physical effect you design around rather than a number you look up.

Why is a window that is too long the worse bug?

The fix is a lockout: the moment you believe the pin has changed, stop looking at it for a while. That covers the way back up as well, because letting go bounces too. Too short a lockout and bounces slip through, so a counter reads six for four presses. That is annoying and obvious, and whoever is testing it notices immediately.

Too long a lockout swallows real presses that happen close together, so the counter reads three for four presses. Nothing on screen looks wrong, no reading is impossible, and the missing press leaves no trace. A bug that produces a plausible wrong answer survives testing much longer than one that produces an obviously wrong one.

Lab 9 · One press, seven presses
Try this firstPress Press the button once. One finger went down, and the trace shows the level falling several times in a few thousandths of a second. Press it again a few times: the number of falls is different every press. Then press Zoom out to 40 ms.
Notice what the bounce looks like once you zoom out. At 40 milliseconds wide the whole burst collapses into one thin vertical smudge. Nobody finds this bug by looking at their circuit or their trace. They find it when a counter says seven and a finger says one.
Lab 10 · The debounce window
Try this firstDrag ignore changes for (ms) up from zero slowly and watch the pill that says how many were counted. Four fingers really went down. Find the range of windows that reports 4, then keep going past it.
Notice both walls you are between. The bouncing sets the floor: the last pill measures the worst burst for you, and any window shorter than that lets bounces through. The ceiling is the 100 milliseconds between the finger coming off the third press and going down on the fourth, because a lockout longer than that is still ignoring the pin when the real press arrives. Any window in between works, and the reason people pick 20 or 50 is that it is comfortably inside both walls rather than because those numbers are special.
A vending machine counts coins with a switch and a 250 millisecond lockout. Customers complain that two coins dropped quickly only register as one. What is the fix?
Shorten it. A lockout only has to outlast the bouncing, which is a few milliseconds, and every millisecond beyond that is time in which a real event can be thrown away. Making it longer makes the complaint worse, which is the tempting answer because the machine is already missing things. Removing it altogether brings back the original bug, where one coin counts as several.
Step 6

Dim an LED without changing the voltage

A pin has two settings. It cannot sit at half a volt, and it cannot give out half a light. So how does every gadget in your house dim its lamps?

By switching. Turn the pin on and off hundreds of times a second, and choose what fraction of each cycle it spends on. On for a tenth of each cycle and the lamp is dim. On for nine tenths and it is nearly full. That fraction has a name, the duty cycle, and the whole technique is called pulse width modulation, usually shortened to PWM. analogWrite(9, 128) asks for about half.

Why does fast flashing look dim rather than flashy?

Your eye adds up light over a short window, roughly a fiftieth of a second, and reports the total. Anything that flashes faster than that arrives inside one window and gets averaged. A lamp that is on for half of every cycle delivers half the light, and half the light is what you see: a steady dim lamp.

Below about 25 cycles a second the flashing lands in separate windows and you see it as flicker. This is not a property of the lamp, it is a property of you, which is why the lab lets you drag the frequency down until your own eye gives up.

Why 0 to 255, and not 0 to 100?

Because the setting is stored in one byte, and a byte holds 0 to 255. That is the natural size for the hardware that makes the pulses, so it is the size the function takes. 0 means never on. 255 means always on. 128 means on for a hair over half of each cycle, because 128 out of 255 is a shade more than half.

Doing the sum the other way is worth a moment: 200 out of 255 is about 78 hundredths, so analogWrite(9, 200) averages about 78 hundredths of 3.3 volts, which is 2.6 volts. The pin never once visits 2.6 volts. That is what the average of a square wave means.

What are let and while?

let b = 0; makes a new name and puts zero in it. Names made with let inside a function exist only while that function is running, which is fine for something being counted up right now and wrong for something that has to be remembered between passes.

while (b <= 250) { ... } runs the block, checks the question again, and keeps going for as long as the answer is true. Something inside the block has to move towards making it false, or the loop never ends. In the fade below, that something is b = b + 10, which is what eventually pushes b past 250 and lets the loop finish.

Lab 11 · The duty cycle
Try this firstDrag analogWrite value (0 to 255) to about the middle. The trace shows the pin high for half of each cycle, and the lamp settles at about half brightness. Now drag cycles per second (Hz) down below 25 and watch the lamp start to flicker.
Notice the pill giving the average voltage. At 128 the pin is still only ever at 0 volts or 3.3 volts, and the average works out at 1.66. Nothing on the board is producing 1.66 volts. The averaging is being done by your eye, and a motor would do the same averaging with its own weight and friction.
Lab 12 · Make it breathe
Try this firstPress Upload and run. The lamp comes on at full brightness and stays there, because the sketch only ever asks for 255. Make the brightness slide up and then back down, upload again, and press Check the fade.
Notice what the checker measures: how many different brightness values pin 9 was given, how close it got to 0 and to 255, and whether it went both up and down. Any code that does those things passes, including code that looks nothing like the published answer, because the marking is on what the pin did rather than on what you typed.
You call analogWrite(9, 64) and put a very fast meter on pin 9. What does the meter see?
Fully on for a quarter, fully off for three quarters. The pin never visits anything between the rails. A slow meter, or an eye, averages that to about 0.83 volts, and it is the average that the brightness follows, so the first answer is what you would measure with the wrong instrument. The third answer mixes the two ideas up and describes something no pin can do.
Step 7

Point a servo horn at an exact angle

A servo is a box with a motor, a gearbox, a sensor that knows where the output shaft is, and a small controller, all in one. Because of that sensor it takes a different kind of order from a plain motor. You do not tell it how fast to turn. You tell it where to point. It works out the rest and holds position.

The order arrives as a pulse: the signal wire goes high, stays high for a set time, then goes low. A pulse 1 millisecond wide means go to one end of the travel, 2 milliseconds means the other end, and 1.5 milliseconds means the middle. The width is the whole message.

And the pulse repeats, about every 20 milliseconds, whether the angle changed or not.

How is a pulse different from just setting a pin high?

Only in that you are paying attention to how long it lasts. A pulse is a pin taken high and then put back low, and its width is the time it spent high. Setting a pin high and leaving it there is a pulse that has not ended yet.

What makes it useful is that time is easy to measure precisely and voltage is not. A wire loses a little voltage along its length and gains a little noise from its neighbours, but 1.5 milliseconds is 1.5 milliseconds at both ends of the wire. Sending information as a duration rather than as a level is a trick that turns up everywhere once you have seen it.

Why send the pulse again if the angle has not changed?

Because the servo forgets. Its controller expects a fresh instruction every 20 milliseconds or so, and after about a tenth of a second of silence it stops pushing and goes limp. That sounds like a flaw and is a safety feature: a servo that lost its signal wire would otherwise keep straining against whatever it was last told, quietly cooking itself.

The repetition is also what lets a servo hold against a push. Each new pulse is compared with where the shaft actually is, and if a hand has moved it, the controller drives it back. A plain motor told to move and then left alone has no idea it has been pushed.

Why does a servo get its own power supply?

A small hobby servo pulls a few hundred milliamps while moving and can spike over an amp when it is pushing against something. A pin can supply about 20. Powering a servo from a pin does not work at all. Powering one from the board's own supply usually drops the whole rail far enough to reset the chip, which looks like a firmware bug and is not one.

So the servo takes its power and ground straight from a supply, and only its signal wire goes to a pin. The one wire that must be shared is ground. Two circuits with no common ground have no agreement about what 0 volts means, so the servo cannot tell how high your pulse is.

Lab 13 · The pulse that sets the angle
Try this firstPress the 0 degrees button, then 180 degrees, then 90 degrees. The horn swings, and the dashed mark on the trace slides between 1.00 ms and 2.00 ms. Then drag angle you ask for slowly across and watch the mark follow it.
Notice that the frame stays 20 milliseconds wide throughout. Only the high part changes width. The pill reports the pulse as between 5 and 10 percent of the frame. So a servo is told everything it knows in a twentieth of the time available, and spends the rest acting on it.
Lab 14 · Sweep it
Try this firstPress Upload and run. The horn snaps from one end to the other and back with nothing in between, because the sketch only ever asks for 0 and 180. Make it move in small steps instead, upload again, then press Check the sweep.
Notice what the checker rejects. Fewer than about thirty different angles, or any single jump bigger than 10 degrees, and it says so. Smoothness is not a feeling here. It is a measured limit on how far the horn is asked to move in one instruction. Underneath every one of those small moves is a pulse between 1.00 and 2.00 milliseconds.
Someone doubles the voltage on a servo's signal wire, hoping the horn will move further. What happens to the angle?
The angle does not change. Width carries the order, and height only has to be enough to be read as a 1. Doubling it changes no timing at all. On a 3.3 volt part it is also a reliable way to destroy the part, so this is an experiment for a simulator rather than a desk. If you want the horn further round, make the pulse wider.
Step 8

Spin a motor both ways without killing a transistor

A plain DC motor is simpler than a servo and harder to drive. Put voltage across it and it spins. More voltage, faster. Swap which side is positive, and it spins the other way. It has no sensor, no controller and no opinion.

Two things stop you wiring one to a pin. It wants hundreds of milliamps and a pin has twenty, and a pin cannot swap its own polarity. Both are solved by four switches arranged in the shape of an H, with the motor as the crossbar. Close the top left and bottom right and current runs one way through the motor. Close the other pair and it runs the other way. That arrangement is called an H-bridge and the four switches in it are transistors. A transistor is a switch with no moving parts: a voltage on one leg decides whether current can flow between the other two. A pin can supply that deciding voltage easily and the current being let through can be far more than the pin could ever carry itself. On a diagram the four are labelled Q1 to Q4, which is what the buttons in the lab are called.

Then there is the part that destroys hardware. A motor winding is a coil of wire, and a coil objects strongly to having its current stopped.

Have I met a transistor before?

You are made of them. A transistor is the same part your processor is built out of, in its millions, switching billions of times a second. The ones in a bridge are simply much bigger, because a switch that carries an amp has to be built to carry an amp, while a switch that only feeds the next switch does not. Same idea, wildly different size.

Q is the traditional letter for a transistor on a wiring diagram, which is why the four are Q1 to Q4 rather than S1 to S4. In a real project you rarely wire four of them yourself. You buy a driver chip with all four inside, and the reason is in the next two notes.

Why does a coil fight back when you switch it off?

A coil with current running through it stores energy in a magnetic field, and it will do whatever it takes to keep that current flowing for a moment longer. This property is called inductance, measured in henries and a small motor's winding is about 0.0015 henries.

The voltage it produces is the inductance multiplied by how fast the current changes. Stop 0.9 amps in about a millionth of a second and that comes out at over a thousand volts, appearing across the switch that just opened. A transistor rated for 40 volts does not survive that, and the failure happens at switch-off rather than during running, which is why it is so puzzling the first time.

What does a flyback diode do about it?

A diode is a one way valve for current. Fitted across each switch the wrong way round for normal operation, it does nothing at all while the circuit is running. The instant a switch opens and the coil starts pushing, the diode becomes the easiest path available and the current runs round through it instead, dying away in the resistance of the winding.

With that path available the coil never has to produce a big voltage, because it never has to force current through anything that is refusing to carry it. The spike stops at about a volt above the supply. The lab shows both cases, and shows the number.

Lab 15 · The bridge, and the spike
Try this firstPress Q1 open, then Q4 open. Both buttons change to closed, the motor starts turning, and the pills report 3.3 volts across it. Now press Q4 closed to open that switch again while the current is still flowing, and read what happens to the transistor.
Notice the pill reporting the last spike. Press Fit a new transistor, then Fit the flyback diodes, and do the same thing again: the spike stops at about 4 volts and nothing dies. Then try closing Q1 and Q2 together, both on the same side, and read why a real driver chip refuses to let you.
Lab 16 · Driving it from firmware
Try this firstPress Upload and run. The motor turns one way and never stops, because the sketch sets one direction and then waits. Make it run forwards, pause, then run backwards, upload again, and press Check the drive.
Notice why the checker insists on a pause. Going straight from full forward to full reverse asks the gearbox to absorb the whole reversal at once, and plastic gears lose that argument. Setting the speed pin to 0 for a tenth of a second in between costs nothing and saves the part. Notice too that the two direction pins plus one PWM pin is the whole interface: the diodes are inside the driver chip, where you can forget about them.
A motor driver runs fine for an hour and then stops working. Whoever built it left the flyback diodes off. What killed it?
The spike at switch-off. The damage happens at the moment the current stops, not while it flows, which is exactly why the part can survive an hour of running and then die. Overheating is a real failure in other circuits, but it would not wait for a switch-off, and a battery voltage climbing on its own is not a thing batteries do. If a driver dies mysteriously, look first at what happens when it switches off.
Step 9

Move a stepper to an exact angle, and draw with it

A stepper motor does not spin smoothly, and that is the point of it. Around the outside sit several coils; in the middle sits a magnet. Energise one coil and the magnet swings to face it and stops. Energise the next one round and it takes another fixed step. Clock through the coils in order and the magnet walks round, one exact angle at a time.

A common size takes 200 steps for a full turn, so one step is 360 divided by 200, which is 1.8 degrees. Count the steps you have sent and you know the angle, with no sensor anywhere in the machine. That is called running open loop, and it is how almost every printer and 3D printer knows where its head is.

The cost of open loop is a real one. If the motor ever fails to follow a step, nothing notices.

Why does a coil pull a magnet at all?

A coil is a length of wire wound many times round a core of iron. Current through wire makes a magnetic field, and winding the wire into many turns stacks those fields on top of each other, so a modest current makes a strong magnet. Switch the current off and the magnet vanishes.

That switchable magnet is the whole trick of every motor in this course. In a stepper it pulls the permanent magnet in the middle round to face it. In the DC motor of Step 8 the same coils are switched automatically by brushes as the shaft turns, which is why that one spins continuously instead of stepping.

What is a half step?

Energise two neighbouring coils at once and the magnet cannot face either, so it settles halfway between them. Alternating single coils with pairs gives twice as many resting places: eight rows in the table instead of four, 400 steps a turn instead of 200, and each step 0.9 degrees instead of 1.8.

It is not free. A half step position is held by two coils pulling sideways at each other, so it has less holding force than a full step, and the strength of the steps now alternates. Real controllers push this much further with microstepping, feeding the coils partial currents to place the magnet anywhere, and each subdivision buys smoothness and loses grip.

How does a plotter know where it started?

It does not, and it cannot work it out. Counting steps tells you how far you have moved from where you began. Nothing at all about where that was. Power a plotter on and the head could be anywhere.

So real machines home first. They drive slowly towards one end until a switch is pressed, then call that position zero and count from there. Every trip your printer makes to the far left with a clunk before it starts printing is exactly this. One cheap switch buys the one piece of information counting cannot supply.

Lab 17 · Clocking the coils by hand
Try this firstPress Next row four or five times. Each press lights a different row of the table, the dashed arrow shows where the coils are pulling, and the rotor turns 1.8 degrees. Then press Skip a row on purpose and read what the rotor does. After that, press Switch to half steps.
Notice the pill counting lost steps. When you skip a row the table moves on and the rotor does not, because the magnet was pulled somewhere it could not reach in one hop and fell back. From then on the controller's idea of the angle is wrong, permanently, with no way to find out. That is the price of having no sensor, and homing at power-on is the only cure.
Lab 18 · The pen plotter
Try this firstPress Upload and run and watch the pen. It draws three sides of a square and stops, so the shape does not close. Add the missing side, upload again, then press Measure the drawing.
Notice that the checker measures rather than reads. It takes the recorded pen positions, works out how wide and how tall the drawing is in millimetres, and checks that the pen finished where it started. One step moves 0.2 millimetres here, so 40 millimetres is 200 steps, and the whole square is arithmetic rather than aim.
A stepper plotter is told to draw a 40 millimetre square, and every square comes out 40 millimetres wide and 39.4 millimetres tall. Where would you look first?
Three steps on the Y axis. 0.6 millimetres divided by 0.2 millimetres a step is exactly three. So either three steps were ordered and the motor did not follow them, or the program is dividing by a slightly wrong number. A stepper's position is a count, so a wrong distance is always a wrong count. A thick pen would change how the line looks, not how big the shape is, and a motor short of power would fail on both axes and usually loudly.
Step 10

Turn a sensor's resistance into a number

Plenty of sensors do not answer yes or no. A light dependent resistor is a small disc whose resistance falls as light rises: about 10000 ohms in a dim room, a few hundred in sunlight. Nothing about it is a 1 or a 0, and there is a real number in there you would like to have.

A pin cannot measure resistance. It can only measure voltage. So the sensor is paired with an ordinary fixed resistor, one end at 3.3 volts and the other at ground, and the pin listens to the joint in the middle. The two parts share the 3.3 volts in proportion to their sizes, so the voltage at that joint moves as the sensor changes. The arrangement is called a voltage divider. It is the most used circuit in electronics.

Then the chip's converter measures that voltage and hands the program a whole number. analogRead answers with something from 0 to 1023, where 0 means 0 volts and 1023 means 3.3.

Why 1024 steps and not 1000?

Because the converter works in bits. Ten bits give 2 multiplied by itself ten times, which is 1024 different values, numbered 0 to 1023. A converter with 12 bits, which many newer boards have, gives 4096 values numbered 0 to 4095. The count is always a power of two because that is what a row of bits counts.

One step is therefore 3.3 volts divided by 1024, about 3.2 thousandths of a volt. The converter cannot see anything finer than that, so two voltages 1 thousandth of a volt apart come back as the same number. Every measurement in every computer has a step size like this hiding in it.

The divider in numbers, once

Say the sensor is at 10000 ohms and the fixed resistor is also 10000. The two are equal, so they share the 3.3 volts equally and the joint sits at 1.65 volts. That is 1.65 divided by 3.3, which is half of the range, so analogRead answers about 512.

Now the room brightens and the sensor drops to 2000 ohms. The fixed resistor is now five times the bigger share, so the joint rises to 3.3 multiplied by 10000 divided by 12000, which is 2.75 volts, and the reading climbs to about 853. The general form is the supply multiplied by the lower resistor divided by both added together and the lab prints exactly that sum as you drag.

Why does the fixed resistor's size change what you can see?

The divider is most sensitive when the two resistances are similar, and goes flat when one is far bigger than the other. Fit a 1000 ohm resistor against a sensor that sits at 10000 in the range you care about and almost the whole voltage lands on the sensor, so the reading barely moves as the light changes.

So the fixed resistor is chosen to be about the sensor's resistance in the middle of the range you actually want to measure. Getting that wrong squashes the interesting part of the range into a handful of numbers, and no amount of programming can recover a spread the circuit never produced.

Lab 19 · Where the number comes from
Try this firstDrag room brightness from dark to bright. The sensor's resistance falls, the voltage at the pin rises, and the number in the converter box climbs towards 1023. Now change fixed resistor to a different value and drag the brightness again.
Notice that the number never leaves 0 to 1023, whatever you do. Notice too where each fixed resistor spends its spread. With 47 kilohm fitted, the whole stretch from a bright office to full daylight moves the reading about ten counts, and every brightness above a lit room is crushed into the top of the range. Fit 1 kilohm and that stretch gets hundreds of counts while the dark end goes flat instead. The reading covers most of 0 to 1023 whichever you fit. What the fixed resistor decides is which brightnesses get the room, and choosing that one part well is most of the work in reading a cheap sensor.
Lab 20 · The automatic nightlight
Try this firstPress Upload and run. The room dims and brightens on its own. The tall trace labelled the light reading is the room, the short one low down is the lamp, and the lamp comes on at all the wrong times. Fix the comparison, upload again, then press Check the nightlight.
Notice where the checker looks hardest: the stretch where the reading sits at exactly 400. Below 400 does not include 400, and a boundary like that is where this kind of code goes wrong far more often than the obvious part does. The sketch never gets to see the light pattern in advance, so guessing the answer from the shape of the trace is not available.
A nightlight uses if (light < 400). In a room hovering right around a reading of 400, the lamp flickers on and off constantly. What would you change?
Two thresholds with a gap. One threshold means one value where a wobble of a single count flips the answer. Two, with a gap between them, means the light has to change by a real amount before anything switches. The trick has a name, hysteresis, and it is in every thermostat you have ever used. Lowering the single threshold just moves the flickering to a different brightness, and reading more often only makes the flickering faster.
Step 11

Ask a smart sensor for a reading over two wires

Some sensors have a small computer of their own inside. A weather sensor like the BME280 has already measured the temperature, pressure and humidity, corrected them, and put the answers away in numbered slots. You do not measure a voltage from it. You ask it a question and it answers with bytes.

The asking happens on two wires shared by every such chip on the board. One, called SDA, carries the bits. The other, called SCL, is a clock: it ticks, and everyone looks at SDA on each tick. Every chip on the pair has its own address, a small number it answers to, so one pair of wires can serve a dozen parts. The arrangement is called a bus, and this particular one is called I2C.

Inside each chip the answers live in numbered slots called registers. So one reading is: name the address, name the register, and listen. Both of those numbers are usually written the way datasheets write them, with 0x in front: 0x76 is one address and 0xFA is one register. The note below unpacks what that means, and the sketch you write uses ordinary numbers for the same values.

What is 0x76?

A number written in sixteens instead of tens. Ordinary counting has ten symbols, 0 to 9, and each place to the left is worth ten times the one on its right. Hexadecimal has sixteen symbols: 0 to 9, then A for ten, B for eleven, C, D, E and F for fifteen. Each place to the left is worth sixteen times the one on its right, and the 0x at the front is a label saying which system this is.

So 0x76 is seven sixteens and six ones, which is 112 plus 6, which is 118. Datasheets use hexadecimal because one hexadecimal symbol is exactly four bits, so 0x76 is also the bit pattern 0111 0110 read straight off. The sketch below uses 118 and 250 where the datasheet says 0x76 and 0xFA, and they are the same numbers.

What is a register, and does reading one change anything?

A register here is a numbered pigeonhole inside the sensor, each one holding a single byte. Register 0xD0 holds a fixed number identifying what kind of chip this is, which is how a program checks it is talking to what it thinks it is. Registers 0xFA and 0xFB hold the latest temperature. Other registers hold settings you write to rather than read.

Reading a register does not consume it or change it. Ask twice and you get the same byte twice, unless the sensor has taken a new measurement in between. That is different from a queue, where reading takes an item away, and it is worth being clear which kind of thing you are reading from.

Why is one temperature split across two registers?

Because a register holds one byte, and a byte can only hold 0 to 255. The sensor wants to report 2137, meaning 21.37 degrees, and 2137 does not fit in a byte. So it splits the number: the top part goes in one register and the bottom part in the next.

Putting it back together is the same idea as reading a two digit number, except the base is 256 instead of 10. In 47, the 4 means four tens. Here the top byte means that many 256s. So the whole number is the top byte multiplied by 256, plus the bottom byte. For 2137 that is 8 lots of 256, which is 2048, plus 89, and 8 and 89 are exactly what the two registers hold.

Lab 21 · Bytes on two wires
Try this firstPress Tick the clock once and read the line underneath. It names the slot the bus has just reached and says what that slot is for. Keep ticking to the end, or press Run to the end to jump there. Then press Send the wrong address and Back to the start, and tick through again.
Notice the ACK slot just after the address. When the address is right the chip pulls the line down for one tick, which is it saying it is there. With the wrong address nobody pulls it down, the line stays high, and the controller learns that nothing on the bus answers to that number. That single tick is how a board discovers what is plugged into it. Notice too that the whole read has two starts, because the direction changes halfway through.
Lab 22 · Read a real temperature
Try this firstPress Upload and run. The output panel prints a temperature, and it is wrong, because the sketch reads only the top of the two registers. Read register 251 too, put the two bytes together, then press Check against hidden readings.
Notice that the checker runs your readTemp five times against sensor values the sketch on screen never sees, including one of only 0.09 degrees and one of 30. Code that happens to give the right answer for 21.37 and nothing else does not pass. say prints a line into the output panel, and return is how a function hands a value back to whoever called it.
Two chips share one pair of wires, one answering to 0x76 and one to 0x3C. How does the second chip know to stay quiet while the board reads the first?
The address at the front decides. Every chip on the pair hears every message begin, and only the one whose address matches replies. That is what lets two wires serve a dozen parts. It is also why two parts sharing one address is a problem you fix with a solder jumper or a different part, never in software. Taking turns would need the chips to know about each other, and they do not.
Step 12

Catch a press while the program is busy

Everything so far has read pins by asking. Round loop goes, and somewhere in it a digitalRead takes a look. That is called polling, and it works right up until the loop gets busy.

Suppose reading a sensor takes 180 milliseconds, which plenty of real sensors do. Then the program glances at the button once every 180 milliseconds and spends the rest of its time elsewhere. A finger press lasts about 40 milliseconds. Most presses now begin and end entirely between two glances, and as far as the program is concerned they never happened.

The fix is to stop asking. Ask the hardware to watch the pin instead.

What happens to the program while the handler runs?

The chip stops it mid-sentence. It writes down where it had got to and every number it was holding at that moment, jumps to your function, runs it, then puts all of that back exactly as it was and carries on from the next instruction. The interrupted code has no way of telling that anything happened.

The function that gets run is called an interrupt handler, or an interrupt service routine, which is why you see ISR in other people's code. You never call it yourself. You hand its name to attachInterrupt, with no brackets after the name, because you are naming the function rather than running it.

Why must a handler be short?

Because while it runs, the rest of the machine is standing still. The main program is paused, and on most chips other interrupts are held off too, including the one that advances the millisecond counter. Time itself stops being counted properly.

So a delay inside a handler is a trap: the delay waits for a clock that is not moving, and never ends. The rule is to get in, change one thing, and get out. A handler that sets a variable to say something happened, leaving loop to do the actual work when it gets round to it, is the normal shape.

RISING, FALLING or CHANGE?

An interrupt fires on an edge, meaning a moment when the level changes, and you choose which kind. RISING is the moment the pin goes from low to high. FALLING is high to low. CHANGE is either.

With a pull-up button, pressing is the falling edge and releasing is the rising one, so FALLING gives one call per press and CHANGE gives two. Picking CHANGE by accident is the reason a counter sometimes reads exactly double, which the checker in the second lab will tell you about if you try it.

Lab 23 · The press a busy loop misses
Try this firstPress Check the pin yourself, then watch the two numbers written on the board. One counts the fingers that really went down, the other counts what the sketch noticed, and they pull apart as the run plays. Then press Let the hardware tell you and watch them stay together.
Notice that the version that works does less looking, not more. It never reads the pin in loop at all. The chip watches the pin in hardware, which costs no program time whatsoever, and wakes your code at the exact microsecond the level falls.
Lab 24 · Catch every press
Try this firstPress Upload and run. Eight fingers went down and the two numbers on the board disagree badly. Write a short handler, attach it in setup, then press Check every press.
Notice one thing the checker will refuse: a delay inside the handler. It reports that the clock is stopped in there, so a slow handler is worse than no handler at all. It also tells you the difference between counting too few, which means nothing is watching the pin, and counting too many, which usually means CHANGE where you wanted FALLING.
A doorbell reads its button at the top of loop, and loop also refreshes a screen, which takes 300 milliseconds. What do people at the door experience?
It misses them. A press shorter than one trip round the loop can happen entirely between two glances at the pin, and then there is nothing left to notice. Ringing late would be the answer if the pin stayed pressed until somebody looked, which fingers do not do. Ringing several times is the bouncing problem from Step 5, which is a different failure with a different fix. An interrupt solves this one because the watching is done by hardware that never gets busy.
Step 13

Run two jobs at two rates with no delay

delay has been useful and it is about to run out of road. It does not pause one thing, it stops the entire program. Ask for one lamp blinking every 125 milliseconds and another every 200, both with delays, and neither one keeps its time, because each is waiting inside the other's schedule.

The way out is to stop waiting and start checking the clock. millis() answers with how many milliseconds the board has been running. Keep a note of when each job last ran, and each pass round loop, ask whether enough time has gone by yet. If it has, do the job and update the note. If it has not, do nothing and move on.

Nothing anywhere waits, so loop spins round thousands of times a second and every job gets looked at constantly.

Where does millis() get its number?

From a counter in hardware that ticks along on its own, driven by the same crystal that clocks the processor. It counts whether your program is busy or not, which is what makes it trustworthy. Reading it costs almost nothing: it is a fetch, not a measurement.

It starts at zero when the board powers up, so the number is not a time of day, it is an age. It also keeps counting during delay, which is a useful thing to know: a delay does not stop the clock, it only stops your program from looking at it.

Why now - last >= 125 rather than testing for exactly 125?

Because you will not be looking at the exact millisecond. loop arrives whenever it arrives, and if some other job took a moment you might glance at 124 and then at 127. Testing for equality would miss 125 entirely and the lamp would never blink again.

Asking whether at least 125 have gone by can never miss. It fires on the first pass at or after the target, which may be a fraction late, and then the note is updated so the next one is measured from there. That single greater-or-equal is the difference between a lamp that blinks forever and one that stops the first time the board is busy.

What is 1 - on13 doing?

Flipping a value between 0 and 1 without an if. If on13 holds 0, then 1 minus 0 is 1. If it holds 1, then 1 minus 1 is 0. Assigning that back gives the opposite of what was there.

Since digitalWrite treats 0 as low and anything else as high, the same variable can be both the remembered state and the value written to the pin. Keeping a note of the state matters here: with no delay to structure the code, the program has to remember whether the lamp is currently on, because nothing else does.

Lab 25 · Delay stops everything
Try this firstPress Written with delay and read the measured numbers in the line underneath: how far each lamp drifted from the rate it asked for. Then press Written with millis and read the same two numbers again.
Notice that nothing was made faster. Same board, same work, same lamps. The numbers are measured from the recorded pin changes rather than quoted, and they come good because no part of the second loop ever stands still. Notice too that the version with delays is not a little bit out, it is out by more than the interval it asked for.
Lab 26 · Finish the scheduler
Try this firstPress Upload and run. Task A already checks the clock properly and asks for pin 13 every 100 milliseconds. It gets nowhere near that, because task B below it still waits. Give task B its own note of when it last ran, then press Check both rates.
Notice which job the remaining wait ruins. The delay(250) belongs to task B, and task B keeps perfect time. It is task A, the innocent one, that is wrecked. A wait harms everything except the thing doing the waiting, which is why one blocking call buried in a large program is so hard to track down from its symptoms.
A sketch reads a sensor every second with delay(1000) and also has to notice a 40 millisecond button press. Someone suggests using delay(50) and reading the sensor every twentieth pass. Is that better?
Better, and still broken. Shortening a wait shrinks the window in which events disappear without closing it, and a 40 millisecond press against a 50 millisecond wait is exactly the case that still fails. Comparing millis() against a note of when the job last ran removes the waiting rather than making it smaller. Calling it as good as millis() is the tempting answer because 50 sounds small, and calling it worse gets the direction backwards.
Step 14

Make the board recover from a hang on its own

Firmware hangs. A sensor stops answering and the code waits for it forever. A loop's exit condition never comes true. Nothing crashes, no message appears, and the device simply stops being a device. If it is on a hillside or in a plant pot, nobody is going to walk over and unplug it.

The watchdog is a counter in hardware that counts upwards on its own and resets the chip if it ever reaches its limit. Your program's job is to keep putting that counter back to zero, once each time round loop. That is called petting it. A healthy program pets it constantly. A stuck program cannot, because a stuck program is not running anything, and after the timeout the chip restarts itself.

Which means the placement of that one line is the entire design.

Why can the program not check on itself?

Because a stuck program is not executing any code that could do the checking. Whatever watchful function you write is stuck in the same place as everything else. The watch has to be kept by something that is not the program.

So the watchdog lives in hardware, alongside the processor rather than inside its instruction stream, and on most chips once it is switched on nothing in software can switch it off again. That refusal is deliberate: a bug that could disable the watchdog would take the safety net with it.

Where should the petting go?

Somewhere the program only reaches when it is healthy. The top of loop is the usual place, because arriving there means the last pass finished. Petting from several places so that some path always reaches one is how you defeat your own watchdog.

Two placements are worse than useless. Petting inside the loop that is stuck keeps the board alive while it does nothing at all. Petting from a timer interrupt does the same, since interrupts often keep running while the main program is jammed, and then the watchdog reports a healthy board forever.

What does a reset actually undo?

Everything in RAM. Every pin drops back to being an input at 0 volts, every variable loses its value, and setup runs again from the top as if the power had been cycled. The program in flash is untouched, which is why the board comes back rather than coming back empty.

So a design that survives a watchdog reset has to survive starting over halfway through whatever it was doing. A motor stops, which is usually right. A counter of how many bottles have passed is lost, which may not be, and if it matters it has to be written somewhere that survives a reset.

Lab 27 · Hang it on purpose
Try this firstPress Upload and run and watch the heartbeat lamp. It blinks, then stops at about 0.7 seconds and never comes back, because stuckSensor is waiting for an answer that is not coming. Switch a watchdog on in setup, pet it in loop, then press Check that it recovers.
Notice the reset marks that appear on the trace once it works. The board hangs, the counter runs out, the chip restarts from setup, and the heartbeat comes back, over and over, with nobody touching it. Notice also what the checker refuses: a watchdog with nothing petting it, which resets the board whether it is stuck or not, and a board that resets but never blinks again afterwards.
Lab 28 · A project ladder with real parts
Try this firstPress one of the project buttons under the table. A parts list with prices and a wiring list appear underneath. Then press It has to move, which keeps only the projects with a motor in them, and drag hours you have up until one of them comes back within reach.
Notice that each project names the steps it is built from. The nightlight is Step 10's divider and the comparison you already got marked. The line follower is Step 8 twice over. The plotter is Step 9 with a real gearbox, which changes the steps per turn from 200 to 2048 and so changes the arithmetic. Prices are the right size rather than the right number, because they move around.
A weather station hangs about once a week, so a watchdog with a 2 second timeout is added, petted at the top of loop. Months later the sketch grows a step that takes 4 seconds. What happens?
It resets constantly. A watchdog knows one thing: how long since it was last petted. Four seconds of honest work looks exactly like four seconds of being stuck. So the timeout has to be longer than the slowest healthy pass round the loop. The other option is to pet the watchdog from inside the long job, and that needs care, because it starts to look like petting from inside a stuck loop. A watchdog that quietly switched itself off would be no protection at all.

Checkpoint after timers and the watchdog

  • Make a pin a real voltage, and read one back without letting it float.
  • Pick a board from numbers instead of from what a tutorial happened to use.
  • Find the missing pinMode, and the upside down button test, on sight.
  • Debounce a switch, and know which direction of error is the dangerous one.
  • Set brightness and speed with a duty cycle, and an angle with a pulse width.
  • Drive a motor both ways through a bridge, and say why the diodes are there.
  • Move a stepper to an exact angle, and explain why it needs to home first.
  • Turn a resistance into a number through a divider, and choose the fixed resistor.
  • Read a register out of an I2C chip and rebuild a number from two bytes.
  • Use an interrupt for anything short and fast, and keep the handler tiny.
  • Write a loop with several jobs at several rates and no delay anywhere.
  • Fit a watchdog, and put the petting in the one place that is honest.

Useful links before the sensor and board chapters

  • Build a Microprocessor. If you have not done it, go and see what is behind the pins: the gates, registers and clock that make those voltages happen in the first place.
  • Computer Networks. Two wires and a clock got you as far as a sensor on the same board. That course starts from one wire between two machines and gets to the other side of the planet.
  • Intro to Machine Learning. Once a device can measure things, the next question is what to conclude from a pile of measurements, and that is a different kind of building.
Step 15

Measure a distance with a pulse of sound

A distance sensor that works by sound has two barrels on the front. One sends, one listens. The cheap one, sold as an HC-SR04, talks to the board through two pins: a trigger pin and an echo pin. In the labs below they are pins 9 and 10. Hold the trigger pin high for ten microseconds and the sensor lets out a short burst of clicks, too high for a person to hear. Sound that high is called ultrasound. The sensor then puts the echo pin high, and drops it again the moment the burst comes back.

So the echo pin stays high for exactly as long as the sound was in the air. That is a time, and you wanted a distance. Every sensor so far handed over a number that already stood for the thing you asked about, a voltage or a temperature. This one hands over a time, and turning it into a distance is your job. Sound travels about 343 metres a second through room temperature air, which is 34300 centimetres in a second. A second holds a million microseconds, so in one microsecond sound covers 0.0343 of a centimetre. Multiply the microseconds by that to get centimetres of flying, then halve the answer, because the sound crossed the gap twice.

The board asks for that measurement with one call, pulseIn, which watches the echo pin and answers with how many microseconds it stayed high. But the pin does not always fall. A soft target soaks the burst up and sends nothing back. A target at an angle sends most of the burst off to one side, and only a trace of it back this way. Then the sketch is waiting for something that is never going to happen. So the waiting has to have an end: after a set time pulseIn stops listening and answers 0, meaning no echo at all. A sensor that cannot answer has to be able to say so.

Why sound? Light would get there quicker.

Much quicker, and that is the problem. Light crosses a room in about a hundred millionth of a second. Timing that needs a clock ticking billions of times a second, and parts that fast cost more than the rest of the robot put together. Sound is close to a million times slower than light, which turns the same job into something a cheap chip can do.

Crossing a room and coming back takes sound thousands of microseconds, and counting microseconds is what the hardware timer from Step 13 does without being asked twice. Sensors that time light do exist and they cost far more, because the hard part was never making the flash. It was catching it.

Why halve it? I want the distance to the wall, not the round trip.

The clock starts when the burst leaves and stops when it gets back, so what it timed was a there and back trip. Walk to a shop and home again and you have walked twice as far as the shop is away. Nothing at the far end can tell the sensor when the sound arrived there, so half a trip is not something it can time. It times the whole thing and you halve the answer.

This is the most common mistake in this step and it has a signature. Every reading comes out exactly twice what a tape measure says. If your numbers are all double, you have not halved. If they are all half, something is halving twice.

There is a second silence, and it sits at the other end of the range. For a short while after the trigger the sensor is still sending its own burst, and switching over to listening, so an echo arriving inside that window goes unheard. That is where the smallest distance in the datasheet comes from: the maker's page of numbers for this part says 2 centimetres. Closer than that and the echo pin never falls. The sketch waits right to the end and reports no reading. At that point, an object 1 centimetre away and no object at all produce the same observation, so the sensor cannot distinguish them.

What is the rest of the board doing while it waits for the echo?

Nothing. pulseIn sits on the echo pin and does not hand control back until the pin falls or the wait runs out. That makes it a blocking call, the same trouble delay caused in Step 13. While it sits there no other job in loop gets a turn, and a button press can come and go unnoticed.

So the length of the wait is a real cost and not just a safety net. Every reading with no echo in it spends the whole wait doing nothing at all. A robot taking ten readings a second with a generous wait can spend most of its life listening for sounds that are not coming. Make the wait long enough for the furthest thing you need to see, and no longer.

Does warm air change the answer?

Yes, a little. Sound moves faster in warm air than in cold, by roughly 0.6 metres a second for every degree. The 343 in the sum is the speed in a room at about 20 degrees. On a hot day at 30 degrees the sound is about 6 metres a second quicker. That is under 2 hundredths of the whole speed, so a distance worked out with the room temperature number is under 2 hundredths wrong. Multiply that by the distance you care about and you have the error in centimetres.

Careful ultrasonic measurement puts a thermometer beside the sensor and corrects the speed before doing the sum. For a robot trying not to hit a chair leg, nobody bothers. The next lab shows why: the surface you are pointing at will let you down long before the temperature does.

Lab 29 · Time the flight of one burst
Try this firstPress Send a pulse. The burst flies out to the hard wall and back, slowed down enough to watch. The pills underneath report how many microseconds the echo pin was high, and what distance the sketch works out from that time. Then press Cloth and send another pulse: nothing comes back at all.
Notice the pill saying how far this surface reaches. Drag distance to the target (cm) out past that figure and the echo stops arriving. The line underneath says why: what comes back is too faint to hear, rather than too slow. Cloth gives up earliest and a hard wall lasts longest, so the reach belongs to what you are pointing at and not to the sensor alone. Then drag the target inside 2 centimetres and press Zoom in on the start. A mark shows the echo arriving before the sensor has finished sending, and the pin never falls. The mark labelled gave up is the sketch letting go, not a very long echo.
Lab 30 · Turn the time into centimetres
Try this firstPress Upload and run. The output panel claims the target is thousands of centimetres away, because readCm hands back the raw microseconds it was given. Do the conversion inside readCm, and give back -1 when pulseIn answers 0, then press Check against hidden targets.
Notice that the checker names the mistake rather than just failing you. It tells apart an answer that is still a time, one that is twice the distance, and one that has been halved twice. The mistake it cares about most is turning a 0 from pulseIn into 0 centimetres. Press A towel 90 cm away and run it again to watch that case arrive. Zero microseconds is not zero distance. It is no answer at all, and -1 is how readCm says so. Three of the hidden targets are silent ones, so a sketch that does the arithmetic and never tests for 0 cannot pass.
A robot cannot see a wall 6 metres away, so somebody doubles how long the sketch waits before it gives up. Does the robot see the wall now?
There was nothing coming, so waiting longer changes nothing. Two separate ceilings limit the range and the sensor stops at whichever comes first. One is patience: an echo still in the air when the wait runs out is thrown away, and a longer wait does lift that one. The other is loudness. The burst spreads out going and spreads out again coming back. What returns from far off is fainter than the sensor can hear, and waiting cannot make a faint sound louder. The pill in Lab 29 that says how far a surface reaches is whichever ceiling bites first. That is why cloth and a hard wall stop at such different distances. Waiting longer is not free either, since the board stands still inside pulseIn the whole time.
Step 16

Read a temperature, and find out your reading is noisy

Step 10 turned a resistance into a number, and Step 11 asked a chip on two wires for a number it had already worked out. This sensor manages with one wire. The board pulls that line low to open a slot, and the sensor either holds it down for a 0 or lets a pull-up snap it back up for a 1. Sixteen bits arrive that way. They already say the temperature, because the sensor counts in whole sixteenths of a degree.

Read it twice in a row and the two answers are different. Nothing in the room changed in that time. The difference is noise: the part of a reading that is not the thing you are measuring. Most readings are a little out, one way or the other, every single time. Now and then one comes back wildly out and is fine again on the next reading, and that is a different problem with a different cure.

What you do about it is a filter: readings go in, a steadier number comes out. Three cheap ones cover most of the ground. A moving average adds up the last few readings and divides. A median puts the last few in order and answers with the middle one. A fading average mixes each new reading into its own last answer. How many readings a filter is allowed to look at is called its window. None of the three is free. A filter can only work from readings that have already arrived, so its answer is always partly about the past.

How can one wire carry a number in both directions?

By taking turns, and by agreeing on time rather than on voltage. A slot is a short fixed stretch of time, and the board opens each one by pulling the line down. For a 1 the sensor lets go immediately and the pull-up drags the line back up. For a 0 the sensor keeps holding it down until the slot is nearly over. The board looks part way through the slot: still low is a 0, already back up is a 1.

The pull-up in the picture below is 4.7 kilohms, which is 4700 ohms, since kilo means a thousand here exactly as it did in kilohertz in Step 2. It is the part that makes sharing possible. Both ends can pull the line down and neither has to push it up, so the two can never fight over the wire. The sensor sends its lowest bit first, which is why the eight bits under the trace read right to left.

The numbers jump about. Is the sensor broken?

No, and telling apart the two ways they jump is most of this step. The first is everyday wobble: every reading is a little out, up or down, by roughly the same small amount. Some of that is the air really stirring next to the sensor. Some is electrical hum picked up on the wire. Some is the sensor having to choose one of its sixteenths when the truth sits between two of them.

The second is a reading that comes back far out and is back to normal immediately after. Nothing in a room warms by several degrees and cools again in a tenth of a second, so a reading like that is not about temperature at all. A bit got knocked over on the wire, or the sensor was disturbed part way through answering. The labs below call those wild readings, and no amount of careful averaging will make one of them true.

Why is a filter always late?

Because it has nothing but readings that have already happened. Take the average of the last five. Those five are spread over five readings' worth of time, and the middle of that stretch is two readings back. So the answer describes the room as it was two readings ago rather than now. Widen the window and the middle of it moves further into the past.

While nothing is changing, being late costs nothing: the past and the present are the same number. The bill arrives when the thing you are measuring really moves. Part way through the run in the second lab a hand closes round the sensor and the temperature climbs for real. A slow filter is still reporting the cold room while the hand is on it, and that is what makes the choice of window a decision rather than a preference.

Why does it matter how many numbers a filter has to remember?

Step 2 counted a board's RAM in kilobytes, and a small one has about two of them, which is 2048 bytes for everything the program is holding at once. A window of twenty-one readings means keeping twenty-one numbers and shuffling them along as each new one arrives. For one temperature that is nothing. For a dozen sensors, each with its own window, it stops being nothing.

The fading average never keeps a list. It holds its own last answer, takes one new reading, works out the next answer from those two, and forgets both of the old numbers. Its proper name is the exponential moving average, and that is all the name means: old readings fade away instead of dropping out all at once. It is the filter you find inside firmware that has no room to spare and the second lab measures how close its answer stays to the other two.

Lab 31 · The same room, measured over and over
Try this firstPress Take twenty readings. The strip under the board fills with numbers that ought to be identical and are not, and the pill row keeps a running highest minus lowest for everything taken so far. Press it again, then press Take one reading and follow the eight dashed marks across the wire trace to see where that one number came from.
Notice the pill that says highest minus lowest, and the one straight after it. The first is how far apart the readings themselves are. The second is how far the temperature the sensor is actually sitting in moved over the same stretch. The gap between them is the noise, and it is the whole of what a filter is for. Only a simulation can print that second number, which is exactly why noise is hard to argue about on a real bench. A cell that comes up in the warm colour is one of the wild readings from the note above, and Start over replays the identical run from its first reading.
Lab 32 · Three filters over one run
Try this firstDrag window, in readings all the way left, then step it right one notch at a time. It moves 1, 3, 5 and on up to 21. The thick line flattens as you go, while the pill counting how many readings late the answer is climbs. Then press Median and look at what the same window does where the run goes wild, and press Fading average to see the same job done with one remembered number.
Notice the panel labelled the working at reading and a number. It does the arithmetic for that one reading in whole sixteenths, so you can check it with a pencil. Show the working at a quiet reading moves it to a stretch with no wild reading in the window. Two more things are worth chasing. The button that begins Slide the true line draws the true temperature shifted by exactly the lateness just measured, and the filter's answer lands on top of it. Being late is not the same as being wrong. At a window of one reading nothing is late, and the button says so. With the median chosen, the answer is always one of the readings exactly as it arrived, never a new number worked out from several of them.
A greenhouse controller reads a temperature ten times a second. About once a minute one reading comes back six degrees out, and the next one is normal again. Someone widens the moving average from 5 readings to 21 to get rid of it. What happens to that wild reading?
Spread thinner, and smeared over more answers. A moving average throws nothing away. A wider window divides the wild reading by more, so each answer moves less, and keeps it in the sum for longer, so more answers move. Add up how far all the answers were pushed and the total is the same either way, which is why widening the window feels like progress and is not. The second lab measures both halves for you: the pill saying how far a wild reading shifts the filter, and the count of answers it changed. The median is the filter that throws it away, because the middle of a sorted row never looks at the ends. And a wider window gives each reading less weight, not more.
Step 17

Ask an accelerometer which way is down

An accelerometer is a chip with a tiny weight inside it, hanging on springs too small to see. Shove the chip and the weight lags behind for an instant, so the springs bend, and what the chip reports is how far they bent. Being shoved like that is called acceleration. The chip measures it in more than one direction at once, and each direction it measures in is called an axis. The sensor in the first lab has two: one along the sensor and one through it.

Gravity bends those springs as well, and that is the part worth having. A sensor lying still on a table is being held up by the table. That push reaches the little weight inside it exactly as a shove would. So a still sensor reports a pull of about one g. It reports it pointing down. One g is the name for the size of gravity's pull at ground level. How that pull is shared between the two axes is how far over the board is tilted. Sitting still, an accelerometer tells a program which way down is.

Then somebody picks the board up, and it stops being true, because the chip cannot tell gravity from a shove. So these parts nearly always carry a second chip beside the first: a gyroscope, which reports how fast the board is turning, in degrees per second. It ignores shoves completely. It has a fault of its own. Both chips answer over the same two wires as the sensor in Step 11, SDA and SCL, at an address of their own.

Why does a sensor sitting still read anything at all?

Because holding something up is a push. The table pushes the chip upwards hard enough to stop it falling, and the weight inside has to be pushed up with it. The springs bend to do that pushing and the bend is what gets measured. The size of that bend, for anything held still at ground level, is what one g means.

Take the table away and the reading goes. A sensor dropped in mid-air reads nothing on any axis while it falls: nothing is holding the weight up any more, so no spring is bent. That is not a fault, and it is how a phone can tell it has been dropped before it lands. Every sensor in orbit reads the same, which is the real reason things float up there.

How do two pulls turn into one angle?

Lay the board flat and gravity pulls straight through it. The axis through the board reads about 1 g, and the axis along it reads about nothing. Stand the board on its edge and the two swap over. Tip it part way and the pull is shared between them and the way it is shared is the angle. The lab draws both readings as arrows out of the middle of the sensor, each one as long as the number it stands for. Watch the pull move from one axis to the other as the board turns.

Turning that pair of numbers into degrees is one line in any language. The function that does it is called atan2, and you hand it the two readings and it answers with the angle. You do not need to know how it works to use it, any more than you need to know how a square root button works. Sensors sold today have three axes rather than two, which is what lets a device tell tipping forwards from tipping sideways.

Lab 33 · Tilt it, shake it, hold it still
Try this firstPress Tilt it up 20 degrees. Three needles swing with the board: the true angle, what the accelerometer says, and what the gyroscope says. Both answers follow it, because a slow tilt is the easy case. Now press Shake it where it is, and then Hold it still for 5 seconds, and read the line underneath after each one.
Notice that each chip breaks in the manoeuvre the other one survives. Shaking throws the accelerometer around, so compare the worst single reading of the shake with the average of all of them. Five still seconds do nothing to the accelerometer at all and let the gyroscope walk away, and it never comes back on its own. Watch pull along the sensor, pull through it and both together while the shaking is on: the pull leaves the range it held at power-up, and that is how a program can know a reading is not gravity. Then drag how hard the shaking is down to nothing, which the lab confirms in words, and shake again. A hand holding a sensor still wobbles.

So there are two answers and neither is good enough. The accelerometer is wrong by a lot for a fraction of a second. The gyroscope is wrong by a little that never goes away and only grows. The two faults do not overlap, and that is what makes a fix possible. Keep the gyroscope's smooth answer, and let the accelerometer pull it gently back towards where down really is. Combining two sensors like that is called sensor fusion and the simplest one of all is the complementary filter.

It is one line of arithmetic, run once for every reading:

estimate = (1 - w) * (estimate + turnRate * 0.02) + w * accelAngle

Carry the estimate forward with the gyroscope first: add the turning rate multiplied by the time since the last reading, which here is 0.02 of a second, because the sketch reads both chips fifty times a second. Then pull the result a fraction of the way towards the angle the accelerometer is claiming. That fraction, w, is the only thing there is to choose. At 0 the accelerometer is never looked at. At 1 the estimate is thrown away and replaced by the accelerometer every single time.

Why not measure the gyroscope's error once and subtract it?

You can, and every serious sketch does. Hold the board still at power-up, average a few hundred readings, and whatever comes out is roughly what the chip reads while nothing is turning. Subtract that from every reading afterwards. It helps a great deal.

It does not fix the problem. The leftover moves as the chip warms up, so a number measured at breakfast is wrong by lunchtime. Whatever is left after subtracting still gets added up fifty times a second: an error of a hundredth of a degree per second is a whole degree after a hundred seconds, and two degrees after two hundred. The measurement also goes badly wrong if the board happened to be moving while you took it, since then you have recorded the movement and called it error. And a gyroscope only ever knows how far it has turned from wherever it started. Nothing in it knows which way down is, so sooner or later you have to ask the other chip.

Is this the same trick as the fading average in Step 16?

Nearly. Step 16 moved its answer a fixed fraction of the way towards each new reading of one sensor, to smooth out noise. This moves its answer a fixed fraction of the way towards a second sensor, to correct a slow error the first sensor cannot see. Same arithmetic, different job.

The name says how the two parts fit: w of the accelerometer and 1 minus w of the gyroscope, every reading, adding up to one whole answer with nothing left over and nothing counted twice. A cleverer version called the Kalman filter chooses the weight for itself, from how noisy each chip has been lately. That is what a drone or a phone actually runs, and it is this idea with the weight no longer a number you picked by hand.

Lab 34 · Mix the two, and pick the weight
Try this firstPress All gyroscope, then All accelerometer. Both draw the line marked the two mixed together over the same recorded run: a tilt near the start, a stretch of shaking, then thirty still seconds, with the moments marked on the time axis. One line is smooth and finishes in the wrong place. The other is right on average and goes wild while the shaking is on. Then press The best of the thirteen, and drag accelerometer weight through all thirteen of its stops, which run from 0 at one end to 1 at the other.
Notice the shape of the last column of the table. The worse of the two errors is large at both ends of the slider and small in between. The stop that wins sits far nearer the gyroscope end than the middle, because the estimate only needs a nudge towards the accelerometer, fifty times a second. Notice what the second column costs you, too. The smaller the weight, the longer the mix takes to close two thirds of a gap. A filter that shrugs off shaking is also a filter that is slow to believe a real change, and that trade is the whole of choosing w.
A balancing robot mixes the two chips with the accelerometer weight set to a half, so that each chip counts for exactly the same amount. It holds its angle on a smooth floor and falls over on a bumpy one. What is going wrong?
Half of every shaken reading is far too much. The weight decides how much of each accelerometer reading reaches the answer, and on a bumpy floor most of what that chip feels is the bumps. An even split looks fair and is the wrong instinct, because the two faults have different shapes in time: one is wrong by a lot for a fraction of a second, the other by a little that never goes away. A small weight lets the shoves cancel each other out and still drags the estimate back over a few seconds. That is why the winning stop in Lab 34 is nowhere near halfway. Keeping up is not the gyroscope's difficulty: Lab 33 measures what shaking adds to it, and it is about what sitting still adds. Nor do the two errors add together from being read at the same moment. They are separate faults in separate chips, and that is exactly what makes mixing them worth doing.
Step 18

Tell one chip package from another, and know which you can solder

Inside every chip is a flake of grey silicon smaller than a fingernail clipping, and you never touch it. What you buy is the package: the body that flake is sealed inside and the metal that body offers you to join to. The same chip, doing exactly the same job, is usually sold in five or six different packages. Which one you buy decides whether you can attach it yourself.

Attaching a part to a board means soldering it. You heat the part's metal and the board's metal with a hot tool called an iron. Then you feed in a wire of soft metal called solder, and it melts and runs over both. When it cools the two are one piece and current can cross. Some packages push their legs through holes drilled in the board and are soldered on the far side, which is called through-hole. The rest sit on top of the board, on patches of metal called pads, with no holes at all, which is called surface mount.

The size of the part does not decide how hard the soldering is, and neither does the number of legs. The pitch decides: the distance from the centre of one pin to the centre of the next. Take the width of the metal itself off that, and what is left is bare board between one pin and its neighbour. That gap is the room you have to be wrong in. A part that hides all its metal underneath its own body leaves you no room at all, because a tip cannot reach under there. The heat has to arrive some other way: through air blown hot enough to melt solder, or through a plate that heats the whole board from below.

What do DIP, SOIC, QFN and BGA actually stand for?

They are descriptions rather than brand names, and each one tells you the shape. DIP is dual in-line package: two parallel rows of legs, made to go through holes. SOIC is small outline integrated circuit, the same two rows shrunk and bent outwards to sit on top of the board instead. TSSOP is thin shrink small outline package, which is that idea shrunk again.

QFN is quad flat no-lead: four sides, flat, and no legs sticking out, because its metal is a ring of pads on the underside. BGA is ball grid array. It has no edge of pads at all, only a field of solder balls underneath, in rows and columns like squares on a chessboard. The number after the name counts the connections, so a DIP-28 has twenty-eight legs and a BGA-144 has one hundred and forty-four balls.

Why is a resistor called 0805, when it looks nothing like 8 by 5 of anything?

The four digits are the size of the part in hundredths of an inch, two for the length and two for the width. So 0805 is 0.08 by 0.05 inches, 0603 is 0.06 by 0.03, and 0402 is 0.04 by 0.02. An inch is 25.4 millimetres, so you can turn either figure into millimetres by multiplying. The lab prints the millimetre size of whichever part you pick, so you can check the arithmetic yourself.

The name says nothing about what is inside the box. Those same sizes carry resistors and every other two ended part. Somebody saying a board is all 0402 is telling you how small the parts are, and nothing about what they do.

Lab 35 · Nine packages, one scale
Try this firstPress 0402, the last button in the row under the two ended parts. It nearly disappears beside the grain of rice, so the picture draws it again underneath, many times bigger, and says by how much. The last pill turns into a warning reading it vanishes. Then press DIP-28, the first button under chip packages, and read that pill again.
Notice that the count of legs decides nothing. DIP-28 carries twenty-eight legs and any iron will do it, while SOIC-8 carries eight and wants a fine tip. Follow the bare gap column instead: the pitch with the width of the metal taken off it. The paragraph tagged soldering it names the exact numbers each verdict came from. Notice too that the picture never changes scale from one package to the next. The header pitch and the grain of rice stay the same length while the part below them grows and shrinks.
If I cannot solder a QFN, is that chip off limits to me?

No, because somebody else will have soldered one already. A breakout board is a small piece of board with the awkward package fitted in the middle. Round its edge is a row of ordinary holes, 2.54 mm apart, the same spacing as the header pins along the edge of a board. The difficult joints are made by machine in a factory, and what reaches you is a part with holes big enough to push a wire into.

That is how most radio chips and most sensors get onto a home bench at all. You pay several times the price of the bare chip for the extra board and the fitting, which is a fair trade the first hundred times. The same trick puts fine pitched chips on a breadboard, the plastic block full of holes 2.54 mm apart that parts push into. Nothing else would get pads a fraction of a millimetre wide into holes that size.

Every pin on a package has a number. The datasheet is the maker's own sheet of drawings and figures for that part. It says what each number is for: which pin takes the supply, which takes ground, which one your button goes on. The numbering starts at pin 1 and runs round the part anticlockwise. Nothing about the metal says which end is which, because the legs at one end look exactly like the legs at the other.

So the package carries a mark, and that mark is the only thing on the part that says where the numbering starts. It might be a notch bitten out of one end, a printed dot in one corner, a bevelled edge down one side, or a corner cut off. Whichever it is, it sits beside pin 1. Solder a chip in turned round from the way the board was drawn for it and the supply arrives on the pin that expected ground. That is usually the end of the chip.

Why does swapping the supply and ground kill a chip so quickly?

Every pin has a pair of protection diodes built in behind it, one up to the supply rail and one down to ground. A diode is a one way valve for current, the same part you fitted across the motor switches in Step 8. In normal use both valves are shut. They are there to catch a stray voltage that climbs above the supply or drops below ground, and steer it away before it reaches anything delicate.

Put the part in backwards and the two rails are pushed on the wrong way round. That leaves those valves pointing the way the current wants to go, so the whole supply pours through them and through the metal threads inside the chip. Nothing is limiting it. Those threads are a fraction of the width of a hair, they heat in milliseconds, and something inside opens or melts before you have finished noticing the smell.

Lab 36 · Find pin 1 on a part that has been turned
Try this firstRound 1 lays a DIP-8 down at some angle and asks you to click the leg that is pin 1. Read the line above the picture, which names the markings this part carries. Find them, and click the leg beside them. Whatever you click, the widget rings the real pin 1, puts a number on every leg, and works out what your answer would have cost. Then press Next part for another package at another angle, and press I cannot find it on any round where you would rather be shown.
Notice which wrong answers the widget will not put a price on. Some legs are places pin 1 could never be at any angle, and it says so rather than inventing damage for you. On the packages with two rows of legs it goes one further. It names the pin that would land on the pad the board holds at 3.3 volts. When that pin is the chip's own ground, it says the chip would get its power backwards. Notice too that the marking moves with the part while the rule does not. Pin 1 is beside the marking, and the numbers run anticlockwise from there, at any angle.
You need one particular chip on a board you are building at home. It is sold in two packages: a TSSOP with legs 0.65 mm apart down two sides, and a QFN with pads 0.8 mm apart tucked under the body. Which one can you put down with an iron and a fine tip?
The one with its legs on the outside. Pitch decides how hard a part is only while the metal is somewhere a tip can reach. Move the metal underneath and the pitch stops deciding anything, because there is nothing to touch. Picking the QFN for its wider pitch is the trap, and the pitch really is wider, which is what makes it tempting. Ruling out both parts is wrong the other way. The lab's verdict for legs 0.65 mm apart is flux and a magnifier. Flux is the sticky stuff that makes solder run onto metal, and that verdict is still a job done by hand.
Step 19

Find the one number in a datasheet that decides your circuit

Behind every chip is a document written by the company that makes it, called a datasheet. It runs to tens of pages of tables, and most of it will never matter to you. Nobody reads one from the front. A datasheet is a thing you search, and for a first circuit you are searching for four numbers.

Here they are. How much supply voltage the chip is designed to run on. How much current one pin may carry. How much current all the pins may carry added together. Those three sit in a block called the recommended operating conditions, and that block is where a design is meant to live. The fourth thing to find is a different block near the front, the absolute maximum ratings: the voltages and currents at which the chip is damaged. That block is the one people misread. An absolute maximum is not a setting. It is not a target. It is the edge of the map, and past it the sheet has stopped describing a chip that works.

Three habits make a single row readable. The columns headed min, typ and max are promises about every chip of that kind, not measurements of the one on your desk. Typ is what a middling chip does, and it is promised to nobody. Min and max are the edges the maker will stand behind. A symbol starting with V is a voltage and one starting with I is a current, on every sheet you will ever open. And an I/O pin is an input/output pin, meaning any of the ordinary pins your program can drive or read. Two legs are not I/O pins: VCC is the leg the 3.3 volt rail comes in on, and GND is the ground leg.

What does "damaged" actually mean? Does the chip explode?

Almost never. The thread of metal joining a pin to the outside world is thinner than a hair, and current warms whatever it flows through. A little warmth is nothing at all. Past the absolute maximum the heat arrives faster than the chip can shed it, and something inside melts, or the material around it changes for good. No bang, no smoke, usually nothing to see.

The nasty part is the timing. Sometimes the pin is deaf the moment you switch on. Sometimes the board works for a month, and then one pin stops while the rest of the chip carries on. You spend a weekend hunting a bug in a program that was never wrong. That is why "it worked when I tried it" says nothing at all about a rating, and why this block sits near the front of the sheet.

The rows say DC current, in or out of a pin. In or out of what?

DC is short for direct current, meaning current that flows steadily in one direction. The electricity in a wall socket does not: it goes back and forth fifty times a second, and that is AC. Everything on this board is DC. A row that also says continuous means the current may run that way for as long as you like, which is a much harder promise than surviving a flick.

Out of a pin and into a pin are both real. An LED wired from a pin down to GND lights when the pin is HIGH, and the current runs out of the pin: that is called sourcing. Wire the same LED from the 3.3 volt rail down to the pin instead. Now it lights when the pin is LOW, with the current running into the pin and away through the ground leg: that is sinking. Some chips can sink more than they can source and print two rows. This one prints a single row for both, which is why it is worded in or out.

Why is there a limit for the whole chip as well as one for each pin?

Count the metal. Every I/O pin draws its current from the same place: one leg marked VCC, and one thread of wire from that leg into the chip. Whatever all your pins take at once passes through that single leg, and so does the current the chip uses to run itself. The same is true on the way home through GND. Those legs and the black body they are set into, are called the chip's package. The package has limits of its own. They owe nothing to how cleverly you spread the load.

So a row of modest pins can kill a chip that no one of them could. Moving a load onto more pins helps the per pin row and does nothing whatever for the total row. A gadget that has to light more lamps than the total allows lights them a few at a time and cycles round fast. An eye sees them all lit at once, which leans on the same fact about you as the dimming in Step 6.

If a row allows a current, why do designers stay well under it?

Because the row is a promise about the chip, and everything else in the circuit is only roughly what it claims to be. A resistor sold as 220 ohms carries a tolerance, often 5 in every 100 either way. The one in your hand may really be 209 ohms. A supply called 3.3 volts may sit a little above that. The room may be warmer than the temperature printed at the top of the electrical block and a hot chip is allowed less than a cool one.

The space you leave between your design and the row is called margin. Aim exactly at a limit and the average part passes while some ordinary fraction of them fails. Those fail in somebody's house rather than on your bench. Deliberately working a part below its ratings is called derating, and using about two thirds of a limit is a common habit rather than a rule.

Lab 37 · Search the sheet for the row that decides it
Try this firstRead Question 1, then press the symbol button on the row you think answers it. The sheet replies at once and works out how far the cell in the question sits from that row. If you pressed the wrong one, it names the row you needed. Press Next question for the next one, and Show me the row when a question defeats you. Then type a word such as current into search the sheet to cut the table down to the rows that mention it. Clear the search brings them all back.
Notice how often the wrong row is the one with the bigger number on it. Several questions have a row in the absolute maximum block that looks like an answer, and choosing it tells you what that block is for. Once you search, a pill appears counting the rows your search is hiding. A word you guess wrong hides the row you came for, and the sheet cannot tell you that. Once a question is settled you can press any symbol you like, and the sheet says what that row gives and which block it came from.
Lab 38 · Wire LEDs to pins until the chip dies
Try this firstPress All eight at 100 ohm. Eight LEDs light, nothing breaks, and the last column of the table now says every pin is over row I_pin. Then press All eight at 68 ohm: the same eight LEDs, one size of resistor smaller, and the chip is destroyed. Fit a new chip puts a fresh one in and starts you back at three LEDs through 220 ohms.
Notice that nothing warned you at 100 ohms. Eight lamps lit, a board that would sail through an afternoon on a cool bench, and every promise in the sheet no longer applying. Then notice which row killed it at 68 ohms. Every pin was still well inside its own absolute maximum, and the chip died from the total instead. All eight currents come in through one leg, and so does the current the chip draws for itself. The pin that failed is the one you never wired anything to. Try Only D2, no resistor for the other way to kill it, one pin over its own rating. Notice too that a dead chip refuses every button afterwards. There is no undo on the far side of an absolute maximum.
Sixteen LEDs, one on each of sixteen pins, 5 milliamps each. The sheet above gives 7 milliamps for one pin, 60 milliamps for all the I/O pins added together, and 100 milliamps through the supply leg before damage. You build it and every LED lights. Where are you?
Outside the sheet, and lit. Sixteen at 5 milliamps is 80 milliamps. Every pin is comfortably inside its own row, which is what makes the first answer tempting. The row for all the pins together is a separate limit, and no amount of spreading helps it. Going past a recommended row costs you the sheet's promises. Going past an absolute maximum costs you the chip, and 80 is short of that one, so nothing is destroyed yet. Add the current the chip draws to run itself, and the real total through the supply leg is a little over 80. That is the sum the second lab does for you.
Step 20

Move a byte over four wires, and see why it beats two

Two wires were enough in Step 11 because a thermometer has almost nothing to say. A few bytes, once or twice a second. Ask the same pair for a whole screenful of dots twenty times over and they run out of second. Screens and memory cards use a different bus, called SPI. It spends wires to buy speed, and there are four of them. SCK is the clock, and the board makes it. MOSI carries bits from the board out to the chip. MISO carries bits from the chip back to the board. CS is chip select, one wire per chip.

Chip select is the whole of addressing here. The board pulls one chip's CS low to mean this message is for you. Nothing else is needed: no address byte at the front, and no ACK tick, which on I2C is the slot where the chip pulls the wire down to say it heard you. Each side holds its byte in a shift register, which is eight bits in a row. On every clock pulse it pushes one bit onto its own wire, top bit first, and takes one bit in off the other wire. So a byte goes out and a byte comes back over the same eight pulses, both at once. That is called full duplex, and one wire cannot do it. On I2C the question and the answer take turns on SDA.

Two things have to match at both ends, and neither is carried on any wire. The first is which voltage the clock rests at while nothing is happening. The second is whether a side reads the data wire on the first edge of a bit or on the second. Two choices with two answers each make four, numbered mode 0 to mode 3, and both ends have to pick the same number. Nothing complains when they do not. The clock stays clean, the wires still wiggle, and the byte is wrong. Or worse: one side reads the wire at the very instant the other side changes it. The first lab measures that. It reports the margin on every read, meaning how long that voltage had been sitting still before anybody looked at it. Margins are in nanoseconds and a thousand of them make one microsecond.

If I only want to read a byte from the chip, what am I sending on MOSI?

Something, whether you meant to or not. The clock belongs to the board, and while it runs both shift registers shift. When the board wants only the chip's answer, it sends filler, usually 0xFF or 0x00. A chip that is expecting to be read ignores whatever arrives. It works the other way too: when the board wants only to send, an answer comes back anyway, and the program throws it away.

That is why the operation has a different name here. A program talking to an SPI chip does not read or write, it transfers, because one byte out and one byte in is the smallest thing that can happen. The first lab shows both bytes moving at once. The one going out is the row of squares you can click. The one coming back is chosen from the menu underneath.

Why are there four modes, when one would have done?

Because nobody ever settled it. SPI was described by one company and copied by everybody. No committee ever said which edge was the right one, so parts shipped with all four combinations, and all four are still on sale. A datasheet writes the two choices as CPOL and CPHA. Polarity is the level the clock rests at between bytes. Phase is whether the reading edge is the first edge of a bit or the second one.

They are two questions rather than four arbitrary numbers, which makes them easy to keep straight. Polarity is the top half of the mode number and phase is the bottom. Mode 0 is both zero. Mode 1 keeps the resting level and moves the reading edge. Mode 2 moves the resting level and keeps the edge. Mode 3 moves both. You never have to guess which one a part wants: it is printed in the datasheet, and setting it is one line in your program.

Why is a link with no margin worse than one that is plainly broken?

A read with no margin is a race. One side is changing the wire at the instant the other looks at it, and which value wins is decided by a few nanoseconds inside two parts that were never promised to agree. It can come out right. It can come out right every single time, on the board on your desk, with short wires, in a warm room.

Then the next board off the shelf has a slightly quicker chip on it, or the wires are longer, or the room is cold. Now it comes out wrong once an hour. A fault that shows up in one unit in ten costs far more than one that shows up in all of them, because the units that work are what stop anybody looking. The first lab will not name a winner for a read with no margin. It prints both possible bytes and says that nothing in the wiring chooses between them.

So which bus do I actually use, and what is UART?

Three questions decide it: how many chips, how fast, and how many pins you can spare. I2C is two wires however many chips hang off them. It pays for that with an address and an ACK on every message, so it suits several slow parts. SPI is three shared wires plus one chip select each. It buys back the address, the ACK and the waiting, so it suits one or two fast parts, such as a screen or a memory card. UART is the third one you will meet. The second lab puts it in the table beside the other two, and Step 21 is about it.

A UART link has no clock wire at all. It is one wire each way between two devices, with both ends agreed beforehand on how fast the bits will come. That is what the cable from a board to a computer uses to carry printed messages. There is no address, because there is nobody else on the wire to address. Nothing is shared either, so a second device costs two more pins and another link inside the chip. Chips are built with only a couple of those, and that limit arrives long before you run out of pins.

Lab 39 · One byte each way, edge by edge
Try this firstPress Tick the clock once five or six times. Each press moves the clock on by one edge. The board picture and the four traces redraw, and the writing at the bottom names the edge. It says which side looked at which wire, what it found there, and how long that had been sitting still. Press Run to the end for the rest of the byte, and the verdict underneath says both bytes arrived whole. Now leave the board on Mode 0. Open the menu the mode the chip expects, choose mode 1, and press Run to the end again.
Notice that a mode mismatch comes in two quite different flavours. With the chip on mode 1, the pill that reported the smallest margin turns into a count of reads with no margin at all. The verdict prints two possible bytes, because nothing decides between them. Now put the chip on mode 3. The clock is clean, no read is a race, and the byte coming back is still wrong. That side puts its first bit out half a bit later than the other side goes looking for it, so every read is out by one place. Then press Never pull chip select low. The chip stops driving MISO, and the board's reads come back as question marks rather than bits. The table prints no byte at all, because eight reads of a wire nobody is holding do not make a byte.
Lab 40 · Wires against speed against how many chips
Try this firstPress A small screen, 20 times a second. The table redraws for one chip at that rate. The bars under it show how much of one second each bus would spend moving those bytes. The line below names the bus that wins and says what the other two would cost. Then press Four temperature sensors and read those same two places again: same board, same three buses, different winner.
Notice which column decides each answer. With four slow sensors, both I2C and SPI are nearly idle, so nothing separates them on time. The pick comes down to pins, and I2C wins, because two is all it ever needs. With one screen the pins stop mattering and the busy column decides instead. I2C spends a large slice of every second on it, and the program gets whatever is left, while SPI is barely awake. Now press Draw the SPI wiring and drag how many chips up to 8. The pin count printed on the board climbs by one per chip, because three of the wires are shared and a chip select cannot be. Do the same on Draw the I2C wiring and it does not move at all. UART loses both rounds, for two different reasons: read its line in the last column each time.
A friend says SPI moves a byte faster than I2C because it has two data wires instead of one, so two bits travel at a time. Where does that go wrong?
The second wire brings the answer back, it does not carry half the question. MOSI and MISO go opposite ways. The eight bits the board is sending still need eight clock pulses, exactly as they would on one wire. What makes SPI quick is in the second lab's table. Its clock runs many times faster than an I2C bus does, and every byte on I2C costs a ninth slot for the ACK, on top of the address, the start and the stop wrapped round each message. Full duplex is still worth having: the answer rides the same eight pulses as the question and costs nothing extra. The last answer has it backwards. SPI needs more wires than I2C, not fewer, and that is what it pays for the speed.
Step 21

Send characters down one wire to a computer

You cannot see inside a running chip. It has no screen, and no window into its memory. So when a program does something you did not ask for, the way to find out why is to make the board tell you. It talks down a single wire, out of the pin marked TX, with the shared 0 V as the other side of the circuit. A program on your computer draws the characters as they arrive. Printing like this is how most faults in real embedded work get found, and it needs no extra hardware.

The bus in Step 11 came with a clock. SCL ticked, and every chip looked at SDA on each tick. The four wires in Step 20 had a clock too. This wire has none. It rests high. To send one character the sender drops it low for one bit time and a bit time is however long it has been told to hold a single bit. That first low is the start bit. Then come the eight bits of the character, one bit time each, smallest first. Then the wire goes back high for one bit time. That is the stop bit. Ten bit times and the character is gone. The part of the chip that does the counting is called a UART and the whole arrangement is often just called serial.

Nothing on the wire says how long a bit time is. Both ends have to be told the same number beforehand. That number is in bits per second, and it is called the baud rate. Tell them different numbers and the listener does not fall silent. It does not complain. It sees the fall. It counts out ten bit times of its own, at the wrong length. Its looks land in the wrong places, so it hands your computer the wrong numbers. What arrives is not nothing. It is text that is almost right, or rubbish.

With no clock wire, how does the far end know when to look?

The fall at the front of a character is the only event it ever gets. From that moment it counts its own bit times. It looks at the middle of each one, not at the edges. The middle is the point furthest from both edges. So the two ends can be a little out of step, and the look still lands inside the bit it belongs to.

How far out they may be follows from that. The tenth look is the last, and it comes nine and a half bit times after the fall. A small difference in speed has all nine and a half of them to pile up in. Once the pile-up passes half a bit time, that look crosses into the bit next door and the character changes. Then the next character starts the counting again from its own fall. That is why a long line is no worse than a short one: the error never gets more than ten bit times to grow in.

Where do numbers like 9600 and 115200 come from, and what does 8N1 mean?

A chip makes a bit time by counting ticks of its own clock. Only certain lengths come out exactly right, so everyone settled long ago on the same short list of speeds. 9600 is the old safe default, and 115200 is the usual fast one. Neither number is special in itself. A bigger one holds each bit for less time. More characters fit into a second, and there is less room for the two ends to disagree.

Serial settings are usually written as the speed and then 8N1. That is eight data bits, then N for no extra check bit, then one stop bit. The check bit it is refusing is a parity bit. Some setups add one so that a single flipped bit can be spotted. Nothing here sends one, and 8N1 is what almost everything uses. Both ends have to agree on all three parts, not only the speed.

My computer has no pins like that. How does the wire get in?

On most boards a second small chip sits next to the main one. It turns this stream of bits into USB. So the cable you already plug in to power the board is carrying it. With a bare chip you add a small adapter that does the same job. Either way, the wire in this step is the wire, with a translator on the end of it.

At the computer, a terminal program draws one character for every number that arrives. It has a speed setting of its own, and that setting is the one people forget. The board gets changed to a new speed. The program on the computer is left at the old one. The screen then fills with nonsense from a board that is working perfectly.

Why bother with a stop bit, if the wire goes high again anyway?

It does two jobs. The first is to guarantee a high before the next character, so that the next fall is a real fall. Characters follow each other with no rest. Without that guaranteed high, two in a row could run together, with no edge between them for the listener to start from.

The second job is a free check. The tenth look expects to find the wire high. If it finds it low, the ten bit times did not line up with the ten that were sent. A real chip reports that as a framing error, and many programs answer by throwing the character away. The stop bit is where a mismatched speed shows up first, because the tenth look has had longest to drift.

Lab 41 · One character, ten bit times
Try this firstPress Send the character. The box marked the character starts with a capital K. A dashed rule labelled now walks across the trace, and the ten looks get named one at a time. The row marked what the receiver has fills in from left to right, and a K appears on the little screen at the right. Then press Back to idle. Press Look at one more bit ten times over, and read the line underneath after every press.
Notice the row marked worth. The bit worth 1 goes down the wire first, so the receiver collects the small bits before the big ones. Step 20 sent the top bit first, and this one is the other way round. Add up the worths of the bits that came back as 1 and you have the character's number. Press K and send it, then press k and send that. Exactly one square changes: the one worth 32, which is the whole difference between a capital and a small letter. Changing both ends were told alters no bit at all. It only changes the pills for how long one bit lasts and how long ten of them take. In those, us is short for microseconds, millionths of a second.
Lab 42 · Two ends told different numbers
Try this firstPress Listener 7% fast. Read the two lines on the screen. sent still says Temp 21.4 C, and seen has turned several of the letters into accented ones, while the digits came through untouched. Then press Both at 9600 to get it back. Now drag and its own clock is out by (%) up one step at a time, until the badge counting framing errors stops saying zero.
Notice which badge goes bad first as you nudge that clock out. The framing errors arrive while every character is still correct. The tenth look has found the wire low where the stop bit should have been high, which is what a chip calls a framing error. It is the warning that comes one step before the text itself starts changing. Push further and the table shows the mechanism, look by look, sliding out of the slot it was counting on. Then press Listener at 19200 and compare the lengths of the two lines on the screen. The listener now takes a fall from the middle of a character for the start of a new one, so more characters come out than ever went in.
A board is set to print at 9600 bits per second, and the terminal program on the computer has been left at 4800. The wire and the board are both fine. What turns up on the screen?
Wrong characters, not silence. There is no clock wire and no conversation, so the listener cannot discover that the number it was given is wrong. It waits for a fall, then counts ten bit times of its own length, which here are twice as long as the ones on the wire. Its looks land in the wrong bits, and the later ones land in the following character altogether. So it can hand up fewer characters than were sent, or more. Arriving half as fast would be the answer if the two ends were negotiating, and they never negotiate anything. Rubbish on screen from a board you can see is running is the signature of a speed that does not match, and it is the first thing to check.
Step 22

Give the board power that does not sag when a motor starts

Every step so far has assumed 3.3 volts arrives on the board and stays there. It does not arrive on its own. What you have is a USB cable at about 5 volts, or four AA cells at 6, or a motor supply at 12. None of them hold still. The part that turns whatever you have into a steady 3.3 volts is called a regulator, and every board in this course has one.

There are two ways to build a regulator, and they fail differently. A linear one behaves like a resistor that adjusts itself. It holds its output at 3.3 volts and every volt it does not pass on it turns into heat. How much heat is one multiplication. Volts multiplied by amps gives watts and a watt says how fast energy is turning into heat. So the heat is the volts thrown away, times the current going through.

A switching regulator chops instead. It connects its input to a coil for part of each cycle, the way PWM chops a pin in Step 6. The coil carries the energy across the gaps, and almost nothing is thrown away. The price is an output that is never quite still. It is being topped up and allowed to fall again, thousands of times a second.

Why not just use a resistor to get from 5 volts down to 3.3?

Because the voltage a resistor drops depends on the current through it. That is the divider from Step 10, doing exactly what it did there. A board might take 30 milliamps while it is idle and 300 with its radio on. A resistor picked to drop 1.7 volts at 30 milliamps drops ten times that at 300, and the rail would move every time the board did anything.

A regulator watches its own output instead, and adjusts thousands of times a second, so the output stays put while the current wanders. What it cannot do is invent voltage. Both kinds need their input to sit above their output by some margin. Below that margin the output simply follows the input down.

Why does a warm regulator matter if it is still doing its job?

Because the heat has to go somewhere, and a part soldered flat to a board has almost nowhere to put it. A small package with no metal bolted to it warms up in proportion to the watts it is burning. Double the waste and you roughly double how far above room temperature it sits.

Past a temperature printed in its datasheet, the part turns itself off to save itself. The rail collapses and the board stops. Then the part cools and starts again. What you see is a device that works for half a minute, dies, and comes back. Nothing in the program is wrong, and reading the program will never show you that.

If the switching kind wastes so little, why does anybody still fit a linear one?

Cost and quiet. A linear part is a component with three legs and a capacitor at each end. A switching one needs a coil, more parts around it, and a careful board layout. It costs more. At small currents the heat a linear part makes is nothing worth avoiding.

The quiet matters when the board is measuring something. Chopping leaves a small wobble on the rail, called ripple, and the converter from Step 10 measures against that same rail. A reading taken at the wrong moment in the wobble comes back a count or two out. The lab below gives the ripple in millivolts and in converter counts, so you can see whether it would reach the number you care about.

Lab 43 · Two ways to make 3.3 volts
Try this firstPress 12 volts in, motor driver too. The two sliders jump to a 12 volt supply and a board taking 500 milliamps. The linear regulator turns red, and the line under it says it gets hot enough to shut itself off. Then press Fit the switching part and compare the two bars. They show both parts side by side, whichever one you have fitted.
Notice which slider changes the heat. Go back to a sensor on USB and drag volts from the supply up on its own. The board at the far end is doing the same job as before, and the linear part gets hotter every step, because it is throwing away more volts at the same current. Now drag that slider all the way down and read the words underneath. Below some input voltage the linear part cannot make 3.3 volts at all, and where that happens moves with the current. Notice too the small box under the wire: flat for the linear part, a sawtooth for the switching one.

Now the failure that catches people out. A motor at the instant it starts is not turning yet. Nothing inside it is pushing back, so it takes several times the current it takes at speed. That gulp lasts a few thousandths of a second. Feed the motor from the chip's own 3.3 volt rail and the regulator reaches the most current it will give, and the rail falls. Every chip has a line drawn across its own supply voltage, and below that line hardware inside the chip holds it in reset. That is the same full restart the watchdog causes in Step 14. A supply that dips through that line has a name, a brownout, and from the outside it looks exactly like a firmware bug.

Two things fix it. The first is a capacitor, which is two metal plates with a gap between them. It holds a small amount of electricity, and gives it back the instant the voltage across it starts to fall. That makes it a tiny local reservoir. One fitted right next to a chip for that job is called a decoupling capacitor, and its size is measured in microfarads, millionths of a farad. The second fix is to stop the motor drinking from the chip's rail at all, and give it a supply of its own.

Why does a motor take more current starting than it does running?

A motor turns because current in its coils makes a magnetic field, which is the switchable magnet of Step 9. Once the rotor is moving, those coils are dragged past a magnet. That produces a voltage of their own, pushing back against the supply, and the push-back is most of what limits the current in a running motor.

A rotor that has not started yet pushes back with nothing. The only thing limiting the current is then the resistance of the winding, which is small. For a little motor that is several times the running current. It dies away over a few thousandths of a second as the rotor picks up speed. A rotor that is jammed never picks up speed, so its current never dies away at all.

If the motor has its own supply, why does the chip's rail still move at all?

Because the two supplies still share a ground wire. They have to. Two circuits with no shared ground have no agreement about what 0 volts means, which is the point made about the servo in Step 7. Every amp the motor takes comes home along that shared wire.

A wire is a resistor with a very small value, a few hundredths of an ohm for a short thick one. Current times that small resistance is a small voltage. It appears as the ground under the chip lifting while the motor pulls. The chip cannot tell that apart from its supply dropping, because it only ever sees the difference between its two pins. Short and thick is the whole of the fix, and the lab below measures what is left.

Lab 44 · The dip that resets the chip
Try this firstPress Play the run. The cursor sweeps across the plot. A program waits, switches the motor on for a while, switches it off, and repeats. It starts with 100 microfarads by the chip and a starting gulp of 1.20 A, and the pills underneath report a reset for every start. Then press Zoom in on the first start to spread that one dip across the frame.
Notice what a bigger capacitor actually buys. With the zoom on, step capacitor by the chip up one value at a time. The dip does not get shallower, and the pill for the lowest rail barely moves. What moves is the first reset mark, sliding further right each time. At the top of the slider it holds out long enough and the resets stop. Now push starting gulp, amps up. Past a certain size no capacitor on the slider is enough. The gulp does die away as the rotor gets going, so the shortfall has an end, and the line underneath works out what covering that end would take: at the top of the slider the answer is near twenty thousand microfarads, and the largest part on offer here is 2200. Press Give the motor its own supply and the resets stop whatever the capacitor is. The rail still moves a little, and that last bit is the shared ground wire from the note above.
A robot resets every time its wheels start turning. Its builder fits a capacitor next to the chip, ten times the size of the old one. Now the reset happens about a millisecond after the motor switches on, instead of straight away, and the board still resets. What does that measurement tell them?
It is buying time, and not enough of it. The reset moved, and something doing nothing would have left it exactly where it was. A capacitor covers the difference between what the motor asks for and what the regulator will give. It can only do that until the electricity it holds runs out, so a bigger one holds out longer without making the dip any shallower. From there the choice is a capacitor big enough to outlast the whole gulp, or a separate supply for the motor, which works whatever the motor does. The last answer has it backwards: a smaller capacitor empties sooner, which is where this builder started.
Step 23

Connect a 5 volt part to a 3.3 volt pin without killing it

Two boards on one bench do not have to agree about voltage. Your board's pins swing between 0 volts and its own 3.3 volt rail. The display or the older sensor you have just bought may run on 5 volts, and plenty of small sensors and memory cards run on 1.8. Join a pin on one to a pin on the other and two different rails now meet on one piece of wire. The two directions across that join are different problems, and only one of them destroys anything.

Going up, into a part that runs on more than you do, is a question about reading. An input decides between a 1 and a 0 by holding what arrives against two voltages out of its own datasheet. VIH is the level it promises to read as a 1. VIL is the level it promises to read as a 0. Between the two it has promised nothing, and either answer can come back. So there is no general answer to whether a 5 volt part reads 3.3 volts as a 1. There is an answer for the part in front of you, and it is a number on the sheet. Parts built to the older TTL numbers put the bar for a 1 a little above 2 volts, whatever rail they run on, and 3.3 clears that easily. Parts built to CMOS numbers set the bar at around seven tenths of their own rail. On 5 volts that is above 3.3, so the same wire tells them nothing.

Going down, into a part that runs on less, is not about reading at all. Every input pin has a diode built into it, joining the pin to its own rail. A diode is a one way valve for current, the part Step 8 fitted across a motor's switches. This one is there for small accidents. A brief spike off a long wire gets passed up into the rail instead of into the chip, and the diode can carry a few milliamps while it does that. A 5 volt output on a 3.3 volt pin is not a brief accident. It holds that pin over its absolute maximum, the block of numbers where a datasheet stops describing the chip and starts describing damage. It holds it there for as long as the thing is plugged in and the diode is what gives out. There are three ways to stop that and the lab has all three. Fit nothing at all, when the numbers allow it. Fit two resistors sharing the voltage, the way the divider in Step 10 shared it. Or fit one small transistor with a pull-up on each side, which is what sits on a board sold as a level shifter.

Where do the TTL and CMOS numbers come from?

TTL is the older family, named after the way those chips are built inside. Its two numbers are fixed and they are low, and they were settled by parts made in the 1970s. Chips made today keep to them so that old and new can be wired together. That is the whole reason a 5 volt part can be perfectly happy with 3.3 volts arriving: a decision taken half a century ago.

CMOS chips set both numbers as a fraction of their own rail instead, around seven tenths for a 1 and three tenths for a 0. Move such a part onto a 3.3 volt rail and its bar for a 1 comes down with it. Leave it on 5 volts and the bar sits above anything your board can send. The two buttons in the lab load each pair and print the numbers they are loading.

Where is this diode, and why has nobody mentioned it until now?

Because nothing has gone near it before. Every input pin has a pair of them, one up to the rail and one down to ground. They carry no current at all while the voltage on the pin stays between the two rails, which is where a pin normally lives. They start carrying only when something pushes the pin outside that range.

Once the pin is pushed above its rail, the diode holds it a little above the rail and will not let it climb further. Everything above that has to be dropped across whatever resistance sits in the path, and that is what decides the current. Current is the thing the diode has a rating for. So the same 5 volts is survivable through a large resistor and fatal through a plain wire, where the only resistance is the sending pin's own few tens of ohms. The lab works the current out for you, and names the rating when you go past it.

Why would putting a resistor in the way make a signal late?

A pin and the wire on it behave like a very small capacitor, the part from Step 22: two pieces of metal near each other holding a little charge. Before the voltage at the pin can change, that charge has to be moved in or out. The amount is tiny, measured in picofarads, which are millionths of a microfarad. The line above the trace in the lab says how much this model allows for a pin with a short jumper wire on it.

Resistance limits how fast charge can move, so it sets how long that filling takes. A pin driving directly has only its own few tens of ohms in the way, and the edge takes nanoseconds, thousandths of a microsecond. Put a 10 kilohm resistor in the way, a kilohm being a thousand ohms and the same edge takes hundreds of times longer. None of that matters while each level lasts a millisecond. When a level is shorter than the edge, the voltage is still on its way up when the receiver looks and the receiver reads whatever has arrived so far.

Why not fit two resistors everywhere and be done with it?

Three reasons, and the lab measures all three. A divider only works one way, from a higher rail down to a lower one, so it can never lift 1.8 volts to what a 3.3 volt CMOS input wants. It pulls current the whole time the line is high, which a battery notices. And it slows every edge, which costs nothing on a button and loses bits on a fast bus.

The transistor answers all three, and it works in both directions on the same wire. That last part is what I2C needs. The ACK tick in Step 11 was the sensor pulling SDA down, so both ends drive that one wire and a one way divider would be no use there. What has to be right when you fit one is which side is which. The deciding leg goes to the lower of the two rails and the leg marked source goes to that same lower side. The transistor drawn in the lab is marked BSS138, which is the part number most of these little boards carry. For a fast one way line, an SPI clock at several megahertz, people fit a chip made for the job instead.

Lab 45 · Both directions across the join
Try this firstPress CMOS levels. The board is sending into the 5 volt part through a plain wire, and every level was arriving as sent. No wire changed and no voltage moved, and now three of the six levels do not arrive. The 3.3 volts that was a 1 against the TTL numbers is neither a 1 nor a 0 against these. Press TTL levels to put it back, then press The 5 V part sends and read the line under the pills.
Notice that the pin does not die of voltage, it dies of current. The pill counting milliamps through the protection diode is the one that decided it, and the narration names the rating it went past. Press Fit a new board with the plain wire still connected, and the new pin dies as it arrives, which is what happens on a real bench. Get the voltage down first: press Resistor divider, then Fit a new board. Now drag the signal all the way to the right, to SPI at 8 MHz, and watch two resistors that were fine a moment ago lose nearly every level. Press One transistor and two pull-ups, and drag pull-up on each side down to its smallest value to get the levels back. The pill counting what the pull-ups pass says what that costs.
You wire a 3.3 volt board's output straight into the input of a 5 volt part. That is the direction that does not damage anything, and nothing is damaged. The part also reads every 1 you send as a 0. What is wrong?
Look up that part's VIH. The level arriving sits in the gap between its VIL and its VIH, where it has been promised nothing, and this one answers 0. A part whose VIH is a fixed low number would read the very same wire as a 1. That is why this works for some people and not for others, and why the rule of thumb is worth less than the sheet. The pull-up is tempting because one rescued a floating pin in Step 4. To lift this line it would have to go up to the 5 volt rail. Then that rail leans on your board's pin through a resistor whenever your pin is not driving, which is the fault the rest of this step is about. A long wire loses a fraction of a volt, not a whole one.
Step 24

Put it together: a line follower and a weather station

Two projects, and between them they use most of this course. Neither one is finished, and neither pretends to be. Each widget ends with a paragraph saying what it leaves out. It names the missing piece and the course that deals with it, and that list is worth as much as the project above it.

The first is a robot that follows black tape across a pale floor. It has two wheels, each driven through the H-bridge from Step 8. It has two sensors pointed at the floor just in front of them. A floor sensor is an LED shining down with a light sensor beside it, the kind Step 10 turned into a number. Black tape sends almost none of that light back, and pale floor sends back plenty. The converter answers with a count from 0 to 1023: 0 for bare floor, 1023 for a spot sitting completely over the tape.

The steering rule is one subtraction. Take the left count away from the right count. Zero means the tape is centred between the two sensors, so drive straight on. If the right sensor is the darker one, the tape has gone off to the right, so steer right. Steer harder the further apart the two counts are. How much harder is one number, called the turn strength here. Picture one sensor completely over the tape and the other on bare floor: the turn strength is the turn it asks for then, in degrees a second. Steering now changes what the sensors see, which changes the steering. That circle, where what a program does comes back to it as its next reading, is a closed loop. This is the first one in the course.

Why two sensors? Would one not do?

One sensor tells you how dark the floor is under it, and nothing else. A reading halfway between tape and floor means the edge of the tape is under the spot. That is equally true whether the tape has slipped to the left or to the right. A robot with one sensor has to hunt: swing one way, see whether the reading got darker, swing back if it did not. It works. It wags all the way down the straights.

Two sensors give a difference, and a difference has a sign. Whichever of the two is darker is the side the tape is on. There are two ways to get a difference of zero, mind. One is dead centre. The other is both spots out on bare floor with the tape nowhere near. The difference cannot tell those apart, but the two readings can, and when both stay near zero for long enough the robot below stops and says it has lost the tape.

If the rule is right, why does it wobble at all?

Because nothing in a real loop happens at the moment it is decided. The sensors sit in front of the wheels, so the robot feels a corner before the wheels reach it. The reading the program steers on was taken a few passes round the loop ago. The wheels then take a moment to settle to the new speed they have been given. Every correction arrives after the situation that asked for it.

A late correction that is small does no harm. A late correction that is large arrives once the error it was meant to cancel has gone. It carries the robot past the middle the other way, and the next one carries it back. That is the snaking you can produce in the lab below, and turning the steering up makes it worse rather than better. Measuring how late a loop is, and choosing the steering to match, is the whole of Control Systems.

Lab 46 · Steer a robot from two floor sensors
Try this firstPress Watch it drive. The picture plays the run back and leaves a trail where the wheels went. The four badges under it change as it goes. The badges below those, and the line under them, describe the whole run at once. Then press Too gentle. This one comes off the tape, and the line at the bottom works out how sharp that bend is and how much turn holding it needs. Then press Too twitchy. This one reaches the end, so look at the shape of the trail rather than the verdict. Last, drag turn strength, degrees a second yourself, and find the lowest setting that still gets to the end of the tape.
Notice that the two failures are not the same failure. Too gentle is not reacting too slowly. It cannot ask for enough turn to hold the tightest bend, whatever it sees. That is why the line at the bottom compares the turn that bend needs against the setting you gave it. Too twitchy still gets round. What it costs shows in two badges: crossings of the middle, and the share of the run spent asking for more turn than the wheels can give. Both climb as you raise the slider. Now press Steady and drag sensor spacing, mm to each end of its travel. The worst wander badge is smallest somewhere in the middle. A pair too close together sits entirely on the tape, and a pair too far apart has both spots out on bare floor.

The second project has no wheels and changes nothing. It asks the BME280 from Step 11 for a temperature and a pressure over the two wire bus, over and over, all day. It smooths the readings with one of Step 16's filters, keeps the newest handful, and throws the rest away. A device that measures and records but never acts is a data logger. The boards left in plant pots, on hillsides and inside walls are nearly all loggers.

Two things about it matter more than any single reading. The first is that a reading can arrive damaged. One bit of a byte flips on the way, or one of the two bytes never turns up and the program uses a zero in its place. Nothing in those bytes says which has happened, so a temperature that never existed goes into the log looking exactly like weather. The second is that the store is small, so most of the day gets thrown away. What is left is whatever the logger worked out while each reading was still in its hands.

Why throw readings away? Why not keep the whole day?

Because the memory on a chip like this is a few tens of thousands of bytes, and the program's own variables live in it too. Four bytes a reading sounds like nothing until the device is meant to sit there for a year. Sooner or later every logger has to decide what to forget.

The usual choice keeps two things. First, the newest few readings, so that recent history can be looked at. Second, a handful of summaries brought up to date as each reading arrives: the biggest jump so far, a running total, the highest and the lowest. Each of those is a couple of numbers being compared and replaced, so they cost the same after ten thousand readings as after ten. What you give up is any question you did not think of in advance, because the readings that would have answered it are gone.

How can smoothing ever make the answer worse?

A filter that leans on the last few readings answers with a mixture of them. Its answer therefore describes some moment part way through that stretch, not now. While the weather is barely moving, and the wobble is the only thing changing, that is a good trade. Lean on more minutes than the weather stays still for and the filter is reporting a temperature that has already gone.

Step 16 measured that trade on a run of readings. The lab below is harder on it. The weather in there was invented by the simulation, so the widget knows the true temperature, and it holds both the raw number and the kept number against it. No real board can do that. Working out what a sensor's answer means when nobody knows the true value is calibration. It is its own subject.

Lab 47 · Log a day of weather into a store that cannot hold it
Try this firstPress Take one reading. The two wires light up, and the panel on the right shows the four bytes the sensor sent back. They appear as hexadecimal, as the whole numbers those bytes make, and as degrees and hectopascals, which is the unit weather forecasts count pressure in. Press Take twenty more twice. The two charts appear, the store fills up, and the badge for readings thrown away starts counting. Then press Log the whole day, and watch the small block on the strip marked the day cross it from left to right. Then try No filter, Moving average and Fading average, and drag readings the filter leans on from 2 up to 10.
Notice what the logger still knows about readings it no longer has. After logging the whole day, the table holds the last few readings of the night, and the strip shows how little of the day that is. Two readings arrived damaged, hours apart, and both were pushed out of the store long ago. The line at the bottom still names the clock times they came in at. The raw side of the biggest jump badge is still far larger than anything the weather itself did, because that badge was kept up to date as each reading went past. Notice too what Fading average with readings the filter leans on at 10 does. The kept number now misses the real temperature by more than the raw readings do, and the line at the bottom says smoothing is losing.
A line follower keeps sliding off the tightest bend, so you turn the steering up until it gets round. Now it snakes down the straights, crossing the middle over and over. What is going on?
The correction is late, not weak. The robot steers on a reading from a few passes ago, and its wheels take a moment to settle after that. The turn takes effect once the robot is already back near the middle and still moving. Turning the steering up makes every late correction bigger. That is why the crossings badge and the badge for asking more turn than the wheels can give both rise as you drag that slider up. Averaging the two sensors would be worse than useless. The difference between them is the only thing that says which side the tape is on, and averaging is exactly what throws that away. Holding a tight bend and settling on a straight are two different demands, and one number cannot serve both well. Splitting them apart is what Control Systems is for.
Step 25

Follow the chip from reset to your first line of code

Pressing reset does not jump straight to setup() or main(). The processor first reads a vector table at an address fixed by the chip. That table gives it an initial stack pointer and the address of a reset handler. The handler selects clocks, copies variables with initial values from flash into RAM, clears zero-initialised RAM, prepares the language runtime and only then calls the application.

The reset-cause register says whether power-on, a watchdog, a brownout, a pin or software caused the restart. Read it early and save it in a boot record. Otherwise a board that “restarts sometimes” erases its best clue on every boot. A fault handler needs the same discipline: preserve the stacked program counter, fault status and software version before resetting or entering a safe state.

Why does a program fail before main?

A bad vector address, wrong linker script, unsupported clock setup, stack outside RAM, failed memory copy or a constructor can all fault first. Attach the debugger at reset, inspect the program counter and vector words, then step through startup. Do not keep adding prints; the serial port may not exist yet.

A watchdog reboot is reported as a normal power-on boot. What should firmware check first?
Preserve the reset cause first. Startup code may change hardware state before the application can inspect it.
Step 26

Budget flash, RAM, stack and heap separately

Flash normally holds code and constants when power is off. RAM holds writable globals, stacks, heaps and peripheral buffers while the chip runs. A program can fit in flash and still crash because a nested interrupt, a large local array or a communications burst pushes the stack into other RAM.

Read the linker map after every release build. It names each section and symbol instead of giving one vague percentage. Avoid unbounded allocation in long-lived firmware; if a heap is needed, test fragmentation and allocation failure. Fill unused stack with a known byte at boot, then inspect its high-water mark after worst-case work and nested interrupts. Keep margin for library updates and failure logging.

What do memory-mapped registers have to do with RAM?

The processor uses addresses for both. Some ranges select RAM or flash; other ranges select peripheral registers. A write to a GPIO register changes hardware rather than storing an ordinary variable. Use the vendor header and the right access width. Reserved bits must be kept at their documented values.

The build uses only half the flash, but it crashes in a deeply nested error path. Which evidence is most useful?
Inspect RAM and stack use. Flash capacity says nothing about a stack collision.
Step 27

Sample an analogue signal without inventing a new one

An ADC compares an input with a reference and returns one of a fixed number of codes. A 12-bit converter has 4096 levels, but that does not make it accurate to 12 bits. Reference tolerance, input noise, offset, gain error, board coupling and calibration all remain. The ADC’s sample capacitor also needs time to charge through the sensor’s source resistance; a high-resistance source may need a buffer or longer acquisition.

Filter the analogue signal before sampling. Any energy above half the sample rate can fold into the kept band as an alias. Sample faster than the signal plus a real filter transition, keep timestamps, and average only when the quantity can tolerate the added delay. Use an external reference or ratio measurement when supply movement would otherwise look like sensor movement.

Why does the first reading after changing channels look wrong?

The ADC’s small sampling capacitor still holds charge from the previous channel. It must settle toward the new voltage through the new source. Data sheets specify acquisition time and source impedance. A dummy conversion, slower ADC clock or buffer may be required; test across the full input range.

A 900 Hz vibration is sampled at 1 kHz with no analogue filter. Can software know it was really 900 Hz from those samples alone?
No. The lost distinction must be protected before the ADC with sample rate and filtering.
Step 28

Keep the files that explain what the compiler put on the chip

The compiler turns each source file into machine code and relocation records. The linker combines them according to a linker script, places vectors and sections at real addresses, and emits an ELF file. Keep that ELF, its symbols, the map file, exact compiler flags, libraries and board definition with each released image. A bare binary can be flashed, but it cannot explain itself during a crash investigation.

Use warnings as errors for the warnings the project understands, static analysis for paths the compiler misses, and unit tests for pure logic on the host. Then use SWD or JTAG to halt at reset, inspect registers, set watchpoints and view memory without changing timing as much as print statements do. A logic analyser checks buses and pins; an oscilloscope checks voltage, edge shape and timing. Pick the tool that sees the failing layer.

Why does a release build behave differently?

Optimisation changes instruction order, removes unused reads and keeps values in registers. Undefined behaviour and data races often surface here. Reproduce with the exact release flags, keep debug symbols, inspect the disassembly around the fault, and fix the invalid assumption rather than disabling optimisation.

Which release artefact tells where code, globals and buffers were placed?
The map and ELF. They connect source names to addresses and section sizes.
Step 29

Give shared state one owner or one short atomic rule

Main code, interrupt handlers and DMA can touch memory at overlapping times. volatile tells the compiler that a value may change outside the current code path; it does not make a multi-byte access indivisible, order two cores, protect a data structure or flush a cache. Those are separate problems.

Prefer one owner and pass small immutable events through a bounded queue. For a short shared snapshot, use the chip’s atomic operation or mask only the relevant interrupt for the few instructions needed. DMA needs explicit buffer ownership: the peripheral fills one buffer while the CPU consumes another, then a completion event swaps them. Count overruns and carry sequence numbers and timestamps.

When should an interrupt handler do less?

Almost always. A handler should capture the event, clear the hardware source and wake or enqueue work. Blocking, printing, allocation and long calculations increase latency for every other interrupt and make timing hard to prove. The Real-Time Systems course develops response-time analysis and priority inversion.

Does marking a 16-bit counter volatile make its read atomic on an 8-bit processor?
No. Volatile controls compiler access, not the hardware width of the operation.
Step 30

Use an RTOS when explicit tasks make the timing easier to prove

A timer-driven main loop can run many products. An RTOS becomes useful when several jobs block on different events, need clear priorities, or come from separate components. It provides tasks, queues, semaphores, timers and a scheduler. It does not create more CPU time, fix an overloaded design or make shared data safe by itself.

For each task, write its worst execution time, period or minimum arrival time, deadline, priority, stack and blocking resources. Utilisation is a first check. Under classic rate-monotonic assumptions, three independent periodic tasks are guaranteed schedulable below about 77.9%, but systems above that can still pass a full response-time calculation. Include interrupt work, critical sections and release jitter.

What is priority inversion?

A high-priority task waits for a lock held by a low-priority task, while a medium-priority task keeps pre-empting the low one. Priority inheritance can raise the lock owner long enough to release it. Better designs also keep critical sections short and avoid sharing resources across unrelated deadlines.

Can adding an RTOS make 12 ms of work meet a 10 ms deadline on the same processor?
No. Reduce the work, change the deadline or add suitable hardware.
Step 31

Count every wake-up before claiming years of battery life

Low-power firmware turns off clocks and peripherals, chooses a sleep state, and wakes from a timer or external event. Average current includes sensor warm-up, measurement, computation, radio search and retry, flash writes, regulator quiescent current and sleep leakage. A wake pin left floating can destroy the budget by waking the chip all night.

Measure a current trace over normal cycles and rare faults. Batteries also have peak-current limits, temperature loss, self-discharge, ageing and a voltage curve; the board may brown out before nominal mAh is used. Test an old/cold cell at the worst transmit or motor pulse, and log wake reasons so unexpected energy has a cause.

Why can a low-dropout regulator dominate sleep?

The MCU may sleep at a few microamps while the regulator itself draws tens or hundreds. Add every part’s quiescent current, pull-up current and leakage. A power switch for a sensor helps only if its own leakage and the sensor’s restart energy make the trade worthwhile.

Which battery-life claim is strongest?
Measure the complete cycle and battery limits. Sleep is only one state.
Step 32

Write persistent state so a power cut leaves one valid answer

Flash and EEPROM wear out after a finite number of erase or write cycles, and a power cut can stop a write halfway. Do not overwrite the only copy of a calibration, counter or configuration in place. Keep at least two records with a version, length, sequence number and CRC. Write an inactive record completely, verify it, then make one small commit marker visible.

On boot, validate both records and choose the newest complete one. Handle sequence wrap and unknown future versions. Rate-limit writes, spread them across pages when needed, and test by cutting power at every byte or state transition. A CRC detects accidental damage; a cryptographic signature is needed when an attacker may change the data.

Why not save the counter after every loop?

It can exhaust endurance quickly and wastes energy. Save only when the application can justify the wear, batch changes, or use a journal/wear-levelled store. If exact monotonic counting matters for security, use hardware designed for it or a protocol that cannot move backwards after a reset.

When is the old configuration safe to erase?
Keep one complete record at every point. That invariant makes power loss recoverable.
Step 33

Route current paths, not just named wires

A schematic says which nodes connect. A PCB also decides the size and shape of every current loop. High-frequency current takes the nearby return path set by fields and plane geometry, not the route that looks shortest on a printed net list. Put a small decoupling capacitor close to each power pair so fast current circulates locally. Keep motor and switcher loops compact and away from sensitive ADC returns.

Protect external connectors where they enter the board. Add the clamp, current limit and filter needed for the expected ESD, surge or wiring fault. Check creepage, clearance, connector ratings and thermal rise for the product’s voltage and environment. Use a near-field probe and spectrum analyser for pre-compliance work, then run the required EMC and safety tests on the final enclosure and cables.

Why did the prototype pass but the enclosure fail?

Cable length, ground bonds, enclosure seams, battery leads and display windows change antennas and return paths. Test the assembled product in each operating mode. Record clock rates, radio channels, motor loads and cable arrangement so a failing emission can be reproduced.

Where should an ESD clamp for a user connector be placed?
At the entry. Keep the surge path short and away from the rest of the board.
Step 34

Keep device identity, boot code and updates in one trust chain

A product needs a unique device identity, protected key storage and a record tying the physical unit to its manufacturing history. Avoid one secret copied across the fleet. Secure boot starts from a small root of trust, verifies the next image and checks that it targets the right hardware. Rollback protection stops a signed but vulnerable old release from returning.

An update uses a signed manifest, resumable chunks, a complete-image hash, an inactive slot and a trial boot with rollback. Decide who may use debug access after manufacture and how a failed unit can be analysed without exposing every device. Threat-model physical access, faulty inputs, network commands and the factory test path. The Connected Devices course follows these controls through a fleet.

Does secure boot make firmware safe?

No. It proves that an allowed signer approved the bytes and that the image meets policy. Bugs, unsafe commands and stolen signing keys remain possible. Keep signing keys offline or in a managed hardware-backed service, require review, and make revocation and recovery part of the release plan.

Why should devices have unique keys?
Unique keys limit the blast radius. Identity and authorisation still need server-side policy.
Step 35

Generated firmware and TinyML models must meet the same bench evidence

An AI coding tool can draft a driver, state machine or test, but it does not know the exact board unless the requirement, data sheet, pin map and failure rules are supplied and checked. Review register writes, buffer bounds, integer widths, interrupt safety, timeouts and error paths. Compile with warnings, inspect the map, run deterministic tests, then compare logic traces and current/voltage measurements with the requirement.

A TinyML model adds a sensor contract, fixed preprocessing and an uncertain output. Budget its flash, RAM, latency and energy. Test on people, devices, sites and noise conditions that were not used for training. Keep confidence limits, a safe non-model fallback and all electrical limits outside the model. Monitor field drift and keep the prior signed model available for rollback. The TinyML course develops training, compression and deployment in detail.

What should an AI-generated peripheral driver prove?

It should prove the same things as handwritten code: correct register sequence and reserved bits, bounded waits, bus recovery, concurrency rules, power-state transitions and known behaviour for every hardware error. A vendor reference driver is useful comparison evidence, not a substitute for the product test.

A generated motor driver passes unit tests but has never run on the board. Is it ready?
No. Host tests cannot see the target’s electrical and timing behaviour.