The Pen Arm: an arm that swings across the page, a carriage that slides in and out along it, and a small motor that lifts the pen off the paper.
Lesson 30 gave you coordinates — x across, y up. This machine cannot do either. It can only choose an angle and a distance along the arm, and every point on the page has to be said in those two.
By the end of the lesson your arm will draw a straight line — which sounds trivial and turns out to be the hardest thing this machine can do.
In the real world 5 min
Where you have seen it
A record player’s tonearm pivots at one end and reaches across the disc. It has no left-and-right at all — its position is one angle, and everything about how the stylus meets the groove follows from that.
A record player’s tonearm. Photo: Cristiano Betta / Wikimedia Commons (CC BY 2.0).
A radar dish reports a bearing and a range. A tower crane has a slew angle and a trolley position along the jib. A backhoe, a dental chair, a factory robot arm — all of them are joints that rotate, so all of them think in angles and reaches.
Why it is built that way
Because a pivot is cheap, strong and compact, and a long straight rail is none of those. An arm that swings can reach a large area from one small base.
The cost is that the machine’s natural numbers are not the page’s natural numbers. The drawing is in x and y. The motors are in angle and reach. Something has to translate, and that translation is the whole job of a robot’s controller.
What would go wrong without it
Drive both motors straight from one point to the next and you get a curve. Not a wobbly line — a smooth, confident, wrong arc, which is much harder to spot as a bug. Every early plotter and every early robot arm made this exact mistake.
The machine’s axes are set by its joints. The drawing’s are not. Somebody has to convert.
The main concept — two numbers that are not x and y 6 min
Every point this arm can reach has two names. In the page’s language it is x across and y up. In the arm’s language it is a swing angle and a reach. The same dot; two descriptions.
Page language (x, y)
Arm language (angle, reach)
Good for
Describing the drawing. Straight lines are easy.
Driving the motors. There is one motor per number.
Bad for
Driving anything — no motor moves in x.
Straight lines. Equal steps in angle are bigger at the far end than the near end.
Equal angles are not equal distances
Swing five degrees with the pen close to the pivot and it moves a few millimetres. Swing five degrees with the pen fully extended and it travels several centimetres. The same motor command means different things at different reaches — which is Lesson 39’s units problem again, but now it changes while the machine is running.
// a straight line is NOT "drive both motors to the end point"
// it is many small steps, each one converted separately
repeat (20)
change [x v] by (step x) :: variables
change [y v] by (step y) :: variables
// convert this single point into the arm's language
set [angle v] to (angle for x y) :: variables
set [reach v] to (reach for x y) :: variables
[B v] run to position (angle) [degrees v] at (25) % speed :: motors
[A v] run to position (reach) [degrees v] at (25) % speed :: motors
end
Step along the line in the page’s language, converting each point as you reach it. Twenty short arcs look straight; one long arc does not.
This is exactly what a real machine does. A CNC router or a 3D printer breaks every line into hundreds of tiny moves for the same reason. The fancy name is interpolation; the idea is that a curve made of enough short pieces is a line.
Getting the conversion without trigonometry
You could use sine and cosine. You do not have to. Measure instead, exactly as in Lesson 35: put the pen down at nine known angle-and-reach settings, mark where each landed, and measure the x and y of each mark with a ruler.
That table is the conversion. For points in between, split the difference — and the arm’s real geometry, gear slop included, is baked into numbers you measured rather than numbers you assumed.
Unknown module “motor-rotation”. It is not in the registry — check the id against app/lego_ev3/_modules/registry.ts.
ComponentData6 min
Variables
Why anybody needs one
Long before there were computers, people had exactly this problem. A shepherd counting sheep through a gate, a trader counting sacks of grain, a builder counting days — none of them can hold the number in their head while they get on with the work. So they scratched a mark on a wall, cut a notch in a stick, or wrote a number on a piece of paper. The number lived outside the person, in a place they had agreed on, and they could go back to it, read it, and change it.
Better still, once the number is written down somebody else can use it. Watch these two: one of them counts and writes, the other never sees a single animal and simply reads the wall.
Abby never remembers the numberBen never sees a henThe wall holds it for both
Abby has a gate and a wall. Before a single hen comes through she chalks 0 on the wall — that is where the number is going to live.A hen goes through. Abby rubs out the 0 and chalks 1. Another goes through, and she does it again.Three hens have been through, and the wall says 3. Abby is not remembering the number — she is reading her own wall each time and writing the next one.Ben has been at the market all morning. He has not seen one hen. He walks up, reads the wall, and knows the answer — without asking Abby anything.That is a variable. Not a number in somebody's head, but a place both of them agreed on: one writes to it, the other reads from it, and it keeps the number in between.Finished. Abby wrote, Ben read, and the wall is what joined them up.
the wall holds it
Notice what never happens: Ben never asks Abby. He does not need to — the number is not in her head, it is on the wall, and the wall is there for anyone who needs it.
Neither Abby nor Ben is holding the number — the wall is. And notice what never happens: Ben does not ask Abby. He does not need to, because the count is not in her head. It is in a place they both agreed on, which is what makes it useful to more than one of them.
That is all a variable is. The robot cannot hold a number in its head either, so you give it a wall of its own, write a name at the top so everyone knows which wall is which — score, count, degree_turn — and the program can read what is on it and write something new. One part of the program writes; another part reads. Exactly Abby and Ben.
The paper, and the two things you can do to it
Say we are counting rotations of a motor. Before we start we write 0 on the paper. Every time the motor completes a turn we cross out what is there and write one more: 0 becomes 1, then 2, then 3. That is change — it has to read the old number to work out the new one.
set is the other thing you can do, and it is completely different: rub the whole paper out and write the number you want. It does not care what was there. Press the buttons and watch what happens to the crossings-out.
score
0
The paper starts blank, so we write 0 on it. That is what a variable is: a place to keep a number while the robot works.
change leaves a trail — every value follows from the one before it. This is what counting is.
set wipes the sheet. Use it to start a count, never to continue one.
Press set score to 0 after counting up a few times and watch the whole history vanish. That is what happens to a count when a set block ends up in the wrong place — and it is the commonest variable bug there is.
Blocks reference
Block
What it does
set [count v] to (0)
Puts a value in, replacing whatever was there.
change [count v] by (1)
Adds to what is already there.
(count)
Reports the current value, for use in a comparison or on the display.
Set, or change?
set replaces; change adds. Counting things needs change. Starting a count needs set. Both programs below have both blocks — the only difference is whether the set block is inside the loop or above it.
set before the loop
when program starts
set count to 0
repeat 4
A run clockwise for 1rotations
change count by 1
set inside it
repeat 4
set count to 0
A run clockwise for 1rotations
change count by 1
Before the loop: counted 0Inside the loop: stuck at 0
Both programs count the turns of a motor. The left sets the count to zero before the loop; the right sets it inside.Turn 1. Both counters read 1, and so far the two programs agree.Turn 2. The left count is 2. The right was set back to zero at the top of the loop, so it is 1 again.Turn 3. The left reads 3. The right still reads 1.Turn 4. The motor turned four times on both robots — only one of them counted them.Finished. Four turns, and one of the two counts is fiction.
stopped
Both programs contain both blocks. Only the position of set [count] to 0 is different.
The count on the right is not broken; it is being told to start again on every pass. Each time round the loop it is wiped back to zero and then changed by one, so the honest answer is always 1 — while the motor cheerfully turns four times. A counter stuck at 1 almost always means a set block that has slipped inside the loop.
Anything oval is a number you can pick up
EV3 Classroom tells you what a block does by its shape, and once you have noticed that, a whole set of questions answers itself:
Oval — reports a number. The blue degrees counted, the timer, a distance, your own variable.
Pointed — reports true or false. These go in an if or a wait until, not in a variable.
Block-shaped — does something. These stack up; they do not fit inside anything.
So when a slot is oval, any oval fits it — and it does not matter in the least where that number came from. You can take the motor’s own A degrees counted and keep it in a variable you named degree_turn, then compare that with a number later. Pick an oval below and watch the same one drop into all three kinds of slot.
pick an oval
the same oval fits all three
set degree_turn to A degrees countedkeep it in a variable of your own
A degrees counted+10do arithmetic with it
A degrees counted>50compare it with a number
Every one of those slots is oval-shaped, and A degrees counted is an oval — so it drops in. Nothing about where the number came from matters.
This is what makes a variable more than a counter. A sensor reading is true only at the instant you read it; copying it into a variable freezes it, so the robot can compare where it is now against where it was when something happened:
when program starts :: events hat
[A v] reset degrees counted :: motors
set [degree_turn v] to ([A v] degrees counted :: sensors)
start moving [right: 30] :: movement
wait until <(([A v] degrees counted :: sensors) - (degree_turn)) > (400)>
stop moving :: movement
Read the condition aloud: how far the motor has gone now, minus where it was when we started, is more than 400. Both are ovals, so both can go into a subtraction, and the subtraction is an oval too — which is why it can go into a comparison. Ovals nest inside ovals as deep as you need.
Reset at the start, every time
A variable keeps its value after the program ends. Run the program again without setting it back and the second run begins where the first left off — the count starts at 14, the robot thinks it has already done the job. Every variable a program changes must be set to its starting value at the top.
Why it matters
A variable is the difference between a machine that repeats a fixed routine and one that responds to how things have gone — counting parts, tracking a score, remembering where it started.
ComponentSensing5 min
The Touch Sensor
The Touch Sensor is the simplest input the EV3 has: a button that is either pressed or not. That sounds trivial, but it is how a robot knows it has hit a wall, reached the end of a track, or been told to start by a person.
released
pressed
The red button out, and the same sensor with it pushed in. These two states are the entire output of this sensor — there is nothing in between.
Blocks reference
Block
What it does
wait until <[1 v] is pressed? :: sensors>
Holds the program here until somebody presses the sensor.
<[1 v] is pressed? :: sensors>
Reports true or false. Drop it into a condition to make a decision rather than a wait.
[1 v] when [bumped v] :: events hat
Starts a whole stack of its own. The dropdown chooses the moment: pressed, released or bumped.
Three different events
A button is not only “pressed”. One press is three things: the moment it goes down, the time it stays down, and the moment it comes back up. Watch what a single press does to three programs at once.
when program starts
forever
if 1 is pressed? then
change count by 1
versus two hat blocks
1 when pressed
1 when bumped
0is pressed? in a loop0when pressed0when bumped
In a loop: 0 answers from one pressBumped: exactly one
Nobody is touching the sensor. All three programs are watching it.A finger presses the button. Watch the red button go in — a couple of millimetres is the sensor's entire movement.The finger is still down. The loop checking «is pressed?» has already run hundreds of times, and every one of them counted.The finger lifts. Only now does «bumped» count, because bumped means pressed AND released.One press. Three completely different answers.Finished. The same press, counted three ways.
released
The middle counter is the one that surprises people. Nothing is wrong with it — a loop really does check that fast, and every check really is a separate answer.
Nothing there is broken. A loop really does get round hundreds of times a second, and each time it asks is pressed? the honest answer is still yes — so if that loop plays a sound or counts something, it does it hundreds of times from one finger. The two hat blocks each fire once, and they fire at different moments: pressed the instant the button goes down, bumped only when it comes back up.
The three options, and what each is for:
Pressed — the button is down right now. Good for “hold to run”.
Released — it is up again. Good for acting when somebody lets go.
Bumped — pressed and released. This is what you want for “click to start”, because it will not fire repeatedly while a finger stays down.
The classic bumper
when program starts :: events hat
set movement motors to [B v] and [C v] :: movement
start moving [straight: 0] :: movement
wait until <[1 v] is pressed? :: sensors>
stop moving :: movement
The robot drives until something presses the sensor. Note that the movement is started unmeasured on purpose — the sensor decides when to stop, not a distance.
Why it matters
Touch sensors are everywhere in machines you cannot see into: a lift knows the doors are shut, a printer knows the lid is closed, a washing machine will not spin until it is latched. They are safety devices as much as inputs.
Describe the drawing in the page’s language. Convert one small step at a time.
▶Two-point calibrationFrom Lesson 35 — measure at known settings and interpolate between them, instead of assuming the machine matches the maths.Show meHide
Unknown module “motor-rotation”. It is not in the registry — check the id against app/lego_ev3/_modules/registry.ts.
Say this back before moving on: “Which language is this number in — the page’s or the arm’s?”
What’s in this build 4 min
Push the pen to the far end of the arm and swing it by hand. Now bring it close to the pivot and swing the same amount. Compare the two marks on the paper. That difference is the entire difficulty of this lesson.
Part
What it is doing here
EV3 Intelligent Brick
The controller — literally, in the industrial sense. Its whole job is translating between the drawing and the joints.
Large Motor — the swing
Turns the whole arm. Gear it down: a degree at the motor should be less than a degree at the arm, or the resolution at full reach is far too coarse to draw with.
Medium Motor — the reach
Slides the carriage in and out. Its degrees convert to centimetres through the rack or lead screw — a fixed number you measure once.
Medium Motor — the pen
Lifts and lowers. Two positions only. Every move between shapes must happen with it up, or the drawing is joined by lines nobody asked for.
Touch Sensor — home
The known angle everything is measured from. Without it, “30 degrees” means nothing — thirty degrees from where?
Backlash will show up as a doubled line. Reverse the swing and the gears take up slack before the arm moves. Always approach a point from the same direction and the slack never appears — the same trick as Lesson 26.
Ports — and the rule 4 min
Sensors go in ports 1, 2, 3, 4. Motors go in ports A, B, C, D. They are not interchangeable, and nothing will tell you politely if you swap them.
Part
Port
Why this one
Reach (Medium)
A
The precise motor on the front port.
Swing (Large)
B
The strong one — it carries the whole arm.
Pen (Medium)
D
The small lift, out of the way of the two that matter.
Home (Touch)
1
Touch stays on 1 across the course.
Check your own build now:
Reach in A, swing in B, pen in D, home in 1.
Tape the paper down. Paper that shifts halfway through makes every measurement in this lesson a lie.
Mark the pivot point on the paper — put a dot directly under the arm’s axle. All your measurements are from there.
Check the pen lifts clear of the paper, and that it does not skip when lowered.
Connect the Brick 4 min
Two routes, and either is fine. USB is the reliable one and the one to fall back on when a room’s Bluetooth is busy; Bluetooth leaves the robot free to move, which some models need.
▶How to connect the BrickUSB and Bluetooth, step by step, with a photograph of every screen. Open it if you have not done this before — or if pairing is not working.Show meHide
USB — the reliable one
Switch the Brick on with the dark grey centre button.
Cable into the Brick’s PC port — the small square socket beside the numbered ports, not one of the numbered ones.
Other end into the computer.
Bluetooth — name it first
Do these in order. Naming the Brick after you go looking for it in the list is how groups end up driving each other’s robots.
Name your Brick. On the Brick: Settings (the spanner) → Brick Name. Type something nobody else will pick, then press the tick. Every Brick is called EV3 until somebody changes it.
Turn Bluetooth on. Settings → Bluetooth. Tick Bluetooth and Visibility. Leave iPhone/iPad/iPod unticked.
Connect from EV3 Classroom. Click the Brick icon at the top of the programming area, find your Brick by name, and click Connect.
Say yes on the Brick. It asks “Connect?” with the computer’s name — choose the tick, then accept the passkey, which is already 1234.
Where to read it. The name sits in the bar across the very top of the screen, on every screen — so you can check which Brick you are holding at any moment without going into a menu. This one is EV3VE. A Brick nobody has renamed says EV3.Step 3, and the reason step 1 exists. Three Bricks in range — read the name before you click Connect. Pairing with the wrong one is not an error: it works perfectly, on somebody else’s robot.
Step 2.Bluetooth switches the radio on; Visibility is what lets the computer find you. With Visibility off your Brick works perfectly and simply never appears in the list.Step 4. Look at the Brick. It asks whether to accept and names the computer. Choose the tick.Then the passkey, already 1234. Press the tick again and you are connected.
The two failures, every class, every time. The Brick has gone to sleep while you were building — press the centre button to wake it. Or you have paired with the group at the next table, which is why the name matters.
The long version, including Port View and how to read the port tiles, is in the Brick & Bluetooth guide.
Bluetooth, and route nothing across the paper. A cable that drags on the sheet moves it, and a drawing machine whose paper moves cannot be calibrated at all.
Confirm the connection 2 min
Check the Brick icon: connected, or not.
Three motor tiles — A, B and D.
One sensor tile — 1.
Run the reach motor one full rotation and measure how far the carriage moved with a ruler. Write down centimetres per rotation. Nothing in this lesson works without that number.
Stuck? The long version, with a photograph of every screen, is in the Brick & Bluetooth guide.
Make it move 10 min
Step 1 — home, then a grid you can measure
when program starts :: events hat
// swing back until the home stop, and call that zero
[B v] start motor [counterclockwise v] at (20) % speed :: motors
wait until <[1 v] is pressed? :: sensors>
[B v] stop motor :: motors
[B v] reset degrees counted :: motors
[A v] reset degrees counted :: motors
[D v] run to position (0) [degrees v] at (30) % speed :: motors
// nine dots: three angles by three reaches
set [a v] to (0) :: variables
repeat (3)
set [r v] to (0) :: variables
repeat (3)
[B v] run to position (a) [degrees v] at (25) % speed :: motors
[A v] run to position (r) [degrees v] at (25) % speed :: motors
[D v] run to position (60) [degrees v] at (40) % speed :: motors
wait (0.3) seconds :: control
[D v] run to position (0) [degrees v] at (40) % speed :: motors
change [r v] by (360) :: variables
end
change [a v] by (150) :: variables
end
Nine dots at known motor positions. Measure each one’s x and y from the pivot with a ruler — that table is your conversion, measured rather than assumed.
Step 2 — the arc that should have been a line
when program starts :: events hat
[D v] run to position (60) [degrees v] at (40) % speed :: motors
[B v] run to position (300) [degrees v] at (25) % speed :: motors
[A v] run to position (720) [degrees v] at (25) % speed :: motors
[D v] run to position (0) [degrees v] at (40) % speed :: motors
Straight from one corner to the other. The pen draws a smooth, confident arc — exactly the bug that is hard to see, because it does not look broken.
Step 3 — twenty small steps
when program starts :: events hat
// where the line starts and ends, in the PAGE's language (cm from the pivot)
set [x1 v] to (6) :: variables
set [y1 v] to (10) :: variables
set [x2 v] to (16) :: variables
set [y2 v] to (10) :: variables
set [steps v] to (20) :: variables
// from your nine-dot table
set [deg per cm v] to (72) :: variables // reach motor degrees per cm
set [deg per cm across v] to (9) :: variables // swing motor degrees per cm sideways, at 10cm out
set [dx v] to (((x2) - (x1)) / (steps)) :: variables
set [dy v] to (((y2) - (y1)) / (steps)) :: variables
set [x v] to (x1) :: variables
set [y v] to (y1) :: variables
[D v] run to position (60) [degrees v] at (40) % speed :: motors
repeat (steps)
change [x v] by (dx) :: variables
change [y v] by (dy) :: variables
// convert THIS point into the arm's language
set [reach v] to ((y) * (deg per cm)) :: variables
set [angle v] to ((x) * (deg per cm across)) :: variables
[A v] run to position (reach) [degrees v] at (25) % speed :: motors
[B v] run to position (angle) [degrees v] at (25) % speed :: motors
end
[D v] run to position (0) [degrees v] at (40) % speed :: motors
The same line, converted twenty times instead of once. Put the two drawings side by side — the difference is the lesson.
x and y are the page. angle and reach are the arm. Keeping the two sets of names apart is what stops the confusion.
The conversion happens inside the loop, once per step. Move it outside and you are back to step 2.
The two constants come from your ruler, not from this page — yours will differ, and that is the point.
Home first, every time. Angles measured from nowhere are not angles.
What success looks like: two lines on the paper between the same two points — one visibly bowed, one straight enough to check with a ruler.
If the line is still bowed, raise the step count to forty. If it is jerky, the steps are too small for the gearing to resolve — lower it to ten and find the middle.
Change it and test 8 min
One change at a time. Predict, then run, then look. Keep every sheet — this lesson is judged on paper.
Set steps to 2. The bow returns, and you can see it becoming an arc. Then 5, then 40, and line the sheets up in order.
Draw the same line close to the pivot, then far from it. The far one is worse at the same step count — because equal angles cover more ground out there.
Draw a square — four lines, pen up between them. Check the corners meet.
Draw a circle the easy way: hold the reach fixed and sweep the angle. A curve is easier than a line on this machine, which is exactly backwards from a plotter that moves in x and y.
Store a shape as a list of x,y points and walk it with one drawing routine — Lesson 15’s recipe, with the conversion tucked inside. Now the shape and the machine are separate things.
On this machine circles are easy and straight lines are hard. The machine’s geometry decides what is cheap.
Where this goes 3 min
The Pen Arm is judged on accuracy, and it is either right or wrong by a measurable number of millimetres.
The next model cannot be. The Scorpion has to decide whether something approaching is a threat, and it will sometimes be wrong in both directions — striking at a shadow, or failing to strike at a hand.
Those two mistakes do not cost the same, and that is what sets the threshold — not accuracy. A real scorpion rations its venom, so striking at nothing is expensive; missing a threat is worse. The number follows from the consequences.
Today the machine aimed exactly. Next it has to choose which mistake it can afford.
Build it 15 min
Build the model before you read any further. Everything after this is about making it do something, and none of it will make much sense with nothing on the table in front of you.
Use the viewer's own controls to zoom and turn pages. Fullscreen makes it big enough to build from.
Check the finished build against the picture before you switch anything on. A motor mounted the wrong way round is far easier to spot now than it is to debug later, when it looks like a program fault.
Challenges & mission 27 min
Work through the challenges in order — each is harder than the last. The mission comes after all three, and it is meant to make you plan before you build.
Challenge 1
Measure the conversion instead of assuming it.
Draw the nine-dot grid, then measure each dot's x and y from the pivot with a ruler and write the table out.
Report degrees per centimetre for the reach, and degrees per centimetre sideways at two different reaches. Those two sideways numbers should not match, and explaining why is the point.
Challenge 2
Draw the same line five ways.
One step, two, five, twenty, forty. Keep every sheet and lay them out in order.
Report the step count at which you can no longer see the bow with a ruler, and the count at which the pen starts to jerk. The answer lives between them.
Challenge 3
Draw the same line near the pivot and far from it.
Use the same step count for both. The far one is worse.
Say why in one sentence, using the words angle and distance. Then fix it by making the step count depend on the reach.
Mission
Draw something somebody asks for.
Take a shape from another person — their initials, a logo, a simple diagram — and draw it with the arm.
Requirements:
1. The shape stored as a list of x,y points in the page's language, kept completely separate from the drawing routine.
2. One routine that converts a point into angle and reach, used everywhere, written once.
3. Pen up between separate strokes, so nothing is joined that should not be.
4. Homing on the touch stop at start-up, and every point approached from the same direction so backlash never appears.
5. Straight lines straight enough to check with a ruler.
Then swap shapes with another group and draw theirs without changing a single line of your program.
If you had to edit the drawing routine to take their shape, the two things were not really separate — and separating the thing being drawn from the machine that draws it is what makes this a plotter rather than one very elaborate drawing.