Cheap Alternative for Hard to Find CDS Light Sensor


CdS (Cadmium Sulfide) photo-resistors are commonly used for detecting light levels. Their resistance varies considerably depending on the intensity of light striking them. They are common, fairly cheap and easy to use. So what’s the problem? They are becoming hard to find. The reason is because of the RoHS directive. Since CdS cells contain cadmium, a toxic heavy metal, this important component is no longer stocked by major electronics distributors. The good news is that not only is there an excellent alternative, but it is more versatile and vastly cheaper.

If you guessed photo-diode you are close, but even better is the humble LED. If you are building an analog circuit, then you will be limited to photo-diodes and photo-transistors due to their greater sensitivity. If, however, you are building a micro-controller based circuit such as a PIC or Arduino, then you can use a simple LED to achieve the same end and even more.

Photo-diodes and LEDs

Both of these devices are essentially the same. Both are diodes enclosed in a translucent case. They will both permit a small amount of reverse current to flow through them when they are reversed biased. The difference is that the photo-diode is optimized for photo-sensitivity while the LED is optimized for its light emission when forward biased. Why then would anyone want to use the LED which is inferior as a photo-detector? There are several excellent reasons:

  • You probably have lots of LEDs already in your parts boxes
  • They are really cheap – only a few pennies whereas photo-diodes cost 50 cents or more
  • You can make use of their spectrum filtering capabilities that photo-diodes have less choice over
  • You can both emit light and sense it at the same time (almost) which leads to a whole slew of applications such as varying output intensity with light levels, bi-directional communication with a single device, etc.

The reason we need to use a micro-controller with LEDs is because their reverse current is so small that we need to use a special property of LEDs in order to make them do double duty as a light sensor. Making use of this property requires a micro-controller.

Using LEDs for Light Sensing

Like many electronic components, LEDs have a small amount of parasitic capacitance associated with them. While normally such properties are a potential problem, in our case, we can use it to make it into a photo-detector. Here’s how.

LED as a photo-sensor

LED as a photo-sensor

Hook up the LED in reverse, connecting the cathode to the micro’s pin, and the anode to ground as shown in the diagram on the left. If the pin is set to output-high, it will charge the LED’s parasitic capacitor. It only takes a millisecond or less for this to happen, so the charging procedure is very fast.

Next, set the pin to input-low which allows the LED to discharge its capacitor. The rate of its discharge is proportional to the amount of light reaching the LED. Under direct lighting, it only takes a millisecond or so to discharge enough to trigger the input low. In dark conditions, it can take a few seconds for it to discharge enough to trigger the input pin.

By measuring the time it takes the LED to discharge, we can tell how much light it is detecting. The amazing thing is we can do this measurement with only one pin, and a digital pin at that! By connecting the cathode to another pin (with a series resistor to limit the current), we can also illuminate the diode when we are not using it to sense light. You can use this technique to not only make the LED’s brightness in proportion  to the ambient light level, but even use it for bi-directional communication.

There is another property of using the LED for measuring light levels, and that property is color spectrum filtering. What that means is that the LED responds to light only within a particular color spectrum. This property can be a problem or an opportunity depending on what you want to do. LEDs will only respond to light frequencies (i.e. colors) that are equal to or higher than that frequency that the LED emits at. Therefore, if you want to sense daylight levels, you should use a red or yellow LED. If you want to measure only the blue through ultra-violet spectrum, then you can use a blue LED for that measurement. You also need to take into account the color of the LEDs packaging. If you use a red LED within a red case, you will only measure red light. Ditto with any other color. To summarize, LEDs act as a high-pass light filter when detecting, but their package is a narrow band-pass light filter for that particular color. You can use this property to measure individual colors, but that is really best done with specialized light sensor chips. The LED is best for cheap, readily available ambient light sensing and communication. For ambient light sensing, red and yellow LEDs are best, and make sure you use ones in clear cases.

Putting It Into Practice

To put the theory into practice, you need just an LED and a micro-controller. For this article, we will use an Arduino-based micro. Here is a simple class written just for this purpose:

