CIRC
09

.:Light:.
.:Photo Resistors:.

green led and photo resistor on circuit 9 breadboard sheet

(ARDX) .:Arduino Experimentation Kit:. (ARDX)

What We're Doing

Whilst getting input from a potentiometer can be useful for human controlled experiments, what do we use when we want an environmentally controlled experiment? We use exactly the same principles but instead of a potentiometer (twist based resistance) we use a photo resistor (light based resistance). The Arduino cannot directly sense resistance (it senses voltage) so we set up a voltage divider (http://ardx.org/VODI). The exact voltage at the sensing pin is calculable, but for our purposes (just sensing relative light) we can experiment with the values and see what works for us. A low resistance value will occur when the sensor is well lit while a high value will occur when it is in darkness.

The Circuit

The Parts

circuit 9 breadboard sheet 3d view CIRC-09
Breadboard Sheet
x1
2 pin header 2 Pin Header
x4
photo resistor Photo-Resistor
x1
wire Wire
10k ohm resistor 10k Ohm Resistor
Brown-Black-Black-Red
x1
560 ohm resistor 560 Ohm Resistor
Green-Blue-Black-Black
x1
green LED Green LED
x1

Schematic

Resources

.:download:.

Breadboard layout sheet
http://ardx.org/BBLS09

Fritzing diagram
https://wcrsyyc.github.io/ardx/fritzing/CIRC09.fzz

.:view:.

assembly video
http://ardx.org/VIDE09

Code (no need to type everything in just)

Download the Code from ( http://ardx.org/CODE09 )
(and then copy the text and paste it into an empty Arduino Sketch)

/*
 * A simple program that will change the intensity of an LED based
 * on the amount of light incident on the photo resistor.
 */

//PhotoResistor Pin
int lightPin = 0; //the analog pin the photoresistor is connected to
//LED Pin
int ledPin = 9;   //the pin the LED is connected to
                  //we are controlling brightness so
                  //we use one of the PWM (pulse width
                  // modulation pins)
void setup()
{
  pinMode(ledPin, OUTPUT); //sets the led pin to output
}

/*
 * loop() - this function will start after setup
 * finishes and then repeat
 */
void loop()
{
  int lightLevel = analogRead(lightPin); //Read the light level
        //the photoresistor is not calibrated to any units so
        //this is simply a raw sensor value (relative light)
  lightLevel = map(lightLevel, 0, 900, 0, 255);
        //adjust the value 0 to 900 to
        //span 0 to 255

  lightLevel = constrain(lightLevel, 0, 255);//make sure the
                                           //value is between
                                           //0 and 255
  analogWrite(ledPin, lightLevel);  //write the value
}

Not Working? (3 things to try)

LED Remains Dark

This is a mistake we continue to make time and time again, if only they could make an LED that worked both ways. Pull it up and give it a twist.

It Isn't Responding to Changes in Light.

Given that the spacing of the wires on the photo-resistor is not standard, it is easy to misplace it. Double check it´s in the right place.

Still not quite working?

You may be in a room which is either too bright or dark. Try turning the lights on or off to see if this helps. Or if you have a flashlight nearby give that a try.

Making it Better?

Reverse the response:

Perhaps you would like the opposite response. Don't worry we can easily reverse this response just change:
analogWrite(ledPin, lightLevel); ----> analogWrite(ledPin, 255 - lightLevel);
Upload and watch the response change:

Night light:

Rather than controlling the brightness of the LED in response to light, lets instead turn it on or off based on a threshold value. Change the loop() code with.

void loop(){
  int threshold = 300;
  if(analogRead(lightPin) > threshold){
    digitalWrite(ledPin, HIGH);
  }else{
    digitalWrite(ledPin, LOW);
  }
}

Light controlled servo:

Lets use our newly found light sensing skills to control a servo (and at the same time engage in a little bit of Arduino code hacking). Wire up a servo connected to pin 9 (like in CIRC-04). Then open the Knob example program (the same one we used in CIRC-08) File > Examples > Library-Servo > Knob. Upload the code to your board and watch as it works unmodified.

Using the full range of your servo:

You'll notice that the servo will only operate over a limited portion of its range. This is because with the voltage dividing circuit we use the voltage on analog pin 0 will not range from 0 to 5 volts but instead between two lesser values (these values will change based on your setup). To fix this play with the val = map(val, 0, 1023, 0, 179); line. For hints on what to do visit http://arduino.cc/en/Reference/Map. HINT: It is also a good idea to make sure that the requested servo position stays in the valid range of 0 to 180. To combine that with the map function, you can use something like

val = constrain( map( val, 100, 900, 0, 180 ), 0, 180 );

to say that values of 100 to 900 will translate to angles from 0 to 180 degrees, but still keep in the valid range if the input value is less than 100 or greater than 900.