The Motorbike: two wheels in line, a Large Motor driving the rear one, a Medium Motor steering the front, and an Ultrasonic Sensor looking up the road.
Everything you have built so far could be told to go from stopped to full speed and would simply do it. A bike cannot. Ask for 80% instantly and the rear wheel spins, the front lifts, or the whole thing goes over sideways.
By the end of the lesson your bike will reach the same speeds it always could, but never jump to them — and stopping will be a controlled thing rather than an event.
In the real world 5 min
Where you have seen it
A lift does not start at full speed. Watch the floor indicator on a tall building and you will see it accelerate over a second or two, run, then ease off before it stops. The engineers could make it snappier and deliberately do not — passengers would stumble, and a lift that spilled coffee would be replaced.
The same shape is everywhere: a train pulling away, a crane slewing, a camera gimbal panning, an electric window closing. All of them ramp up, run, and ramp down. It is so standard that motion-control engineers call it a trapezoidal profile — a picture of speed against time that is a trapezium.
Why it is built that way
Because a sudden change of speed is a large force, and force is what breaks things and tips them over. A gentle change of the same size, spread over a second, is a small force — same destination, much less drama.
A ramp does not limit how much the machine does. It limits how quickly it changes its mind.
What would go wrong without it
A crane that slewed instantly would swing its load; a lift would injure people; a bike falls over. And in every case the machine is being commanded something it can technically do — full speed is within its power. What it cannot do is get there in no time.
The limit that matters is usually not the value. It is the rate of change of the value.
The main concept — limiting the rate of change 6 min
A ramp keeps two numbers: the speed you want, and the speed you are currently commanding. Every time round the loop, the current one moves a small step towards the wanted one.
forever
if <(current) < (wanted)> then
change [current v] by (2) :: variables
end
if <(current) > (wanted)> then
change [current v] by (-2) :: variables
end
[B v] start motor at (current) % speed :: motors
end
The whole idea. wanted may jump from 0 to 80 in an instant; current takes forty passes to follow it.
Without a ramp
With a ramp
Command
start motor at (wanted)
start motor at (current)
0 → 80
Instant. The bike rears or slips.
About a second. The bike accelerates.
Emergency stop
Instant. The bike pitches forward.
Controlled — unless you choose otherwise.
Top speed reached
Same.
Same. Nothing is given up but suddenness.
The step size is the acceleration
That 2 is how much the speed may change per pass of the loop. Make it 1 and the bike is stately. Make it 20 and you have effectively removed the ramp. It is the only tuning knob, and it has a physical meaning: it is the acceleration limit.
The loop speed matters as much as the step size. A step of 2 in a loop that runs 100 times a second is a very different acceleration from a step of 2 in a loop with a wait 0.1 in it. If you add anything slow to the loop, the ramp changes without your touching it — which is a genuinely surprising bug the first time it happens.
Up and down need not match
Real vehicles brake harder than they accelerate, and so should yours. Two step sizes, chosen separately:
if <(current) < (wanted)> then
change [current v] by (accel) :: variables
end
if <(current) > (wanted)> then
change [current v] by ((0) - (brake)) :: variables
end
accel of 2 and brake of 6: builds speed gently, sheds it three times faster. That asymmetry is a safety decision.
Do not overshoot the target
If wanted is 41 and the step is 2, current goes 40, 42, 40, 42 — oscillating for ever around a value it can never land on. The fix is the deadband you already know from Lesson 10: when the gap is smaller than the step, just set it.
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.
ComponentControl5 min
Comparing and combining
A sensor that reports a number cannot be used to make a decision on its own — 23 is neither true nor false. An operator turns that number into an answer by comparing it with something.
Blocks reference
Block
What it does
<(x) > (50)>
True when the left value is bigger than the right.
<(x) < (50)>
True when it is smaller.
<<> and <>>
True only when both conditions are true.
<<> or <>>
True when at least one of them is.
Try it: which way round does it go?
Forget the symbols for a moment. A comparison is a question about position on a number line: is x to the left of the other number, or to the right? Left is smaller, right is bigger — and that is the whole of it.
Drag the orange x and the black marker, and change the comparison. The green stretch is every position of x that would make the answer true — so you can see where the answer flips before you get there. Turn not on and watch the green jump to the other side.
Drag either marker, or use the arrow keys.
-3 < 4true
is x to the LEFT of it?
< is true while x sits on the left. Slide x past the marker and it flips.
> is the same question the other way round — so exactly one of the two is true, unless the markers are on the same spot.
= is true for one single position out of twenty-one. Try landing on it. That is why a sensor is almost never compared with =: a reading passes straight through the exact number without ever being measured there.
not flips the answer, whatever it was. not (x < 4) covers everything x < 4 does not — including landing exactly on 4.
Try it: which numbers make it true?
The lab above asks one question at a time: is this x true? A robot never has just one x, though — a sensor reading slides up and down all the time, so what really matters is which stretch of the line makes the condition true. This one draws the whole answer at once.
Drag the circle to move the number you are comparing against, and change the comparison. Everything shaded green is a value of x that would make it true.
Drag the circle, or use the arrow keys. It moves in steps of 0.2.
x < 0.2x < 0.2
Every number to the left of 0.2 — but not 0.2 itself, so the circle is hollow.
Watch the circle, because it carries the part everyone gets wrong:
Hollow ○ — the boundary is not included. x < 0.2 shades everything left of 0.2 but leaves 0.2 itself out, because 0.2 is not less than 0.2.
Filled ● — the boundary is included. Choose = and nothing is shaded at all: one single number qualifies.
Now turn not on with x > 2 selected and watch two things happen together. The shading jumps to the other side, and the circle fills in — because “not greater than 2” means 2 or less, and 2 has to be part of it. That pairing is the whole reason a hollow circle is worth drawing.
Why a robot cares. Two conditions that look almost identical — light < 30 and not (light > 30) — differ by exactly one value, the reading of precisely 30. A robot sitting right on its threshold behaves differently under the two, and that is the sort of bug that only shows up occasionally and looks like a broken sensor.
Try it: and, or, not
These three join answers together rather than numbers. The trap is that English is looser than a program: “stop if it is close and the bumper is pressed” sounds like it covers both situations, when it covers neither on its own.
Flip the two conditions and watch the table. There are only four possible situations in total, and and and or differ on exactly two of them.
close: trueandbumper: falsefalse
close
bumper
and
or
true
true
true
true
true
false
false
true
false
true
false
true
false
false
false
false
and is fussy: it wants both. Three of the four rows are false.
and is true on one row out of four. It narrows — the robot acts less often, but more certainly.
or is true on three rows out of four. It widens — the robot acts more readily.
The two agree on the top and bottom rows and disagree in the middle. Whenever swapping one for the other seems to make no difference, you have only tried the rows where they agree.
Watch them decide
Two sensors are running below: an Ultrasonic reporting a number, and a Touch Sensor reporting true or false. Watch the comparison turn the number into an answer, and watch and and or disagree.
when program starts
forever
if distance < 15 and is pressed? then
stop moving
if distance < 15 or is pressed? then
play beep 60 for 0.2 seconds
Nothing is within 15 cm and the bumper is out. Both conditions are false.Something comes close. The comparison flips to true — the bumper has not been touched.It backs away, and instead the bumper is pressed. Now the other condition is the true one.Close AND pressed. Only now is «and» true — while «or» has been true ever since the first of them was.Finished. Four situations, and the two operators disagreed in three of them.
and false · or false
and was true in one row out of four. or was true in three. That is the whole difference, and it is why one of them makes a robot look broken.
The comparison is doing one job: it takes a reading that is neither true nor false and, by holding it against a number you chose, produces something a decision can use. The moment the blue fill crosses the black marker is the moment the answer changes.
Choosing the threshold
The number you compare against is a design decision, not a fact. “Close” for a parking sensor might be 15 cm; for a robot arm it might be 3. Pick it by measuring what the sensor actually reads in the situation you care about, then leave a margin.
Combining two conditions
and narrows: both must hold, so the robot acts less often but more certainly — stop only if something is close and the bumper is pressed. or widens: either will do, so the robot acts more readily — stop if something is close or the bumper is pressed.
In the four situations above, and was true in one of them and or in three. That is the practical difference: swapping one for the other does not adjust a robot slightly, it changes how often it reacts at all.
ComponentMotion4 min
Speed and power
Speed is set separately from movement. You tell the motor how fast it should go, and then you tell it to go — two blocks, in that order.
Speed is a percentage of what this motor can do, not a real-world unit — the same 50 % moves a light arm quickly and a heavy one slowly.
Blocks reference
Block
What it does
[A v] set speed to (25) % :: motors
Sets the speed for this motor from now on. Nothing moves — it only changes what the next movement will do.
[A v] run [clockwise v] for (2) [rotations v] :: motors
Now moves, at whatever speed was last set.
Set it first
when program starts :: events hat
[A v] set speed to (25) % :: motors
[A v] run [clockwise v] for (2) [rotations v] :: motors
Swap those two blocks round and the program still contains a speed of 25 % — it just never gets used. Both shafts below are asked for exactly 2 rotations; watch how long each one takes.
speed first — works
A set speed to 25 %
A run clockwise for 2rotations
speed last — does nothing
A run clockwise for 2rotations
A set speed to 25 %
0.00rotations · slow0.00rotations · fast
Speed first: the movement was slowSpeed last: it only affects the NEXT movement
Two programs. Same two blocks in each — only the order is different.Both are running — and the right-hand one is already finished. The left is barely a third of the way.Its speed block runs now, far too late to affect the movement above it. The left motor is still going, slowly, as it was told to.Both turned exactly 2 rotations. Only one of them did it at the speed the program asked for.Finished — it will run again in a moment.
stopped
Both shafts turn exactly 2 rotations. Only the time they take is different — and the right-hand program never gets the slow movement it was written to have.
The right-hand movement is over before the left is a third of the way round, because it ran at the default speed. Its set speed to () block does run — you can see it light up — but by then the movement it was meant to slow down has already happened. A speed block only ever affects the movements after it. This catches people out constantly.
Slow is often better
A high speed is not a better program. Slow movements are gentler on the gears, easier to watch and debug, and look more like the real machine — a barrier that snaps up in a fraction of a second reads as broken rather than fast.
Keep what you want and what you are commanding as two separate numbers, and let the second chase the first.
▶Power rampsFrom Level 2, Lesson 5 — starting smoothly. Today it becomes a general rule about any changing value.Show meHide
ComponentMotion4 min
Speed and power
Speed is set separately from movement. You tell the motor how fast it should go, and then you tell it to go — two blocks, in that order.
Speed is a percentage of what this motor can do, not a real-world unit — the same 50 % moves a light arm quickly and a heavy one slowly.
Blocks reference
Block
What it does
[A v] set speed to (25) % :: motors
Sets the speed for this motor from now on. Nothing moves — it only changes what the next movement will do.
[A v] run [clockwise v] for (2) [rotations v] :: motors
Now moves, at whatever speed was last set.
Set it first
when program starts :: events hat
[A v] set speed to (25) % :: motors
[A v] run [clockwise v] for (2) [rotations v] :: motors
Swap those two blocks round and the program still contains a speed of 25 % — it just never gets used. Both shafts below are asked for exactly 2 rotations; watch how long each one takes.
speed first — works
A set speed to 25 %
A run clockwise for 2rotations
speed last — does nothing
A run clockwise for 2rotations
A set speed to 25 %
0.00rotations · slow0.00rotations · fast
Speed first: the movement was slowSpeed last: it only affects the NEXT movement
Two programs. Same two blocks in each — only the order is different.Both are running — and the right-hand one is already finished. The left is barely a third of the way.Its speed block runs now, far too late to affect the movement above it. The left motor is still going, slowly, as it was told to.Both turned exactly 2 rotations. Only one of them did it at the speed the program asked for.Finished — it will run again in a moment.
stopped
Both shafts turn exactly 2 rotations. Only the time they take is different — and the right-hand program never gets the slow movement it was written to have.
The right-hand movement is over before the left is a third of the way round, because it ran at the default speed. Its set speed to () block does run — you can see it light up — but by then the movement it was meant to slow down has already happened. A speed block only ever affects the movements after it. This catches people out constantly.
Slow is often better
A high speed is not a better program. Slow movements are gentler on the gears, easier to watch and debug, and look more like the real machine — a barrier that snaps up in a fraction of a second reads as broken rather than fast.
Say this back before moving on: “Wanted jumps. Current walks.”
What’s in this build 4 min
Stand the bike up and push it gently. How much speed can it gain before it becomes unstable? That is the number your ramp exists to respect.
Part
What it is doing here
EV3 Intelligent Brick
The frame, and the reason the bike is top-heavy. A tall mass is exactly what makes sudden acceleration a problem.
Large Motor — the rear wheel
Drives the bike. It has more torque available than the tyre can put down — which is why an instant command spins the wheel instead of moving the bike.
Medium Motor — the steering
Turns the front wheel. Steering also wants ramping: a bike whose bars snap to full lock at speed goes down instantly.
Ultrasonic Sensor — the road ahead
Supplies the wanted speed: clear road means fast, something ahead means slow. It sets the target; the ramp decides how quickly the bike obeys.
Wheels and tyres (not electronic)
Check both are true and neither rubs. A dragging wheel needs more power to start, which pushes you towards exactly the sudden commands this lesson is about avoiding.
Give it a straight, clear run of at least two metres. Ramping takes distance by definition — a bike that accelerates gently needs room to do it, and testing on a short table teaches you nothing except that it fell off.
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
Steering (Medium)
A
The fine-control motor, first port.
Rear wheel (Large)
B
The drive. Only one driven wheel, so there is no movement pair here.
Road ahead (Ultrasonic)
4
Ultrasonic stays on 4 across the course.
Check your own build now:
Steering in A, drive in B, sensor in 4.
Centre the steering and note it as zero before every run.
Do not use a movement pair. One driven wheel means start motor, not start moving — a movement block expects two.
Check the sensor points along the road, level, not down at the floor a few centimetres ahead.
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. A cable on a two-wheeler is a fall. The bike is balanced at best, and a lead pulling on one side is exactly the disturbance it cannot absorb.
Confirm the connection 2 min
Check the Brick icon: connected, or not.
Two motor tiles — A and B.
One sensor tile — 4.
Find the fastest speed the bike can be given from standstill without misbehaving. Try 20, then 40, then 60 with a plain start block, catching it each time. Write down where it stops working — that number is why the ramp exists, and you will beat it by the end of the lesson.
Stuck? The long version, with a photograph of every screen, is in the Brick & Bluetooth guide.
Make it move 10 min
Show the problem, then fix it. Catch the bike on the first one.
Step 1 — no ramp
when program starts :: events hat
wait (2) seconds :: control
[B v] start motor at (70) % speed :: motors
wait (3) seconds :: control
[B v] stop motor :: motors
Hold the bike upright for the first run. Both the start and the stop are violent, and neither is a program fault — the machine simply cannot do what it was told that quickly.
Step 2 — the ramp
when program starts :: events hat
set [current v] to (0) :: variables
set [wanted v] to (0) :: variables
set [accel v] to (2) :: variables
set [brake v] to (5) :: variables
clear display :: display
when program starts :: events hat
forever
if <((wanted) - (current)) > (accel)> then
change [current v] by (accel) :: variables
end
if <((current) - (wanted)) > (brake)> then
change [current v] by ((0) - (brake)) :: variables
end
if <([abs v] of ((wanted) - (current))) < (accel)> then
set [current v] to (wanted) :: variables
end
[B v] start motor at (current) % speed :: motors
write (wanted) at line (2) :: display
write (current) at line (4) :: display
end
when program starts :: events hat
wait (2) seconds :: control
set [wanted v] to (70) :: variables
wait (4) seconds :: control
set [wanted v] to (0) :: variables
Three stacks. One holds the settings, one is the ramp, one decides what is wanted. Watch lines 2 and 4: line 2 jumps, line 4 climbs.
Step 3 — let the road decide
when program starts :: events hat
forever
set [gap v] to ([4 v] distance in cm) :: variables
if <(gap) > (60)> then
set [wanted v] to (70) :: variables
end
if <<(gap) < (60)> and <(gap) > (25)>> then
set [wanted v] to (30) :: variables
end
if <(gap) < (25)> then
set [wanted v] to (0) :: variables
end
end
Replace the timed stack with this. The road sets wanted; the ramp stack turns those jumps into something the bike can survive.
The ramp stack is the only thing that commands the motor. One writer, from Lesson 11. Everything else only sets wanted.
The third rule stops the oscillation. When the gap is smaller than one step, land exactly on the target rather than stepping past it for ever.
Braking is faster than accelerating — 5 against 2. The bike gains speed gently and loses it decisively, which is what a vehicle should do.
Lines 2 and 4 are the whole lesson on screen. The gap between them is the ramp doing its job.
What success looks like: the bike pulls away smoothly, runs, slows as it approaches an obstacle and stops before it — with no lurch at either end, at a top speed that would have thrown it over in step 1.
If line 4 never reaches line 2, your step size is smaller than the rounding, or the third rule is missing. If it reaches it in one pass, the step is so big the ramp is doing nothing.
Change it and test 8 min
One change at a time. Predict, then run, then look.
Set accel to 20. You have effectively removed the ramp. Compare with step 1 — this is the same failure, arrived at from the other direction.
Set accel to 0.5. Very smooth, very slow to get going. Time how long it takes to reach full speed and decide whether you would accept it.
Find the largest acceleration your bike tolerates. Raise it until the front wheel lifts or the rear slips, then come back a step. Write it on the board — that number is a property of your machine, not of the program.
Make brake equal to accel. The bike now takes as long to stop as to start. Put an obstacle in and see whether it stops in time — this is why braking is allowed to be harsher.
Add wait (0.05) seconds to the ramp loop. The acceleration changes dramatically without your touching accel. Explain to a partner why — this is the loop-speed trap, and it catches everyone once.
A ramp costs you nothing at the top and everything in suddenness. That is almost always the right trade.
Where this goes 3 min
Your bike is careful about how it changes speed. It is not careful at all about whether it should be running.
Press Run with the steering off-centre, or the sensor unplugged, or the bike lying on its side, and it sets off regardless — because nothing in the program checks anything before it starts.
A machine that refuses to start when conditions are wrong, and says why, is easier to use and much harder to break. Aircraft call it a pre-flight check; programmers call it a guard clause. The next model is a helicopter, and it will not take off until it is happy.
You have made a machine that moves well. Next, one that knows when not to.
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
Find the largest acceleration your bike survives.
Raise the step size until the front wheel lifts or the rear slips, then come back one step.
Write the number on the board with your top speed. It is a fact about your machine, not about the program.
Challenge 2
Brake harder than you accelerate.
Use two separate step sizes. Set braking three times the acceleration and test stopping in front of an obstacle.
Then make them equal and try the same stop. Say which you would fit to a real vehicle and why.
Challenge 3
Find the loop-speed trap.
Add a "wait 0.05 seconds" inside the ramp loop and run it without changing the step size.
The acceleration changes dramatically. Explain to a partner exactly why — this catches everybody once, and understanding it is worth more than avoiding it.
Mission
Drive a course at the highest average speed you can without ever lurching.
Set out a straight run with an obstacle part way along and a stopping line at the end. The bike must accelerate away, slow for the obstacle, pass it, speed up again, and stop on the line.
Judged on three things, in this order:
1. It never lurches, wheelies or slips. Any of those and the run does not count.
2. It stops within 10 cm of the line.
3. Total time.
Two rules: the acceleration and braking limits are named variables you can defend, and the wanted speed is set only by what the sensor sees — no timed sequences.
The interesting discovery is that the fastest run is not the one with the highest top speed. Work out why, and write one sentence about it.
This is what you are building: the Motorbike.
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.