LDR response time

I built a small night light that turns on when the room light is turned off, glows for a bit and then dims down, giving me enough time to find my bed, in what used to be pitch black darkness, once I turn off the lights.

It works as advertised. LDR connected to an ATtiny45, driving a few LEDs through an ULN2003. The only thing that somewhat bothers me is the fact that LEDs don't light up the moment I turn off the room light, but it takes about half a second (eyeballing here). When I envisaged this project in my mind I had an image of it turning on so fast that the delay is not noticeable, yet here it is. Certainly less than a second, but noticeable.

To troubleshoot I added detection of turning on the lights, and it seems significantly faster.

I found some old datasheet for an LDR (not the one I'm using), and surprise, surprise, rise and fall response times differ by the factor of 4-6 (depending on the model), but are still below 90ms (usually below 35 ms) on the slower end.

So, while this is more of a rant than a cry for help, is there a way to decrease the response time? Phototransistor, maybe?

Why not just re-wire the room lights with 2x SPDT switches like traditionally done on a stairway, with one by the bed, so you can just switch the light off from the bed or by the door? XD

Yeah, the thought of demolishing half a wall is kind of putting me off. We still build our houses with bricks and concrete here.

90ms is certainly LONG but human should find it "lightning fast", as matter of fact, lightning usually lasts 100ms. Not sure how you build it, but when I built my sound/light detector using analog read, it was not noticable at all.

Basically I put a photodiode + into A0 of Arduino and - into ground and do analogRead and compare values, when difference between two reads exceeds certain value, it is an event . . . here is the thread:


Of course, a photodiode like the PiN diode sold by Sparkfun at Miniature Solar Cell - BPW34 - PRT-09541 - SparkFun Electronics will be faster than an LDR, your circuit should be fast to a human. How about posting a schematic and you code?

Without seeing your schematic and your code we can't really help. All I can say is that it is generally taken that any two actions which take place at around 20mS or less apart are perceived as happening at the same time by the average human. 20-50mS most see them as pretty much simultaneous. >50mS and the majority of people see them as completely separate events.

Really, majenko? 50 ms? That is in the ballpark of what datasheets said.

Code, and partial schematic.

int ledPin = 0;
int ledState = 0;
int sensorPin = 3;
int sensorVal;
int limit = 20;
int pause = 100;

void setup ()
  pinMode (ledPin, OUTPUT);

void loop ()
  sensorVal = analogRead (sensorPin);
  if (sensorVal > limit && ledState == 0)
    ledState = 1;
    analogWrite (ledPin, 255);
    delay (30000);                            // 30 seconds of light
    for (int i = 255; i >= 0; i--)            // start the dimming
      analogWrite (ledPin, i);
      delay (pause);
  if (sensorVal <= limit-1 && ledState == 1)
    analogWrite (ledPin, 255);                // indicates that the room light has been detected
    delay (300);
    analogWrite (ledPin, 0);
    delay (300);
    analogWrite (ledPin, 255);
    delay (300);
    analogWrite (ledPin, 0);
    delay (300);
    analogWrite (ledPin, 255);
    delay (300);
    analogWrite (ledPin, 0);
    ledState = 0;


LDRs are known for having slow response times in low light. A phototransistor is more suitable for that application.

Besides the possibility of going to phototransistors, it should be possible to use adaptive code for quicker responses. The turn-off time will be dependent upon what threshold you're using - ie, your limit variable - and also the ambient LDR level with the lights on. So, maybe you can read the average ambient level with the lights on, and select a threshold level based upon some percentage of that, maybe 75 or 80%, etc, rather than using a fixed threshold value.

Thanks guys.
I had some problems with determining the value for threshold (limit variable). When using Uno and serial print to read the value it was significantly different than what worked on ATtiny.
Also the value 20 is rather fragile. For some, if I reason put anything else there the detection stops working (neither 21 or 19 work).

In the second part “if (sensorVal <= limit-1 && ledState == 1)” limit-1 is also the only way for it to work.

For now, I’m fairly happy how all this functions and I don’t think I’ll be messing with the code unless I find a better light sensor (transistor).

When I started this I knew LDRs were slower than phototransistors, I just didn’t think that the delay would be noticeable to the naked eye. Also, I had a few LDRs sitting around and no transistors, so the choice was obvious :slight_smile:

Also the value 20 is rather fragile. For some, if I reason put anything else there the detection stops working (neither 21 or 19 work).

This doesn't sound at all reasonable. There is something going on here you're not telling us about. For one thing, do you have any idea what the actual LDR readings are for the lights-on, lights-off conditions in the room? You have to know that info as a starting point.

An unconnected LDR of the same make and model shows: Lights on, 10 kOhm Lights off, more than 40 MOhm (that's how far the meter goes and it shows no connection). If I add a little bit of light I can measure it in tens of MOhm range, but you get the picture, pretty high resistance.

The one soldered on the device shows 220 Ohm in darkness and 205 Ohm with lights. So it appears I might have burned it while soldering.

In any case, analogRead on Uno returned around 680 to 750 (depending which direction LDR was facing relative to the light bulb) with lights on and 950 to 1020+ in semi darkness produced by my monitors shining from 50 cm away.

But like I said, those values did not work when I transfered everything to tiny, possibly due to my pyrolytic actions.

If the actual analog readings are roughly 700 in one case and 1000 in the other
case, it doesn’t sound like limit = 20 is gonna work. ???

In any case, you might swap out the LDR, verify a good set of readings, and go
from there in selecting the threshold value.

Also, take a good look at your check statements, there are actually 4 possible
conditions, but you only check 2 of them. This is probably not the best scenario.
Is it possible to get stuck in one of the other 2 conditions? A good state-machine
will actively account for all possible states.

  if (sensorVal > limit && ledState == 0)
  if (sensorVal <= limit-1 && ledState == 1)

Yes, I intentionally left the gap between the condition for turning on and off. The resistor value is not exact and fluctuates somewhat. Usually that would be no problem since there would be a significant difference in operating values (light / darkness), but for some reason there is virtually no gap in my case. Darkness is at around 18 and light is detected at 22 or so. The gap is there to ensure that that fluctuation does not enter the wrong condition.

I made up a similar circuit, and can't reproduce your problem at all.

When I turn off my test light the LED comes on instantly (as far as I can see).

I made it up on a Uno and added some serial prints to confirm the values I was getting on the analogRead.

I would suggest to use a photodiode/phototransistor and use differential threshhold -- take the difference between reads and use that as indicator of light detection.

Of course, use an absolute reading as precondition -- if the absolute read is lower than certain value, it means dark. Then combine with the differential threshhold to indicate a change of light. This way, you can avoid the situtation when there is a flash of light when the room is lit by other bulbs.

Just a thought.

Just got home from work, fired up my iron and unsoldered the LDR, put a new one in, adjusted the code so the limit variable is 900 (my initial measurement with Uno) and BANG! The thing works like a charm. No noticeable delay, no floating between conditions. Just proper functioning.

Closer inspection of the old LDR revealed some unhealthy looking discoloration. Guess I burned it while soldering after all. Thanks for help guys.

Looking back at the code you listed, I don't see how you ever even got it to work. There are no debug statements in there. That's like groping around in the dark [hmm, deja vu]. If you had enabled the Serial port and fedback the values being output from the LDR, you'd probably have been able to fix this in a very short time. I can't write a program except the first few passes are mostly testing various aspects of how things are operating.

My first try was on a breadboard with Uno. Serial was used, of course, to determine the resistor values. The trouble started when I transfered it all to perfboard and ATtiny. Since tiny doesn't support serial, that stuff had to go. In that process it appears that I burned the LDR while soldering. That is when I started to poke in the dark (both literally and figuratively) for the values that work.

Photoresistors can be used to create an audio volume limiter - indeed they were commercially before voltage controlled chips and then software mostly took over the role. I used ORP12 very successfully - illuminated at first by thermionic 'magic eye' connected to the audio output, and later by LED. Risetime (i.e. full control of audio peak) was around 20 millisec. Recently, I bought the 'identical' NORP 12 and found it to be much slower. Not measured yet, but visually I reckon at least 200 msec, despite very bright white LED. That's too slow - you get audible overshoot.

How 'fast' depends on how much resistance change is sought, of course. If only a few percent, then the cell gets there quickly. One way to accelerate action is to maintain a dim background illumination, if other factors allow that. This was the case with my magic eye limiter: the residual heater glow held the cell in readiness, though I hadn't realised that at the time.