class AmbientLightSensor {
  AmbientLightSensor(int ledPin) : mLedPin(ledPin), mMeasureAnalog(false) {}

  void setAnalogMeasurement(int thresholdLevel); // measure from an analog pin
  void setDigitalMeasurement(); // measure from a digital pin (default)

  int measure();

  int mLedPin;
  bool mMeasureAnalog;
  int mAnalogThresholdLevel; // (0 to 1023)

  void charge();
  void discharge();

  int measureUsingAnalogPin();
  int measureUsingDigitalPin();

void AmbientLightSensor::setAnalogMeasurement(int thresholdLevel)
  mAnalogThresholdLevel = thresholdLevel;
  mMeasureAnalog = true;

void AmbientLightSensor::setDigitalMeasurement()
  mMeasureAnalog = false;

void AmbientLightSensor::charge() {
  // Apply reverse voltage, charge up the pin and led capacitance
  pinMode(mLedPin, OUTPUT);
  digitalWrite(mLedPin, HIGH);

void AmbientLightSensor::discharge() {
  // Isolate the diode
  pinMode(mLedPin, INPUT);
  digitalWrite(mLedPin, LOW); // turn off internal pull-up resistor, see

int AmbientLightSensor::measure() {
  delay(1); // charge it up
  return (mMeasureAnalog)? measureUsingAnalogPin() : measureUsingDigitalPin();

int AmbientLightSensor::measureUsingDigitalPin() {
  long startTime = millis();
  // Time how long it takes the diode to bleed back down to a logic zero
  while ((millis() - startTime) < 2000) { // max time we allow is 2000 ms
    if ( digitalRead(mLedPin)==0) break;
  return millis() - startTime;

int AmbientLightSensor::measureUsingAnalogPin() {
  long startTime = millis();
  // Time how long it takes the diode to bleed back down to a logic zero
  while ((millis() - startTime) < 2000) { // max time we allow is 2000 ms
    if ( analogRead(mLedPin) < mAnalogThresholdLevel) break;
  return millis() - startTime;

To use the class, the code is simple. Here’s an example:

AmbientLightSensor led(12); // LED is hooked up to digital pin 12

int led2 = 9; // led to indicate darkness is hooked up to digital pin 9

void setup()

void loop()
  int ledVal; ledVal = led.measure();
  if (ledVal > 300) // a decent level of darkness
    digitalWrite(led2, ON);
    digitalWrite(led2, OFF);

  delay(200); // check every 0.2 secs

Other Concerns

When sensing low light levels, using a digital pin for discharge threshold detection can take a significant amount of time – several tenths of a second or more. For this reason, the AmbientLightSensor class also permits using an analog pin which uses analogWrite to detect the discharge threshold. With the digital pin, the threshold voltage is fixed by the physical characteristics of the device. By using an analog pin, we can detect a sufficient amount of discharge much more quickly by setting this voltage higher. To use an analog pin, the code is similar, but in your setup function insert this line:

led.setAnalogMeasurement(512); // maxes at about 300 (fully dark)

I have found an analogRead level of 512, which corresponds to 50% of Vcc limits the discharge time in the dark to about 300 milliseconds, which still giving a good range of sensitivity. You can of course, vary this level to suit your particular application.

When the LED is used solely as a photo-detector, you do not need a current limiting resistor. If you desire to use it also as a light emitter, then you will need to add one in. The resistor itself is only for the forward biased state. It does not affect the reverse-bias detection operation.


You are now armed with the tools you need to use an LED you have lying around to replace the need for a difficult-to-find CdS photo resistor. Even if you have no trouble sourcing CdS cells, it is now clear that LEDs are cheaper (by about 10 times) and easier to use. In most applications, you don’t even need an analog pin, but only a digital one. The code is simple as we have seen, and is easy to use and modify to suit your particular needs. Lastly, you have not only a simple, inexpensive solution, but the possibility of novel applications as well.

Please share your comments and applications for using LEDs for photo-detection in the comments below.

Cheap Alternative for Hard to Find CDS Light Sensor by Provide Your Own is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

This entry was posted in Tech and tagged , , , . Section: . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.