Module 8 - Sensors & Calibration

23. Resistive Sensors, Dividers & the LDR

Turn a resistance change into a voltage the ADC can read, calculate sensor resistance from counts, and switch reliably on light level with hysteresis.

Estimated time 2-3 hours

Learning outcomes

  • Explain why a resistive sensor needs a fixed resistor to form a voltage divider
  • Wire an LDR divider into an analogue pin in the course order (fixed resistor to 5 V, sensor to GND)
  • Calculate sensor resistance from an ADC reading and check it with a multimeter
  • Choose a fixed resistor that gives useful sensitivity at the light level you care about
  • Switch an output with separate ON and OFF thresholds so it does not chatter

Parts and preparation

Uno, LDR, 10 kΩ fixed resistor, LED with 330 ohm resistor, breadboard, jumper wires and a multimeter.

Before power: inspect wiring, confirm supply voltage and ensure all connected circuits share GND.

Resistive Sensors, Dividers & the LDR instructional connection diagram

Why resistive sensors need a voltage divider

Arduino analogue pins measure voltage (0 to about 5 V on an Uno), not resistance. An LDR or an NTC thermistor only changes resistance. Place the sensor in series with a known fixed resistor and the mid-point voltage becomes a fraction of the supply that follows the sensor. That mid-point goes to an analogue pin.

This is the same divider idea as the potentiometer in Lesson 14, except one half is fixed and the other half is the sensor.

What changesWhat the Uno measuresWhat you calculate
Sensor resistance (ohms)ADC count 0-1023 (voltage)Resistance, then a threshold or a temperature
Wiring order and RfixedDirection of the readingWhich formula to use

How an LDR works

An LDR (Light Dependent Resistor), usually a cadmium sulphide (CdS) cell, changes resistance with illumination. In the dark it can be megaohms; in bright light a few hundred ohms.

Light frees charge carriers in the photoconductive material, so resistance falls. LDRs are slow (tens to hundreds of milliseconds) and strongly nonlinear, so this course uses them for dark / bright decisions rather than calibrated lux.

Graph showing LDR resistance falling from megaohms in the dark to low ohms in bright light
LDR behaviour: dark → high R; bright → low R. Use thresholds and hysteresis rather than a linear lux scale.
ConditionTypical LDR resistance (order of magnitude)
Dark / coveredHundreds of kΩ to MΩ
Indoor room lightLow kΩ range (part-dependent)
Bright / near a lampHundreds of ohms

Divider calculation (course wiring)

Course wiring puts the fixed resistor to 5 V and the sensor to GND:

5 V → 10 kΩ → junction to A1 → LDR → GND

Junction voltage: Vout = 5 V × Rsensor / (Rfixed + Rsensor). The ADC maps about 0-5 V to 0-1023, so the sensor resistance is:

Rsensor = Rfixed / (1023.0 / ADC - 1.0)

With this order, a darker room raises the LDR resistance, raises Vout and raises the ADC count. Swap the two parts and both the direction and the formula change - always match the code to the physical order.

Schematic of 5 V through a 10 kilohm resistor to an analogue pin, with the sensor from the junction to ground
Course divider: fixed resistor to 5 V, sensor to GND, mid-point to the analogue pin.
ADC readingRough meaning (10 kΩ to 5 V, sensor to GND)
Near 0Junction near GND - shorted sensor, open fixed resistor, or very low Rsensor
Near 512Rsensor ≈ Rfixed (about half of 5 V)
Near 1023Junction near 5 V - open sensor, broken GND side, or very high Rsensor

Worked resistance example

Rfixed = 10000 Ω and analogRead returns 768.

Rsensor = 10000 / (1023.0 / 768 - 1.0) = 10000 / 0.332 ≈ 30 100 Ω - a fairly dim room for a typical LDR.

Vout = 768 / 1023 × 5 V ≈ 3.75 V. Measure the junction with your multimeter: if it reads 3.75 V but Serial shows a very different count, suspect the code or the pin, not the sensor.

If ADC is 0 or 1023, do not use the formula - it divides by zero or gives nonsense. Treat those readings as a wiring fault.

Choosing the fixed resistor

The divider is most sensitive when Rfixed is close to the sensor resistance at the light level you want to detect. Measure the LDR with the multimeter (power off) in the two conditions that matter, then pick a standard value between them.

A 10 kΩ resistor suits most indoor dark / bright decisions. Detecting dusk outdoors may need 100 kΩ; detecting a bright lamp may need 1 kΩ.

LDR in the condition you care aboutGood RfixedEffect
About 1 kΩ (bright)1 kΩLarge ADC change near bright light
About 10 kΩ (room light)10 kΩLarge change around normal room light
About 100 kΩ (dusk)100 kΩLarge change as it gets dark

Thresholds and hysteresis

Set thresholds by experiment: cover the LDR and note the count, uncover it under room light and note the count, then choose values between them.

A single threshold chatters: noise near that value flips the output on and off many times a second. Hysteresis uses two thresholds - switch ON above one value, switch OFF only below a lower one. The gap between them must be larger than the noise you see in Serial.

Comparison of a single threshold causing rapid output chatter versus separate ON and OFF thresholds giving a stable output
Two thresholds with a gap absorb noise so the output does not chatter.
const int darkOn = 700;     // count rises above this: dark
const int brightOff = 600;  // must fall below this to switch off
bool lampOn = false;

if (!lampOn && raw >= darkOn) {
  lampOn = true;
} else if (lampOn && raw <= brightOff) {
  lampOn = false;
}

