Znap: a tracked creature with a hinged jaw and an Ultrasonic Sensor in its head, built to guard the patch of table in front of it.
The obvious program is one threshold: something within 20 cm, snap. It works, and it makes a machine that is either asleep or violent with nothing in between.
By the end of the lesson Znap will stir, then threaten, then strike — and calm back down when you retreat — which is how nearly every animal handles an intruder.
In the real world 5 min
Where you have seen it
A praying mantis does not strike the moment something enters its reach. It turns its head to track. It rocks. If the intruder keeps coming, it rears and spreads its forelegs — a display that costs nothing and often ends the encounter. Only then does it strike, and the strike takes about a twentieth of a second.
A European praying mantis. Photo: Oliver Koemmerling / Wikimedia Commons (CC BY-SA 3.0).
The ladder is nearly universal. A cat’s ears flatten before it swipes. A rattlesnake rattles. A dog growls, then bares its teeth, then bites. Each rung is cheaper than the next and each gives the other party a chance to withdraw.
Why it is built that way
Because acting is expensive and risky, and a warning that works costs almost nothing. An animal that struck at everything would waste energy and get hurt; one that never struck would be ignored.
Machines are built the same way. A car beeps before it brakes. A fire alarm has a pre-alarm. A power supply warns, then throttles, then shuts down — because a full shutdown is disruptive and worth avoiding if a warning will do.
What would go wrong without it
A single threshold gives a machine with two personalities and nothing between, and it is startling in exactly the wrong way. Worse, at the boundary it flickers — snapping and calming several times a second while somebody stands still at 20 cm.
Warn before you act. It is cheaper, and it usually works.
The main concept — a ladder of responses 6 min
A graded response is a set of levels, each with its own behaviour and its own entry condition. It is a state machine, but the states are ordered — level 3 is more than level 2 — and that changes how you move between them.
Level
Znap does
Entered when
0 — asleep
Still. Light off.
Nothing within 60 cm.
1 — stirring
Jaw twitches, light green.
Something closer than 60 cm.
2 — threatening
Jaw open wide, hiss, light orange.
Closer than 35 cm.
3 — striking
Snap, lunge forward, light red.
Closer than 20 cm and it has been threatening for a second.
Level 3 needs two things, not one. Close and persistent. Something that flashes past at 15 cm has not challenged anything, and an animal that struck at every passing shadow would exhaust itself. That second condition is a timer used as evidence — Lesson 23’s elapsed time, judging rather than scheduling.
Climbing down is harder than climbing up
The obvious mistake is to use the same distances in both directions. Stand at exactly 35 cm and Znap threatens, calms, threatens, calms — several times a second.
// UP at 35, DOWN at 45 — the gap is what stops the flicker
if <<(level) = (1)> and <(gap) < (35)>> then
set [level v] to (2) :: variables
end
if <<(level) = (2)> and <(gap) > (45)>> then
set [level v] to (1) :: variables
end
Hysteresis, from Lesson 10, now applied to a behaviour rather than a motor. Each rung is entered nearer and left further away.
Come down one rung at a time
An animal that has just struck does not go straight back to sleep — it stays alert for a while. Dropping from 3 to 0 the instant the intruder leaves looks like a reset, not a creature.
Descend one level at a time, with a pause between, and Znap looks like something that is calming down rather than something that was switched off.
Why not just four separate rules?
You could test all four distances every pass with no level variable at all — and it would flicker, could not require persistence, and could not behave differently on the way down. The level is memory, and memory is what makes the ladder possible.
ComponentData6 min
Variables
Why anybody needs one
Long before there were computers, people had exactly this problem. A shepherd counting sheep through a gate, a trader counting sacks of grain, a builder counting days — none of them can hold the number in their head while they get on with the work. So they scratched a mark on a wall, cut a notch in a stick, or wrote a number on a piece of paper. The number lived outside the person, in a place they had agreed on, and they could go back to it, read it, and change it.
Better still, once the number is written down somebody else can use it. Watch these two: one of them counts and writes, the other never sees a single animal and simply reads the wall.
Abby never remembers the numberBen never sees a henThe wall holds it for both
Abby has a gate and a wall. Before a single hen comes through she chalks 0 on the wall — that is where the number is going to live.A hen goes through. Abby rubs out the 0 and chalks 1. Another goes through, and she does it again.Three hens have been through, and the wall says 3. Abby is not remembering the number — she is reading her own wall each time and writing the next one.Ben has been at the market all morning. He has not seen one hen. He walks up, reads the wall, and knows the answer — without asking Abby anything.That is a variable. Not a number in somebody's head, but a place both of them agreed on: one writes to it, the other reads from it, and it keeps the number in between.Finished. Abby wrote, Ben read, and the wall is what joined them up.
the wall holds it
Notice what never happens: Ben never asks Abby. He does not need to — the number is not in her head, it is on the wall, and the wall is there for anyone who needs it.
Neither Abby nor Ben is holding the number — the wall is. And notice what never happens: Ben does not ask Abby. He does not need to, because the count is not in her head. It is in a place they both agreed on, which is what makes it useful to more than one of them.
That is all a variable is. The robot cannot hold a number in its head either, so you give it a wall of its own, write a name at the top so everyone knows which wall is which — score, count, degree_turn — and the program can read what is on it and write something new. One part of the program writes; another part reads. Exactly Abby and Ben.
The paper, and the two things you can do to it
Say we are counting rotations of a motor. Before we start we write 0 on the paper. Every time the motor completes a turn we cross out what is there and write one more: 0 becomes 1, then 2, then 3. That is change — it has to read the old number to work out the new one.
set is the other thing you can do, and it is completely different: rub the whole paper out and write the number you want. It does not care what was there. Press the buttons and watch what happens to the crossings-out.
score
0
The paper starts blank, so we write 0 on it. That is what a variable is: a place to keep a number while the robot works.
change leaves a trail — every value follows from the one before it. This is what counting is.
set wipes the sheet. Use it to start a count, never to continue one.
Press set score to 0 after counting up a few times and watch the whole history vanish. That is what happens to a count when a set block ends up in the wrong place — and it is the commonest variable bug there is.
Blocks reference
Block
What it does
set [count v] to (0)
Puts a value in, replacing whatever was there.
change [count v] by (1)
Adds to what is already there.
(count)
Reports the current value, for use in a comparison or on the display.
Set, or change?
set replaces; change adds. Counting things needs change. Starting a count needs set. Both programs below have both blocks — the only difference is whether the set block is inside the loop or above it.
set before the loop
when program starts
set count to 0
repeat 4
A run clockwise for 1rotations
change count by 1
set inside it
repeat 4
set count to 0
A run clockwise for 1rotations
change count by 1
Before the loop: counted 0Inside the loop: stuck at 0
Both programs count the turns of a motor. The left sets the count to zero before the loop; the right sets it inside.Turn 1. Both counters read 1, and so far the two programs agree.Turn 2. The left count is 2. The right was set back to zero at the top of the loop, so it is 1 again.Turn 3. The left reads 3. The right still reads 1.Turn 4. The motor turned four times on both robots — only one of them counted them.Finished. Four turns, and one of the two counts is fiction.
stopped
Both programs contain both blocks. Only the position of set [count] to 0 is different.
The count on the right is not broken; it is being told to start again on every pass. Each time round the loop it is wiped back to zero and then changed by one, so the honest answer is always 1 — while the motor cheerfully turns four times. A counter stuck at 1 almost always means a set block that has slipped inside the loop.
Anything oval is a number you can pick up
EV3 Classroom tells you what a block does by its shape, and once you have noticed that, a whole set of questions answers itself:
Oval — reports a number. The blue degrees counted, the timer, a distance, your own variable.
Pointed — reports true or false. These go in an if or a wait until, not in a variable.
Block-shaped — does something. These stack up; they do not fit inside anything.
So when a slot is oval, any oval fits it — and it does not matter in the least where that number came from. You can take the motor’s own A degrees counted and keep it in a variable you named degree_turn, then compare that with a number later. Pick an oval below and watch the same one drop into all three kinds of slot.
pick an oval
the same oval fits all three
set degree_turn to A degrees countedkeep it in a variable of your own
A degrees counted+10do arithmetic with it
A degrees counted>50compare it with a number
Every one of those slots is oval-shaped, and A degrees counted is an oval — so it drops in. Nothing about where the number came from matters.
This is what makes a variable more than a counter. A sensor reading is true only at the instant you read it; copying it into a variable freezes it, so the robot can compare where it is now against where it was when something happened:
when program starts :: events hat
[A v] reset degrees counted :: motors
set [degree_turn v] to ([A v] degrees counted :: sensors)
start moving [right: 30] :: movement
wait until <(([A v] degrees counted :: sensors) - (degree_turn)) > (400)>
stop moving :: movement
Read the condition aloud: how far the motor has gone now, minus where it was when we started, is more than 400. Both are ovals, so both can go into a subtraction, and the subtraction is an oval too — which is why it can go into a comparison. Ovals nest inside ovals as deep as you need.
Reset at the start, every time
A variable keeps its value after the program ends. Run the program again without setting it back and the second run begins where the first left off — the count starts at 14, the robot thinks it has already done the job. Every variable a program changes must be set to its starting value at the top.
Why it matters
A variable is the difference between a machine that repeats a fixed routine and one that responds to how things have gone — counting parts, tracking a score, remembering where it started.
ComponentSensing6 min
The Ultrasonic Sensor
The Ultrasonic Sensor measures distance. It sends out a burst of sound too high for people to hear, listens for the echo, and works out how far away the surface is from how long the echo took — exactly how a bat finds a moth, and how a submarine uses sonar.
front
side
The two round openings on the front are the point of this sensor: one sends the burst of sound out, the other listens for the echo coming back.
Blocks reference
Block
What it does
([4 v] distance in [cm v] :: sensors)
Reports how far away the nearest thing in front of the sensor is, as a number in centimetres.
wait until <([4 v] distance in [cm v] :: sensors) < (15)>
Holds the program until something comes closer than 15 cm.
A number, not a yes or no
This is the important step up from the Touch Sensor. Touch gives you true or false; the Ultrasonic gives you a number, and the deciding is left to you. Pick a threshold below and watch where the robot ends up.
when program starts
start moving straight: 0
4 wait until distance <15cm
stop moving
60cm · reading15cm · threshold
Nothing is close. The sensor reports about 60 cm and the program waits.The robot drives forward. The sensor is sending a burst of sound and timing its echo, over and over, and the number falls.The reading has dropped past the threshold. The condition is true, so the robot stops.Try another threshold. The program is identical — only that one number is different.Finished. The threshold is yours to choose — the sensor only supplies the number.
stopped
The black line on the bar is the threshold; the blue fill is the reading. The robot stops the instant the fill crosses the line.
Three different robots, and only one number is different between them. That is what having a number rather than a yes-or-no buys you: the behaviour is tuned by editing one slot, not by rebuilding the program. It also means the sensor can never tell you it is “close” — close is a decision you make about a reading.
Why it matters
Car parking sensors, automatic doors at a shopping centre, and the sensor that stops a lift door closing on somebody all work this way. Reacting before contact is what makes a machine feel safe.
If your set has an Infrared Sensor instead
The Home/Retail EV3 set (31313) ships an Infrared Sensor and a Beacon in place of the Ultrasonic and Gyro sensors. The Infrared Sensor also measures distance, so the programs in this module work with it — but it reports a rough 0–100 proximity rather than real centimetres, and it is affected by sunlight and by dark surfaces in ways the Ultrasonic is not.
IR Sensor
Beacon
The Infrared Sensor and its Beacon, from the Home set. If your kit has these, expect proximity numbers rather than centimetres — and retune any threshold accordingly.
ComponentControl4 min
The Timer
A wait pauses for a length of time. The timer is different: it runs in the background and can be read at any moment, so the robot can know how long something has taken while it is still happening.
Blocks reference
Block
What it does
(timer)
Reports the seconds since the timer was last reset.
reset timer
Sets it back to zero, so the next reading counts from here.
The timeout — a safety net
The most valuable use of a timer is escaping a wait that might never end. A robot told to drive until it sees a wall will drive for ever if the wall is not there. Combined with a timer, it can give up:
Repeat until the wall is close or five seconds have passed. That one change turns a program that can hang into one that always finishes. Both robots below are looking for a wall that is not there.
no way out
repeat until distance < 15
start moving straight: 0
with a timeout
reset timer
repeat until distance < 15 or timer> 5
start moving straight: 0
write GAVE UP at line 1
1.2stimer212cm · distance
Both robots are told to drive until something is within 15 cm. The room ahead is empty.Three seconds. No wall. Both are still driving — and the right-hand program is also watching its timer.The timer passes 5. The right-hand robot gives up, stops, and says so.The left robot is still going. Its condition can never become true, so that block will hold the program for ever.The right-hand program finished. The left one has not, and there is nothing to say why.
timer 1.2 s
The sensor is not faulty and the program is not wrong. There is simply no wall, and only one of these two programs has a way of noticing that.
The left-hand robot is not broken, and neither is its sensor. Its condition is simply one that will never come true, so the program sits on that block for ever — with nothing on the Brick to say so. The right-hand program asks the same question with an escape route bolted on, and finishes every time.
Why it matters
Real systems time themselves out constantly — a lift that cannot close its doors eventually gives up and beeps rather than trying for ever. A robot with no timeout simply stops responding, and there is nothing on screen to say why.
Each rung entered nearer than it is left, and the top rung earned by persistence.
▶Deadband and hysteresisFrom Lesson 10 — different thresholds for entering and leaving, so a value on a boundary cannot flicker.Show meHide
ComponentSensing6 min
The Ultrasonic Sensor
The Ultrasonic Sensor measures distance. It sends out a burst of sound too high for people to hear, listens for the echo, and works out how far away the surface is from how long the echo took — exactly how a bat finds a moth, and how a submarine uses sonar.
front
side
The two round openings on the front are the point of this sensor: one sends the burst of sound out, the other listens for the echo coming back.
Blocks reference
Block
What it does
([4 v] distance in [cm v] :: sensors)
Reports how far away the nearest thing in front of the sensor is, as a number in centimetres.
wait until <([4 v] distance in [cm v] :: sensors) < (15)>
Holds the program until something comes closer than 15 cm.
A number, not a yes or no
This is the important step up from the Touch Sensor. Touch gives you true or false; the Ultrasonic gives you a number, and the deciding is left to you. Pick a threshold below and watch where the robot ends up.
when program starts
start moving straight: 0
4 wait until distance <15cm
stop moving
60cm · reading15cm · threshold
Nothing is close. The sensor reports about 60 cm and the program waits.The robot drives forward. The sensor is sending a burst of sound and timing its echo, over and over, and the number falls.The reading has dropped past the threshold. The condition is true, so the robot stops.Try another threshold. The program is identical — only that one number is different.Finished. The threshold is yours to choose — the sensor only supplies the number.
stopped
The black line on the bar is the threshold; the blue fill is the reading. The robot stops the instant the fill crosses the line.
Three different robots, and only one number is different between them. That is what having a number rather than a yes-or-no buys you: the behaviour is tuned by editing one slot, not by rebuilding the program. It also means the sensor can never tell you it is “close” — close is a decision you make about a reading.
Why it matters
Car parking sensors, automatic doors at a shopping centre, and the sensor that stops a lift door closing on somebody all work this way. Reacting before contact is what makes a machine feel safe.
If your set has an Infrared Sensor instead
The Home/Retail EV3 set (31313) ships an Infrared Sensor and a Beacon in place of the Ultrasonic and Gyro sensors. The Infrared Sensor also measures distance, so the programs in this module work with it — but it reports a rough 0–100 proximity rather than real centimetres, and it is affected by sunlight and by dark surfaces in ways the Ultrasonic is not.
IR Sensor
Beacon
The Infrared Sensor and its Beacon, from the Home set. If your kit has these, expect proximity numbers rather than centimetres — and retune any threshold accordingly.
Say this back before moving on: “How close, and for how long?”
What’s in this build 4 min
Work the jaw by hand through its whole range. How much of it is “open” and how much is the snap? Each rung needs its own distinguishable jaw position.
Part
What it is doing here
EV3 Intelligent Brick
The body, and the alert lamp. The status light is doing real work — it is how somebody approaching can read the threat level without looking at the jaw.
Medium Motor — the jaws
Must reach four distinguishable positions: shut, twitching, wide, and the snap. Medium because a strike is a fast flick.
Large Motor ×2 — the treads
Lunge forward at level 3 and retreat afterwards. They only ever move at the top rung, which is what makes the strike feel like a strike.
Ultrasonic Sensor — the eye
Reports one distance. Every rung is a comparison against it, so its noise becomes the machine’s twitchiness — smooth it, from Lesson 14.
The jaw linkage (not electronic)
Should snap crisply and not stick open. A jaw that closes slowly turns the top rung into a disappointment.
Give Znap room to lunge, and keep fingers out of the jaw. The strike is deliberately quick, and the whole point of the ladder is that you get two warnings first — but only if you are watching the machine rather than the screen.
Ports — and the rule 4 min
Sensors go in ports 1, 2, 3, 4. Motors go in ports A, B, C, D. They are not interchangeable, and nothing will tell you politely if you swap them.
Part
Port
Why this one
Jaws (Medium)
A
The expressive motor — every rung uses it.
Left tread (Large)
B
The movement pair, used only at the top rung.
Right tread (Large)
C
The other half.
The eye (Ultrasonic)
4
Ultrasonic stays on 4 across the course.
Check your own build now:
Jaws in A, treads in B and C, sensor in 4.
Close the jaw fully and note it as zero. All four jaw positions are measured from there.
Mark the four distances on the table with tape: 60, 45, 35 and 20 cm. You will be standing on them repeatedly, and guessing distances makes the whole lesson untestable.
Check the treads can lunge forward 10 cm without the model falling off the table.
Connect the Brick 4 min
Two routes, and either is fine. USB is the reliable one and the one to fall back on when a room’s Bluetooth is busy; Bluetooth leaves the robot free to move, which some models need.
▶How to connect the BrickUSB and Bluetooth, step by step, with a photograph of every screen. Open it if you have not done this before — or if pairing is not working.Show meHide
USB — the reliable one
Switch the Brick on with the dark grey centre button.
Cable into the Brick’s PC port — the small square socket beside the numbered ports, not one of the numbered ones.
Other end into the computer.
Bluetooth — name it first
Do these in order. Naming the Brick after you go looking for it in the list is how groups end up driving each other’s robots.
Name your Brick. On the Brick: Settings (the spanner) → Brick Name. Type something nobody else will pick, then press the tick. Every Brick is called EV3 until somebody changes it.
Turn Bluetooth on. Settings → Bluetooth. Tick Bluetooth and Visibility. Leave iPhone/iPad/iPod unticked.
Connect from EV3 Classroom. Click the Brick icon at the top of the programming area, find your Brick by name, and click Connect.
Say yes on the Brick. It asks “Connect?” with the computer’s name — choose the tick, then accept the passkey, which is already 1234.
Where to read it. The name sits in the bar across the very top of the screen, on every screen — so you can check which Brick you are holding at any moment without going into a menu. This one is EV3VE. A Brick nobody has renamed says EV3.Step 3, and the reason step 1 exists. Three Bricks in range — read the name before you click Connect. Pairing with the wrong one is not an error: it works perfectly, on somebody else’s robot.
Step 2.Bluetooth switches the radio on; Visibility is what lets the computer find you. With Visibility off your Brick works perfectly and simply never appears in the list.Step 4. Look at the Brick. It asks whether to accept and names the computer. Choose the tick.Then the passkey, already 1234. Press the tick again and you are connected.
The two failures, every class, every time. The Brick has gone to sleep while you were building — press the centre button to wake it. Or you have paired with the group at the next table, which is why the name matters.
The long version, including Port View and how to read the port tiles, is in the Brick & Bluetooth guide.
Bluetooth — it lunges. A cable in front of Znap is also an object within 20 cm, and it will hold the machine at the top rung permanently.
Confirm the connection 2 min
Check the Brick icon: connected, or not.
Three motor tiles — A, B and C.
One sensor tile — 4.
Walk slowly towards Znap and watch tile 4 pass your four tape marks. Confirm the sensor reads sensibly at all four — if it jumps about at 60 cm, your outer rung will trigger on nothing.
Stuck? The long version, with a photograph of every screen, is in the Brick & Bluetooth guide.
Make it move 10 min
Build the single-threshold version first. Standing at the boundary and watching it flicker is what makes the rest of the lesson obvious.
Step 1 — one threshold
when program starts :: events hat
forever
if <([4 v] distance in cm) < (20)> then
[A v] run [clockwise v] for (90) [degrees v] at (100) % speed :: motors
[A v] run [counterclockwise v] for (90) [degrees v] at (60) % speed :: motors
end
end
Stand at exactly 20 cm and hold still. Znap snaps repeatedly — asleep or violent, with nothing in between and no stable state at the boundary.
Step 2 — the ladder
when program starts :: events hat
set movement motors to [B v] and [C v] :: movement
set [level v] to (0) :: variables
[A v] reset degrees counted :: motors
reset timer :: control
set [at level since v] to (timer) :: variables
clear display :: display
// ---- the smoothed distance, for everybody ----
when program starts :: events hat
forever
set [total v] to (0) :: variables
repeat (5)
set [total v] to ((total) + ([4 v] distance in cm)) :: variables
end
set [gap v] to ((total) / (5)) :: variables
end
// ---- deciding the level ----
when program starts :: events hat
forever
set [was v] to (level) :: variables
// climbing UP — nearer thresholds
if <<(level) = (0)> and <(gap) < (60)>> then
set [level v] to (1) :: variables
end
if <<(level) = (1)> and <(gap) < (35)>> then
set [level v] to (2) :: variables
end
if <<<(level) = (2)> and <(gap) < (20)>> and <((timer) - (at level since)) > (1)>> then
set [level v] to (3) :: variables
end
// climbing DOWN — further thresholds, one rung at a time
if <<(level) = (3)> and <(gap) > (30)>> then
set [level v] to (2) :: variables
end
if <<(level) = (2)> and <(gap) > (45)>> then
set [level v] to (1) :: variables
end
if <<(level) = (1)> and <(gap) > (70)>> then
set [level v] to (0) :: variables
end
if <not <(level) = (was)>> then
set [at level since v] to (timer) :: variables
end
write (level) at line (1) :: display
write (gap) at line (3) :: display
end
// ---- doing what the level says ----
when program starts :: events hat
forever
if <(level) = (0)> then
set status light to [off v] :: display
[A v] run to position (0) [degrees v] at (30) % speed :: motors
end
if <(level) = (1)> then
set status light to [green v] :: display
[A v] run to position (25) [degrees v] at (30) % speed :: motors
[A v] run to position (0) [degrees v] at (30) % speed :: motors
end
if <(level) = (2)> then
set status light to [orange v] :: display
[A v] run to position (110) [degrees v] at (60) % speed :: motors
play sound [Animals / Snake hiss v] :: sound
end
if <(level) = (3)> then
set status light to [red v] :: display
[A v] run to position (0) [degrees v] at (100) % speed :: motors
move [forward v] for (0.4) [rotations v] at (60) % speed :: movement
move [backward v] for (0.4) [rotations v] at (40) % speed :: movement
[A v] run to position (110) [degrees v] at (60) % speed :: motors
end
end
Four rungs, entered nearer and left further, with the top one requiring a second of persistence. Line 1 shows the level so the ladder is watchable.
Up thresholds and down thresholds differ everywhere. 35 up, 45 down. 20 up, 30 down. That gap is what stops the flicker.
Level 3 needs a second at level 2 first. Walk past quickly and Znap threatens but does not strike — which is exactly what a mantis does.
at level since resets whenever the level changes. Forget that and the persistence test measures the wrong interval.
The treads only move at level 3. Keeping the lunge for the top rung is what gives it weight.
What success looks like: approach slowly and Znap wakes, then threatens, then strikes. Retreat and it climbs back down through the rungs rather than switching off. Walk past quickly and it threatens but never strikes.
If it never reaches level 3, the persistence test is measuring from the wrong moment — check that at level since is reset on every level change and nowhere else.
Change it and test 8 min
One change at a time. Predict, then run, then look.
Make the up and down thresholds identical. Stand exactly on a boundary and watch the level flicker on line 1. Then restore the gap.
Remove the persistence test. Walk quickly past at 15 cm — Znap now strikes at anything that passes. Say which of the two behaviours looks more like an animal.
Let it drop from 3 straight to 0. Retreat and watch it switch off rather than calm down. One line, and a noticeable loss of character.
Add a fifth rung between stirring and threatening — a slow head turn, say. Two thresholds and one behaviour block, and nothing else changes.
Make the persistence two seconds. Now a deliberate, slow approach is required to provoke it. Ask somebody who has not seen it to try to make it strike, and watch what they work out.
Every rung is entered nearer than it is left. Without that gap, a ladder is just a flicker.
Where this goes 3 min
Znap responds. It does not owe anybody anything — nothing it does has to balance.
The next model does. A vending machine takes payment and gives goods, and those two have to match. It must never hand out more than it was paid for, and it must never take money and give nothing.
A transaction is the first thing in this course that can be unfair rather than merely wrong — and the interesting cases are all the ones where it goes wrong half-way through.
Today the machine chose how hard to react. Next it has to keep its side of a bargain.
This is what you are building: the Znap.
Build it 15 min
Build the model before you read any further. Everything after this is about making it do something, and none of it will make much sense with nothing on the table in front of you.
Use the viewer's own controls to zoom and turn pages. Fullscreen makes it big enough to build from.
Check the finished build against the picture before you switch anything on. A motor mounted the wrong way round is far easier to spot now than it is to debug later, when it looks like a program fault.
Challenges & mission 27 min
Work through the challenges in order — each is harder than the last. The mission comes after all three, and it is meant to make you plan before you build.
Challenge 1
Prove the flicker.
Set the up and down thresholds to the same number, stand exactly on a boundary and watch the level on line 1.
Count how many times it changes in ten seconds. Then restore the gap and count again. The two numbers are why hysteresis exists.
Challenge 2
Take the persistence test out.
Walk quickly past at 15 cm with the test removed, then again with it back in.
Say in one sentence which version looks more like an animal, and what the timer is actually measuring when it is used as evidence rather than as a schedule.
Challenge 3
Add a rung.
Put a fifth level between stirring and threatening — a slow head turn, a low sound, something cheap.
You may add two thresholds and one behaviour block and nothing else. If you had to change anything in the deciding stack beyond that, the ladder was not built as a ladder.
Mission
Build a guard that nobody argues with.
Set Znap to guard something on the table for ten minutes while people come and go.
Requirements:
1. Four distinguishable levels, each with its own jaw position, light colour and sound.
2. Every rung entered nearer than it is left, with the gap written down.
3. The strike requires closeness AND persistence, and you can point at the line that enforces it.
4. The descent is one rung at a time, with a pause, so it calms rather than switches off.
5. The level is on screen throughout.
Then hand it to somebody who has not seen the program and ask them to work out, by experiment alone, what makes it strike.
Write down what they tried and what they concluded. A ladder that a stranger can read from the outside is a ladder that works; one they cannot is four thresholds wearing a costume.