Arduino Ladder · Bozoma Innovation Hub

Bozoma Innovation Hub  ·  Arduino Ladder  ·  Band 7

Distance and Display

Your board learns to measure how far away something is, using sound you cannot hear. Then it learns to say the answer on a screen of its own, instead of into a serial monitor nobody is watching. That second half is what turns a project into a device.

About 8 hours. Finish Bands 4 and 5 first. Band 6 is useful but not required: the servo here is optional.

Choose your build

Swap means build it instead of the one on this page: it teaches the same things and leaves you just as ready for the next band. Everything else on this page still applies, including the Check yourself questions. Practice is short, comes after the core, and gives you no sketch: the job, the check, and the code is yours. Bench is not a build at all: it is an instrument or an idea, done once, and everything after it is easier for having done it.

Sketches for this band

Click one to save it, or get every sketch at once from the downloads page. Each file opens with a plain-English header telling you what it does and how to wire it.

Start here

Why a screen changes everything

Everything you have measured so far has been reported to a serial monitor. That means the board has to be attached to a computer, and somebody has to be looking at the right window.

A device with its own screen is a different thing. Unplug it, carry it to the tank, and it still tells you what it knows. That is the whole difference between an experiment and something a person can use.

So this band does two jobs at once:

  • A new sense. Distance, measured with a click you cannot hear, and the arithmetic that turns a time into a length.
  • A new output. Sixteen characters by two rows, which sounds like plenty and turns out to be a design problem all of its own.

By the end you will be able to

  • Measure a distance and say where every number in the calculation comes from
  • Tell the difference between “zero centimetres” and “I heard nothing”
  • Wire an LCD screen, of either kind, and get letters onto it
  • Explain why a screen flickers, and write to it in a way that does not
  • Fit a useful message into sixteen characters
  • Install a library you did not already have

What you need

  • Your board, USB cable and breadboard
  • An HC-SR04 ultrasonic sensor, the one with two silver eyes and four pins
  • An LCD1602 screen, either kind. Part 5 tells you which you have.
  • A passive buzzer, the one where you can see a small green circuit board underneath
  • A 10k potentiometer, only if your screen has sixteen bare pins
  • A tape measure or a ruler, and a wall
  • About twenty jumper wires
  • A full-size breadboard, the long kind with numbers running past 60. This band runs out to column 42.
  • Optional: a servo from Band 6, for a lid that opens
If you have no LCD screenEverything in this band works with the serial monitor instead, and the sensor half is unaffected. Parts 5 to 7 become reading rather than building. What you will miss is the design problem of sixteen characters, which is genuinely worth meeting, so borrow one if you can.
Part 1

Think first: shouting at a wall

15 min

No board for this part. You need a wall, a large open space, and a friend if you have one.

If you have somewhere with an echo

A long corridor, a big empty room, a wall across a field, the side of a building.

Stand well back from the wall and clap once, hard. Listen.

You should seeIf you are far enough away, you hear your own clap come back a moment later. If you are too close, the two run together and you hear one sound.

Walk further back and clap again. Then further again.

You should seeThe gap between the clap and its echo gets longer, and the further you go the more obvious it is.

If there is nowhere with an echo

Do it with a ball instead, which is the same experiment slowed down so you can see it.

Stand two big steps from a wall and roll a ball at it, hard enough to come back to you. Count out loud, one number per second, from the moment it leaves your hand to the moment it returns.

Now stand four big steps back and do exactly the same, rolling with the same strength.

You should seeTwice the distance takes roughly twice the count. Not exactly, because a rolling ball slows down. Sound does not, which is why sound is the better tool for this.
Write these down
  1. What exactly did you measure? A distance, or something else?
  2. The sound went to the wall and came back. So does your measurement describe the distance to the wall, or something else?
  3. If you knew how fast sound travels, could you work out the distance from your time? Say how, in words, without doing any arithmetic.
  4. You clapped in a room with a soft curtain on one wall and heard no echo at all. Does that mean the curtain is not there?

That last question is the one that will save you an hour later. No echo does not mean nothing is there. It means nothing came back.

Soft things swallow the click. Angled things send it off sideways. Very close things get their echo back before the sensor has finished listening. Your sensor reports the same thing for all three as it does for an empty room.

Keep the paper. In Part 3 your sensor will read 0, and you will already know what that means.

Part 2

What the sensor actually gives you

20 min

Take out the HC-SR04. It is a small board with two silver cylinders on the front, which look like eyes and are not. One is a tiny loudspeaker. The other is a tiny microphone.

Look at the four pins along the bottom edge. Their names are printed on the board itself: VCC, Trig, Echo, GND. Read them off your own board now rather than trusting any picture, including the one below.

TR HC-SR04wall the click goes out the echo comes back the distance you want The sensor gives you a time, in millionths of a second. It never gives you a distance. Sound covers about 1 cm every 29 millionths of a second, and the time you measured covers the trip out and the trip back. distance in cm = time / 29 / 2
The sensor sends a click and listens for it to come back. What it hands you is the length of time that took, and that time covers the journey there and the journey back.

The two numbers, and where they come from

Here is the line that turns the sensor's answer into centimetres. Every part of it means something.

long cm = microseconds / 29 / 2;
29
Sound travels about one centimetre every 29 millionths of a second in ordinary air. That is the speed of sound written upside down, in a form that is convenient here. Dividing by it turns a time into a length.
2
Your click went to the wall and came back. So the length you just calculated covers the distance twice. Halving it gives you the distance to the wall.

Neither number is magic and neither should be copied without understanding. If you were measuring underwater the 29 would be completely different, because sound travels four times faster in water. The 2 would stay the same, because there and back is there and back wherever you are.

Why 29 and not 0.034

You may see this written as cm = microseconds * 0.034 / 2 elsewhere. It is the same sum. 0.034 centimetres per microsecond is the speed of sound; 29 microseconds per centimetre is the same fact upside down.

Dividing by 29 keeps everything in whole numbers. This chip is much faster at those. It also brings back the trap from Band 4: 147 / 29 / 2 gives 2, not 2.53.

