Using LEDs as a light/dark sensor

When I found this site I searched this forum for some info and found none . So I thought to post it here as it works well and gets rid of the Cds LDR
http://provideyourown.com/2011/cheap-alternative-for-hard-to-find-cds-light-sensor/

Here is an example of its use,Reversed LED to Sense on D2 no resistor ,LEDs on 5&6 normal resistors

class AmbientLightSensor {
public:
  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();
 
protected:
  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 http://arduino.cc/en/Tutorial/DigitalPins
}
 
int AmbientLightSensor::measure() {
  charge();
  delay(1); // charge it up
  discharge();
  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;
}
//8888888888888888888888888888888888888888888888888888888888888888888888888888888
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
   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
  int ledVal = led.measure();
  
  if (ledVal >300) {// a decent level of darkness
    digitalWrite(led2, HIGH);}
  else{
    digitalWrite(led2, LOW);}
 
  delay(200); // check every 0.2 secs

  // read the input on analog pin 5:
  int sensorValue = analogRead(A5);
  // print out the value you read:
  Serial.println(sensorValue);
  Serial.println(ledVal);
  
  analogWrite(6 ,( map(5,0,150,0,1023)));//( map(5,0,200,0,1023))
  delay(500);        // delay in between reads for stability
  if (sensorValue <400 && ledVal <10){
    analogWrite(5 , HIGH);
    analogWrite(6 ,( map(A5,0,150,0,1023)));
    delay(3000);
   analogWrite(5 , LOW); 
  } 

}

The original idea came from Mitsubishi lab and you can google the article.

There are quite a few ways to implement it, depending on your hardware availability.

I pay 7 US cents for CDS sensors here from a retail shop ?

But then I read about the RoHS aspect, which will eventually take over here in Africa ( we still have flaky unpainted asbestos roof sheets all over the place as an example )

dhenry:
The original idea came from Mitsubishi lab and you can google the article.
There are quite a few ways to implement it, depending on your hardware availability.

I googled that site but did not get anything specific . I wonder if you remember anything else about the article ,as I would like to read it ,thanks

I feel sure Grumpy_Mike has done something on this with example video of using LED's as switches/lights.

He has - LED Sensing

The class is in th first post .Put it in your program and then put the one line in the loop and you are doing it -pretty short and sweet . Grumpy Mikes is a nightmare to understand (excuse me Mike)

Boffin1:
I pay 7 US cents for CDS sensors here from a retail shop ?

But then I read about the RoHS aspect, which will eventually take over here in Africa ( we still have flaky unpainted asbestos roof sheets all over the place as an example )

Funnily enough some truths on asbestos have been conveniently lost.
It was the blue asbestos product that was causing the trouble . It has tiny hooks on the fibers when magnified which hook into and stay in the lungs.Grey asbestos gave no known problems unless you were silly with it. The hooks were much smaller as were the fibers.Roof sheets are grey asbestos and fine sand and cement and I would use them anytime. So were the "fibro" sheets used on the outside and inside house walls. Now they use a cellulose fibre ,fine sand and cement instead.and warn you of the silica dust . Ho hum

So much money to be made by hyping up the asbestos problem , they just don't bother telling you the truth.

Try this: http://www.merl.com/papers/docs/TR2003-35.pdf

and this: http://www.altera.com/literature/wp/wp-01076-led-driver-reduces-power-adjusting-intensity-ambient-light.pdf

they just don't bother telling you the truth.

It isn't about telling the truth. It is about "how can I benefit from that?".

dhenry:
Try this: http://www.merl.com/papers/docs/TR2003-35.pdf

and this: FPGA Documentation Index

Thats good info right there - Thanks

I have just finished a program using this method. I tested to see what size difference it made .
On a tiny85 with 8192 bytes of space on the flash this method used 526 bytes and using a LDR used 442 bytes so this method adds 84bytes only. I was very impressed with that !

I would think it should take far less than that to implement, 100 - 200 bytes maybe? Maybe your figures contain overhead?

Well I have to pay my expenses somehow.
I simply removed the function call to calculate this but I left the class definition in the code as I did not think that would affect things .It has to turn the pin on ,charge it for a millisecond ,turn the pin off and measure the discharge time to get a reading.

The other approach is to charge up the capacitive sensor, and then perform an adc on it. The Chold in the adc will cause the voltage to drop a little - charge transfer effect. The lower the capacitance of the sensor, the more the voltage drops. That forms a basis for sensing if the sensor has been touched.

