ADC / Arduino Lab#
Wire a Sharp infrared distance sensor to an Arduino Due, apply the Objective 2.5 ADC math to the Due's own converter, then characterize and calibrate the sensor into a voltage-to-distance conversion good to ±0.5 cm — and prove it on distances you did not use to build it.
At a glance
Run at Lesson 22. Work in pairs — your partner must not be someone from your Project 1 group. Ideally only one of you has programmed a microcontroller before. You demo your working sensor to your instructor during the period and individually answer the questions in Gradescope; together they are worth 1 project point.
GenAI is authorized only up to Level 3 — use of GenAI as a feedback tool on student-generated work, as defined in the AW GenAI Policy. This is stricter than the course default. Excel, MATLAB, or a similar tool is permitted for the curve fit.
Lab Goal#
Block 2 has taken you from the frequency domain through filters, analog-to-digital conversion, and signal conditioning. Today you build the whole chain yourself and make it produce a number you can check against a ruler.
By the end of the period you will have a sketch that reads a Sharp infrared distance sensor and prints distance in centimeters, accurate to ±0.5 cm anywhere from 2 to 15 cm — and you will have evidence that it is that accurate, measured at distances you deliberately kept out of the calibration.
That accuracy claim is the whole lab. Getting a number out of the sensor takes ten minutes. Getting a number you can defend is the engineering.
Equipment#
Arduino Due development board and its mini-USB cable
Sharp GP2Y0A51SK0F analog infrared distance sensor — rated 2 cm to 15 cm, with a three-wire lead (white, red, black)
A ruler with millimeter marks
A flat target — a book cover, a notebook, or an index card taped to something that stands up on its own
Your laptop, with the Arduino IDE installed
Part 1 — What You Are Working With#
A microcontroller is a low-cost, single-chip computer. The microcontroller on your board is just the one large chip in the middle; everything else on the development board exists to make wiring and programming convenient. A product built around a microcontroller gets a custom board carrying only what that product needs. Microcontrollers are one kind of embedded system — the others you should know by name are FPGAs and ASICs, which trade development cost and flexibility against speed, unit cost, and hardware security. The Lesson 22 deck has the comparison table; we use a microcontroller here because it is cheap, fast to develop against, and power-efficient.
That is all the background you need to start wiring.
Part 2 — Wire the Sensor#
Connect the sensor’s three-wire lead to the Due:
Wire |
Pin on the Due |
What it carries |
|---|---|---|
White |
|
the sensor’s analog output — the signal you will measure |
Red |
|
power into the sensor |
Black |
one of the |
the ground return |
The sensor runs on 5 V. The Due’s analog pins do not.
The red lead goes to 5V because that is what the sensor needs to operate. Its output
is a different signal entirely: the white lead never rises above about 2.46 V, which is
safely under the Due’s 3.3 V analog input limit. That is the only reason a 5 V-powered
part is safe to read with this board.
Never wire the red 5 V lead into A0 or any other analog pin. The Due’s pins are
not 5 V tolerant — unlike an Arduino Uno’s — and putting 5 V on one destroys the board.
Check the white/red/black assignment against the table above before you plug in the USB
cable.
Part 3 — Set Up the IDE and Read Raw Counts#
Download and install the Arduino IDE from docs.arduino.cc/software/ide/.
Connect the Arduino to your laptop with the provided USB cable. Plug the mini-USB into the port labeled
USB Programming— the middle of the three connectors on that edge of the board, between the native-USB jack and the barrel jack. That port both powers the board and programs it. The other mini-USB jack cannot program the board — use it by mistake and you will spend the period wondering why nothing uploads.Launch the IDE and open the starter sketch,
DistanceSensor.ino.In the dropdown at the top of the IDE, select which board and which COM port you are using. It usually detects them for you; if it does not, ask your instructor.
Upload the sketch and open the Serial Monitor (the magnifying glass in the top right). Set it to 9600 baud.
You should see a new line every 2 seconds carrying a raw count and a voltage, and
d = ? where the distance will go. Move your hand toward and away from the sensor: the
numbers should move smoothly and repeatably. If they do not change at all, re-check the
white lead is in A0.
Where those two numbers come from#
The starter sketch runs Objective 2.5’s math on real hardware. analogRead() on the Due
defaults to 10-bit conversion over an input range of 0 V to 3.3 V, so:
Record that \(\Delta V\) — you will be asked for it in Gradescope.
The raw count analogRead() hands you is the quantization level from the reading:
and the sketch’s raw * 3.3 / 1024 simply runs that backward to recover the voltage. It
can only ever recover it to within one \(\Delta V\) — 3.22 mV of quantization error is the
noise floor under everything you do today.
Part 4 — Collect the Calibration Data#
The sensor gives you volts. You want centimeters. Nothing in the sketch knows how to get from one to the other yet, and nothing can until you measure it.
Set the ruler down with its zero at the front face of the sensor, stand your target upright on the ruler, and record the voltage the Serial Monitor prints at each distance below.
Use at least 8 fit distances spread across the full 2–15 cm range, and
at least 3 check distances that you will not use in the fit.
A good split — fit at 2, 3, 4, 5, 7, 9, 11, 13, 15 cm, check at 2.5, 6, 8, and 12 cm:
Role |
Distance \(d\) (cm) |
Measured \(V\) (V) |
\(1/V\) (V⁻¹) |
|---|---|---|---|
fit |
2 |
||
fit |
3 |
||
fit |
4 |
||
fit |
5 |
||
fit |
7 |
||
fit |
9 |
||
fit |
11 |
||
fit |
13 |
||
fit |
15 |
||
check |
2.5 |
||
check |
6 |
||
check |
8 |
||
check |
12 |
The sketch prints every 2 seconds. Wait for two or three prints at each distance and record a typical value rather than the first one you see — and keep the target square to the sensor, because a tilted target reflects less light and reads as farther away.
You should see the voltage fall as the target moves away, from roughly 2 V at 2 cm to roughly 0.4 V at 15 cm. It falls fast at first and then flattens out. That shape is the problem you are about to solve.
Stay inside 2–15 cm
Below about 1.5 cm the sensor’s output turns around and falls again — the curve on the specification sheet peaks near 2.46 V and then drops. A reading of 1.7 V could mean about 0.5 cm or 3.0 cm, and nothing in your data can tell you which. The 2 cm lower limit is not conservatism, it is where the sensor stops being a function.
Part 5 — Fit the Conversion, Then Plug It In#
Objective 2.6 gave you one linear map, \(v_{out} = K v_{in} + B\), and a method for finding \(K\) and \(B\) from two endpoints. You have never yet pointed it at a real transducer. Do that now — with one preparatory step.
The problem. Your \(V\)-versus-\(d\) data is not a straight line, so a straight-line fit cannot describe it. Fit a line straight through the raw pairs and it slices across the curve: on the sensor’s own published curve, fit at the nine fit distances from Part 4, that line is off by about −2.5 cm at 2 cm, +2.2 cm at 5 cm and −3.3 cm at 15 cm — four to seven times the spec, undershooting at the ends and overshooting in between. No choice of slope and intercept fixes that. It is the wrong shape.
The fix. Fit a straight line to transformed data instead. Add the \(1/V\) column to your table, then plot \(d\) on the vertical axis against \(1/V\) on the horizontal axis. Those points fall very nearly on a straight line, because the sensor’s output is close to proportional to the reciprocal of distance.
Fit that line the way Objective 2.6 taught you — from two endpoints — and then, if you have the tool, check it against a trendline:
which is exactly Objective 2.6’s \(v_{out} = K v_{in} + B\), with \(1/V\) as the input and distance as the output. \(K\) is your gain, in cm·V; \(B\) is your bias, in cm. Note that both now carry units the Lesson 21 versions did not: the same algebra is doing a different job here, converting in software behind the converter instead of conditioning a voltage ahead of it.
Start with the two-point method you already know
Use the Objective 2.6 machinery on your 2 cm and 15 cm rows: write \(2 = K(1/V_2) + B\) and \(15 = K(1/V_{15}) + B\), subtract to eliminate \(B\), solve for \(K\), then back-substitute. It is the same procedure as the thermocouple example, and on the sensor’s published curve it lands inside spec.
Then, second, a trendline over all nine fit points — Excel, MATLAB, or similar. Two points can only be fit exactly, so a two-point fit hands the whole job of absorbing measurement noise to two readings; a trendline fits the same straight line through all nine at once and averages that noise out. Expect the two-point fit to land near the ±0.5 cm limit and the trendline fit to beat it comfortably.
Sanity-check your constants before you type them in. \(K\) should come out somewhere around 5 to 8 cm·V and \(B\) somewhere between −2 and 0 cm. A \(K\) that is negative, or off by a factor of ten, means the axes went in backward — you plotted \(1/V\) against \(d\) instead of \(d\) against \(1/V\).
Now open the sketch and find this block:
// ====== PLUG IN (Part 5): YOUR CALIBRATION ======
const float CAL_K = 0.0; // cm * V
const float CAL_B = 0.0; // cm
// ================================================
Type your two constants in, complete the distanceCm() function just below it so it returns
CAL_K / volts + CAL_B, and upload. The d = ? in the Serial Monitor becomes a distance in
centimeters as soon as CAL_K is no longer zero.
Part 6 — Validate Against the Check Distances#
You now have a conversion that fits the data you built it from. That is not evidence it works — it is close to a tautology. How would you test your conversion? On distances it has never seen.
Put the target at each of your check distances — the ones you kept out of the fit — and record what the sketch now prints:
Check distance (cm) |
Sketch reports (cm) |
Error (cm) |
|---|---|---|
2.5 |
||
6 |
||
8 |
||
12 |
The spec: \(|\text{error}| \leq 0.5\) cm at every check point.
You should see errors of a few tenths of a centimeter, scattered in both directions. If one check point is badly off while the others are fine, re-measure it — a tilted target or a misread ruler is far more likely than a bad fit. If all of them are off in the same direction, your fit has a bias: check that you did not accidentally include a check point in the fit, and check the arithmetic on \(B\).
If you cannot meet spec, go back to Part 4 and re-take the readings that look least consistent. Do not adjust \(K\) and \(B\) by hand until the check points pass — a constant tuned to hit the check points has turned them into fit points, and you are back to having no evidence at all.
Record your maximum \(|\text{error}|\) across all check points. Gradescope asks for it.
Part 7 — Demo and Gradescope#
Demo to your instructor. Show the Serial Monitor printing live distances, and be ready to put the target at a distance your instructor picks and have it read correctly.
Individually answer the Gradescope questions. You will need your \(\Delta V\), your \(K\) and \(B\), your maximum check-point error, and your explanation of why the fit was done on \(1/V\).
Both partners keep a copy of the working sketch, with the constants in it. You need it at Lesson 26.
Submission Checklist#
Sensor wired white→
A0, red→5V, black→GND, checked before powerStarter sketch running and streaming raw counts and volts at 9600 baud
\(\Delta V\) for the Due’s ADC computed from \(2^b\) and the 0–3.3 V range
Calibration table filled in — at least 8 fit distances across 2–15 cm and at least 3 check distances held out
\(d\) plotted against \(1/V\) and a line fit to it
\(K\) and \(B\) recorded, sanity-checked, and typed into the sketch’s PLUG-IN block
distanceCm()completed and the Serial Monitor printing centimetersEvery check distance validated, errors recorded, max \(|\text{error}| \leq 0.5\) cm
Working sensor demonstrated to your instructor
Gradescope questions answered individually
Documentation statement — collaboration and any GenAI use
Both partners leave with a copy of the calibrated sketch
On to Project 2#
You leave today with working code that contains your calibration constants \(K\) and \(B\) and a
function distanceCm(). At Lesson 26 that function becomes the range channel of a
fire-control system: the Arduino watches the sensor and decides, on its own, when a target
has been detected and when it is inside the engagement envelope.
Those decisions are thresholds on distance — a detection gate at 12.0 cm and an
engagement envelope at 6.0 cm — so they are only ever as accurate as the calibration you
just built. A biased seeker declares in-range early. Half a centimeter of bias in
distanceCm() is half a centimeter of bias in every engagement decision Project 2 makes.
Files#
Starter sketch — DistanceSensor.ino