For a parking guard, whole centimetres are plenty. For something needing millimetres, you would keep the microseconds and scale them differently.

Words to know
ultrasonic
Sound too high for a person to hear. This sensor uses it so that measuring does not make a noise.
microsecond
A millionth of a second. There are a thousand of them in a millisecond.
pulseIn
Waits for a pin to go HIGH, times how long it stays HIGH, and hands you that time in microseconds.
time of flight
Measuring a distance by timing how long something takes to get there and back. Radar and depth sounders work the same way.
Part 3

Guess, then measure something

40 min
+ − − + j i h g f e d c b a 16 20 25 30 USB ARDUINO UNO HC-SR04 VCC / Trig / Echo / GND HC-SR04 VCC / Trig / Echo / GND f20 f20 f21 f21 f22 f22 f23 f23 j20 j20 j21 j21 j22 j22 j23 j23 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
Four wires straight to the Arduino. No rail is used yet, so there is no feed wire to forget.

Read the sketch first. You have seen every instruction in it except two.

digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

unsigned long microseconds = pulseIn(echoPin, HIGH, 25000);

long cm = microseconds / 29 / 2;
Guess before you run it
  1. delayMicroseconds(10). You know delay counts in milliseconds. How long is this wait, as a fraction of a second?
  2. What do you think happens if nothing at all is in front of the sensor? Give a number.
  3. The 25000 at the end of pulseIn is a time limit. Using the 29 from Part 2, roughly how far away is that in centimetres? Show your working.
  4. What would happen without that limit, if no echo ever came back?

Now wire it

Start from an empty boardUnplug the USB. Take everything from Band 6 off the breadboard: the servo wires, the knob, the light, the button, the resistor. Put them back in the box. Leave only the two rail wires if you like, but check where they go before you trust them. If Band 6's battery pack is still connected, disconnect it and put it away. Nothing in this band uses it, and a six-volt rail sitting there while you wire a screen is a hazard with no purpose.

Both ends of every wire. Pull them out of the Arduino header too, so nothing is left in the pins. A wire you forgot is invisible when you are looking at the breadboard, and one Arduino pin takes one wire.

Which rails this band means. Your breadboard has two pairs, one along each long edge, and on most boards the two pairs are not joined to each other. In this band, “the + rail” and “the − rail” always mean the pair along the top edge, nearest row j. Pick that pair now and use only it. The buzzer sits down in rows a and b, so its rail wire is a long one that runs round the end of the board; run it rather than reaching for the nearer rail, because mixing the two pairs means nothing works and nothing looks wrong.

Push the sensor into the breadboard. Its four pins go into f20, f21, f22 and f23. Stand it up so the two silver eyes face away from the board.

All four pins go in one block, rows f to j. The sensor is not wide enough to straddle the middle channel, and it does not need to: its four pins are separate anyway.

You should seeThe sensor standing up firmly with all four pins fully in, and the eyes pointing out across the table rather than at the ceiling.
If the pins will not go inThey are thicker than an LED's legs and need a firm push. Press on the board of the sensor, evenly, not on one pin. If it goes in crooked, pull it straight out and start again.

Check the pin order on your own board. Read the printing next to the pins. On almost all of them the order is VCC, Trig, Echo, GND, reading left to right with the eyes facing you. Column 20 is the leftmost one.

If yours is in a different orderFollow your board, not this page. Wire each named pin to the place the table says, whichever column it lands in, and write down what you did.

Four wires: j20 to 5V, j21 to pin 10, j22 to pin 11, j23 to GND.

You should seeFour wires, each firm at both ends, going to four different places.
Pin 11 may have to move laterTurn your screen over now and look at the back. If it is bare, with sixteen pins along the top and no small board on the back, then that screen is going to want pin 11 for itself in Part 6, and only one wire fits in a pin.

You can leave Echo on pin 11 for this part, because the screen is not wired yet. Part 6b will tell you when to move it to pin 9, and every sketch after that already expects it there. Write a note to yourself now so you are not surprised.

Plug in, upload b7_01_ping_given.ino, and open the serial monitor (Tools, then Serial Monitor, and check the box in the corner says 9600).

You should seeTwo numbers streaming past about five times a second: a time in microseconds and a distance in centimetres. Put your hand in front of the sensor and watch both fall together. Take it away and watch them climb.
If both numbers are always 0Nothing is coming back. Point it at a wall, flat on, from about 30 cm. If it is still 0, check the Trig and Echo wires: they are easy to swap, and swapped they give exactly this.
If the numbers are wild and jump aboutHold the sensor still. It is very sensitive to being tilted, and it will happily measure the ceiling or the table rather than what you meant.
If nothing prints at allThe serial monitor is not at 9600, or the board is not selected. Check the box in the corner of the serial monitor window first.
The answers to the four questions

1. Ten millionths of a second. A hundred thousand times shorter than delay(1). That is why there is a separate instruction for it: delay cannot do waits this short.

2. Most people say a very large number. The answer is 0, and that surprises everybody. When no echo returns, pulseIn gives up and hands back 0. A reading of 0 means “I heard nothing”, which is the opposite of “something is touching me”.

3. 25000 divided by 29 is about 862 centimetres of travel, and half of that is about 4.3 metres. So anything further than about four metres reads as 0.

4. Without a limit, pulseIn falls back to its own default, which is a whole second. It sits there for that second waiting for an echo that never comes, and while it waits nothing else on the board runs at all. That is the Band 5 problem in a new place: a single instruction that stops everything. Your own limit of 25000 turns a one-second stall into a twenty-five thousandth of a second one.

Now check it against a real ruler

A number on a screen is a claim. Claims get checked.

Lay a tape measure or ruler on the table with its zero right at the front of the sensor's eyes.

Stand a book upright at 10 cm, flat side facing the sensor. Read the serial monitor. Write down what the sensor says next to what the ruler says.

Repeat at 20, 40, 80 and 150 cm. Fill in this table.

Ruler saysSensor saysDifference
10 cm
20 cm
40 cm
80 cm
150 cm
You should seeAgreement within a centimetre or two across the whole range. That is genuinely good for a part this cheap.

