Imagine that your BOE Shield-Bot is navigating a course, and there’s a bright light at the end. Your robot’s final task in the course is to stop underneath that bright light. There’s a simple phototransistor circuit you can use that lets the Arduino know it detected bright light with a binary‑1, or ambient light with a binary-0. Incandescent bulbs in desk lamps and flashlights make the best bright-light sources. Compact fluorescent and LED light sources are not as easy for the circuit in this activity to recognize.
Ambient means ‘existing or present on all sides’ according to Merriam Webster’s dictionary. For the light level in a room, think about ambient light as the overall level of brightness.
(1) phototransistor
(2) jumper wires
(1) resistor, 2 kΩ (red-black-red)
(1) incandescent or fluorescent flashlight or desk lamp
After some testing, and depending on the light conditions in your robotics area, you might end up replacing the 2 kΩ resistor with one of these resistors, so keep them handy:
(1) resistor, 220 Ω (red-red-brown)
(1) resistor, 470 Ω (yellow-violet-brown)
(1) resistor, 1 kΩ (brown-black-red)
(1) resistor, 4.7 kΩ (yellow-violet-red)
(1) resistor, 10 kΩ (brown-black-orange)
The drawing below will help you tell apart the phototransistor and infrared LED, since they look similar.
The schematic and wiring diagram below show the schematic and wiring diagram of a circuit very similar to the ones in streetlights that turn on automatically at night. The circuit outputs a voltage that varies depending on how much light shines on the phototransistor. The Arduino will monitor the voltage level with one of its analog input pins.
The PhototransistorVoltage sketch makes the Serial Monitor display the voltage measured at A3—one of the Arduino’s five analog input channels that are accessible through the BOE Shield. In the circuit you just built, a wire connects A3 to the row where the phototransistor’s emitter and resistor meet. The voltage at this part of the circuit will change as the light level sensed by the phototransistor changes. The Serial Monitor screencapture below shows some example voltage measurements.
/* * Robotics with the BOE Shield - PhototransistorVoltage * Display voltage of phototransistor circuit output connected to A3 in * the serial monitor. */ void setup() // Built-in initialization block { Serial.begin(9600); // Set data rate to 9600 bps } void loop() // Main loop auto-repeats { Serial.print("A3 = "); // Display "A3 = " Serial.print(volts(A3)); // Display measured A3 volts Serial.println(" volts"); // Display " volts" & newline delay(1000); // Delay for 1 second } float volts(int adPin) // Measures volts at adPin { // Returns floating point voltage return float(analogRead(adPin)) * 5.0 / 1024.0; }
The sketch HaltUnderBrightLight will make the BOE Shield-Bot go forward until the phototransistor detects light that’s bright enough to make the voltage applied to A3 exceed 3.5 V. You can change the 3.5 V value to one that’s halfway between the high and low voltage values you recorded from the last sketch.
/* * Robotics with the BOE Shield - HaltUnderBrightLight * Display voltage of phototransistor circuit output connected to A3 in * the serial monitor. */ #include <Servo.h> // Include servo library Servo servoLeft; // Declare left and right servos Servo servoRight; void setup() // Built-in initialization block { tone(4, 3000, 1000); // Play tone for 1 second delay(1000); // Delay to finish tone servoLeft.attach(13); // Attach left signal to pin 13 servoRight.attach(12); // Attach right signal to pin 12 servoLeft.writeMicroseconds(1700); // Full speed forward servoRight.writeMicroseconds(1300); } void loop() // Main loop auto-repeats { if(volts(A3) > 3.5) // If A3 voltage greater than 3.5 { servoLeft.detach(); // Stop servo signals servoRight.detach(); } } float volts(int adPin) // Measures volts at adPin { // Returns floating point voltage return float(analogRead(adPin)) * 5.0 / 1024.0; }
The Arduino’s A0, A1…A5 sockets are connected to Atmel microcontroller pins that are configured for analog to digital conversion. It’s how microcontrollers measure voltage: they split a voltage range into many numbers, with each number representing a voltage. Each of the Arduino’s analog inputs has a 10-bit resolution, meaning that it uses 10 binary digits to describe its voltage measurement. With 10 binary digits, you can count from 0 to 1023; that’s a total of 1024 voltage levels if you include zero.
By default, the Arduino’s analogRead function is configured to use the 0…1023 values to describe where a voltage measurement falls in a 5 V scale. If you split 5 V into 1024 different levels, each level is 5/1024ths of a volt apart. 5/1024ths of a volt is approximately 0.004882813 V, or about 4.89 thousandths of a volt. So, to convert a value returned by analogRead to a voltmeter-style value, all the volts function has to do is multiply by 5 and divide by 1024.
Example:
The analogRead function returns 645; how many volts is that?
Answer:
The sketches have been calling the volts function with volts(A3). When they do that, they pass A3 to its adPin parameter. Inside the function, analogRead(adPin) becomes analogRead(A3). It returns a value in the 0 to 1023 range that represents the voltage applied to A3. The analogRead call returns an integer, but since it is nested in float(analogRead(adPin), that integer value gets converted to floating point. Then, it’s multiplied by the floating point value 5.0 and divided by 1024.0, which converts it to a voltmeter value (just like we converted 645 to 3.15 V).
float volts(int adPin) // Measures volts at adPin { // Returns floating point voltage return float(analogRead(adPin)) * 5.0 / 1024.0; }
Since return is to the left of the calculation in the volts function block, the result gets returned to the function call. The sketch PhototransistorVoltage displays the value returned by the volts function with Serial.print(volts(A3)).
HaltUnderBrightLight uses that vaule in the if(volts(A3) > 3.5) expression to bring the BOE Shield-Bot to a halt under the light.
Binary vs. Analog and Digital
A binary sensor can transmit two different states, typically to indicate the presence or absence of something. For example, a whisker sends a high signal if it is not pressed, or a low signal if it is pressed.
An analog sensor sends a continuous range of values that correspond to a continuous range of measurements. The phototransistor circuits in this activity are examples of analog sensors. They provide continuous ranges of values that correspond to continuous ranges of light levels.
A digital value is a number expressed by digits. Computers and microcontrollers store analog measurements as digital values. The process of measuring an analog sensor and storing that measurement as a digital value is called analog to digital conversion. The measurement is called a digitized measurement. Analog to digital conversion documents will also call them quantized measurements.
The Ardunio’s map Function
In the PhototransistorVoltage sketch, we converted measurements from the 0 to 1023 range to the 0.0 to 4.995 volt range for display. For other applications, you might need to convert the value to some other range of integers so that your sketch can pass it to another function, maybe for motor control, or maybe for more analysis.
That's where the Ardunio’s map function comes in handy. It's useful for “mapping” a value in one range of integers to an equivalent value in some other range. For example, let’s say you want to map a measurement in the 0 to 1024 range to a range of 1300 to 1700 for servo control. Here is an example of how you could use the map function to do it:
int adcVal = analogRead(A3);
int newAdcVal = map(adcVal, 0, 1023, 1300, 1700);
In this example, if the value of adcVal is 512 , the result of the map function for the newAdcVal call would be 1500 . So, the measurement got mapped from a point about half way through the 0..1023 range to its equivalent point in the 1300...1700 range.
A resistor “resists” the flow of current. Voltage in a circuit with a resistor can be likened to water pressure. For a given amount of electric current, more voltage (pressure) is lost across a larger resistor than a smaller resistor that has the same amount of current passing through it. If you instead keep the resistance constant and vary the current, you can measure a larger voltage (pressure drop) across the same resistor with more current, or less voltage with less current.
The Arduino’s analog inputs are invisible to the phototransistor circuit. So, A3 monitors the circuit but has no effect on it. Take a look at the circuit below. With 5 volts (5 V) at the top and GND (0 V) at the bottom of the circuit, 5 V of electrical pressure (voltage) makes the supply of electrons in the BOE Shield-Bot’s batteries want to flow through it.
The reason the voltage at A3 (VA3) changes with light is because the phototransistor lets more current pass when more light shines on it, or less current pass with less light. That current, which is labeled I in the circuit below, also has to pass through the resistor. When more current passes through a resistor, the voltage across it will be higher. When less current passes, the voltage will be lower. Since one end of the resistor is tied to Vss = 0 V, the voltage at the VA3 end goes up with more current and down with less current.
If you replace the 2 kΩ resistor with a 1 kΩ resistor, VA3 will see smaller values for the same currents. In fact, it will take twice as much current to get VA3 to the same voltage level, which means the light will have to be twice as bright to reach the 3.5 V level, the default voltage in HaltUnderBrightLight to make the BOE Shield-Bot stop.
So, a smaller resistor in series with the phototransistor makes the circuit less sensitive to light. If you instead replace the 2 kΩ resistor with a 10 kΩ resistor, VA3 will be 5 times larger with the same current, and it’ll only take 1/5th the light to generate 1/5th the current to get VA3 past the 3.5 V level. So, a larger resistor makes the circuit more sensitive to light.
Connected in Series When two or more elements are connected end-to-end, they are connected in series. The phototransistor and resistor in this circuit are connected in series.
Two properties affect the voltage at VA3: current and resistance, and Ohm’s Law explains how it works. Ohm’s Law states that the voltage (V) across a resistor is equal to the current (I) passing through it multiplied by its resistance (R). So, if you know two of these values, you can use the Ohm’s Law equation to calculate the third:
In some textbooks, you will see E = I × R instead. E stands for electric potential, which is another way to say “volts."
Voltage (V) is measured in units of volts, which are abbreviated with an upper-case V. Current (I) is measured in amperes, or amps, which are abbreviated A. Resistance (R) is measured in ohms which is abbreviated with the Greek letter omega (Ω). The current levels you are likely to see through this circuit are in milliamps (mA). The lower-case m indicates that it’s a measurement of thousandths of amps. Similarly, the lower-case k in kΩ indicates that the measurement is in thousands of ohms.
Let’s use Ohm’s Law to calculate VA3 in with the phototransistor, letting two different amounts of current flow through the circuit:
The examples below show the conditions and their solutions. When you try these calculations, remember that milli (m) is thousandths and kilo (k) is thousands when you substitute the numbers into Ohm’s Law.
Example 1: I = 1.75 mA and R = 2 kΩ
Example 2: 1 = 0.25 mA and R = 2 kΩ
Let’s say that the ambient light in your room is twice as bright as the light that resulted in VA3 = 3.5 V for bright light and 0.5 V for shade. Another situation that could cause higher current is if the ambient light is a stronger source of infrared. In either case, the phototransistor could allow twice as much current to flow through the circuit, which could lead to measurement difficulties.
Question: What could you do to bring the circuit’s voltage response back down to 3.5 V for bright light and 0.5 V for dim?
Answer: Cut the resistor value in half; make it 1 kΩ instead of 2 kΩ.