This week I spent some time messing around with an led light sensor. Hopefully someone will find the attached code useful, or, pardon the pun, enlightening...

/* LED_LIGHT_CONTROL_IBLE
 * -----------------------
 * This program uses separate led's for light and sensing light.
 * Works with room ambient or daylight.
 * LED light sensing modified from Hunter's Instructible. Acheives sharp
 * cut off and on according to "int light = X". Could also fade lights
 * in/out on analog pins.
 *
 * Hunter Carlson
 * June 9 2009
 * Edits added Nov. 9, 2012 -fabelizer
 *
 * Requires at least 2 (or 3 or more) LEDs, one to analog pins 4 & 5, other
 * to D8 & GND through a resistor. I used a water clear superbright
 * red led for the sensor led, white for led1. 
 * See comments below for polarities and connections.
 */

int sense01 = 5;        // sensing LED anode connected to analog pin5
int sense02 = 4;        // sensing LED cathode connected to analog pin4
                        // you can switch out different leds on these
                        // pins to see which works best. Run the
                        // serial monitor and watch the changes.
                                                
int LED01 = 8;          // LED anode to dig pin8, cathode to 220R
                        // 220R to GND.
int LED02 = 9;          // LED anode to dig pin9, cathode to 220R
                        // 220R to GND.
                       
int val01 = 0;          // variable to store the value read from sense01
int val02 = 0;          // variable to store the value read from sense02

int light1 = 110;       // set light threshold for led1
int light2 = 80;        // set light threshold for led2

void setup()
{
  Serial.begin(9600);        // setup serial (comment out to save memory)
  pinMode(LED01, OUTPUT);    // led1 pin set to output
  pinMode(LED02, OUTPUT);    // led2 pin set to output
}

void loop()
{
  val01 = analogRead(sense01);      // read sense01 led
  val02 = analogRead(sense02);      // read sense02 led
  
   //debug print
  Serial.print(val01              // comment this section out to save memory
  Serial.println(val01-val02);    // result is printed and compared with light1 or 2 
  Serial.println();               // blank line between values
  
                                    // first led 'led1'
 if ((val01 - val02) >= light1) {   // check if light in area
      digitalWrite(LED01, LOW);     // if light enough, turn off led1
    } else {                      
      digitalWrite(LED01, HIGH);    // if dark enough, turn on led1
    }
    
                                    // second led 'led2'
 if ((val01 - val02) >= light2) {   // check if light in area
      digitalWrite(LED02, LOW);     // if light enough, turn off led2
    } else {                      
      digitalWrite(LED02, HIGH);    // if dark enough, turn on led2
    }
    
delay(100);                         // just to slow things down a bit

}

enjoy!
-fab

Hmm I'm working on something similar atm
Using this page

With a 4 LED setup and this code I am getting some results but not anything I can use reliably yet.
I am finding a noticeable difference in the red LEDs compared to the water clear superbright .
The water clear superbright gives pretty good results with up to a half inch separation between the LEDs

I will try your setup Thanks

My Code at present for testing

const int led1 = A2;
const int led2 = A1;

int value1, value2;
int threshold1 = 120;
int threshold2 = 120;

void setup(){
  Serial.begin(9600);
  pinMode(led1,INPUT);
  pinMode(led2,INPUT);
  }

void loop(){
  value1 = analogRead(A2);
  value2 = analogRead(A1);
  if(value1 >= threshold1){
    Serial.print("Value 1 : ");
    Serial.println(value1);
    out(led1,led2,threshold1);
    pinMode(led2,INPUT);
   
  }
  else if(value2 >= threshold2){
    Serial.print("Value 2 : ");
    Serial.println(value2);
   
    out(led2,led1,threshold2);
    pinMode(led1,INPUT);
   
  }
}

void out(int a, int b, int threshold){
  pinMode(b,OUTPUT);
  //if (a==led2)
  //delay(30);
  //else
  //delay(60);
  int value = analogRead(a);
    if(value >= threshold){
      analogWrite(b,value);
         }
    else{analogWrite(b,0);    }
     Serial.print("Value Following: ");
    Serial.println(value2);
  }

I'm getting huge differences in different types of LED's
The small 3 mm seem unuseable if I have them on extension wires which I need to mount through the container for waterproofing purposes.

the 5mm is much better but again varies drasticaly when you extend it . The capacitance varies with the extension leads I suppose..Using your hands to shade them often changes its capacitance greatly as does heat.

They don't look like something I can reliably use at this point.