Photosensor - how to program adjustment to room's lighting

Hello Arduino Community,
Please note: I'm a newbie.

I have drafted a sketch I am happy with. It controls an LED and DC motor with light, where the brightest gives both a soft "on" (not full on), and when dark, it turns them on to full.

Where I am stumped is how can I get this sketch to adjust itself for different lighting scenarios.
I'd like to get the same readings of "brightest" in a brightly lit room as a not so brightly lit room. Language that will let the arduino set the lightLevel to start with the same value as in a brightly lit room. If the room has less light than a brightly lit room, the soft "on" will still work as it would in the brightly lit room, but as it gets darker would still make LED and DC motor go to full 'on'.

Thank you in advance.

Sketch below:

const int motorPin = 9;
const int ledPin = 10;
const int sensorPin = 0;

int lightLevel, high = 0, low = 1023;

void setup() {
// put your setup code here, to run once:

pinMode(motorPin, OUTPUT);
pinMode(ledPin, OUTPUT);

}

void loop() {
// put your main code here, to run repeatedly:

lightLevel = analogRead(sensorPin);

manualTune();

analogWrite(ledPin, 255 - lightLevel);
analogWrite(motorPin, 255 - lightLevel+30);

}

void manualTune()
{

lightLevel = map(lightLevel, 0, 900, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);

}

Where I am stumped is how can I get this sketch to adjust itself for different lighting scenarios.

How would YOU do it? You can't. There is some ambient light level. You can't know if, on some other day, at some other time, there will be more light. Or less light.

That's the question:
There has to be a way to be able to have the sensor read the room's light level, and then start there, where that brightness-and-darkness range gets adjusted into the 0- 255.

There has to be a way to be able to have the sensor read the room's light level

Isn't that what it is doing?

and then start there

It sounds like you want to read the light level once, when the Arduino resets, and use that as a baseline. Permission is granted.

where that brightness-and-darkness range gets adjusted into the 0- 255.

I don't understand this statement.

Perhaps you should throw in some real numbers. Like, on a really bright day, the sensor reading is around X, and on a non-so-bright day, the sensor reading is around Y, and what I'd like is...

Yes, it is.

BUT what I'm hoping to do is get that the initial 'soft-on' to happen even if in a less bright room.

What is happening now is that in a less bright room, where there is still light, just not as much as a bright bright fluorescent light overhead, it is still behaving like if it has no light, turning everything to full-on.

I'm hoping to be able to have the arduino adjust to that less illumination (not NO illumination) to set itself in the soft-on mode, and still go to full-on when COMPLETELY dark.

avpm:
Yes, it is.

BUT what I'm hoping to do is get that the initial 'soft-on' to happen even if in a less bright room.

What is happening now is that in a less bright room, where there is still light, just not as much as a bright bright fluorescent light overhead, it is still behaving like if it has no light, turning everything to full-on.

I'm hoping to be able to have the arduino adjust to that less illumination (not NO illumination) to set itself in the soft-on mode, and still go to full-on when COMPLETELY dark.

Some numbers, please.

What light level, absolute or percentage of "blindingly bright", should trigger the "soft-on"? Is the reading going up or down when that should happen?

Sorry, I just read your previous email correctly.

“It sounds like you want to read the light level once, when the Arduino resets, and use that as a baseline. Permission is granted.”

Exactly!!

I am being able to do it manually.

In the void manualTune():
lightLevel = map(lightLevel, 0, 890, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);

Messing around with those two numbers I can adjust it to have that initial soft-on with less light.
But I’m stumped on how to do it.
I took it from a tutorial that also suggests an automatic way to do it- but it’s just reading on and off:

void autoTune()
{
// As we mentioned above, the light-sensing circuit we built
// won’t have a range all the way from 0 to 1023. It will likely
// be more like 300 (dark) to 800 (light).

// In the manualTune() function above, you need to repeatedly
// change the values and try the program again until it works.
// But why should you have to do that work? You’ve got a
// computer in your hands that can figure things out for itself!

// In this function, the Arduino will keep track of the highest
// and lowest values that we’re reading from analogRead().

// If you look at the top of the sketch, you’ll see that we’ve
// initialized “low” to be 1023. We’ll save anything we read
// that’s lower than that:

if (lightLevel < low)
{
low = lightLevel;
}

// We also initialized “high” to be 0. We’ll save anything
// we read that’s higher than that:

if (lightLevel > high)
{
high = lightLevel;
}

// Once we have the highest and lowest values, we can stick them
// directly into the map() function. No manual tweaking needed!

// One trick we’ll do is to add a small offset to low and high,
// to ensure that the LED is fully-off and fully-on at the limits
// (otherwise it might flicker a little bit).

lightLevel = map(lightLevel, low+30, high-30, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);

// Now we’ll return to the main loop(), and send lightLevel
// to the LED.
}

I took it from a tutorial that also suggests an automatic way to do it- but it's just reading on and off:

That snippet you posted doesn't read anything.

We can't see how, or if, you call that function.

/*

Example sketch 06

PHOTO RESISTOR

Use a photoresistor (light sensor) to control the brightness
of a LED.

Hardware connections:

Photo resistor:

Connect one side of the photoresistor to 5 Volts (5V).
Connect the other side of the photoresistor to ANALOG pin 0.
Connect a 10K resistor between ANALOG pin 0 and GND.

This creates a voltage divider, with the photoresistor one
of the two resistors. The output of the voltage divider
(connected to A0) will vary with the light level.

LED:

Connect the positive side (long leg) of the LED to
digital pin 9. (To vary the brightness, this pin must
support PWM, which is indicated by “~” or “PWM” on the
Arduino itself.)

Connect the negative side of the LED (short leg) to a
330 Ohm resistor.

Connect the other side of the resistor to GND.

This sketch was written by SparkFun Electronics,
with lots of help from the Arduino community.
This code is completely free for any use.
Visit http://www.arduino.cc to learn about the Arduino.

Version 2.0 6/2012 MDG
*/