Now try three awkward things. Write down what happens for each one.

  1. A folded towel or a jumper at 40 cm.
  2. The book at 40 cm, but turned at a steep angle.
  3. Your hand at 2 cm.
You should seeThe towel reads far away or 0, because soft things swallow the click. The angled book reads far away or 0, because the click bounces off sideways and never comes home. Your hand at 2 cm reads badly or not at all, because the sensor cannot hear an echo that arrives before it has finished shouting.
This is the calibration lesson from Band 4, in a new coat

In Band 4 you found that a light reading means nothing until you go and measure what it means in your room. Here you have found something slightly different and just as important.

The sensor is accurate in the middle of its range and lies at both ends. It also lies about certain surfaces, at any distance at all.

So write two numbers in your build log: the closest and the furthest distance you would trust from your own sensor. Take them from your table, not from this page. Those two numbers belong to your build.

Part 4

Look closer: the shape of a measurement

25 min

Look at the five lines that start the measurement.

digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

That is a pulse: off, on for exactly ten microseconds, off again.

The sensor's own instructions say it needs at least ten. The two microseconds of LOW at the start are there to make sure the pin has settled before the pulse begins.

You are not choosing these numbers. They come from the sheet the sensor's maker published, and reading such a sheet is a skill worth having. Search for “HC-SR04 datasheet” and look for the timing diagram. It will look hard to read, and you only need two lines of it.

If you have no internetYou are not missing anything you need. The two numbers are already in front of you: 2 microseconds LOW to settle the pin, then 10 microseconds HIGH to start the measurement. Look up the sheet another day, when you are somewhere with a connection, purely to see what one looks like.

Why unsigned long and not int

unsigned long microseconds = pulseIn(echoPin, HIGH, 25000);

You met this in Band 5 with millis, and the reason is the same. An ordinary int on this chip holds numbers up to 32767. The limit here is 25000, which fits, but only just, and a longer limit would not.

The habit is worth keeping even when a number happens to fit today: anything holding a duration in microseconds or milliseconds is unsigned long. You will not remember which ones were tight.

The function with a name

In b7_04 and b7_05, all of that lives in one place:

long readDistance() {
  ...
  return microseconds / 29 / 2;
}

This is exactly what you learned to do in Band 5. Nine lines with one job, given a name, so that everywhere else in the sketch you can write readDistance() and be done.

Notice what else it buys you. Suppose you decide that a reading of 0 should mean “far away” rather than “touching”. You change that in one place.

That decision is a rule about your device. Rules about your device belong in one place each.

A question to answer in your log

In b7_05, readDistance turns a 0 into 999 before handing it back. In b7_01 it does not.

Why is that right for one and wrong for the other? Answer in two sentences.

Check your answer

b7_01 is a measuring instrument. You want to see exactly what the sensor said, including 0, because you are learning what it does. Hiding the 0 would hide the lesson.

b7_05 is a device that has to act. Acting on a 0 as though it meant “touching” would make the guard scream at an empty room. So the decision “no echo means far away” is made once, on purpose, in the one place that reads the sensor.

Part 5

Which screen do you have?

20 min

Take out the LCD and turn it over. What you see on the back decides everything about the next hour, so do this before reading further.

With an I²C board on the back Bare, sixteen pins GNDVCCSDASCL contrast knob Four wires. Two are power, two carry the letters. Uses Arduino pins A4 and A5 and nothing else. Start here if you have it. Twelve wires plus a knob. Every one has to be right before a single letter appears, and a wrong knob looks exactly like a dead screen. A blank screen is almost never a broken screen. Turn the knob first.
The two kinds. One has a small board soldered to the back with four pins on it. The other is bare, with a strip of sixteen pins along the top edge and no board on the back.
If the back has…You haveYou needGo to
A small green board soldered on, with four pins labelled GND VCC SDA SCLThe I²C kind4 wires. No potentiometer.Part 6a
Nothing. Just a strip of 16 pins along the top of the screen itselfThe bare kind12 wires and a 10k potentiometerPart 6b
If you have a bare screen and a loose four-pin board in the bagThey are meant to go together and somebody has to solder them. If you cannot solder, use the bare wiring in Part 6b. It works perfectly and it teaches you more. The cost is sixteen wires and a knob instead of four wires, so about twelve extra connections.

The trap, before you build either one

This is the single most common wasted evening in all of hobby electronics, and you can avoid it by reading one paragraph.

Distance 42 cm Knob too far one way Blank. Looks broken. It is not. Somewhere in the middle Letters you can read. Stop here. Knob too far the other way Solid blocks. Also not broken. Turn the knob slowly all the way from one end to the other before you change anything else.
The same working screen at three contrast settings. Only the middle one is readable, and neither of the others means anything is broken.

Every one of these screens has a contrast adjustment. On the I²C kind it is a tiny blue screw on the back. On the bare kind it is the potentiometer you are about to wire to pin 3.

Set wrongly, a perfectly working screen shows absolutely nothing. No hint. No faint text. Nothing at all, exactly as though it were dead.

The ruleWhen a screen shows nothing, turn the contrast slowly from one end to the other before you change anything else. Not after checking the wiring. Before. It takes five seconds and it is the answer most of the time.

Turn it too far the other way and you get a row of solid blocks. That is also not broken. Somewhere between blank and blocks is readable text, and the range is narrow.

Part 6

Wire the screen and get letters on it

50 min

Do one of the two builds below, whichever matches the back of your screen. Then rejoin at Part 7.

6a. The I²C kind, four wires

+ − − + j i h g f e d c b a 16 20 25 30 USB ARDUINO UNO HC-SR04 VCC / Trig / Echo / GND HC-SR04 VCC / Trig / Echo / GND LCD1602, I2C LCD1602, I2C GND GND VCC VCC SDA SDA SCL SCL f20 f20 f21 f21 f22 f22 f23 f23 j20 j20 j21 j21 j22 j22 j23 j23 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
The sensor's two power wires move off the Arduino and onto the rails, so the screen can share the one 5V pin. Trig and Echo do not move.
First, install the library

