User Tools

Site Tools


oak:tutorials:photocell

This is an old revision of the document!


Oak: using a photocell (photoresistor)

In this lesson, we will connect a photoresistor to the Oak. A photoresistor is like a potentiometer (a variable resistor) except light is acting instead of a knob. When there is a lot of light, the resistance drops; with low light, the resistance is higher. Using this property, we can send a voltage through a photoresistor, measure the resistance via a change in voltage, and obtain a value for how much light is shining on the photoresistor.

Components

Part Quantity Identification
Oak with soldered headers 1
Breadboard1
Photocell1
Jumper wires7
Resistor, 10k ohm1Black-Brown-Orange
3.3V USB UART or an Arduino*1

Note: if using an Arduino to read serial, you will need to follow the instructions at the tutorial on serial with an Arduino. In contrast, you don't need either of these components if you learn how to use Particle.variable() as described in this tutorial.

Concepts

Voltage divider

In the circuit we create below, electricity will flow from the Oak's Vcc pin into one leg of the photocell. When electricity leaves the photocell, it will see two paths: one to pin 'A0, and the other to ground through the 10k resistor. This creates what is known as a voltage divider, which is very helpful for measuring small changes in voltage. There's a great writeup of why this is required on the Electronics StackExchange Q&A site here. An Adafruit tutorial also features a discussion on adjusting the resistor value to target different ranges of measurement in the section on using a photoresistor.

The short version is that a voltage divider creates a ratio in the voltages in each path based on their individual resistances. The voltage going to A0 can be found as follows:

A0 voltage = 3.3V (Vcc) * 10k / (10k + photocell_resistance)

The ratio of the resistor going to ground divided by total resistance tells us how much will be measured at A0. If the photocell resistance is small, there will be very little difference between Vcc and A0 with a direct connection. By using the ratio produced by a voltage divider, the A0 voltage will vary a lot more as the resistance of the photocell changes.

ADC

An analog sensor is one that produces a change in electrical properties in response to changes in the thing being measured. This is in contrast to digital sensors which use a communication protocol to report out an actual number. A photocell is an analog sensor in that it's resistance changes in response to light. We do not obtain a direct number from the photocell; instead, we need to measure the electricity going through it and convert that to a number of some form.

An Analog to Digital Converter (ADC) does this for us. It will read in a voltage and compare it to a reference voltage (Aref), which serves as the maximum value it could read. The measured voltage is then converted into a number ranging from 0 (measured voltage = 0) to maximum (measured voltage = reference voltage), which depends on the microcontroller. The Arduino, for example, converts 0 - Aref into 0-255. The Oak, converts to a range of 0-1023.

analogRead()

The analogRead() function is how we access the ADC. When we call analogRead(A0), we are telling the Oak to convert the voltage it measures at A0 into a number between 0-1023 depending on how big it is. By using the delay() function, we can adjust how often these readings are taken. We can also use an if() statement to do something else based on the 0-1023 value.

the if() statement

For the second portion of this tutorial, the code will use an if() statement. This is one of the fundamental ways to control the Oak's behavior. The format is:

if( some condition ) { do this; }

In our case, the condition we're checking for is whether or not the A0 light reading is above or below 250. If it's above 250, we do nothing. If it's below 250, we turn on the on-board LED. To compare the actual statements above to the actual code below, here are the lines. Can you see how they work?

if(light < 250) { digitalWrite(1, HIGH); }

if(light >= 250) {digitalWrite(1, LOW); }

Circuit

To connect the photocell, we will use the following circuit:

To complete the circuit, follow these steps:

  • Insert the photocell legs into two different rows
  • Connect the 10k resistor from one photocell leg (either is fine) to a new row with a jumper wire
  • Connect pin A0 of the Oak to the same row containing both leads from the resistor and photocell
  • Connect a ground pin of the Oak to the free lead on the resistor
  • Connect a Vcc pin on the Oak to the free lead of the photocell

For reference, here is the setup above in real life:

photocell-wiring.jpg

If you wish to read the photocell output via serial, please take this time to follow the instructions as described here for a UART and here when using an Arduino.

Code: reading the photocell

We will begin by simply reading the value produced by the photocell signal to A0:

// variable to store our reading
int light;

// the setup() loop sets pinModes, starts things like Serial,
// and is run once when the Oak powers on
void setup()
{                
  
  // initialize the analog pin as an input
  pinMode(A0, INPUT);

  // start serial communication and create a variable for particle.io access
  Serial.begin(9600);
  Particle.variable("light", light);

}


// the loop() routine runs over and over again
void loop()
{

  // take a reading
  light = analogRead(A0);
  
  // print it out
  Serial.println(light);

  // a short delay as we don't need extremely fast readings
  delay(250);

}

This code reads A0, stores the number it obtain in the variable called light, sends it ot the computer via serial, and then pauses for 0.25 seconds.

Using serial, the output will look like this as you cover and uncover the sensor:

764
737
620
421
313
246
200
153
157
165
408
630
491
235
153
163
763
765

If you are using Particle.variable(), you would issue a call like this, substituting your device ID and access token in their appropriate locations:

curl https://api.particle.io/v1/devices/id_here/light?access_token=token_here

The result will look like this, where the value in “result” is the output of A0

{
  "cmd": "VarReturn",
  "name": "button",
  "result": 529,
  "coreInfo": {
    "last_app": "",
    "last_heard": "2016-03-19T20:51:30.817Z",
    "connected": true,
    "last_handshake_at": "2016-03-19T20:32:30.268Z",
    "deviceID": "12345678",
    "product_id": 82
}

Code: turning on an LED when it's dark

Now, we'll use these values to turn on and off the on-board LED at pin 1 based on how light or dark it is. Based on your readings, pick value 50-100 higher than your lowest reading. For the sensor above, 250 was chosen. If we add some code to our sketch, we can automatically turn on the on-board LED when the sensor is in low light. To do this, we add the LED functionality from the blink tutorial and use an if() statement:

// variable to store our reading
int light;

void setup()
{                

  // enable the on-board LED as an output
  pinMode(1, OUTPUT);
  
  // initialize the analog pin as an input
  pinMode(A0, INPUT);


  // start serial communication and create a variable for particle.io access
  Serial.begin(9600);
  Particle.variable("light", light);

}


// the loop() routine runs over and over again
void loop()
{

  // take a reading
  light = analogRead(A0);
  
  // print it out
  Serial.println(light);

  // turn on/off the LED based on light reading
  if(light < 250) { digitalWrite(1, HIGH); }
  if(light >= 250) {digitalWrite(1, LOW); }
  
  // a short delay
  delay(250);

}

Adjust the cutoff values as desired; with this code added, we get a nice effect like this:

Conclusion

Congratulations! You just connected to an analog sensor and read the values! Sensors are a crucial component to many projects, so this is an invaluable skill that will serve you well. For a next step, perhaps you could try connecting a different analog sensor? There are many Arduino tutorials for other types of sensors, such as Adafruit's on using the TMP36 temperature sensor.

Or perhaps you can think up some projects that might include a photocell? Now that you have this sensor in your toolbox for future project, here's some [perhaps silly] ideas to get you going:

  • an automated night light
  • reminder to turn off your outside flood lights in the morning
  • track the sunset/sunrise time each day
  • auto close your curtains/blinds when it's bright
oak/tutorials/photocell.1458708839.txt.gz · Last modified: 2016/03/22 21:53 by jwhendy