Digital ChallengeWorkshop · Arduino × Processing
L02Workshop lab

Light Meter — LDR

A resistor that sees.

Build a voltage divider with a photoresistor, read 0–1023 on A0, and turn classroom light into a live bar — the same circuit idea you will reuse for the ohm meter.

2 × 45 min difficultyPhysicsMathematicsComputer Science
Light Meter — LDR
Voltage divideranalogRead()map()Threshold LED
01Before you start

What you’ll learn

By the end of this lab you can…
  • 1Explain why an LDR alone cannot be read by Arduino — you need a second resistor.
  • 2Wire a voltage divider and predict whether more light raises or lowers the voltage at A0.
  • 3Convert analogRead (0–1023) to a voltage and to a bar width.
  • 4Add a darkness threshold that could drive an LED or a buzzer.
Key vocabulary
LDR / photoresistor
A resistor whose resistance drops when more light hits it.
Voltage divider
Two resistors in series. The middle tap is a fraction of the supply voltage.
analogRead()
Arduino function that samples A0–A5 as an integer 0–1023 (10-bit ADC, 0–5 V).
ADC
Analog-to-digital converter. 5 V / 1023 ≈ 4.9 mV per step.
map()
Processing (and Arduino) helper that remaps a number from one range into another.
02Kit list

Required equipment

ComponentQtyPurpose
Arduino Uno1ADC + serial
Photoresistor (LDR)1Light-dependent resistance
10 kΩ resistor1Fixed leg of the divider
Breadboard + jumpers1Prototyping
USB + both IDEs1Power, code, display
03Theory

Why two resistors?

Arduino’s analog pins measure voltage, not resistance. An LDR by itself is just a rubbery resistor — you have to turn that resistance into a voltage. The cheapest way is a voltage divider: LDR on the 5 V side, 10 kΩ down to GND, tap in the middle to A0.

Formula
V_A0 = 5 V × R_fixed / (R_LDR + R_fixed)
This matches the workshop wiring: LDR to 5 V, 10 kΩ to GND.

More light → R_LDR falls → a larger fraction of 5 V appears at A0 → analogRead climbs toward 1023. Cover the sensor with your hand and the number drops.

InteractiveVoltage divider labSweep the lux slider. Watch R_LDR, V_A0 and the Processing bar move together.
Fixed resistor
R_LDR
3.8 kΩ
V at A0
3.63V
analogRead
742
Light intensity: 742
Why 10 kΩ?
The divider is most sensitive when R_fixed ≈ R_LDR in the light you care about. Classroom LDRs are often a few kΩ in daylight and hundreds of kΩ in the dark. 10 kΩ is a good first guess.
04Hands-on

Build the divider

LDR + 10 kΩ voltage divider — workshop handbook figure.
LDR + 10 kΩ voltage divider — workshop handbook figure.
ConnectionGoes to
LDR leg 15V
LDR leg 2A0 and one leg of 10 kΩ
Other 10 kΩ legGND
Tip
The LDR has no polarity — either way around is fine. The 10 kΩ banded resistor does not either.
05Firmware

Arduino — one number, one line

LDR_Serial.inoArduino · C++
const int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int lightValue = analogRead(sensorPin); // 0 (dark) … 1023 (bright)
  Serial.println(lightValue);
  delay(200);
}

analogRead(A0) returns an integer. Serial.println adds the newline Processing is waiting for. 200 ms is about 5 samples per second — fast enough for a bar, slow enough to read.

06Visualise

Processing — number + bar

LightBar.pdeProcessing · Java
import processing.serial.*;

Serial myPort;
int lightLevel = 0;

void setup() {
  size(480, 220);
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\\n');
}

void draw() {
  background(245);
  fill(20);
  textSize(20);
  text("Light intensity: " + lightLevel, 40, 50);
  fill(0, 100, 255);
  rect(40, 90, map(lightLevel, 0, 1023, 0, 380), 36, 4);
}

void serialEvent(Serial p) {
  String val = trim(p.readStringUntil('\\n'));
  if (val.matches("\\\\d+")) {
    lightLevel = int(val);
  }
}
UpdatedUses serialEvent and rejects non-numeric junk so a debug line cannot crash the sketch.
07From the workshop

Student tasks

Basic
Wire the divider and watch Serial Monitor while you cover the LDR.
Numbers fall in the dark, rise in the light.
Basic
Show the value as text + bar in Processing.
The bar tracks your hand.
Intermediate
Turn the window background from black to white with the reading.
`background(map(lightLevel, 0, 1023, 0, 255))`.
Advanced
Add a threshold that would light an LED on the Arduino.
Digital pin goes HIGH when it is darker than your chosen value.
Challenge
Log light vs time and compare “next to the window” vs “under the desk”.
A CSV you can graph in a spreadsheet.
08When it doesn’t work

Troubleshooting