This one does not come with the Arduino software, so you have to fetch it once.

  1. In the Arduino software, click Tools, then Manage Libraries.
  2. Type LiquidCrystal I2C in the search box.
  3. Find the one by Frank de Brabander and click Install.
You should seeThe word INSTALLED next to it in the list when it finishes. It takes a few seconds.
If you have no internet on that computerYou can download the library as a .zip on any computer, carry it on a USB stick, and use Sketch, then Include Library, then Add .ZIP Library. Search the web for “LiquidCrystal_I2C github” and use the green Code button to download it.
Before you startUSB unplugged.

Four wires from the screen's four pins: GND to the − rail, VCC to the + rail, SDA to A4, SCL to A5. Then, if you have not already: one wire from the + rail to 5V, and one from the − rail to a GND pin, and move both of the sensor's power wires off the Arduino: j20 from the 5V pin onto the + rail, and j23 from the GND pin onto the − rail. One Arduino pin takes one wire, and the screen wants both of those pins too. Part 8's pin plan assumes you have done this.

Why the rails rather than straight to the Arduino: the sensor is already using the one 5V pin, and one Arduino pin takes one wire. The rails are how two things share one pin without two wires ever meeting in one hole.

A4 and A5 are not being used as ordinary analog pins here. On this chip they are the two pins used for talking to other boards, and you cannot choose different ones. Nothing else in your build may use A4 or A5 from now on.

Plug in and upload b7_02_lcd_i2c_given.ino.

You should seeThe backlight comes on, and two lines of text: Bozoma Hub on the top row and Band 7 ready on the bottom.
If the backlight is on but there is no textContrast. Find the tiny blue screw on the back board and turn it slowly with a small screwdriver, all the way one way and then all the way the other. The text will appear somewhere in between. Do this before anything else.
If you have done the contrast and there is still nothingThe address. Change 0x27 near the top of the sketch to 0x3F and upload again. Those are the only two addresses these boards use, so one of them is right.
If the backlight does not come on at allCheck GND and VCC. With those two wrong, nothing else can work and everything else looks fine.

Now break it on purpose, so you have seen it once. With the text showing, turn the little blue screw on the back slowly, all the way in one direction.

You should seeThe words fade and then vanish completely. The backlight is still on and the screen looks exactly like a dead one. Nothing has changed in your wiring or your code.

Now turn it back until the words return, and stop there.

Two minutes now, and the next time a screen goes blank on you, you will reach for that screw instead of pulling wires out. That is the whole reason for this step.

6b. The bare kind, twelve wires and a knob

+ − − + j i h g f e d c b a 1 5 10 15 20 25 30 35 USB ARDUINO UNO LCD1602, bare 16-pin header in row j LCD1602, bare 16-pin header in row j contrast contrast HC-SR04 HC-SR04 f1 f1 f11 f11 f12 f12 f13 f13 f14 f14 f15 f15 f16 f16 f2 f2 f20 f20 f21 f21 f22 f22 f23 f23 f3 f3 f30 f30 f31 f31 f32 f32 f4 f4 f5 f5 f6 f6 j1 j1 j10 j10 j11 j11 j12 j12 j13 j13 j14 j14 j15 j15 j16 j16 j2 j2 j20 j20 j21 j21 j22 j22 j23 j23 j3 j3 j30 j30 j31 j31 j32 j32 j4 j4 j5 j5 j6 j6 j7 j7 j8 j8 j9 j9 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
Twenty wires. Screen pins 7, 8, 9 and 10 are deliberately empty, and Echo has moved to pin 9 because the screen has taken pin 11.

This is the longest single build in the course. Do it in one sitting, slowly, and test in the middle rather than at the end.

Read this before your first wireThe screen's pins are numbered 1 to 16 from the left as you look at the front, and the numbers are usually printed on the board. Find pin 1 and pin 16 on your own screen and mark which end is which with a scrap of tape. Getting this backwards means twelve wires in the wrong place.
Before you startUSB unplugged.

Move the sensor's Echo wire first. Take the wire out of Arduino pin 11 and put it into pin 9. Leave its other end in j22.

The screen is about to take pin 11 for itself, and only one wire fits in an Arduino pin. Every sketch from here on already expects Echo on pin 9.

You should seeArduino pins 11, 12, 5, 4, 3 and 2 all completely empty, ready for the screen. Only pins 9 and 10 have sensor wires in them.

Push the screen's pin strip into row j, with its sixteen pins in columns 1 to 16. So screen pin 1 sits in j1, screen pin 2 in j2, and so on all the way along: j1 j2 j3 j4 j5 j6 j7 j8 j9 j10 j11 j12 j13 j14 j15 j16. Sixteen pins, sixteen columns, none skipped. The numbers match, which makes everything after this easier.

Row j on purpose. The screen's body will lie over the rows behind it, and every wire you are about to place goes into row f of the same column, which stays clear.

You should seeAll sixteen pins in row j, the screen sitting level, and nothing bent underneath.

Put the 10k potentiometer in at f30, f31, f32. Wire j30 to the − rail and j32 to the + rail. Its middle leg is f31, and a wire from j31 will go to the screen in a moment.

The four power and contrast wires first. Do these before the six data wires, because they are the ones that let you test.

Screen pinCalledWire fromTo
1VSSf1− rail
2VDDf2+ rail
3V0f3j31, the knob’s middle leg
5RWf5− rail
15Af15+ rail (backlight)
16Kf16− rail (backlight)

Then + rail to 5V and − rail to GND.

Move the sensor's two power wires now, before you plug inBack in Part 3 the sensor's j20 went straight to the Arduino's 5V pin and its j23 straight to a GND pin. The screen wants both of those pins as well, and one Arduino pin takes one wire. So move them: j20 to the + rail, j23 to the − rail. From here on, one wire runs from the + rail to 5V and one from the − rail to GND, and everything else on the board feeds from the rails. Part 8's pin plan assumes you have done this.

Every wire goes into row f, in the same column as the screen pin it belongs to. The screen's own pin is in row j of that column, and the column joins them underneath. One hole, one leg, exactly as in every band since Band 1.

