Challenge 1
Ten blows, and a screen that agrees with your ears. Count the blows out loud as they happen, then check the final number is about ten times 360. If they disagree, the machine is right and you are wrong — find out where.
EV3 Robotics›Level 2 · Intermediate›Lesson 11
Level 2 · Lesson 11 · EV3-L02-1160 minutes · Ages 9–16 · Model: Hammering Machine
The Hammering Machine: a Large Motor driving a hammer that rises and falls, over and over, with the Brick screen and speaker reporting each blow.
You built a hammer in Lesson 7 and told it to strike ten times. But how did you know it struck ten times? You counted, out loud, watching it. The machine had no idea.
Today the machine keeps its own tally — and not by counting the loop. By reading how far its own shaft has actually turned.
Before car parts were pressed, they were forged: a heavy weight lifted by steam and dropped onto hot metal, again and again, in a shop loud enough to be heard streets away. Drop hammers built the twentieth century.

Forging is not one big hit. It is a known number of measured blows — the metal moves a little with each one, and the smith knows roughly how many it takes. Too few and the part is the wrong shape. Too many and the metal work-hardens and cracks.
So a forge counts. A modern press counts every stroke it has ever made, because the count is how you know when a tool needs replacing — dies wear out after a known number of hits, not after a length of time.
A machine that cannot count its own work cannot be trusted to report it. If the hammer jams half way through a run and you were not watching, a machine that only counts instructions given will cheerfully tell you it did all ten. A machine that counts shaft actually turned will not.
There is a difference between what a machine was told to do and what it did.
Inside every EV3 motor is a counter that ticks round as the shaft turns. It has been running since the moment you switched the Brick on. Nobody has asked it anything yet.
([A v] degrees counted) :: motors
Reporters are a different shape for a reason. You do not put this in a stack on its own; you drop it into a slot in another block, where a number would otherwise go:
write ([A v] degrees counted) at line (2) :: display
| Block | What it does |
|---|---|
| ([A v] degrees counted) | Reports total degrees turned since the last reset. 360 is one full turn, so ten turns reads 3600. |
| [A v] reset degrees counted | Sets that number back to zero. Without it you are counting from wherever the last run left off. |
You could count strikes by counting how many times the loop went round. But that only tells you how many times you gave the order. If the hammer jams on strike six, a loop count still reaches ten.
The encoder cannot lie about it. If the shaft did not turn, the number does not go up. That is why the reading on the screen is evidence and a loop count is only a claim.
Every EV3 motor contains a sensor that counts how far it has actually turned. That means a motor is not only an output — you can ask it where it is, and the answer describes what really happened rather than what you asked for.
| Block | What it does |
|---|---|
([A v] degrees counted :: sensors) | Reports how far this motor has actually turned since the count was last reset, in degrees. |
[A v] reset degrees counted :: motors | Sets the count back to zero, making right here the new reference point. |
([A v] speed :: sensors) | Reports how fast the motor is turning right now, as a percentage. A motor that is being driven but reads zero is a motor that is stuck. |
Those two are not always the same. Here are two identical motors, running the same program, with only their mechanisms different.
the same program, on two identical motors
Nothing on the Brick announces a stall. The only evidence is that the counter stopped changing while the motor was still being told to turn.
Nothing on the Brick announces the jam. The motor is still being driven, the program is still sitting on the same block, and the only trace of the problem anywhere is a counter that has stopped climbing. Comparing what you asked for with what was counted is how a robot notices — which is the whole of stall detection.
When the Brick powers on, the count is simply whatever it happens to be. It is not a position on the machine — it becomes one only when you tie it to something physical.
That is what reset degrees counted is for, and it is not just a tidy-up block for the top of a program. Where you put it decides what zero means, so putting it part-way through — after the mechanism has been driven somewhere known — is the normal way to use it, not an abuse of it.
A conveyor has no idea where it is. Give it a touch sensor at one end and it can find out: drive it until the sensor is pressed, and it is now at a place you can name. Only then reset the count, and that end becomes 0.
when program starts :: events hat [A v] start motor [counterclockwise v] :: motors [1 v] wait until [pressed v] :: sensors [A v] stop motor :: motors [A v] reset degrees counted :: motors
The order is the whole point. Reset before the sensor is pressed and you have zeroed a random spot; reset after it, and every later reading means “how far from home”. This is called homing, and it is why a printer rattles its head to one side when you switch it on.
Drive towards home gently. The mechanism is deliberately being run into its own end stop, so a slow speed saves the gears — and the touch sensor is what stops it, which means it stops in the same place every time regardless of where it started.
Home is often a corner, and a corner is an awkward place to measure from. Say the conveyor carries a chute that dispenses bricks, and you would rather describe its position as left and right of the middle. Then home once, drive the known distance to the middle, and reset again there:
when program starts :: events hat [A v] start motor [counterclockwise v] :: motors [1 v] wait until [pressed v] :: sensors [A v] stop motor :: motors [A v] reset degrees counted :: motors [A v] run [clockwise v] for (900) [degrees v] :: motors [A v] reset degrees counted :: motors
Now the middle is 0. Moving right counts up, moving left counts down past zero into negative numbers — the count is perfectly happy to go negative — and “go back to the middle” becomes the simplest instruction in the program: drive until the count reaches 0.
Both resets earn their place. The first one turns a meaningless number into a distance from a real, repeatable place. The second one moves zero to where the maths is easiest. A reset in the middle of a program is only a mistake when the mechanism is somewhere you cannot name.
Because the count is in degrees, and a wheel of known size travels a known distance per turn, the reading can be converted into how far the robot has actually driven. That is how a robot reports a distance in centimetres rather than in rotations — and it is why changing the wheels changes the answer.
This is how a printer knows the paper jammed, how a car window stops when it meets your hand, and how a robot arm knows it has reached its limit. A machine that can only give orders is fragile; one that can check what happened can recover.
Ask the machine what it did. Do not assume it did what you asked.
The Brick’s screen is a small black-and-white whiteboard. You can wipe it, draw one of the built-in pictures on it, or write your own words at a spot you choose. It is how the robot tells a person what it is doing.
| Block | What it does |
|---|---|
clear display :: display | Wipes the screen blank, ready for something new. |
display [Eyes / Neutral v] :: display | Draws a built-in picture chosen from a list — eyes, faces, arrows, symbols. |
display [Eyes / Neutral v] for (2) seconds :: display | Draws the picture, holds the program for that long, and then carries on. Handy when a face should be seen before anything else happens. |
write [Hello] at line (1) :: display | Writes your own text on one of the screen’s eight lines. |
write [Hello] at x: (10) y: (40) with font [normal black v] :: display | Writes text at an exact spot instead of a line, and lets you choose the size. Use it when a message has to line up with something else on the screen. |
The screen has no memory of whose writing is whose. It keeps every mark until something wipes it — including the marks left by the last run. Watch the same program with and without its clear display block.
with clear display
without it
Let it loop two or three times. The left screen still reads cleanly; the right one is the same program with one block missing.
Both Bricks are told exactly the same thing. The left one wipes the screen first, so line 7 holds one message and reads correctly. The right one never wipes, so each new message is drawn over the last and the words turn into a smudge. This is why a program that seems to display nonsense is usually displaying the truth — several times over.
There are two blocks for writing text, and they describe where in two completely different ways. Watch one message move around the screen under both of them.
the screen is 178 pixels across and 128 down
The arrows are the two numbers. The one along the top is x; the one down the side is y, and it counts downwards from the top edge.
write [EV3] at line (1) is the simple one. You give it a line number and it puts the text there, starting hard against the left edge — you do not choose how far across, only how far down.
For most robots this is all you need: a status word on line 1, a reading on line 3, a warning on line 5. Pick your lines at the start and keep each one for one job, the way you would keep one colour of status light for one meaning.
write [EV3] at x: () y: () with font [] treats the screen as a grid of pixels — 178 across and 128 down — and lets you put the text anywhere on it.
The block ends with a font dropdown, and normal black is the usual choice. A larger font makes the writing easier to read from across the room but takes more room across the screen, so fewer characters fit before the text runs off the edge.
The text slot of either block will take a reporter, so a sensor value can be shown directly: drop (4 distance in cm) into the slot and the screen shows the reading. That is the EV3’s version of a print statement, and it is the fastest way to find out what a robot actually thinks it is seeing.
A bare number on its own is hard to read, though. To show DIST: 23 rather than 23, use the operator block join [DIST: ] () to glue the label to the value, and put the join into the write block’s text slot.
when program starts :: events hat clear display :: display forever write (join [DIST: ] ([4 v] distance in [cm v] :: sensors)) at line (1) :: display end
Note the forever: a value written once is a value from the start of the program. To watch a reading change, the write block has to be inside a loop.
Once one value is on the screen the rest follows, and the useful trick throughout is join: it glues two pieces of text together and hands the result to the write block. Anything that reports a value can go in either slot — a variable, a sensor, or another join.
Counting is the classic case. A variable counts how many times the Touch Sensor has been pressed, and a bare 5 on the screen tells nobody anything — PRESSED: 5 tells them everything:
when program starts :: events hat clear display :: display set [count v] to (0) :: variables forever wait until <[1 v] is pressed? :: sensors> change [count v] by (1) :: variables write (join [PRESSED: ] (count)) at line (1) :: display wait until <not <[1 v] is pressed? :: sensors>> end
The two wait until blocks are what make it count presses rather than counting as fast as the loop runs while your finger is down. That is the Touch Sensor’s own lesson, but it shows up here because a counter on the screen is where you first notice it going wrong.
Give every reading its own line and keep it. A line that changes meaning halfway through a program is unreadable at a glance, which is the only speed a screen on a moving robot gets read at.
when program starts :: events hat clear display :: display forever write (join [DIST: ] ([4 v] distance in [cm v] :: sensors)) at line (2) :: display write (join [DEG: ] ([A v] degrees counted :: sensors)) at line (5) :: display end
degrees counted is worth putting on the screen the first time you use it — it is the fastest way to find out whether a motor is turning as far as you think it is, and it is the block behind every “why did it stop early” question.
Sensors report numbers, and people read words. The Colour Sensor reports 5; the person watching wants RED. A chain of if … then … else blocks does the translation, and it is worth doing once into a variable rather than in every write block:
if <([3 v] color :: sensors) = (5)> then
set [name v] to [RED] :: variables
else
if <([3 v] color :: sensors) = (4)> then
set [name v] to [YELLOW] :: variables
else
set [name v] to [OTHER] :: variables
end
end
write (join [COLOR: ] (name)) at line (4) :: displayThe same shape turns a distance into a warning. Here the screen carries the number and what the number means, which is what lets somebody across the room tell whether the robot is about to hit something:
if <([4 v] distance in [cm v] :: sensors) < (10)> then
set [status v] to [TOO CLOSE!] :: variables
else
if <([4 v] distance in [cm v] :: sensors) < (30)> then
set [status v] to [OBSTACLE FOUND] :: variables
else
set [status v] to [NOTHING FOUND] :: variables
end
end
write (status) at line (3) :: displayDrive all four of those at once below. The screen is the real thing — five write blocks, five lines, and every one of them a join.
Drive the sensors and read the screen. Every line is one write block with a join in its text slot.
| Line | What goes in the write block | On the screen now |
|---|---|---|
| 1 | join "PRESSED: " (count) | PRESSED: 3 |
| 2 | join "DIST: " (4 distance in cm) | DIST: 24 |
| 3 | (status) — set by the if chain | OBSTACLE FOUND |
| 4 | join "COLOR: " (name) | COLOR: RED |
| 5 | join "DEG: " (A degrees counted) | DEG: 180 |
Line 4 says COLOR: RED, but the sensor only ever said 5. The if chain in between is what turns a number into a word.
The moment a reading goes inside a loop, one of two things goes wrong, and which one depends on where the clear display block went.
Almost everybody tries clear inside the loop first. It gives the right text — and a screen that blinks several times a second, because between the clear and the write there is genuinely nothing on the screen and the loop goes round faster than your eye.
So the clear gets moved to the start of the program, the blinking stops, and the words go wrong. Writing text paints only the characters it has and leaves everything past them exactly where it was. Write RED over YELLOW and the LOW is still there: the screen says REDLOW. Go the other way — yellow first, then red — and it looks fine, which is why this bug takes so long to pin down.
when program starts :: events hat clear display :: display forever write (name) at line (3) :: display end
Watch the bottom three rows rather than the Brick. They are what the screen is actually doing: old characters, new characters, and whatever survives.
The fix is to make the new text at least as long as the old one, and join already does that: pad it with spaces. RED plus three spaces is six characters — exactly enough to paint over YELLOW. Nothing is left behind, and nothing is ever blank.
write (join (name) [ ]) at line (3) :: display
Pad to the length of the longest thing that line can ever show. Six characters covers RED, BLUE and GREEN but not NOTHING FOUND — count the longest message, and add spaces to match. The same applies to numbers: DIST: 5 after DIST: 40 leaves a stray 0 on the end, so a line that shows a two-digit reading needs a trailing space.
Use clear-inside-the-loop when the whole screen changes at once and a flicker does not matter; use the padding trick whenever a value is being watched.
Once several values need showing, the line number becomes a counter and the values come out of a list: write item 1 at line 1, item 2 at line 2, and so on inside a repeat. That needs the list blocks rather than the display blocks, so it lives with them — Lists covers building one and reading it back item by item, and the loop that walks it is the same loop that fills the screen.
Machines in the real world tell you what they are doing: a microwave counts down, a lift shows its floor, a car dashboard warns you. A robot that shows WAITING and then OPEN is far easier to understand — and far easier to debug — than one that moves silently.
Say this back before moving on: “Reset it first, or I am counting from last time.”
| Part | What it is doing here |
|---|---|
| EV3 Intelligent Brick | Reads the motor’s counter and puts it on screen. Its weight also keeps the machine still while the hammer works. |
| Large Motor — the hammer drive | Lifts and drops the hammer. It contains the counter this whole lesson reads from — the counter is part of the motor, not part of the Brick. |
| The Brick screen | The instrument panel. Today it shows a measurement rather than a message. |
| The Brick speaker | One beep per blow, so you can count by ear and check the screen agrees with what you heard. |
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 |
|---|---|---|
| Hammer motor (Large) | A | One job motor. It matters more than usual today that you know which port it is in, because you will be naming that port inside a reporter as well as inside the motor blocks. |
| Sensors | none | The counter is not a sensor — it is inside the motor, and it arrives down the motor cable. |
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.
Either works. The machine stays put. Bluetooth is slightly nicer here because you will be reading the Brick’s own screen a lot, and a cable decides where the Brick has to sit.
Ten blows, a beep for each, and a running total climbing on the screen as it works.
when program starts :: events hat clear display :: display [A v] reset degrees counted :: motors write [Degrees:] at line (1) :: display repeat (10) [A v] run for (360) [degrees v] at (45) % speed :: motors play beep (65) for (0.1) seconds :: sound write ([A v] degrees counted) at line (2) :: display end write [Siap] at line (4) :: display
What success looks like: ten blows you can hear, and a number on screen that climbs in steps of about 360 and finishes near 3600. Count the beeps yourself and check the screen agrees.
If the final number is well short of 3600, the hammer is stalling somewhere. The motor is being told to turn 360 and is not managing it — which is precisely the fault a loop count would have hidden from you.
Write down the final number after every run. That column of numbers is the record of what you changed, and it is more reliable than remembering.
reset degrees counted and run the program twice in a row without touching anything. The second run finishes near 7200. Explain why in one sentence.write block above the motor block inside the loop. Same blocks, different order. What does the screen show at the end now, and why is it 360 short?Step 5 is the point of the whole lesson, in about four seconds. The loop is still counting to ten. The screen tells you the truth anyway.
A counter inside the machine is worth more than a counter inside the program.
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.
Ten blows, and a screen that agrees with your ears. Count the blows out loud as they happen, then check the final number is about ten times 360. If they disagree, the machine is right and you are wrong — find out where.
Make the machine report in blows rather than degrees. The screen should end up showing something a person can use — the number of hits, not the number of degrees — and you may only use blocks you have already met. There is more than one way to do it.
Catch a stall. Run twenty blows and hold the hammer gently for two of them so it cannot turn. The machine must finish and its final number must show the work it actually did. Then say, from the number alone, how many blows it really landed.
Use the hammer as a measuring instrument. A machine that counts its own work can compare things. Your job is to put three materials in order of hardness — plasticine, a folded paper pad, an eraser, or anything else your teacher approves. Design the test before you run it. Every material gets the same strike from the same height the same number of times in the same place. Write down what you are measuring — depth of dent, whether it springs back, how it sounds — BEFORE you run anything, because deciding afterwards is how you talk yourself into the answer you were expecting. Run it, record the reading and the result for each material, and rank them. Two questions when you present it. What did you have to hold constant for the test to be fair, and which of those was hardest? And the degrees counter tells you the hammer moved — it does not tell you it hit anything. Describe what you would add to the model so it could tell the difference between striking a material and striking thin air.

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.