// As usual, we’ll create constants to name the pins we’re using.
// This will make it easier to follow the code below.

const int sensorPin = 0;
const int ledPin = 10;

// We’ll also set up some global variables for the light level:

int lightLevel, high = 0, low = 1023;

void setup()
{
// We’ll set up the LED pin to be an output.
// (We don’t need to do anything special to use the analog input.)

pinMode(ledPin, OUTPUT);
}

void loop()
{
// Just as we’ve done in the past, we’ll use the analogRead()
// function to measure the voltage coming from the photoresistor
// resistor pair. This number can range between 0 (0 Volts) and
// 1023 (5 Volts), but this circuit will have a smaller range
// between dark and light.

lightLevel = analogRead(sensorPin);

// We now want to use this number to control the brightness of
// the LED. But we have a problem: the analogRead() function
// returns values between 0 and 1023, and the analogWrite()
// function wants values from 0 to 255.

// We can solve this by using two handy functions called map()
// and constrain(). Map will change one range of values into
// another range. If we tell map() our “from” range is 0-1023,
// and our “to” range is 0-255, map() will squeeze the larger
// range into the smaller. (It can do this for any two ranges.)

// lightLevel = map(lightLevel, 0, 1023, 0, 255);

// Because map() could still return numbers outside the “to”
// range, (if they’re outside the “from” range), we’ll also use
// a function called constrain() that will “clip” numbers into
// a given range. If the number is above the range, it will reset
// it to be the highest number in the range. If the number is
// below the range, it will reset it to the lowest number.
// If the number is within the range, it will stay the same.

// lightLevel = constrain(lightLevel, 0, 255);

// Here’s one last thing to think about. The circuit we made
// won’t have a range all the way from 0 to 5 Volts. It will
// be a smaller range, such as 300 (dark) to 800 (light).
// If we just pass this number directly to map(), the LED will
// change brightness, but it will never be completely off or
// completely on.

// You can fix this two ways, each of which we’ll show
// in the functions below. Uncomment ONE of them to
// try it out:

manualTune(); // manually change the range from light to dark

//autoTune(); // have the Arduino do the work for us!

// The above functions will alter lightLevel to be cover the
// range from full-on to full-off. Now we can adjust the
// brightness of the LED:

analogWrite(ledPin, lightLevel);

// The above statement will brighten the LED along with the
// light level. To do the opposite, replace “lightLevel” in the
// above analogWrite() statement with “255-lightLevel”.
// Now you’ve created a night-light!
}

void manualTune()
{
// As we mentioned above, the light-sensing circuit we built
// won’t have a range all the way from 0 to 1023. It will likely
// be more like 300 (dark) to 800 (light). If you run this sketch
// as-is, the LED won’t fully turn off, even in the dark.

// You can accommodate the reduced range by manually
// tweaking the “from” range numbers in the map() function.
// Here we’re using the full range of 0 to 1023.
// Try manually changing this to a smaller range (300 to 800
// is a good guess), and try it out again. If the LED doesn’t
// go completely out, make the low number larger. If the LED
// is always too bright, make the high number smaller.

// Remember you’re JUST changing the 0, 1023 in the line below!

lightLevel = map(lightLevel, 300, 800, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);

// Now we’ll return to the main loop(), and send lightLevel
// to the LED.
}

void autoTune()
{
// As we mentioned above, the light-sensing circuit we built
// won’t have a range all the way from 0 to 1023. It will likely
// be more like 300 (dark) to 800 (light).

// In the manualTune() function above, you need to repeatedly
// change the values and try the program again until it works.
// But why should you have to do that work? You’ve got a
// computer in your hands that can figure things out for itself!

// In this function, the Arduino will keep track of the highest
// and lowest values that we’re reading from analogRead().

// If you look at the top of the sketch, you’ll see that we’ve
// initialized “low” to be 1023. We’ll save anything we read
// that’s lower than that:

if (lightLevel < low)
{
low = lightLevel;
}

// We also initialized “high” to be 0. We’ll save anything
// we read that’s higher than that:

if (lightLevel > high)
{
high = lightLevel;
}

// Once we have the highest and lowest values, we can stick them
// directly into the map() function. No manual tweaking needed!

// One trick we’ll do is to add a small offset to low and high,
// to ensure that the LED is fully-off and fully-on at the limits
// (otherwise it might flicker a little bit).

lightLevel = map(lightLevel, low+30, high-30, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);

// Now we’ll return to the main loop(), and send lightLevel
// to the LED.
}

I have drafted a sketch I am happy with. It controls an LED and DC motor with light, where the brightest gives both a soft "on" (not full on), and when dark, it turns them on to full.

brightest what ?
ambient light - or will you be controlling with an external light - are you controlling the motor with a light, or is the motor reacting to the ambient light ?
so;
bright => motor slow
dark => motor fast
is that what you want ?

it seems that even if you can adjust the baseline to ambient light at different settings, you cannot map the other end if you don't know how dark (or how bright) it can get afterwards.

before writing the code, try a simple pseudo-code of what you actually want to do.

  1. sense existing light - is this minimum, maximum or middle ?
  2. if light change to darker - then motor speed up
  3. if light change to brighter - then motor slow down

OK, thanks! I'll give it a go.
A.