Which way the screen's body should hangThe screen is much wider than its pin strip, so its body has to lie over something. Turn it so the body hangs out over the top edge of the board, past the rails and off the side, rather than down over the middle channel. That leaves rows f to i clear for the wires you are about to place. It does cover the rail holes above roughly columns 1 to 24, so put the rail end of every wire in this build into a rail hole to the right of column 25, where you can still reach it.

If your screen will not sit that way, do not fight it: use female-to-male jumper wires straight onto its sixteen pins and leave the breadboard for the sensor and the knob. The wiring is identical, and the table above still tells you what joins to what.
If your screen's backlight has no resistorAlways put a 220 ohm resistor in the pin 15 wire, between f15 and the + rail, rather than a plain wire. Some of these boards have a small resistor built into the back next to pins 15 and 16 and some do not, you cannot tell reliably by looking, and on a board that has one the extra 220 ohms costs almost no brightness. On a board that has none, a plain wire lets the backlight pull far more current than the Arduino's 5V pin should give: the whole board dims, the screen may reset, and the backlight burns out early. Fitting the resistor either way costs you nothing and cannot go wrong.

Test now, before the other six wires. Plug in the USB, then turn the potentiometer slowly all the way from one end to the other and watch the screen.

You should seeAt one extreme, nothing. Somewhere in the middle, a row of faint rectangles across the top line. That is the screen alive and asking for something to display. Leave the knob where those rectangles are just visible.
If you never see rectangles anywhere in the knob's travelCheck pins 1, 2 and 3 and the two rail wires. Nothing else matters yet, because you have not wired anything else.

Those rectangles are the best news in this build. They prove power and contrast are right, which is most of what goes wrong, and you now know it before adding six more wires.

Now the six data wires. Unplug the USB first.

Screen pinCalledWire fromTo Arduino pin
4RSf412
6Ef611
11D4f115
12D5f124
13D6f133
14D7f142

Screen pins 7, 8, 9 and 10 stay empty, and that is correct, not a mistake. They are a faster way of talking to the screen that needs four more wires, and this way is fast enough.

Upload b7_03_lcd_parallel_given.ino. The LiquidCrystal library it uses already comes with the Arduino software, so there is nothing to install.

You should seeBozoma Hub on the top row and Band 7 ready on the bottom.
If you see the row of rectangles but no wordsOne of the six data wires is wrong or loose. Check them against the table one at a time. The rectangles prove the screen is fine, so the fault is certainly in those six.
If you see nothing at all nowYou knocked the contrast knob while wiring. Turn it back until the rectangles appear, then look again.
If the letters are scrambled or half a lineTwo data wires are swapped. The order 12, 11, 5, 4, 3, 2 is RS, E, D4, D5, D6, D7, and the library expects them in that order.
Words to know
I²C
A way for two boards to talk over just two wires. Said “eye squared see”. On this chip it always uses pins A4 and A5.
address
A number that says which board on those two wires you mean, the way a house has a number. These screens are 0x27 or 0x3F.
contrast
How dark the letters are against their background. Set wrongly, a working screen shows nothing at all.
padding
Extra spaces printed after your text so the row always receives the same number of characters, and nothing old is left behind.
Both kinds, same three instructions

Whichever you wired, from here on the sketch talks to the screen the same way:

screen.setCursor(0, 0);     // column 0, top row
screen.print("Hello");
screen.setCursor(0, 1);     // column 0, bottom row
screen.print(42);

Columns are numbered 0 to 15 and rows 0 to 1. Both start at zero, like the array positions in Band 3. print takes text in quotes or a number without them, exactly like Serial.print, which you already know.

Part 7

Now break it on purpose

35 min

Join the sensor and the screen together in the obvious way and something unpleasant happens.

If you have the bare screenb7_04 is written for the I²C kind and will not run as it stands on yours. Read this part rather than running it. Everything it teaches is the same either way, and you will meet both faults for real in Part 8.

If you would rather run it, two changes are needed, not one: replace its top three lines with the two from b7_03, and change int echoPin = 11; to 9, because your screen has pin 11.

Upload b7_04_buggy_flicker.ino with the sensor still on pins 10 and 11, as you wired it in Part 3. That is the I²C screen's arrangement; if you have the bare screen your Echo wire moved to pin 9 in Part 6b, so read the box above rather than uploading this.

What you will actually seeThe number is right, and the screen is horrible. It flickers hard enough to be tiring to look at, and reading the number takes effort.
Work out why before you read on
  1. Look at the sketch. What is the first thing it does to the screen every round?
  2. How long is the screen blank while that happens?
  3. Hold the sensor perfectly still, so the number stops changing. Does the flicker stop?
  4. What does that last answer tell you?
The answer, after you have written yours

Two mistakes, and they add up.

One. screen.clear() wipes all thirty-two character positions and takes about two milliseconds. Every round the screen is genuinely blank for a moment, and your eye sees it.

Two. It rewrites the number even when the number has not changed. Question 3 is the giveaway: hold it still, the number stays at 42, and the flicker carries on regardless. Nothing on the screen needed to change and it changed anyway.

Notice the shape of this. It is Band 6's lesson again, in a completely different place. The reading was perfectly good. The fault was in acting on it when you did not need to.

The fix, and the trap inside the fix

The obvious repair is to stop calling clear(). Do it: comment that line out and upload again.

You should seeThe flicker is gone. And a new problem arrives.

Move the sensor so the reading goes from 100 down to 99.

You should seeThe screen reads 990. Or go from 42 to 8 and it reads 82.
Why, and this catches everybody once

A screen never wipes itself. Printing 99 where 100 was writes over the first two characters and leaves the third exactly as it was. The old 0 is still sitting there and it always will be.

So you cannot use clear(), because it flickers, and you cannot not use it, because of leftovers. The answer is neither.

Send a fixed width every time, padded with spaces. Here is the version from b7_05:

if (cm < 100) screen.print(" ");
if (cm < 10)  screen.print(" ");
screen.print(cm);
screen.print(" cm          ");

The spaces are not decoration. They are an eraser, and they cost nothing, because those character positions were going to be written anyway.

