LDR Modules

modules light

LDRs are an easy solution to react to brightness changes. Let's look at corresponding Arduino modules.

LDR Modules

LDR sensor modules allow to measure the intensity of ambient light by using a light dependent resistor (LDR). If you want to learn more about LDRs themselves, have a look at the LDR tutorial in the Circuit Basics series. We already used an LDR in an earlier tutorial to build a simple twilight switch. In this tutorial we will take a look at two modules that feature an LDR. The first is a threshold module. It allows to set a brightness threshold using a potentiometer and has a digital output that becomes active as soon as the light intensity is below the threshold. The second one is an analog one. It is basically a simple voltage divider circuit with an LDR. We will take a look at both of these modules and build an improved version of the twilight switch. Let's dive right in.

Threshold Module

Let's first look at the threshold module. Like many Arduino modules is available from various manufactures. Just have a quick search for 'Arduino LDR module' and I'm sure you'll find one that looks like the one I used. The module comes with an LDR, a potentiometer to set the threshold and a LM399 analog comparator. The latter determines whether the brightness is below the set threshold and sets the digital output accordingly. This makes this module really easy to use. In theory one could even use it without an Arduino, because it does all the work for you.

Let's start by connecting the module to the Arduino. The circuit is shown in the picture below. You have to connect the power pins marked GND and VCC with the Arduino's GND and 5V pins. Next we need to connect the modules digital output to one of the Arduino's pins. I chose pin 9. I additionally connected an LED to pin 8. We will turn on this LED ones the amount of ambient light falls below the threshold. Wiring of the LDR threshold module

There is not much to do in our Arduino program. In the setup procedure we set the correct pin modes. We use pin 8 as digital output to control our LED and pin 9 as a digital input to read the output value of the module. In the loop procedure we continuously check whether the output of the module is HIGH. If yes the ambient light level is below the threshold. In this case, we turn on the LED using digitalWrite. If not, we turn off the LED.

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, INPUT);
}

void loop() {
  if(digitalRead(9)) {
    digitalWrite(8, HIGH);
  } else {
    digitalWrite(8, LOW);  
  }
}

Once you uploaded the code to your Arduino, you should be able to turn on the LED by covering the LDR. You might want to adjust the threshold by turning the potentiometer. The video below shows our simple twilight switch in action.

There is an issue with our simple twilight switch. As shown at the end of the video, the output is unstable if the light intensity is close to the set threshold. The LED will start flickering. If this was a street light or a lamp in your house this would be really annoying. What can we about this? Well, we already had the same problem with the temperature threshold module. It can be solved by using different thresholds for turning the LED on and off. This is also called using a hysteresis. Sadly our module does not provide the option to set a second threshold and neither does it have an analog output which would enable us to implement this.

What are our options? Well, we cannot solve this problem properly, as we only have the digital output. There are some workarounds that might work out for you depending on your use case. Without gradual change of light intensity, there is no problem at all. In a light barrier for example, the brightness level should never be that close to the threshold. There should be two distinct states and one can pick a suitable threshold in between them. For this assumption to hold true one needs a sufficiently bright light source for the light barrier, which can be clearly distinguished from the ambient light. If there is a gradual change (e.g. sunset and sunrise), we need another solution. The easiest way is to read the output value at a really slow rate e.g. every 15 minutes. This way the LED won't flicker rapidly, as its state is only updated every 15 minutes. The critical light level probably won't last for 15 minutes. Last but not least, one can make up more creative solutions. We could e.g. detect that the output is not stable by checking if the output level is the same for a certain amount of time. We only react if the output was stable long enough.
Here is a code example that checks if the state is stable for at least one second:

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, INPUT);
}

int counter = 0;
int targetState = LOW;

void loop() {
  if(digitalRead(9) == targetState) {
    counter ++;
  } else {
    targetState = digitalRead(9);
    counter = 0;  
  }

  if(counter > 100) {
    if(targetState) {
      digitalWrite(8, HIGH);
    } else {
      digitalWrite(8, LOW);  
    }
  }
  delay(10);
}

The result is shown in the video. While we don't get a rapid flickering anymore, the LED state is still not stable. By closely watching the output LED on the module one can see that most of the state switches are ignored. If, however, the output is stable just long enough to pass our checks the main LED changes state too. We can prevent this by increasing the time the output has to be stable. If we overdo this, we end up with a complex solution that basically behaves similar to the much simpler version where we only check the output value every 15 min. Let's have a look how to properly solve this with an analog LDR module.

Analog Module

The KY-018 analog light sensor module features an LDR, a 10 kΩ resistor and an analog output. To connect it to the Arduino, wire 5V to the middle pin and GND to . The analog output S has to be connected to an analog input of the Arduino. I chose A0 for this task. The LED remains connected to pin 8. Wiring of the analog LDR module

As you can see in the schematic of the LDR module right next to the wiring diagram, the modules circuit is so simple that it can be easily built on a breadboard. This is what we did, when we used an LDR for our twilight switch in the tutorial on analog inputs. We can also use the code from there, if we make some adjustments. On the module the LDR and R1 are swapped with each other, compared to the circuit we build in the analog input tutorial. The consequence is that we get a lower voltage and therefore a lower ADC reading for brighter light. In the original code we turned on the LED if the ADC reading was below a certain threshold. With this module we need to turn on the LED if the ADC reading is above a certain threshold. Here is the adjusted code:

void setup() {
  pinMode(8, OUTPUT);
}

void loop() {
  int intensity = analogRead(A0);
  if(intensity > 150) {
    digitalWrite(8, HIGH);
  } else {
    digitalWrite(8, LOW);  
  }
}

You can see the behavior of our circuit in the video below. As you can see at the end of the video, we get the same unstable behavior, with the analog module, as well. This time we have more information, however. The ADC reading tells us that the brightness is close to the threshold value. We also have the freedom to pick a different threshold for turning the LED back on and implement a hysteresis by doing so.

Let's see what adjustments need to be done. We don't want turn off the LED in the else block anymore, instead we introduce a new if clause for the second threshold. In my case I used a threshold of 150 for turning the LED on and a threshold of 100 for turning the LED back off. If the ADC reading is in the unsure and possibly unstable area in between both thresholds, we simply do nothing and stay in the old state. The final code for the improved twilight switch looks like this:

void setup() {
  pinMode(8, OUTPUT);
}

void loop() {
  int intensity = analogRead(A0);
  if(intensity > 150) {
    digitalWrite(8, HIGH);
  }
  
  if(intensity < 100) {
    digitalWrite(8, LOW);  
  }
}

As you can see in the video below we don't get any flickering anymore. If the light is dimmed the LED will turn on at some point, but it won't turn off on slight brightness variances anymore. For the LED to turn off the brightness has to be raised above the second threshold. We finally got a clean solution and if the brightness changes rapidly, we get an instant response too. We don't have to wait for a several seconds or even 15 minutes.

If you still observe unstable behavior, adjust the threshold values and make sure that the two threshold values are not too close to each other.

Previous Post Next Post