Challenge 1
Sort twenty bricks, three of them unknown. The counts should read 17 sorted and 3 rejected. If the unknowns went into real bins, the reject path is not working. Report both numbers.
EV3 Robotics›Level 2 · Intermediate›Lesson 48
Level 2 · Lesson 48 · EV3-L02-4860 minutes · Ages 9–16 · Model: EV3 Sorter Bot
The Sorter Bot: bricks arrive one at a time, a Colour Sensor looks at each, and a chute swings to drop it into the right bin.
Every sensing decision you have made so far compared a number against a threshold — nearer or further, brighter or darker, faster or slower. This one cannot. A red brick is not more than a blue one.
By the end of the lesson your machine will put each brick where it belongs — and will have somewhere to put the ones it cannot identify, which turns out to be the hard part.
A recycling plant runs mixed waste past a line of sensors and blows each item into a different stream with a puff of air. Optical sorters identify plastics by the light they reflect; magnets take the steel; eddy currents throw out the aluminium.

Every one of those lines has a stream for things it could not identify. It is not a failure — it is a designed outcome, and it is usually the most carefully handled one, because an unknown item in the wrong stream contaminates a whole batch.
A threshold always produces an answer. Ask “is it closer than 20 cm?” and every possible reading is either yes or no.
A classifier can be genuinely stuck. Show it something that matches none of its categories and the honest answer is “I do not know” — and a machine without a way to say that will pick its nearest guess and act on it with complete confidence.
The dangerous version is not the machine that refuses. It is the one that puts an unknown item in the nearest bin and gives no sign anything unusual happened. The mistake is invisible until somebody opens the bin.
Every classifier needs a bin for “I do not know”. A machine that cannot admit that will guess instead.
Classification maps a reading onto one of a fixed set of names. The names have no order — red is not between blue and green — so nothing you learned about thresholds applies.
| Threshold (everything so far) | Classification (today) | |
|---|---|---|
| Question | How much? | Which one? |
| Answers | Two, and they are ordered. | Several, and they are not. |
| Can it fail? | No. Every number is above or below. | Yes. Something may match nothing. |
| Tuned by | Moving one number. | Deciding what counts as each category — and what counts as none. |
set [seen v] to ([3 v] color) :: variables set [bin v] to (0) :: variables if <(seen) = [red v]> then set [bin v] to (1) :: variables end if <(seen) = [blue v]> then set [bin v] to (2) :: variables end if <(seen) = [yellow v]> then set [bin v] to (3) :: variables end // bin is still 0 — nothing matched
bin starts at 0 meaning “unknown”, and only a real match changes it. The unknown case needs no rule of its own, which is why it is so easy to forget.Start the answer at “unknown” and let matches overwrite it. The alternative — starting at bin 1 and hoping something corrects it — sends every unrecognised brick to the red bin, silently.
Notice seen is read once and every test uses it. Read the sensor inside each if and the brick may move between tests, so two different rules could both fire — or none could. This is Lesson 6’s habit and Lesson 11’s, and it matters more here than anywhere.
The Colour Sensor reports a colour name, but it decides that name from reflected light, and light depends on the room. A brick that reads blue at your table can read black under a shadow.
The robust version measures each category before sorting — show the machine one brick of each kind, let it record what it actually sees, and classify by nearest match to those. That is Lesson 12 turned from one threshold into a set of examples.
The Colour Sensor looks down at a surface and can answer three quite different questions: what colour is this?, how bright is this? and how light is the room? Choosing the wrong one is the usual reason a line-following robot refuses to work.
| Block | What it does |
|---|---|
([3 v] color :: sensors) | Reports which colour it sees, from a short list — red, blue, green, black, white and a few more. |
([3 v] reflected light intensity :: sensors) | Reports how bright the surface is, as a number from 0 (black) to 100 (white). |
<[3 v] is color [red v]? :: sensors> | Reports true or false for one particular colour. |
([3 v] ambient light intensity :: sensors) | Reports how much light is falling on the sensor, 0 to 100, with its own lamp switched off. |
The sensor does not describe a colour — it picks one from a list of eight, and that list is the whole of what it can ever say:
| Reports | Means |
|---|---|
| 0 | no colour — too far away, or too dark to call |
| 1 · 2 · 3 | black, blue, green |
| 4 · 5 · 6 | yellow, red, white |
| 7 | brown |
Anything you put under it is forced into one of those eight. There is no orange and no purple: an orange brick comes back as red or as yellow, and often as red one moment and yellow the next as the robot creeps along. Light blue and grey are the other classic pair to avoid — grey is neither black nor white, so it flips between them.
This is why colour mode is a good fit for a task you control and a bad fit for one you do not. Sorting the LEGO bricks that come in the set works, because they are made in exactly these colours. Reading a printed sheet, a coloured tile from another set, or anything pastel is asking the sensor to answer a question it does not have a word for.
Two practical points follow from how it decides. It shines its own lamp and looks at how much red, green and blue comes back, so it must be close — about half a centimetre, and no more than a centimetre. Lift it and the answer decays to 0. And because it takes those three readings before it can answer, colour mode is the slowest thing this sensor does; a robot driving quickly can pass right over a small patch without ever reporting it.
When a colour must be recognised reliably, test it. Drive the robot slowly over the real surface with color shown on the screen and watch what it actually says — including what it says at the edges between two colours, which is where the wrong answers live.
Both questions are asked of the same surface at the same moment. Watch the two answers travel across a strip of colours and then over the edge of a black line.
Watch the two read-outs over the last third of the strip. One of them changes once. The other changes the whole way across.
Over the patches, both read-outs are useful. Over the edge of the line they part company: the colour name has only two answers to give and jumps between them, while the number slides smoothly from 88 down to 8. Every value in that slide tells you how far onto the line the sensor is — which is information the name simply does not carry.
A line follower built on colour names only knows “black” or “not black”, so it can only lurch. Built on reflected light it can tell how far onto the line it has drifted, which is what makes smooth following possible.
The first two modes both switch the sensor’s own lamp on and measure what bounces back off the surface. Ambient light intensity does the opposite: the lamp goes off, and the sensor simply reports how much light is arriving from wherever — 0 in the dark, up to 100 in bright light.
| Mode | Own lamp | Measures | Points |
|---|---|---|---|
| colour | on | which of eight colours the surface is | at the surface, very close |
| reflected light | on | how much of its own light comes back | at the surface, very close |
| ambient light | off | how bright the surroundings are | wherever you want to measure |
That makes it the only one of the three that is not really about the floor. A number between 0 and 100 means very little on its own, so watch the same sensor sit through five different rooms — nothing underneath it changes at any point.
the sensor’s own lamp is off — it is measuring the room
Nothing under the sensor changed at any point in this run. Ambient light is the one mode that is not asking about the surface at all.
Those are the shape of the scale rather than exact figures, but the shape is the useful part: a lit room is nowhere near 100, and the top of the range is reserved for a light pointed straight at the sensor. Cover it with your hand and the number drops to near zero — which is the easiest way to check the sensor is doing what you think.
Point it at the ceiling and it tells you whether the room lights are on; point it forwards and a torch will spike the reading, which is a way of signalling to a robot without touching it.
Do not reach for it as a substitute for reflected light. Room light falling on a black line and on white paper is almost the same, so ambient mode can barely tell them apart — the reason reflected light works is precisely that the sensor brings its own light and measures how much of it survives.
It is also the mode most at the mercy of the room. A reading taken by a window in the morning will not match the same spot in the afternoon, so anything built on ambient light needs measuring on the day, in the place, with the lights as they will be.
Even the two lamp-on modes are affected by room lighting — a reading taken by a sunny window differs from one taken in a corner. The sensor must also sit close to the surface and at a constant height, because lifting it changes the reading even though the surface has not changed.
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.
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.
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.
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.
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.
| 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 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
set inside it
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.
EV3 Classroom tells you what a block does by its shape, and once you have noticed that, a whole set of questions answers itself:
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
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.
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.
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.
Start at unknown. Let a real match change it. Never let the machine guess quietly.
The Colour Sensor looks down at a surface and can answer three quite different questions: what colour is this?, how bright is this? and how light is the room? Choosing the wrong one is the usual reason a line-following robot refuses to work.
| Block | What it does |
|---|---|
([3 v] color :: sensors) | Reports which colour it sees, from a short list — red, blue, green, black, white and a few more. |
([3 v] reflected light intensity :: sensors) | Reports how bright the surface is, as a number from 0 (black) to 100 (white). |
<[3 v] is color [red v]? :: sensors> | Reports true or false for one particular colour. |
([3 v] ambient light intensity :: sensors) | Reports how much light is falling on the sensor, 0 to 100, with its own lamp switched off. |
The sensor does not describe a colour — it picks one from a list of eight, and that list is the whole of what it can ever say:
| Reports | Means |
|---|---|
| 0 | no colour — too far away, or too dark to call |
| 1 · 2 · 3 | black, blue, green |
| 4 · 5 · 6 | yellow, red, white |
| 7 | brown |
Anything you put under it is forced into one of those eight. There is no orange and no purple: an orange brick comes back as red or as yellow, and often as red one moment and yellow the next as the robot creeps along. Light blue and grey are the other classic pair to avoid — grey is neither black nor white, so it flips between them.
This is why colour mode is a good fit for a task you control and a bad fit for one you do not. Sorting the LEGO bricks that come in the set works, because they are made in exactly these colours. Reading a printed sheet, a coloured tile from another set, or anything pastel is asking the sensor to answer a question it does not have a word for.
Two practical points follow from how it decides. It shines its own lamp and looks at how much red, green and blue comes back, so it must be close — about half a centimetre, and no more than a centimetre. Lift it and the answer decays to 0. And because it takes those three readings before it can answer, colour mode is the slowest thing this sensor does; a robot driving quickly can pass right over a small patch without ever reporting it.
When a colour must be recognised reliably, test it. Drive the robot slowly over the real surface with color shown on the screen and watch what it actually says — including what it says at the edges between two colours, which is where the wrong answers live.
Both questions are asked of the same surface at the same moment. Watch the two answers travel across a strip of colours and then over the edge of a black line.
Watch the two read-outs over the last third of the strip. One of them changes once. The other changes the whole way across.
Over the patches, both read-outs are useful. Over the edge of the line they part company: the colour name has only two answers to give and jumps between them, while the number slides smoothly from 88 down to 8. Every value in that slide tells you how far onto the line the sensor is — which is information the name simply does not carry.
A line follower built on colour names only knows “black” or “not black”, so it can only lurch. Built on reflected light it can tell how far onto the line it has drifted, which is what makes smooth following possible.
The first two modes both switch the sensor’s own lamp on and measure what bounces back off the surface. Ambient light intensity does the opposite: the lamp goes off, and the sensor simply reports how much light is arriving from wherever — 0 in the dark, up to 100 in bright light.
| Mode | Own lamp | Measures | Points |
|---|---|---|---|
| colour | on | which of eight colours the surface is | at the surface, very close |
| reflected light | on | how much of its own light comes back | at the surface, very close |
| ambient light | off | how bright the surroundings are | wherever you want to measure |
That makes it the only one of the three that is not really about the floor. A number between 0 and 100 means very little on its own, so watch the same sensor sit through five different rooms — nothing underneath it changes at any point.
the sensor’s own lamp is off — it is measuring the room
Nothing under the sensor changed at any point in this run. Ambient light is the one mode that is not asking about the surface at all.
Those are the shape of the scale rather than exact figures, but the shape is the useful part: a lit room is nowhere near 100, and the top of the range is reserved for a light pointed straight at the sensor. Cover it with your hand and the number drops to near zero — which is the easiest way to check the sensor is doing what you think.
Point it at the ceiling and it tells you whether the room lights are on; point it forwards and a torch will spike the reading, which is a way of signalling to a robot without touching it.
Do not reach for it as a substitute for reflected light. Room light falling on a black line and on white paper is almost the same, so ambient mode can barely tell them apart — the reason reflected light works is precisely that the sensor brings its own light and measures how much of it survives.
It is also the mode most at the mercy of the room. A reading taken by a window in the morning will not match the same spot in the afternoon, so anything built on ambient light needs measuring on the day, in the place, with the lights as they will be.
Even the two lamp-on modes are affected by room lighting — a reading taken by a sunny window differs from one taken in a corner. The sensor must also sit close to the surface and at a constant height, because lifting it changes the reading even though the surface has not changed.
Say this back before moving on: “Which one is it — and what if it is none of them?”
Hold each of your bricks at the Colour Sensor and read the Brick screen. Do all of them report a colour, reliably? Any that do not are your reject bin’s first customers.
| Part | What it is doing here |
|---|---|
| EV3 Intelligent Brick | The sorting station. Its screen reports what was seen and where it went — which is how a misfiled brick becomes traceable. |
| Large Motor — the feed | Brings bricks past the sensor one at a time. Its job is to present exactly one item, held still, in the same place every time. |
| Medium Motor — the chute | Swings to the chosen bin. Medium because it is a quick, precise positioning move. |
| Colour Sensor — the classifier | The judgement. Distance and ambient light both change what it reports, so it must be mounted at a fixed, close distance. |
| Ultrasonic Sensor — is anything there | Confirms a brick has actually arrived before the colour is trusted. Without it the machine classifies empty air, which usually reads as black and quietly fills a bin. |
Fix the sensor distance and never change it. A Colour Sensor a centimetre further away reports different colours, so a machine calibrated at one height and run at another will misclassify everything — and look, from the outside, like a program fault.
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 |
|---|---|---|
| Chute (Medium) | A | The positioning motor. |
| Feed (Large) | B | The one moving bricks against friction. |
| Classifier (Colour) | 3 | Colour stays on 3 across the course. |
| Presence (Ultrasonic) | 4 | Ultrasonic stays on 4 across the 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.
USB is fine, but mind your shadow. The sorter stays put, so a cable costs nothing — just do not lean over the Colour Sensor while it works, or you become part of the calibration.
Stuck? The long version, with a photograph of every screen, is in the Brick & Bluetooth guide.
Classify first and report; only then let the chute move. A sorter that files before you trust its judgement is very hard to debug.
define classify set [seen v] to ([3 v] color) :: variables set [bin v] to (0) :: variables if <(seen) = [red v]> then set [bin v] to (1) :: variables end if <(seen) = [blue v]> then set [bin v] to (2) :: variables end if <(seen) = [yellow v]> then set [bin v] to (3) :: variables end when program starts :: events hat clear display :: display forever wait until <([4 v] distance in cm) < (8)> :: control classify :: custom write (seen) at line (1) :: display write (bin) at line (3) :: display wait until <([4 v] distance in cm) > (12)> :: control end
when program starts :: events hat
delete all of [bin angle v] :: list
add (0) to [bin angle v] :: list
add (60) to [bin angle v] :: list
add (120) to [bin angle v] :: list
add (180) to [bin angle v] :: list
set [sorted v] to (0) :: variables
set [rejected v] to (0) :: variables
[A v] reset degrees counted :: motors
clear display :: display
forever
// bring the next brick up
[B v] start motor at (30) % speed :: motors
wait until <([4 v] distance in cm) < (8)> :: control
[B v] stop motor :: motors
wait (0.3) seconds :: control
classify :: custom
write (seen) at line (1) :: display
// swing the chute to the chosen bin — bin 0 is reject
set [target v] to (item ((bin) + (1)) of [bin angle v]) :: list
[A v] run to position (target) [degrees v] at (40) % speed :: motors
if <(bin) = (0)> then
change [rejected v] by (1) :: variables
play sound [Mechanical / Error v] :: sound
write [UNKNOWN] at line (3) :: display
set status light to [orange v] :: display
else
change [sorted v] by (1) :: variables
write [SORTED] at line (3) :: display
set status light to [green v] :: display
end
write (sorted) at line (5) :: display
write (rejected) at line (7) :: display
// release it and wait for it to clear
[B v] start motor at (30) % speed :: motors
wait until <([4 v] distance in cm) > (12)> :: control
enditem (bin + 1) because lists count from 1 and bins count from 0. That off-by-one is deliberate and worth reading twice.What success looks like: bricks of the three known colours go to their own bins, anything else goes to reject with a noise, and the two counts on screen tell you how the run went.
If everything is rejected, the sensor is too far from the brick or the room is too dark. If everything goes to one bin, the sensor is reading the chute rather than the brick — check what it can see when nothing is there.
One change at a time. Predict, then run, then look. Run twenty bricks each time and record sorted against rejected.
bin at 1 instead of 0. Now unknown bricks go silently into bin 1. Run the same twenty and watch the reject count stay at zero while the machine is quietly wrong.classify. Nothing else should need touching.A classifier that never rejects anything is not confident — it is uncalibrated, and hiding it.
Your sorter swings its chute to one of four positions. Four numbers, one per bin — a machine that knows a handful of places.
The next model has to reach anywhere. A writing robot cannot have a list of positions for every point of every letter; it needs a way to describe a place in general, and to move to any of them.
A position is a pair of numbers, and a shape is a list of positions. That idea — a coordinate system — is what lets a machine draw a letter it was never specifically programmed for, and it is the next lesson.
Today the machine chose between places it knew. Next it learns to describe one.

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.
Sort twenty bricks, three of them unknown. The counts should read 17 sorted and 3 rejected. If the unknowns went into real bins, the reject path is not working. Report both numbers.
Make it guess quietly. Start the bin at 1 instead of 0, so anything unmatched goes to the red bin with no sound and no count. Run the same twenty bricks. The reject count stays at zero and the machine looks perfect. Write one sentence on why this is worse than a machine that refuses.
Change the light and watch it fail. Calibrate and sort in normal light, then shade the sensor with a book or move to a window and run the same twenty bricks again. Report the two sets of counts. Then say which earlier lesson this is, and what you would add to make the sorter survive the move.
Build a sorter you could trust with somebody else's bricks. It must sort at least four colours, reject anything it does not recognise, and — the mission — work in a room it was not set up in. That means it teaches itself the colours before it starts: show it one brick of each kind, let it record what it actually sees, and classify by nearest match to what it recorded. Requirements: - a reject bin, used loudly, and counted - sorted and rejected counts on screen throughout - a setup routine a stranger could follow from the screen alone - no colour name typed anywhere in the sorting logic Then the test. Carry it to a different table with different lighting, run the setup, and sort twenty bricks. Report sorted against rejected. A high reject count is not a failure — it is the machine telling you the truth about conditions it cannot handle. A zero reject count in a strange room is the thing to be suspicious of.