The two if lines at the top are the part worth understanding. They make the number itself always three characters wide: 7 becomes   7, 42 becomes  42, and 742 is already 3. Without them a three-digit reading would send one character more than a two-digit one, and the row would stop adding up.

Put that together with only writing when the value actually changed, and you have a screen that is steady, correct, and never blank.

if (cm == lastShown) {
  return;
}
lastShown = cm;
Count it yourselfThe screen is 16 characters wide, and the row must always receive exactly 16. Count it for a reading of 42:

One space from the first if, because 42 is under 100. Then 42, which is 2. That is 3 so far, and the number is now three wide as promised. Then " cm" plus ten spaces, which is 13. Three plus thirteen is 16.

Now do it for 7 and for 742 and check you get 16 both times.

Write too few and a long value leaves a leftover digit behind. Write too many and the extra characters go off the end into memory you cannot see, so the row quietly stops matching what you counted, which is harder to spot than the leftover.
Part 8

Build the parking guard

60 min
+ − − + j i h g f e d c b a 16 20 25 30 35 40 45 USB ARDUINO UNO HC-SR04 VCC / Trig / Echo / GND HC-SR04 VCC / Trig / Echo / GND + + buzzer buzzer a40 a40 a42 a42 b40 b40 b42 b42 f20 f20 f21 f21 f22 f22 f23 f23 j20 j20 j21 j21 j22 j22 j23 j23 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
The finished guard, on the I²C route. The buzzer sits down in rows a and b, so its rail wire runs the long way round to the top pair.

Now a whole device. It measures how far away you are and tells you three ways at once.

  • The number, on the bottom row.
  • A word saying what to do, on the top row.
  • A beep that gets faster as you close in, and becomes one solid tone under 10 cm.

Three ways at once is the point. A driver is not looking at a screen, and a person across the room cannot hear a small buzzer. A device that reports one way only works for one person in one position.

The pin plan

PartPinHolesWiring
Sensor VCC+ railf20Wire j20 to the + rail, not straight to 5V; you moved it there in Part 6, and the row below runs the + rail to 5V. The screen wants 5V too, and one Arduino pin takes one wire.
Sensor Trig10f21Wire j21 to pin 10
Sensor Echo11 or 9f22Wire j22 to pin 11 (I²C screen) or pin 9 (bare screen)
Sensor GNDGNDf23Wire j23 to the − rail
Buzzer6long b40, short b42Wire a40 to pin 6; wire a42 to − rail. No resistor.
Screen——Exactly as you wired it in Part 6. Do not move it.
Power the + rail5V—One wire from the + rail to the 5V pin. If you skipped Parts 5 to 7 because you have no screen, this is the wire you have never run, and without it the sensor's VCC row above connects to dead metal.
GroundGND—One wire from the − rail to a GND pin
Why the Echo pin is different for the two screensThe bare screen uses Arduino pins 12, 11, 5, 4, 3 and 2 for itself. Pin 11 is taken, so the sensor's Echo lives on pin 9 instead, and Part 6b had you move it. The I²C screen uses only A4 and A5, so pin 11 is free and Echo stays there. The two worked sketches already have the right pin in them. Use the one that matches your screen and you do not have to think about it again.
Before you startUSB unplugged. Every time.

Stage one: the buzzer. Long leg towards the pin. Test it with b5_01_tone_given.ino from Band 5, changing buzzerPin from 12 to 6 at the top.

You should seeThree notes rising, then a pause, over and over.
If it clicks instead of playing notesYou have an active buzzer rather than a passive one. It still works for this build; you just get one fixed note instead of two different ones.

Stage two: check the sensor still works with b7_01_ping_given.ino, changing echoPin to 9 first if you have the bare screen.

You should seeSensible distances in the serial monitor, matching your ruler as before.

Now upload the worked sketch for your screen. Use b7_05_bin_worked_i2c.ino if yours has the four-pin board on the back. Use b7_05_bin_worked_parallel.ino if it has sixteen bare pins.

You should seeParking guard for a second, then a word on the top row and a distance on the bottom. Walk your hand slowly in: Clear, then Keep coming, then Nearly there, then STOP. The beeping starts slow and speeds up, and becomes one solid tone under 10 cm. Take your hand away and it goes quiet and reads --- cm.
If the screen shows --- cm and never changesThe sensor is reading 0, so the sketch is treating it as far away. Go back to stage two and get the sensor printing sensible numbers on its own first.
If it beeps constantly with nothing in front of itSomething is in front of it: the sensor is pointing at the table, at the breadboard, or at a wire arching over it. Point it at open space and look along the line of the eyes to check.
If the words change but the number is stuckLook at lastShown in the sketch. If you have changed the screen-writing part, you may be updating the word but returning before the number.

Fit it into sixteen characters

Look at the top row. Nearly there is 12 characters and fits. Now try writing your own words for the four ranges, and find out how quickly sixteen runs out.

The exercise

Write four messages of your own, one for each range. Use whatever language your users actually speak. Each one must fit in 16 characters, and a stranger must be able to act on it at once. Count every character, including spaces.

Then ask somebody to read them cold and tell you what they would do. If they hesitate, the message is too long or too clever. Sixteen characters is a real constraint and it is a good teacher.

If you are working aloneWrite your four messages on a slip of paper, put it away, and look at it again tomorrow. Read each one and say out loud what you would do about it. Anything you have to read twice is too long or too clever, exactly as if somebody else had hesitated over it.
Part 9

Look closer

35 min

a. Read loop first

void loop() {
  long cm = readDistance();
  showDistance(cm);
  updateBeep(cm);
  delay(50);
}

Four lines: measure, show, beep, pause. Anyone can read that and say what the device does. Everything complicated is behind a name.

That delay(50) at the bottom is a blocking wait, and Band 5 taught you to be suspicious of those. Be suspicious of it. It means the beep timing can only be checked twenty times a second, so a beep can be up to 50 thousandths of a second late. On a beep that lasts 350, that is small enough to accept. That is a judgement, not an exemption. If your device needed millisecond timing, this delay would have to go.

b. Follow the beeping by hand

Assume gapFor returns 350 and lastBeep is currently 4000. Fill this in.