ProblemLikely causeFix
Value stuck near 0 or 1023.LDR and 10 kΩ swapped, or A0 not on the junction.LDR to 5V, 10 kΩ to GND, A0 at the join.
Barely changes.Wrong fixed resistor, or the LDR is in a plastic bag / facing the table.Point it at the room. Try 4.7 kΩ or 22 kΩ if you have them.
Jittery bar.Mains lights flicker at 100 Hz; ADC noise.Average 8 readings, or increase delay.
Golden rule
Check the physical connections first, then the code. If nothing works, unplug, close both programs, reconnect and try again.
09Student edition

Exercises

Basic · 1Intermediate · 3Advanced · 1Challenge · 1
L02-E1BasicPredict 5 min

Cover the sensor

Wiring: LDR to 5 V, 10 kΩ to GND, tap to A0. You cover the LDR with your palm. Does analogRead go up or down? Explain in two sentences.

More resistance on the top half of the divider means less voltage at the tap.
Down. Covering the LDR raises R_LDR. A larger top resistor drops more of the 5 V, so V_A0 (and the 0–1023 reading) falls.
L02-E2IntermediateCalculate 10 min

Voltage at A0

R_LDR = 4 kΩ, R_fixed = 10 kΩ, V_in = 5.0 V. Compute V_A0 and the expected analogRead (round to nearest integer).

V = 5 × 10 / (4 + 10). raw = round(V / 5 × 1023).
V_A0 = 5 × 10/14 = 3.57 V. raw ≈ 3.57/5 × 1023 = 731.
L02-E3IntermediateCalculate 6 min

ADC step size

Arduino’s ADC is 10-bit, 0–5 V. How many millivolts is one analogRead step? If the reading jumps from 400 to 401, how much did the voltage change?

5 V / 1023 ≈ 4.89 mV per step. A jump of 1 is about 4.9 mV.
L02-E4IntermediateDebug 8 min

The bar never moves

Processing shows “Light intensity: 0” forever. The Serial Monitor (when Processing is closed) shows numbers. Find the bug.

stuck.pdeProcessing · Java
void draw() {
  if (myPort.available() > 0) {
    String val = myPort.readStringUntil('\\n');
    lightLevel = int(val);
  }
}
int(null) and leftover \r will fail. Also, reading in draw can catch half a line.
readStringUntil can return null. Windows often sends \r\n, so int("412\r") is 0. Trim and guard. Prefer serialEvent.
serialEventProcessing · Java
void serialEvent(Serial p) {
  String val = p.readStringUntil('\\n');
  if (val == null) return;
  val = trim(val);
  if (val.matches("\\\\d+")) lightLevel = int(val);
}
L02-E5AdvancedCode 12 min

Night-light firmware

Add an LED on D8 (220 Ω to GND). Turn it on when lightValue < 350 and off otherwise. Keep sending the reading to Processing.

pinMode(8, OUTPUT); in setup. digitalWrite(8, lightValue < 350 ? HIGH : LOW);
LDR_NightLight.inoArduino · C++
const int sensorPin = A0;
const int ledPin = 8;
const int DARK = 350;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int lightValue = analogRead(sensorPin);
  digitalWrite(ledPin, lightValue < DARK ? HIGH : LOW);
  Serial.println(lightValue);
  delay(200);
}
L02-E6ChallengeDesign 15 min

Calibrate a classroom scale

You cannot trust 0–1023 as “percent brightness”. Write a 6-step procedure to calibrate your kit: record dark-desk, room, and window-sill readings, then decide how Processing should map those three numbers onto a 0–100 % scale.

1. Cover the LDR, average 20 samples → dark. 2. Point at the ceiling lights → room. 3. Hold at the window → bright. 4. In Processing, pct = constrain(map(lightLevel, dark, bright, 0, 100), 0, 100). 5. Label the bar with those three marks. 6. Recalibrate if you change the 10 kΩ or the room.
10Check yourself

Self-check quiz

Progress
0/5 answered · 0 correct
  1. Q01

    An LDR’s resistance when you shine a torch on it…

  2. Q02

    In this lab’s wiring, more light makes V_A0…

  3. Q03

    analogRead of 0 V is…

  4. Q04

    Why not connect the LDR alone from 5 V to A0?

  5. Q05

    A good first fixed resistor for a classroom LDR is…

11Beyond the classroom

Real world & extensions

Where this is used
Night-lightStreet lampPhone brightness sensorAlarm clock “is it morning?”
Extension ideas
  • +Drive an LED on D8 when lightValue < 300.
  • +Compare two LDRs (A0 and A1) and draw two bars.
  • +Use saveFrame() every 10 s for a time-lapse of the classroom.
Cross-curricular connections
SubjectConnection
PhysicsPhotoconductivity — photons free charge carriers in the semiconductor.
MathematicsInverse relationship (roughly): more lux, less ohms. Voltage is a rational function of R.
CSSampling: 5 Hz is enough for a hand wave, not for a strobe.
12Think about it

Reflection & conclusion

?1

Did covering the sensor with a notebook change the reading as much as covering it with your hand? Why might that be?

?2

If you swapped LDR and 10 kΩ, how would the “night-light” logic have to change?

?3

Name a product you own that secretly contains this circuit.

Conclusion

You turned resistance into voltage, voltage into a number, and a number into a picture. Lab 04 (ohm meter) is the same divider — you just solve for the unknown resistor.