Challenge 1
Make the forklift refuse. Run it with no pallet on the forks and leave it for thirty seconds — the mast must not move at all. Then push a pallet on and watch it start. Both halves of that are the challenge.
EV3 Robotics›Level 2 · Intermediate›Lesson 14
Level 2 · Lesson 14 · EV3-L02-1460 minutes · Ages 9–16 · Model: EV3 Forklift Robot
The Forklift: a driving base with a mast on the front, a Medium Motor to raise and lower the forks, and a Touch Sensor that knows when a pallet is actually on them.
Raising the forks is easy. Knowing when it is safe to raise them is the job — and it is not one question.
Is there a pallet on the forks? And is the mast still below its limit? Both have to be true. Either one on its own gives you a forklift that lifts thin air, or one that keeps winding when it has already run out of mast.
Forklifts are everywhere goods are moved — warehouses, ports, building sites, the back of every supermarket. A counterbalance forklift can pick up a tonne and a half on two steel forks and carry it at walking pace.

A forklift is a lever with a very heavy load on the short end, and it only stays upright because of a counterweight at the back. That balance has limits, so real forklifts are covered in interlocks — rules the machine enforces regardless of what the driver asks for.
The interesting ones are nearly always about two things at once. The mast will not tilt forward unless the load is low and the handbrake is off. The machine will not drive unless the operator is in the seat and the seatbelt is fastened. One condition is a preference. Two conditions is a rule.
Check only whether a pallet is present and the machine will happily keep lifting after the mast has reached the top, straining the motor against a mechanical stop. Check only the height and it will lift nothing at all, wearing out the mechanism for no reason. Neither check is wrong; each is just incomplete.
Most real safety rules are two conditions joined by the word “and”.
The green and block is a hexagon with two hexagonal holes in it. Put a condition in each hole and the whole thing is true only when both of them are.
<<[1 v] is pressed?> and <([D v] degrees counted) < (720)>> :: operators
Note the shapes again. Both halves are hexagons, and the result is a hexagon — which is why it drops into a Switch exactly like a simple condition. Nothing about the Switch changes. You have just made the question more precise.
| Pallet on forks? | Below the limit? | and gives | Forklift does |
|---|---|---|---|
| yes | yes | true | Lifts. The only safe case. |
| yes | no | false | Waits. The mast is already up. |
| no | yes | false | Waits. Nothing to lift. |
| no | no | false | Waits. |
Four rows, one true. That is what and is for: it is strict, and being strict is the point of an interlock.
| Block | True when | Reach for it when |
|---|---|---|
| <<> and <>> | Both halves are true. | Everything must be right before something happens. Safety rules. |
| <<> or <>> | Either half is true — or both. | Any one of several reasons is enough. Stop buttons, alarms. |
| <not <>> | The one inside is false. | Saying “while there is no pallet” without writing a backwards comparison. |
Stop rules are usually or, not and. A machine should stop if the emergency button is pressed OR the load is too heavy OR the door is open — any one is enough. Notice that safety uses both words, for opposite jobs: and to permit, or to forbid.
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.
| 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. |
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.
is x to the LEFT of it?
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.
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:
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.
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 | 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.
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.
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.
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.
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.
And is strict, or is generous. Pick the one that matches the sentence you would say out loud.
Up to now a robot has been able to wait for a sensor. Deciding is different: the robot checks the sensor and does one thing or another depending on the answer — and then carries on either way.
| Block | What it does |
|---|---|
if <> then end | Runs the blocks inside only when the condition is true. Otherwise skips them. |
if <> then else end | Runs one set of blocks when true and a different set when false. |
A decision made once, at the start, is almost never what you want. Here are two robots with the identical if-else, testing the identical sensor against the identical number — one inside a loop and one not.
decision inside a loop
the same decision, once
A decision is only worth as much as the last time it was made. Inside a loop, that is a few milliseconds ago.
Nothing is wrong with the right-hand program’s decision. It asked the question, got a truthful answer, and acted on it correctly. It simply never asked again, and the world moved on. Decisions belong inside a loop, so the robot keeps re-deciding as things change.
when program starts :: events hat
forever
if <([4 v] distance in [cm v] :: sensors) < (15)> then
stop moving :: movement
else
start moving [straight: 0] :: movement
end
endOnce there is more than one question, decisions can be arranged in four ways. They look nearly identical stacked up in the editor, which is exactly why they get muddled — the thing that differs is not what the blocks say, it is which routes through them exist.
One question sorts them almost completely:
| Are the questions… | Use | How many bodies can run |
|---|---|---|
| independent — any combination can be true | separate ifs | none, some, or all |
| one question, two answers | if / else | exactly one |
| the second only matters when the first is true | nested if | one, and only via the outer |
| mutually exclusive cases — exactly one should win | chained if / else | exactly one, the first that matches |
Each if is asked no matter what the others answered, so any number of them can fire on the same pass. That is the right shape when the conditions genuinely have nothing to do with each other.
forever
if <[3 v] is ambient light intensity [< v] (20) %? :: sensors> then
[A v] start motor [clockwise v] :: motors
end
if <[4 v] is distance [< v] (15) [cm v]? :: sensors> then
[D v] start motor [clockwise v] :: motors
end
endExactly one branch runs, every time. Reach for this whenever the robot must do something either way — and in preference to two ifs testing opposite conditions, which is the same idea written twice and can drift apart.
Putting one if inside another means the inner question is only ever asked when the outer one is true. Use it when the second question is meaningless otherwise: there is no point asking which side an obstacle is on when there is no obstacle.
if <[4 v] is distance [< v] (15) [cm v]? :: sensors> then
if <([2 v] angle :: sensors) < (0)> then
start moving [right: 50] :: movement
end
endWhen not to nest. If you only want “both true” and nothing happens at the outer level, an and says it in one block and reads better:
if <<[4 v] is distance [< v] (15) [cm v]? :: sensors> and <([2 v] angle :: sensors) < (0)>> then start moving [right: 50] :: movement end
Nesting earns its place when something happens at the outer level too, or when there is an else at each level and the two mean different things.
This is the shape for a list of cases where exactly one should win: colour bands, distance bands, speed ranges. EV3 Classroom has no else-if block, so you build a chain by putting the next if inside the else of the last one.
And here is why it matters, because this is the single commonest bug in this whole module. Three bands written as three separate ifs are each perfectly correct, and together they are wrong: a reading of 20 is under 30 and under 60 and under 90, so all three run and the last one to run is the one that sticks.
three separate ifs
chained — if / else / if
↑ the rest is inside the else — never asked
Separate ifs are not wrong here so much as unguarded: nothing stops a second one matching. Chaining is what makes “the first one wins” true.
The rule to carry away: if the cases are meant to be exclusive, they must be made exclusive. Chaining does it by construction. Separate ifs only work if you are careful to write non-overlapping bands yourself — light < 30, 30 to 60, 60 and over — which is more to get right and easy to break later.
This is the point at which a machine stops following a script and starts responding. A thermostat, an automatic door, a robot vacuum — all of them are a decision inside a loop.
Say this back before moving on: “And means both, every time.”
| Part | What it is doing here |
|---|---|
| EV3 Intelligent Brick | Sits at the back and acts as the counterweight, exactly as it does on a real forklift. Move it forward and the model tips under load. |
| Large Motor ×2 — the drive | Ports B and C, driven as a pair so the forklift approaches a pallet square rather than at an angle. |
| Medium Motor — the mast | Raises and lowers the forks. It must hold when it stops, or a lifted pallet comes straight back down. |
| Touch Sensor — the pallet detector | Mounted at the back of the forks so a pallet pushed fully on presses it. A pallet resting half on will not, which is correct behaviour rather than a fault. |
| The pallet (not electronic) | Build one you can pick up reliably. A pallet that snags is a pallet you cannot test with. |
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 |
|---|---|---|
| Left drive (Large) | B | B is left, as the Movement blocks assume. |
| Right drive (Large) | C | C is right. |
| Mast (Medium) | D | Off the movement pair — and its port appears inside the condition as well as in the lift blocks. |
| Touch Sensor | 1 | Touch is always port 1 in this course. |
Check your own build now:
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.
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.
EV3 until somebody changes it.EV3.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. The forklift drives to the pallet, and a cable across the floor is the one thing on the test course you did not plan for.
and can never be true and the forklift will simply never lift.An interlocked mast: it lifts a little at a time, but only while both conditions hold.
when program starts :: events hat
set movement motors to [B v] and [C v] :: movement
[D v] set motor to [hold position v] at stop :: motors
[D v] reset degrees counted :: motors
clear display :: display
write [FORKLIFT] at line (1) :: display
forever
if <<[1 v] is pressed?> and <([D v] degrees counted) < (720)>> then
write [ANGKAT] at line (3) :: display
[D v] run for (90) [degrees v] at (30) % speed :: motors
else
write [TUNGGU] at line (3) :: display
end
endWhat success looks like: with no pallet, nothing happens however long you wait — the screen says TUNGGU. Push a pallet on and the mast climbs in steps, then stops by itself at the limit and goes back to TUNGGU with the pallet still held up. Take the pallet off and it stops immediately.
If the mast never moves, check the two halves one at a time by temporarily deleting the and and using each half alone. An and that is always false usually has exactly one broken half, and testing them together tells you nothing about which.
Wind the mast back to the bottom before every run, and work through the four rows of the truth table rather than just the happy one.
and to or. Predict what happens before you run it, then find out — this is the single most useful minute of the lesson.and back and change the limit to 180. A much lower ceiling. Does it still stop cleanly?and: only lift when a pallet is on, the mast is below the limit, and the mast has moved at least a little already — > (0). Say what that changes and whether it is an improvement.Step 3 is the one to talk about. With or the forklift lifts when there is a pallet or when it is below the limit — and since it starts below the limit, it lifts immediately with nothing on the forks, and carries on to the top. The same two checks, joined by a different word, produce a machine with no interlock at all.
Test a combined condition one half at a time. Together they only ever tell you yes or no, never which half was wrong.
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.
The same build on Google Drive — sometimes a video, sometimes a scan:
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.

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.
Make the forklift refuse. Run it with no pallet on the forks and leave it for thirty seconds — the mast must not move at all. Then push a pallet on and watch it start. Both halves of that are the challenge.
Add a lowering control that is just as strict. The forks may only come down when the mast is above the bottom AND a pallet is not being carried, so a load is never dropped. Say which condition you had to invert and how.
Pick up, carry and place. Drive to a pallet, lift it, drive somewhere else and set it down — with the interlock live the whole time. The pallet must not be dropped, and it must still be there when the machine walks away.
Write the safety rules for your forklift, then make it obey them. Real machines are built from a list of rules an engineer wrote down before any code existed. Your job is to produce that list and then enforce it. Write at least four rules on paper, each as a sentence with the word "only" in it — "the mast may only rise when ...". For each rule, say which conditions it needs and whether they are joined by AND or by OR. At least one of your rules must use OR, and you should be able to explain why that one is different from the others. Then build them and test each rule by trying to break it. Getting the machine to do the right thing is half the work; proving it will not do the wrong thing is the other half. Two questions when you demonstrate it. Which rule was hardest to enforce, and did you have to change the model rather than the program to do it? And your forklift cannot tell a heavy pallet from a light one — describe what you would add so it could refuse a load that was too heavy.