Welcome to the analog world! This time we will create a twilight switch using a LDR and the analog input of our Arduino.
In the last tutorials we focused on digital inputs and outputs, this time we will take a look at the analog inputs of the Arduino Uno.
An Arduino has six analog input pins A0
to A5
, which can be used to measure voltages. The voltage is measured between the selected pin and GND
, whereby the maximum voltage that can be measured is around 5 V. As there is an infinite amount of different voltages between 0 V and 5 V we need some way of representing it. The way this works is that the analog value will be discretized as an integer between 0
and 1023
. 0
represents 0 V and 1023
represents 4.995 V. The component doing the measurement and the discretization is also called an analog to digital converter or for short an ADC.
If we wanted to, we could calculate the voltage by using the following formula:
\[ V_{Analog} = {{ADC \cdot V_{Ref}} \over 1024}\]
0
and 1023
There is also an internal 1.1 V voltage reference that could be used instead of the 5 V supply voltage. We will not cover look into it in this tutorial, but it might be helpful when dealing with an unstable supply voltage or for measuring the battery voltage.
What are we going to do? Today's task is to build a twilight switch. If it gets dark we want to turn on a light, in our case an LED. To create this twilight switch we will need a sensor to measure the light intensity. In this tutorial, we will use a light dependent resistor (LDR). The resistance of an LDR decreases with increasing light intensity. How do we measure this? Let's take a look at the circuit.
As usual, I have connected the LED in series with a 220 Ω resistor. The more interesting part is the circuit used to connect the LDR to the analog pin A0
.
The LDR and the fixed 10 kΩ resistor form a so-called voltage divider. To make it a bit clearer I included the circuit diagram for the relevant part of the circuit.
The voltage is measured in between of the two resistors. The total voltage difference is 5 V, but the voltage measured at A0
will only be a fraction of it depending on the resistance of the LDR. We can calculate this resistance, using the measured voltage and determine the light intensity. I will do a separate tutorial on voltage dividers and the accompanying math. At this point it is enough to conceptually understand what is going on.
If both resistors had the same value the voltage drop is the same for each resistor and we measure 2.5 V at A0
.
If the light is bright, the LDR will have a lower resistance than the fixed resistor and the measured voltage will be closer to 5 V. If there is no light, the LDR will have a very high resistance and the measured voltage will be close to 0 V.
For our twilight switch we don't need the actual resistance of the LDR. We don't even need the actual voltage at A0
. It is enough to know that the ADC reading will be somewhere between 0
and 1023
and that we get higher values for a high light intensity The only thing we need to do for our twilight switch, is to find a suitable threshold value at which it is dark enough to turn on the LED.
Writing the code is not that hard this time. We just need one new function:
analogRead(pin)
pin
: Analog pin to use for the measurement (A0
to A5
)0
and 1023
The next step is to find the threshold value. For this we make use of serial communication to transmit our raw measurements to the computer. We can look up the values in the serial monitor and can experiment until we find a suitable threshold value.
The code is simple: Just use analogRead(A0)
to read the voltage level, store the value in a variable and send it to the computer. The analog pin does not need to be initialized in a specialized way in the setup
procedure. We can use it directly.
void setup() {
Serial.begin(9600);
}
void loop() {
int intensity = analogRead(A0);
Serial.println(intensity);
}
Once you found the right threshold value, you can remove the code for the serial communication and add a condition, checking for the threshold value instead. If the light intensity is under the threshold we will turn the LED on, if not we turn it off. There is nothing more to say. It is really that simple.
void setup() {
pinMode(8, OUTPUT);
}
void loop() {
int intensity = analogRead(A0);
if(intensity < 850) {
digitalWrite(8, HIGH);
} else {
digitalWrite(8, LOW);
}
}
I made a short video to show you the final result. Of course, you need to find your own threshold value appropriate for your use case. Mine is most likely way to high because I used an extra light while filming. That was easy, wasn't it? The same method will work as well for any other resistance based input like temperature sensors or potentiometers. Therefore, you have a lot to experiment with after this tutorial. Just one last hint, depending on the resistance value you measure you might need to adjust the fixed resistor as well and of course find the suitable threshold again. Of course, we do not get any absolute values here. For temperature sensors it would be nice to have values in °C. I'm sure we will dig into that in one of the future tutorials.