millis()now − lastBeep≥ 350?Buzzer changes?lastBeep after
4100
4300
4350
4500
4700
Answer, after you have filled it in

4100: gap 100, no, no change, stays 4000. 4300: gap 300, no, stays 4000. 4350: gap 350, yes, buzzer flips, lastBeep becomes 4350. 4500: gap 150, no, stays 4350. 4700: gap 350, yes, flips again, becomes 4700.

So it flips every 350 milliseconds, which means on for 350 and off for 350, which is a full beep every 700. If you want a beep every 350 you halve the gap. Work out why before reading on: a beep is two flips, not one.

This is exactly the millis pattern from Band 5, and nothing about it is new. What is new is where you found it: the same shape solves a different problem.

c. Break it on purpose

In your copy, delete the line lastBeep = now; from inside the if. Predict, then upload.

Answer

lastBeep stays at 0 forever, so now - lastBeep is always enormous and always bigger than the gap. The if is true on every single round, so the buzzer flips thousands of times a second.

You will not hear beeping. You will hear a rough continuous noise, because you are now switching the tone on and off faster than a beep.

This is the same bug as the one in Band 5 Part 10b. If you recognised it before uploading, that is the course doing its job.

d. The number that decides everything

Change delay(50) at the bottom of loop to delay(500). Upload and walk your hand in.

Answer

The screen is calm and the guard is useless. It notices you half a second late, and the beeping becomes lumpy because the beep timing can only be checked twice a second.

Now try delay(5). The screen becomes noisy again. The number flickers between 41 and 42 as the reading wobbles, and every wobble is a screen write.

There is a right answer for your device and this page does not know it. It depends on how fast a car moves, how far away it starts, and how quickly a person can react. 50 is a reasonable starting point for a hand. Write down what you chose and why, in your log.

Part 10

Change it

45 min

Work on a copy of the worked sketch that matches your screen.

Bronze
Make the bottom row show a bar instead of a number: one block character for every 10 cm, up to sixteen. You will need a for loop and screen.print((char)255), which prints a solid block. Then say in one sentence which is easier to read from three metres away, and why.
Silver
Add a smallest ever reading that is remembered and shown on the top row, with a button to reset it. This is genuinely useful for a parking guard: it tells you how close you actually got. Watch out for the reading of 0.
Gold
Take the average of the last five readings instead of using each one raw, and show that instead. The screen will become noticeably calmer. This is hard for an interesting reason: you need somewhere to keep five numbers and a way to throw the oldest away each time. An array from Band 3 and a position that wraps round will do it.
A warning about GoldAveraging makes a device calmer and slower. Both. If your guard averages five readings taken 50 milliseconds apart, it is telling you where the car was a quarter of a second ago. For a hand that is fine. For a reversing car it may not be. Say in your log which you would choose and why.
Make

Make: something a person reads and acts on

120 min
What to build

A device with a screen that somebody who is not you can walk up to, read, and know what to do about. Pick one, or bring your own:

  • A parking guard for a real doorway, gate or vehicle, mounted where it would live
  • A bin that tells you how full it is, with the sensor in the lid pointing down
  • A queue counter for a charging kiosk: how many people, and roughly how long
  • A water level display for a tank or a bucket, reading in centimetres from the top
  • A doorway counter that adds one every time somebody passes
  • A smart bin whose lid opens on a servo when you come near, if you did Band 6
It is finished when all of these are true
  • The screen never flickers and never shows a leftover character
  • It behaves sensibly when the sensor hears nothing, rather than reporting zero
  • Every message fits in sixteen characters and needs no explanation
  • It is housed and mounted where it would actually be used, not lying on a desk
  • You measured its accuracy against a ruler and wrote the numbers down
  • Somebody read the screen and did the right thing without you saying anything. If you are working alone, this counts as passed when you photograph the screen from where a user would stand, look at the photograph a day later, and know what to do from the photograph alone.

The test that matters most in this band

Put it where it belongs, hand nobody any instructions, and watch one person walk up to it.

Write down what they read first, how long before they acted, and whether they did the right thing. If they read the number before the word, your layout is telling them to. If they hesitated, count the characters in the message they hesitated over.

If you are doing this course alonePhotograph the screen from where a user would stand, at the distance they would stand, then look at the photograph tomorrow. If you cannot tell what to do from the photograph, neither could they. This works better than you would expect, because a photograph strips away everything you know about your own build.

Show your work

Post four things: a video of somebody using it, a close photo of the screen with a real reading on it, your ruler-accuracy table, and your build log. Then look at one other person's screen layout and tell them one thing you had to read twice.

If you are doing this course aloneThere may be nobody to post to and nobody else's work to look at. That is fine, and it does not let you off this part. Do it this way instead: save the photos and the video into a folder named for this band, write the same notes into your build log, and then be your own second reader. Come back to your own sketch the next day, read it cold, and write down the one thing you would do differently now. That is the whole value of looking at somebody else's work, and you can get most of it from your own.
Part 11

Check yourself

20 min

Code you have not seen. Answer from reading only. Do not upload it.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C screen(0x27, 16, 2);

int trigPin = 10;
int echoPin = 11;
int lastCm = -1;

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  screen.init();
  screen.backlight();
}

void loop() {
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  unsigned long us = pulseIn(echoPin, HIGH);
  int cm = us / 29 / 2;

  if (cm != lastCm) {
    lastCm = cm;
    screen.setCursor(0, 0);
    screen.print(cm);
    screen.print(" cm");
  }

  delay(100);
}
  1. The sensor is pointed at a wall 100 cm away, then slowly at one 99 cm away. What does the top row of the screen say?
  2. The sensor is now pointed out of a window at open sky, so no echo ever comes back. What does the device do? Answer carefully: this is not a question about the screen.
  3. Compare the pulseIn line with the one in b7_01_ping_given.ino. One value is missing here. Which, and what does leaving it out change?
  4. The wall is 60 cm away and nothing is moving. Roughly how many times a second is the screen written to?
  5. int cm and unsigned long us. The wall is 3 metres away. Is int big enough to hold the answer? Show the arithmetic.
  6. Somebody wants this to also sound a buzzer that beeps faster as things get nearer, and adds a tone and a delay inside the if. Name two separate things that will go wrong.
