Challenge 1
Make the ride change speed at a moment you chose. Pick a number of turns, work out the degrees, and have the ride step up exactly then. Watch the screen and check it happened at the count you predicted, not near it.
EV3 Robotics›Level 2 · Intermediate›Lesson 6
Level 2 · Lesson 6 · EV3-L02-0660 minutes · Ages 9–16 · Model: EV3 Amusement Park Small Swing Rides
The Swing Ride: chairs hanging on strings from a turning top. It spins, and as it spins the chairs swing outward and lift.
Every program you have written so far does the same thing every time you run it. It cannot do anything else — the blocks are in an order, and the order is the whole story.
Today a program makes up its own mind. The ride starts slowly, keeps an eye on how far it has turned, and speeds up on its own once it has been going long enough.
The chair swing — the wave swinger — at every funfair and pasar malam. Riders sit in seats on chains, the top turns, and the seats fly out into a wide circle well above the ground.

The chairs fly outwards because anything moving in a circle is constantly being pulled towards the middle to keep it there — and the chains are what pull. The faster the top turns, the harder the chains have to pull, and the only way a chain can pull harder is by hanging at a wider angle. So the seats rise as the ride speeds up. Nothing lifts them; the angle is the lift.
Which is also why the operator starts slowly. Bring a swing ride up to full speed instantly and the chairs do not rise smoothly — they lurch outward and swing back, and the passengers are thrown about.
A ride that runs at one speed from the moment it starts is a ride nobody wants to be on. The whole experience is the change: slow, then faster, then the seats lifting. And the operator does not stand there with a stopwatch — the ride knows where it is in its own cycle.
A machine that can only follow a list cannot react. A machine that can ask a question can.
A Switch block is a C-shape with a hexagonal hole in its head. Blocks inside the C only run when whatever is in the hole is true.
if <([A v] degrees counted) > (1080)> then [A v] set speed to (55) % :: motors end
Three separate things are going on there, and it is worth naming all three:
| Piece | Shape | What it is |
|---|---|---|
| ([A v] degrees counted) | Rounded | A reporter — a number. You met it in Lesson 8. |
| <() > ()> | Hexagon | A condition — it is either true or false, never a number. Put a reporter in one side and a number in the other. |
| if <> then | C-shape | The Switch — runs what is inside it, but only if the hexagon is true. |
The shapes are the rules. A rounded block will not drop into a hexagonal hole, and that is the editor stopping you from asking a nonsense question. “If 1080 then” means nothing; “if the count is more than 1080 then” means something.
A Switch tests once, at the moment the program reaches it. If the answer is false it skips the inside and moves on, and it will never look again.
So a decision that needs to be made repeatedly has to be inside a loop — which is why today’s program wraps the Switch in a repeat. The loop asks the question over and over; the Switch answers it each time.
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.
A Switch does not watch. It asks once, when you reach it — so put it somewhere you will reach it again.
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.
Say this back before moving on: “The hexagon is a question, not a number.”
| Part | What it is doing here |
|---|---|
| EV3 Intelligent Brick | Asks the question a few times a second and acts on the answer. This is the first lesson where the Brick is deciding rather than obeying. |
| Medium Motor — the top | Turns the ride. Its own encoder is where the condition’s number comes from, so it is both the thing being controlled and the thing being measured. |
| The chairs and strings (not electronic) | Free to swing outward. If they catch on anything the ride will never lift, however fast it turns. |
| The Brick screen and speaker | Report the turn count and announce the change of speed, so you can see the decision being made rather than guessing. |
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 |
|---|---|---|
| Ride motor | A | One job motor — and today its port appears in three places: the start, the speed change, and inside the condition. |
| Sensors | none | The question is answered from the motor’s own counter, which arrives down the motor cable. No sensor needed to make a decision. |
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 suits this one. You will be watching the Brick screen count while the ride turns, so the Brick wants to be where you can read it.
The ride starts gently, watches its own turn count, and steps up to full speed once it has done three turns.
when program starts :: events hat
clear display :: display
[A v] reset degrees counted :: motors
write [SWING RIDE] at line (1) :: display
[A v] start motor at (20) % speed :: motors
repeat (24)
write ([A v] degrees counted) at line (3) :: display
if <([A v] degrees counted) > (1080)> then
[A v] set speed to (55) % :: motors
write [LAJU] at line (5) :: display
end
wait (0.25) seconds
end
[A v] stop motor :: motors
write [TAMAT] at line (7) :: displayWhat success looks like: the ride turns slowly with the chairs hanging almost straight down, the number on screen climbs, and then — with nothing changing on the outside — it visibly speeds up and the chairs fly out. Nobody pressed anything.
If it never speeds up, either the count is going backwards or the ride is too slow to reach 1080 in twenty-four passes. Read the number on screen at the end: if it stopped at 700, your threshold is simply higher than the ride ever gets.
One change at a time. Watch the number on the screen at the moment the ride changes — that is the decision happening.
play beep (60) for (0.1) seconds inside the if, under the speed change. Run it and listen to what happens after the threshold is passed.Step 3 is the discovery. The beep does not sound once — it sounds on every remaining pass of the loop, because the condition stays true once the count is past 1080. The Switch is doing exactly what you asked, and what you asked was not what you meant. Remember it; it is one of the commonest bugs there is.
A condition that becomes true usually stays true. If you want something to happen once, that is a different question.
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 ride change speed at a moment you chose. Pick a number of turns, work out the degrees, and have the ride step up exactly then. Watch the screen and check it happened at the count you predicted, not near it.
Give the ride three stages instead of two — slow, medium, fast — using two Switches with different thresholds. The screen must say which stage it is in at all times.
Make something happen ONCE. Put a beep inside your Switch and you will hear it fire on every pass. Find a way to get exactly one beep at the moment the ride changes speed, using only blocks you have met. There is more than one answer and all of them are worth having.
Run the ride the way an operator would. A real swing ride has a cycle: load, start gently, build to full speed, hold it for the length of the ride, wind down, and stop somewhere the passengers can get out. Your job is to build that whole cycle and have the machine manage it by itself. Plan it on paper first as a list of stages, each with the turn count it starts at and what changes when it does. Add the counts up so you know how long the whole ride is before you build it. Then run it in front of somebody who has not seen it and ask them to tell you, just by watching, where each stage began. Two questions when you present it. Which stage boundary was hardest for your watcher to spot, and what would you change to make it obvious? And your ride counts degrees of the motor, not rides given — describe what you would change so it could tell an operator how many complete rides it has run today.

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.