IP Man: a training dummy whose arm swings on a motor, and a second, faster motor whose job is to block that arm at exactly the right instant.
Every model so far has reacted to where something is. Try that here and you will always miss — by the time the sensor reports the arm arriving, the block has not even started moving.
By the end of the lesson your machine will fire early, by an amount you have measured rather than guessed — and it will still work when you change the arm’s speed.
In the real world 5 min
Where you have seen it
The wooden dummy — mook jong — is how Wing Chun students drill against a fixed opponent. What they are training is not strength. It is starting the block before the strike arrives, because a human arm needs about a fifth of a second to get anywhere and a strike does not wait.
A Wing Chun wooden dummy. Photo: Stopmanager / Wikimedia Commons (CC BY-SA 3.0).
Every fast sport is the same. A cricketer plays the ball from where it will be. A table-tennis player has committed to a shot before the ball crosses the net. A goalkeeper facing a penalty starts to move before the striker’s foot lands.
Why it is built that way
Because nothing reacts instantly, and the delay is not a fault to be fixed — it is a known quantity to be planned around. Nerves take time. Motors take time to spin up. A camera takes time to produce a frame.
An engineer measures that delay once and then builds it into the plan. A camera on a bottling line triggers the reject arm for a bottle that has not reached it yet, using the belt speed and the known distance. Nobody tunes that by eye.
What would go wrong without it
You get a machine that is always a fraction late and cannot be fixed by trying harder. Speeding up the loop shaves milliseconds off a delay measured in tenths of a second — the arrow is pointing at the wrong problem.
If you cannot be instant, be early — by exactly as much as you are slow.
The main concept — lead time 6 min
Between deciding and doing there is a gap. Call it the lag. To arrive on time, act one lag early — and the only honest way to know the lag is to measure it.
Quantity
What it is
How you get it
Lag
Command sent → block actually in place.
Measure it: reset the timer, fire the block, wait until it arrives, read the timer. Twenty times, and average.
Period
How long the arm takes to come round once.
Measure it: time between two presses of the Touch Sensor.
Lead
How early to fire.
Compute it. Fire when the arm is lag away from the block, not when it is at the block.
Two ways to say “early”
The arm passes a reference point, then reaches the block a fixed time later. So after the reference press you wait — but for less than the full travel time.
// travel = how long from the reference point to the block
// lag = how long the block takes to get there
// so wait the difference, then fire
set [wait for v] to ((travel) - (lag)) :: variables
if <(wait for) < (0)> then
set [wait for v] to (0) :: variables
end
wait until <[1 v] is pressed? :: sensors>
wait (wait for) seconds :: control
[A v] run to position (90) [degrees v] at (100) % speed :: motors
The whole idea in one subtraction. Everything else in this lesson is measuring the two numbers that go into it.
If the lag is longer than the travel time, no amount of cleverness will get the block there. The machine is physically too slow, and the honest fix is a faster block or an earlier reference point — not a bigger number. Watching a program hit that wall is worth more than a working one.
Why this is not a closed loop
Lesson 5’s closed loop watches an error and corrects it. That works beautifully when there is time to notice being wrong. Here there is not. By the time the error exists, the strike has landed.
So you use the other half of control: feed-forward — act from what you know about the system rather than from what has already gone wrong. Fast machines use both, and Lesson 48 will finally put them together.
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.
ComponentSensing5 min
The Touch Sensor
The Touch Sensor is the simplest input the EV3 has: a button that is either pressed or not. That sounds trivial, but it is how a robot knows it has hit a wall, reached the end of a track, or been told to start by a person.
released
pressed
The red button out, and the same sensor with it pushed in. These two states are the entire output of this sensor — there is nothing in between.
Blocks reference
Block
What it does
wait until <[1 v] is pressed? :: sensors>
Holds the program here until somebody presses the sensor.
<[1 v] is pressed? :: sensors>
Reports true or false. Drop it into a condition to make a decision rather than a wait.
[1 v] when [bumped v] :: events hat
Starts a whole stack of its own. The dropdown chooses the moment: pressed, released or bumped.
Three different events
A button is not only “pressed”. One press is three things: the moment it goes down, the time it stays down, and the moment it comes back up. Watch what a single press does to three programs at once.
when program starts
forever
if 1 is pressed? then
change count by 1
versus two hat blocks
1 when pressed
1 when bumped
0is pressed? in a loop0when pressed0when bumped
In a loop: 0 answers from one pressBumped: exactly one
Nobody is touching the sensor. All three programs are watching it.A finger presses the button. Watch the red button go in — a couple of millimetres is the sensor's entire movement.The finger is still down. The loop checking «is pressed?» has already run hundreds of times, and every one of them counted.The finger lifts. Only now does «bumped» count, because bumped means pressed AND released.One press. Three completely different answers.Finished. The same press, counted three ways.
released
The middle counter is the one that surprises people. Nothing is wrong with it — a loop really does check that fast, and every check really is a separate answer.
Nothing there is broken. A loop really does get round hundreds of times a second, and each time it asks is pressed? the honest answer is still yes — so if that loop plays a sound or counts something, it does it hundreds of times from one finger. The two hat blocks each fire once, and they fire at different moments: pressed the instant the button goes down, bumped only when it comes back up.
The three options, and what each is for:
Pressed — the button is down right now. Good for “hold to run”.
Released — it is up again. Good for acting when somebody lets go.
Bumped — pressed and released. This is what you want for “click to start”, because it will not fire repeatedly while a finger stays down.
The classic bumper
when program starts :: events hat
set movement motors to [B v] and [C v] :: movement
start moving [straight: 0] :: movement
wait until <[1 v] is pressed? :: sensors>
stop moving :: movement
The robot drives until something presses the sensor. Note that the movement is started unmeasured on purpose — the sensor decides when to stop, not a distance.
Why it matters
Touch sensors are everywhere in machines you cannot see into: a lift knows the doors are shut, a printer knows the lid is closed, a washing machine will not spin until it is latched. They are safety devices as much as inputs.
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.
Measure the lag. Subtract it. Do not tune it by feel.
▶Closed loopFrom Lesson 5 — measure, compare, correct, repeat. Feed-forward is its complement: act before the error exists.Show meHide
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.
Say this back before moving on: “How slow am I, and how early does that make me fire?”
What’s in this build 4 min
Fire the block by hand from the Brick and watch it. Does it snap across, or does it ease into place? Everything that eases is lag, and lag is the number this lesson is about.
Part
What it is doing here
EV3 Intelligent Brick
The trainer. Its screen carries the two measured numbers, which is what turns the lesson from tuning into engineering.
Large Motor — the swinging arm
The target. Its speed sets the whole timetable, so changing that speed must change the lead — otherwise the machine has only memorised one situation.
Medium Motor — the block
Must be the fast one. Its lag is what you are compensating for, and a Large motor here would make the lag longer than the travel time.
Touch Sensor — the reference point
Pressed by the arm at a known place in its swing. It does not say “block now” — it says “the clock starts now”.
Colour Sensor — the hit
Reports whether the block was actually in the way. Without it you are judging your own timing by eye at a tenth of a second, which nobody can do.
The reference point must be far enough before the block to leave room for the lag. If the Touch Sensor sits right beside the block, the machine has no warning at all and the lesson has nowhere to go. Move it back along the swing.
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
Block (Medium)
A
The fast, precise motor.
Arm (Large)
B
The strong one — it swings a long lever.
Reference (Touch)
1
Touch stays on 1 across the course.
Hit (Colour)
3
Colour stays on 3 across the course.
Check your own build now:
Block in A, arm in B, touch in 1, colour in 3.
Turn the arm by hand through a full swing. Confirm it presses the Touch Sensor once, cleanly, and well before it reaches the block.
Set the block to its retracted position and note that as zero.
Check the block and the arm actually collide when both are in position — if they miss each other mechanically, no timing will help.
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.
Use Bluetooth, and check the battery before measuring. A tired battery makes both motors slower, which changes the lag and the travel time together — measure on a fresh battery or your numbers will drift under you.
Confirm the connection 2 min
Check the Brick icon: connected, or not.
Two motor tiles — A and B.
Two sensor tiles — 1 and 3.
Swing the arm by hand past the Touch Sensor and watch tile 1 flick to 1 and back. A press that sticks on will destroy every measurement in this lesson, because the clock will start at the wrong instant.
Stuck? The long version, with a photograph of every screen, is in the Brick & Bluetooth guide.
Make it move 10 min
Three programs: one that fails on purpose, one that measures, and one that uses the measurements.
Step 1 — react, and always be late
when program starts :: events hat
[B v] start motor [clockwise v] at (40) % speed :: motors
forever
wait until <[1 v] is pressed? :: sensors>
[A v] run to position (90) [degrees v] at (100) % speed :: motors
[A v] run to position (0) [degrees v] at (100) % speed :: motors
end
Fire the instant the sensor reports. The block arrives behind the arm every single time — watch it, because this is the failure the rest of the lesson answers.
Step 2 — measure the two numbers
when program starts :: events hat
clear display :: display
// ---- how long does the block take to arrive? ----
set [total v] to (0) :: variables
repeat (10)
[A v] run to position (0) [degrees v] at (100) % speed :: motors
wait (0.5) seconds :: control
reset timer :: control
[A v] run to position (90) [degrees v] at (100) % speed :: motors
set [total v] to ((total) + (timer)) :: variables
end
set [lag v] to ((total) / (10)) :: variables
write (lag) at line (1) :: display
// ---- how long from the reference point to the block? ----
[A v] run to position (90) [degrees v] at (100) % speed :: motors
[B v] start motor [clockwise v] at (40) % speed :: motors
set [total v] to (0) :: variables
repeat (5)
wait until <[1 v] is pressed? :: sensors>
reset timer :: control
wait until <([3 v] reflected light intensity) < (25)>
set [total v] to ((total) + (timer)) :: variables
wait until <not <[1 v] is pressed? :: sensors>>
end
set [travel v] to ((total) / (5)) :: variables
[B v] stop motor :: motors
write (travel) at line (3) :: display
With the block left extended, the arm hits it and darkens the Colour Sensor — so the second loop measures reference-to-block directly. Write both numbers down.
Step 3 — act early
when program starts :: events hat
set [lag v] to (0.35) :: variables // your measured numbers
set [travel v] to (0.60) :: variables
set [blocked v] to (0) :: variables
set [missed v] to (0) :: variables
[A v] run to position (0) [degrees v] at (100) % speed :: motors
set [lead v] to ((travel) - (lag)) :: variables
if <(lead) < (0)> then
set [lead v] to (0) :: variables
write [TOO SLOW TO BLOCK] at line (7) :: display
end
[B v] start motor [clockwise v] at (40) % speed :: motors
forever
wait until <[1 v] is pressed? :: sensors>
wait (lead) seconds :: control
[A v] run to position (90) [degrees v] at (100) % speed :: motors
reset timer :: control
set [hit v] to (0) :: variables
repeat until <<(hit) = (1)> or <(timer) > (0.5)>>
if <([3 v] reflected light intensity) < (25)> then
set [hit v] to (1) :: variables
end
end
if <(hit) = (1)> then
change [blocked v] by (1) :: variables
play sound [Mechanical / Blip 4 v] :: sound
else
change [missed v] by (1) :: variables
end
[A v] run to position (0) [degrees v] at (100) % speed :: motors
write (blocked) at line (3) :: display
write (missed) at line (5) :: display
wait until <not <[1 v] is pressed? :: sensors>>
end
Fire one lag before the arm arrives, then score it. Blocked and missed on screen turn “it looks about right” into a number.
lead is computed, not typed. Change either measurement and the timing follows automatically.
A negative lead is a real answer. It means the block cannot get there in time — the machine says so rather than pretending.
The score is the test. Twenty swings, and blocked should be nearly all of them.
Waiting for the sensor to release stops one swing counting twice.
What success looks like: the block is already in place as the arm arrives, and after twenty swings the blocked count is far ahead of the missed one.
If it is still late, re-measure the lag — a motor that has to reverse first is slower than one starting from rest. If it is now early, the block gets there and retracts before the arm arrives; hold the position for a moment before returning.
Change it and test 8 min
One change at a time. Predict, then run, then look. Predict using the numbers, not by feel — that is the skill.
Set the arm to 70% speed without changing anything else. Predict the miss count first. Travel shortens, the lead does not, and the block is now early.
Re-measure travel at the new speed and put it in. The block lands correctly again — and you have now proved the method rather than one number.
Set the block motor to 30% speed. The lag grows; predict whether the lead goes negative before you run it.
Set the lead to zero. Back to step 1’s failure, on purpose, with the score on screen to prove it.
Measure travel automatically at start-up — let the machine time two swings before it starts blocking. Now it adapts to any arm speed by itself.
A machine that measures its own lag keeps working when the world changes. One with a tuned number does not.
Where this goes 3 min
IP Man deals in one dimension: how long until the arm is here. The next model has to say where, on a flat sheet of paper.
The Pen Arm swings and reaches. It cannot move left and right — it can only choose an angle and a distance along the arm, and every point on the page has to be expressed in those two.
That is the same pair of numbers a record player’s tonearm, a radar dish and a crane all work in — and converting between them and ordinary x and y is what makes a drawing come out straight.
Today the machine aimed in time. Next it aims in space, without using x and y.
This is what you are building: the EV3 IP MAN 1.
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
Measure the lag twenty times.
Reset the timer, fire the block, wait until it arrives, read the timer. Twenty runs.
Report the average and the spread. If the spread is large, say what is causing it — a motor starting from rest is not the same as one reversing.
Challenge 2
Change the arm speed and predict the miss count first.
Drop the arm to 70 percent without touching the lead. Write your prediction down BEFORE running it, then run twenty swings and compare.
Then re-measure travel at the new speed, put it in, and report the new counts. Predicting from numbers is the skill; the working machine is just the receipt.
Challenge 3
Push it past what it can do.
Slow the block motor until the computed lead goes negative and the machine says it cannot block in time.
Report the block speed at which that happens. Then say which two things you could change to fix it, and why a bigger lead number is not one of them.
Mission
Make it adapt on its own.
Program the machine to measure both numbers at start-up — timing two swings for travel and two block movements for lag — and then block for a hundred swings.
Requirements:
1. Nothing typed in. Every number in the timing comes from a measurement the machine took.
2. The lead computed, never tuned.
3. A negative lead reported honestly on screen instead of silently clamped and forgotten.
4. Blocked and missed counted separately and shown.
5. It still works after somebody changes the arm speed and restarts it, without you touching the program.
Then have somebody change the arm speed to a value you were not told, restart it, and run twenty swings.
Report the score. A machine that measures its own lag survives a world it was not tuned for; one carrying a number you found by trial and error does not, and the difference only shows up when somebody changes something behind your back.