Answers

1. 99 cm followed by a leftover, so it reads 99 cmm or similar. "100 cm" is six characters and "99 cm" is five, so the sixth character from before is never written over. There is no padding here, and this is the fault Part 7 was about.

2. It stops dead for a whole second, over and over. With no limit given, pulseIn uses its own default of one second, and it waits out every bit of that whenever no echo comes back. Nothing else on the board runs during that wait: not the screen, not a buzzer, nothing. So the loop that was running ten times a second now runs about once a second, and the screen keeps showing the last number it had, which makes it look like it is working perfectly. This is the question that matters most in this band. A missing timeout does not give you a wrong number. It stops the whole board, and it does it silently.

3. The third value, the timeout, which is 25000 in b7_01. With it, a missing echo returns 0 after about 25 thousandths of a second and everything carries on. Without it, the wait can be far longer, and the device stops for all of it.

4. Almost never. The reading is steady, so cm != lastCm is false nearly every round and nothing is written. It only writes when the number genuinely changes, which is the correct behaviour and the point of lastCm.

5. Yes, easily. 3 metres is 300 cm, and an int on this chip holds up to 32767. The reason us has to be unsigned long is different: the time for 3 metres is about 17400 microseconds, which fits, but the timeout and longer distances do not fit as comfortably, and durations are the thing that overflows first. Keep the habit.

6. Two things, and they are both from earlier bands. One: a delay inside the if blocks, so the sensor stops being read while the beep is on, which is the Band 5 problem. Two: the beep would only ever happen when the number changes, because it is inside the if. Stand still at 20 cm and the warning goes silent, which is exactly when you most want it.

Part 12

Say these out loud

Part 11 was the real test. This is a warm-up for it, and a list to come back to. Say each of these out loud, to somebody or to yourself, without looking anything up.

  • Say where the 29 and the 2 come from in the distance calculation
  • Say what a reading of 0 means, and name two things that cause it
  • Name three surfaces this sensor is bad at, and say why
  • Explain why a screen flickers, and give the two-part fix
  • Say why printing 99 over 100 shows 990
  • Say what to try first when a screen shows nothing at all
  • Install a library you do not already have, without help
The one sentence from this band

A measurement is a claim, and an unchecked claim is a guess with a number on it.

You checked yours against a ruler and found where it could be trusted and where it could not. Every device you build from here on deserves the same treatment, and most devices in the world never get it.

Still stuck after 30 minutes?

Photograph the board from above in good light, and photograph the screen itself showing whatever it is showing, even if that is nothing. Post both, plus one sentence on what you expected. Say which kind of screen you have. Nearly every screen question is answered by those two photographs together.

If there is nobody to send it toWrite the three things down anyway, in your build log: what you expected, what happened, and what you have already tried. Putting a problem into words solves a surprising number of them on its own. Then work down the problems table at the bottom of this page one more time, slowly. If it is still stuck, leave it until tomorrow and come back fresh. Do not sit and stare at it.
Problems

When something goes wrong

What you seeWhat it usually isWhat to do
Screen shows nothing at allContrastTurn the knob or the blue screw slowly from end to end. Do this first, every time. See Part 5.
Screen shows solid blocks on the top rowContrast, the other waySame knob, other direction. The screen is fine.
Backlight on, contrast done, still nothing (I²C)Wrong addressChange 0x27 to 0x3F and upload again.
Rectangles show but no words (bare)One of the six data wiresThe rectangles prove power is right. Check pins 4, 6, 11, 12, 13, 14 against the table.
Distance always 0Trig and Echo swapped, or nothing in rangePoint it at a flat wall 30 cm away first. Then check those two wires.
Distance stuck at one numberThe sensor is pointing at your own breadboard or a wireLook along the line of the two eyes and clear everything in the way.
Readings jump wildlyThe sensor is loose or tiltingFix it down. A sensor that moves measures a different thing each time.
Screen flickersclear() every roundSee Part 7. Write only when the value changed, and pad with spaces.
Old digits left on screenShort text over long textPad to a fixed width with spaces. See Part 7.
Text wraps onto the wrong lineMore than 16 charactersCount them, including your spaces.
LiquidCrystal_I2C not declaredLibrary not installedTools, Manage Libraries, search, install. See Part 6a.
Everything freezes for a second at a timeNo timeout on pulseInThe third value, 25000, is not optional. Put it back.
Done

What you know now

Your board can measure a distance now, and it can tell somebody about it without a computer in the room. Those two together are what a device is.

The more useful thing you learned is smaller and harder to see. You took a number your sensor gave you and you did not believe it until you had checked it against a ruler. Then you found the places it could be trusted and the places it could not, and wrote those down.

Most people never do that, and it is the difference between a project that works in a video and one that works in a room.

Before you move on, make sure you have

  • A video of somebody using your device, and a close photo of the screen with a real reading on it
  • Your completed ruler-accuracy table from Part 3, all five rows
  • Your notes on the three awkward surfaces, and the two distances you decided you would trust
  • Your completed beep timing table from Part 9b
  • Your four sixteen-character messages, counted
  • Your build log for this band
  • Five or six correct answers in Part 11, including question 2

Next is Band 8: Build for Nzemaland. The last band, and the only one with no new parts in it. You find a problem somebody actually has, decide beforehand what would count as solving it, and then find out honestly whether you did.

Ship it

One video under sixty seconds, and one post of five lines. The video is the same one this band already asks you for as evidence, so this is not extra work. It is the same work, done once, somewhere a person can see it.

Point the camera at: somebody using it, with the display readable on camera.

The four shots: three seconds of the thing sitting still, fifteen of you doing something to it, fifteen of it responding all the way to the end, and ten of the honest bit, which is your measurement or the wire that was wrong the first time.

The line worth writing in the post: your ruler-accuracy table, and where the sensor lied to you.

Show your work has the five-line template, a worked example, and the three checks to make before anything goes public. Tag it #BozomaBuilds so all nine of yours sit together.