Thursday, November 17, 2011

Sparkfun Inventor's Kit Circuit-09: Photo Resistors

Most of the robotics that goes on in the military involves what is called "man in the loop", that is, the presence of a human being controlling the ultimate decisions the robot makes.  And that makes sense, particularly when lethality is involved.  Still, there is an important place for fully autonomous robots, robots that can make critical decisions on their own, and the challenge of creating such "artificial intelligence" is seen by many as the apogee of robotics education.

The Sea Perch program, sponsored by the Office of Naval Research, started out with an underwater rover that was "tethered" through a CAT 5 Ethernet cable and the students, usually middle school age kids, learned to build and solder together the controller, small box like unit that had toggle switches to control the three propeller motors on the submersible.   Going to RC (Radio control) was not considered a viable option because of the difficulty of transmitting radio waves under water, so the next step in "hacking your Sea Perch" (what Daryl Davidson, the hip robotics education specialist and executive director  of the AUVSI (Association for Unmanned Vehicle Systems International) appropriately calls "pimping your Perch") is to "take the man out of the loop" and, through the application of sensors and a micro-controller, give some autonomy to the submersible robot craft.

MIT has been working on exactly that with their Sea Perch Sensor Suite, a kit based on an Arduino board.  It is described as, "a microcontroller-based platform that can be fabricated with minimal tools in a few hours, for under $200. When first fabricated, the sensor monitors:
- Water Temperature
- Depth
- Light
- Conductivity
And can be expanded with basic electronic and computing skills to monitor an assortment of other variables."

If you are working with the Sparkfun Inventor's Kit, Circuit-09 gives you an introduction to the world of autonomy with the introduction of a photo-resistor.  The manual says, "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 us a photo resistor (light based resistance)."

This is the first step in creating a robot that can sense its environment and respond to it.  From the perspective of a marine robotics program, the use of a photoresistor is appropriate since light sensitive organs evolved in the ocean very early on, giving organisms the capability for "phototaxis" or "movement toward or away from light".  This simple behavior can be rather easily done with the arduino, and might be one of the first one should attempt when "pimping the perch" -- i.e. use a photoresistor to make the Sea Perch move up or down,  toward or away from the surface,  based on the amount of light shining down on it (something many squid and plankton do in the ocean!).

The Sparkfun manual tells us that Arduinos cannot directly sense resistance.  They sense voltage, so what is needed is a voltage divider (http://ardx.org/VODI). We don't need to calculate the exact voltage at the sensing pin at this point so this experiment is about sensing relative light values and see what works.  We won't be driving a Sea Perch with this, but using an LED instead of a motor, we will see how the variable amount of light falling on the photoresistor affects the brightness of the LED.  Low voltages (high resistance to the current)  will be produced when the light is shining strongly, and high voltages (less resistance to the current) when it is dark; for a Sea Perch this could be useful so that the robot dives in the day and returns to the surface at night.  For this example daylight will shut off the LED and darkness turn it on, and this is exactly what people use for security lights.

The wiring isn't complex -- just one 330 Ohm resistor and one 10 K resistor, the LED and the Photoresistor, and the code is here:
http://ardx.org/CIRC09:

 /*
* A simple programme 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
                  //the photoresistor is not calibrated to any units so
                  //this is simply a raw sensor value (relative light)
//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
                                        // lightlevel
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 betwween
                                           //0 and 255
analogWrite(ledPin, lightLevel);  //write the value
}


The code  uses digital pin 9 so that we can use PWM (pulse width modulation) to simulate analog light levels.

When you upload the circuit and put your hand around the photoresistor the LED goes on. If you want the opposite effect, the manual tells us to change the code from analogWrite(ledPin, lightLevel); to analogWrite(ledPin, 255 - lightLevel);
When I try it the light now stays on, even when I put my hand around it or dim the room.  I changed it then to  analogWrite(ledPin, 100 - lightLevel); and I get a dimmer LED but it still won't go out when I cup my hand around it to darken the photoresistor.  Changing the span to span 0 to 100 and constraining the light level to 0,100 and then writing 100 - lightLevel doesn't do much except make the constant LED dimmer. But it works the other way around, with your hand causing the light to go on by blocking light from the Photoresistor.

The next suggestion the manual has is creating a "night light" that turns on based on a threshold value using this code:

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

This unfortunately doesn't work for me; I had to set the int threshold to around 10 to get the light to turn on when I cupped my hand around it.  Nonetheless, it does work with a low enough threshold. Your task is to find out what that threshold is for your environment.

And now we can begin to think about running a Sea Perch motor or a servo based on this principle.
I wire up the servo the way I did in Circuit-08, connecting the white servo wire to the positive lead of the LED which is connected to digital pin 9 on the Arduino, and the red and black servo wires to 5V and ground respectively. Now when I put my thumb over the photoresistor the servo spins and the light goes on, but of course then the servo gets stuck in one position.  I reverse the HIGH and LOW commands and the servo spins in the other direction.  But I can't quite control it yet.

The manual says to load up File>Examples>Servo>Knob from the Arduino sketch library like we did in the last circuit.  When I upload that it makes the light go on and the servo spin to the end of its range and then it just sits and vibrates.  The manual says,
"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. Hints on what to do are found at: http://arduino.cc/en/Reference/Map."
The manual says we are engaging in "a little bit of Arduino code hacking".  I try messing with the values but can't get much to happen.

It doesn't seem intuitive to me, so I decide to give up and move on; one of the nice things about this field is that you can always circle back later when things seem clearer.  If you get stymied, don't stop, just keep working through different examples!









No comments:

Post a Comment