Maths + LDR = I'm Stuck.

 LightVal=analogRead(A1); 
  if (AmbientLight==true)
   {     
      //Dark = 800 - 1024
      //Light = 200 - 400
      //Direct Sunlight 1 - 200
      //DayTime = 400 - 700         
       if (LightVal>800) 
        {
           AmbLightVal = LightVal/4;  //800/4 = 200          
           AmbLightVal = AmbLightVal  - 200;
           analogWrite(SBLEDPin,AmbLightVal); //fade 255 = max, 0 = off           
           Serial.println(AmbLightVal); 
           delay(250);
        }
       if (LightVal<800) 
           analogWrite(SBLEDPin,0); //fade 255 = max, 0 = off           
   }

The LED (IS coming on) but it's a bit kinda, On/Off ish, there's no smooth transistion as it goes dark, I would like my 12watt LED to come on (slowly)...

so as the value rises to 700, the LED brightness should be around 10 (using analogWrite) and around 200 (250 is max obviously) when it's really dark say around the value of 900..

The value itself is read via voltage divider (LDR and a 20k Resistor) and I get the value like that.

I hate Math!!! I HATE IT, it's great and wonderful for all of those who can do fancy calculations, but for me, ughhh. :slight_smile: can anyone help cheers :slight_smile:

Probably a minor thing, in fact, in this instance... but a nice example of a little "sloppiness" which, on general principle should always be avoided....

Where you have....

if (LightVal>800)...

You ought to have....

if (LightVal>799)...

(As your code stands, the case of when LightVal EQUALS 800 causes no action.)

====
But that probably won't help fix your problem. Sorry. Code looks good to me, as far as giving you a gradually brighter LED as the light falling on the sensor falls. But the brightest light you'll get is level 55, isn't it? Is that what's happening? Ramps up from "off", but never gets very bright?

How about... forgive the crude pseudocode?....

Level <768: Ambilight off
Level >767: Ambilight set to (LightLevel-768)

... that would give you....

LightLevel...
... Ambilight setting

768 0
769 1

..etc.. up to...

1023 255

(Always consider both ends of such things.)

====
Eventually, you are going to want to define three ranges...

Level < (say 800) : Ambilight off
Level >(say 900): Ambilight set to full on
Level in band between the above (800-900, inclusive, given breakpoints I chose): Ambilight set to 0 to 255, depending on light level. This is tedious maths, but not VERY difficult... and because you're not the first person to find the maths a pain, there's....

http://arduino.cc/en/Reference/Map

there's no smooth transistion as it goes dark, I would like my 12watt LED to come on (slowly)...

Of course not, because you haven't provided for one.

You need to test the range of values that you get from the LDR. The absolute range is 0 to 1023, but it is unlikely that yours actually returns that full range of values.

Even if it did, you divide the value by 4, if it is above 800, resulting in a range of 200 to 254. From that, you subtract 200, resulting in a range of 0 to 54. It is unlikely that values below 20 or so will result in you seeing any light, so your range of visible values will only be about 10% of the theoretically possible values.

Any LDR value below 800, which will be most of them, will result in the LED being off.

Is that what you really want?

Another thing to bear in mind - the eye's response to brightness is logarithmic and able to deal with a range of brightnesses over a thousand to one easily. Your output has only 256 levels, the values 0, 1, 2, 3, will appear obviously different in brightness since the ratios are so large (1/0 - infinite, 2/1 = 2, 3/2 = 1.5). At the other end of the scale 253, 254, 255 will appear identically bright since the eye can't detect small ratios (255/254 = 1.004).

So you need to get a finer resolution at the low end and perhaps coarser at the high end to get a good smooth response to the eye.

You can use linear interpolation like this to increase the range of values from 0..255 to 0..4095

int state = 0 ;

void myAnalogWrite (int val)  // input value 0..4095
{
  state += val ;
  if (state < 0)
    state = 0 ;
  if (state > 4095)
    state = 4095 ;
  int out = state >> 4 ;  // take high bits
  state -= out << 4 ;          // leave behind the error term for next time
  analogWrite (SBLEDPin, out) ;
}
  • not tested!

You just have to call analogWrite at a fast enough rate to hide the flickering when at low brightnesses - every ms would probably do.

What happens if you call myAnalogWrite (1) repeatedly is that it will call analogWrite() with value 1 every 16 times, and 0 for the other 15 - so the perceived brightness is 1/16 of what analogWrite(..., 1) would produce.

You might then add a function to take a brightness value and do inverse logarithm (exponential) mapping on it to get a value in the range 0..4095.