Check it with the multimeter and scope

Measure the junction voltage with the multimeter while Serial prints the count. Predict the count as V / 5 × 1023 and compare - they should agree within a few counts. A disagreement points to a wrong pin in the sketch or a supply that is not really 5 V.

On the oscilloscope (DC coupling, 1 V/div) the junction is a steady level that moves as you shade the sensor. Under mains lighting you may see a small 100 Hz ripple: that is the lamp flicker, and it is one reason readings wobble near a threshold.

Wiring and safe build sequence

Breadboard wiring for 23. Resistive Sensors, Dividers & the LDR
Breadboard layout for this lesson. Match colours and pins before powering the circuit. Click the image for a larger view.
  1. 5 V -> 10 kΩ -> A1 junction -> LDR -> GND
  2. D9 -> 330 ohm -> LED anode; LED cathode -> GND (night-light output)
  3. Multimeter COM to GND, V to the A1 junction for the calibration check
Power rule: switch off before moving wires. Arduino I/O pins are control signals; high-current loads require a driver and suitable external supply.

Worked sketch: night light with hysteresis

Download .ino sketch
const byte ldrPin = A1;
const byte lampPin = 9;
const float seriesR = 10000.0;   // fixed resistor to 5 V
const int darkOn = 700;          // switch the lamp on above this count
const int brightOff = 600;       // switch it off only below this count

bool lampOn = false;
unsigned long lastReport = 0;

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

void loop() {
  int raw = analogRead(ldrPin);
  if (raw <= 0 || raw >= 1023) {
    digitalWrite(lampPin, LOW);
    Serial.println("Divider fault");
    delay(500);
    return;
  }

  if (!lampOn && raw >= darkOn) {
    lampOn = true;
  } else if (lampOn && raw <= brightOff) {
    lampOn = false;
  }
  digitalWrite(lampPin, lampOn);

  if (millis() - lastReport >= 500) {
    lastReport = millis();
    float resistance = seriesR / (1023.0 / raw - 1.0);
    Serial.print("ADC ");
    Serial.print(raw);
    Serial.print("  R ");
    Serial.print(resistance, 0);
    if (lampOn) {
      Serial.println(" ohm  lamp ON");
    } else {
      Serial.println(" ohm  lamp OFF");
    }
  }
}

How the code works

  1. The divider order (10 kΩ to 5 V, LDR to GND) makes the count rise as it gets darker.
  2. darkOn and brightOff are separate, so the lamp does not flicker when the light sits near one value.
  3. Readings of 0 or 1023 are treated as a wiring fault and switch the lamp off.
  4. The Serial report runs every 500 ms with the millis pattern, so the lamp still responds instantly.

Calibration logger: ADC and resistance

Download .ino sketch

What this sketch is for: Run this first to choose your thresholds. It prints the raw ADC count and the calculated LDR resistance twice a second - cover and uncover the sensor and write the numbers in your logbook.

const float seriesR = 10000.0;  // fixed resistor to 5 V

void setup() {
  Serial.begin(9600);
  Serial.println("LDR on A1 (10k to 5 V, LDR to GND)");
}

void loop() {
  int raw = analogRead(A1);
  if (raw <= 0 || raw >= 1023) {
    Serial.println("Divider fault");
    delay(500);
    return;
  }

  float resistance = seriesR / (1023.0 / raw - 1.0);

  Serial.print("ADC ");
  Serial.print(raw);
  Serial.print("  R ");
  Serial.print(resistance, 0);
  Serial.println(" ohm");
  delay(500);
}

How the code works

  1. Formula matches course wiring: 5 V -> 10 kΩ -> A1 -> LDR -> GND.
  2. Record covered, room-light and bright readings, then set darkOn and brightOff between them.
  3. delay() is fine here - this sketch only logs, it does not control anything.

Test and record evidence

Expected result: Covering the LDR raises the count; the LED switches on above 700 and stays on until the count falls below 600. Serial prints ADC, resistance and lamp state twice a second, and the multimeter junction voltage agrees with ADC / 1023 × 5 V.

Practical evidence checklist

Common faults and checks
  • Count moves the wrong way when you cover the LDR: the resistor and LDR are swapped - match the course order or invert the thresholds.
  • Lamp flickers near the switching point: widen the gap between darkOn and brightOff beyond the noise you see in Serial.
  • ADC stuck at 0 or 1023: open wire, missing GND or a short across one half of the divider.
  • Counts change very little between dark and light: choose a fixed resistor closer to the LDR resistance in the condition you care about.
Extension challenge: Replace the fixed thresholds with a calibration step: at start-up, read the room for two seconds, then set brightOff to that average plus 50 and darkOn to plus 150.

Check your understanding

Q1. Why does an LDR need a fixed resistor to be read by an Uno?

Show answer

The ADC measures voltage; the LDR only changes resistance, so a divider converts it to a voltage.

Q2. With 10 kΩ to 5 V and the LDR to GND, does the count rise or fall as it gets darker?

Show answer

It rises - the LDR resistance increases, so the junction voltage rises.

Q3. What is Rsensor for this wiring?

Show answer

Rsensor = Rfixed / (1023.0 / ADC - 1.0).

Q4. How do you choose Rfixed for best sensitivity?

Show answer

Pick a value close to the sensor resistance at the light level you want to detect.

Q5. Why use two thresholds instead of one?

Show answer

The gap (hysteresis) stops noise near the switching point from making the output chatter.