Sensing the light

Electronics theory

Fig. 1: Analog signals make take on arbitrary values, whereas digital signals are restricted to just two states.

Fig. 1: Analog signals make take on arbitrary values, whereas digital signals are restricted to just two states.

The Arduino contains a voltage meter called an analog-to-digital converter. This instrument measures the voltage between an analog pin (A0 .. A5) and ground.

The analog-to-digital converter does not work in units of volts. Instead it uses integers in the range of 0 to 1023. The significance of this range is that the Arduino uses 10 binary digits to represent analog values, and there are 1024 unique combinations of 10 binary digits (\(2^{10} = 1024\)).

The relationship between the voltage and the analog-to-digital converter output is given by $$v = n \times \frac{5}{1023},$$ where \(v\) is the voltage and \(n\) is the integer value returned by the analog-to-digital converter.

Light sensor theory

A light dependent resistor (LDR) is a light sensor that acts like a resistor. The resistance varies with the amount of light that shines onto it.

An Arduino cannot measure resistance directly, but it can measure voltage. Therefore we need a circuit whose voltage is related to the resistance of the sensor. Such a circuit is called a voltage divider.

Fig. 2: Schematic layout for LDR circuit.

Fig. 2: Schematic layout for LDR circuit.

In the circuit shown above in Fig. 2, the voltage on pin A0 is related to the resistances of R2 and R3 via the equation $$V_{A0} = 5\times\frac{R_3}{R_2 + R_3}.$$


We will use a light dependent resistor (shown below) to create an analog signal to measure.

Build the circuit of Figs. 2 – 3 on your breadboard:

Fig. 3: Breadboard layout for LDR circuit.

Fig. 3: Breadboard layout for LDR circuit.


TYpe the following code into the Arduino IDE. Don’t forget to save your code into a new file so that you don’t overwrite your previous work.

void setup() {
  // put your setup code here, to run once:
  // Set the baud rate

void loop() {
  // put your main code here, to run repeatedly:

  // Create an integer variable called "ldr"
  int ldr;

  // Create a floating point variable called "voltage"
  float voltage;

  // Read from pin A0
  ldr = analogRead(A0);

  // Tell the user what value we read
  Serial.print("Analog value: ");

  // Calculate the corresponding voltage
  voltage = ldr * 5.0 / 1023.0;
  Serial.print("Voltage: ");

  // Delay

Topics for workshop discussion


Add in a flashing LED (as per Lesson 3). Adjust the code such that the LED flashes at different speeds depending upon the light incident upon the sensor.

Extension topics

The value of the fixed resistance (R3 in Fig. 2) depends upon the properties of the LDR. Ideally you want \(R_2 \approx R_3\) near the midpoint of the range of light intensities that you expect to measure. You can check this for any particular LDR using a multimeter to measure its resistance under typical illumination.

If \(R_3\) is poorly matched to the particular sensor, the range of achievable voltages will be small and the measurement precision will be poor. Mathematically minded people might be interested in considering the limiting cases of \(R_3 \to 0\) and \(R_3 \to \infty\) in the voltage divider equation $$V_{A0} = 5\times\frac{R_3}{R_2 + R_3}.$$

This work is licensed under a Creative Commons Attribution 4.0 International License. For comments or corrections, please contact