I need to use multiple photocells as input, but its more than the amount of analog pins that my arduino has.
I'm wondering if theres any way to use a photocell as a digital input, with the photocell triggering at a specific set threshold of light.
It doesn't seem quite possible but I thought I'd ask.
-
1You might like to look at analog multiplexor ICs. The 4051 is popular. It uses 3 digital lines to select 1 of 8 analogue inputs. I found a page describing the 4051 on arduino.cc: playground.arduino.cc/Learning/4051 I hope this helps. Regards,Michael Vincent– Michael Vincent2016年09月07日 15:29:24 +00:00Commented Sep 7, 2016 at 15:29
3 Answers 3
I see two possible options for achieving what you want:
Voltage divider
This is the solution proposed by William Roy: you make a voltage divider circuit and check whether it gives a voltage above the threshold of the digital input. For example:
+5V ---+
|
R
|
+--- digital input
|
LDR
|
GND ---+
There are a couple of issues with this approach though:
Every digital input is fitted with a Schmitt trigger which makes it hysteretic, meaning the voltage threshold for switching from
LOW
toHIGH
is higher than the threshold for switching fromHIGH
toLOW
. If the pin voltage is between the two thresholds, it will read eitherHIGH
orLOW
, as determined by the history of that voltage. Depending on your application, this may not be a problem, and may even be desirable. But if you want, as you wrote in your question, "a specific set threshold of light", it sure will be problematic.You do not know what those threshold voltages are. The datasheet of the ATmega328P (the main chip of the Uno) states that they should "typically" be around 2.1 and 2.6 V, but it only guarantees that the low threshold should be no less than 1.5 V and the high threshold no more than 3 V. For any input voltage between 1.5 and 3 V (which is a very significant range), the chip manufacturer doesn't guarantee what the pin will read.
The first issue can be solved by using a write-before-read protocol: first you set the pin to OUTPUT LOW, which will force the input Schmitt trigger to the LOW state. Then you set it to INPUT and take a reading. This way you will read HIGH if and only if the pin voltage is above the high threshold. The low threshold becomes irrelevant. Example code:
/*
* Read the given pin avoiding the input hysteresis.
*
* Returns HIGH if the pin voltage is above the upper (LOW to HIGH)
* threshold, LOW otherwise.
*
* WARNING: The pin is set to OUTPUT LOW for a very short time.
*/
int anhystereticRead(uint8_t pin) {
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
pinMode(pin, INPUT);
return digitalRead(pin);
}
The second point can be solved by calibrating your input using a trimpot instead of a resistor. You would adjust the pot until the threshold is exactly what you want. Using fixed resistors instead of a pot will make it very difficult to achieve your "specific set threshold of light", unless you can live with a very rough precision.
Capacitive measurement
The second option is use the LDR as the resistor in an RC circuit, and measure the charging time of the circuit, like this:
digital output --- LDR ---+--- digital input
|
capacitor
|
GND
Starting with a discharged capacitor, you set the output to HIGH
and
measure how long it takes for the input to read HIGH
. This time is
typically something like 0.73 R C, where R is the
resistance of the LDR and C the capacitance of the capacitor. The
exact numerical factor is not know, as it depends on the high threshold
voltage of the digital pin.
For details and example code, you could check the Capacitance Meter and RC Time Constants Arduino tutorial, or search the Web for "Arduino capacitance meter". You will find material about how to measure an unknown capacitance using a know resistance, but you can use the same technique to measure an unknown resistance using a known capacitance. And you should replace the waiting loop:
while (analogRead(input) < THRESHOLD) {} // wait
by a similar loop using the digital input threshold:
while (digitalRead(input) == LOW) {} // wait
The interesting thing about this technique is that you do not need a trimpot to set the illuminance threshold: you will measure the charging time and set the threshold in software. Also, this technique is not affected by the input hysteresis. The main drawback is that the measurement takes longer than the voltage divider technique.
Edit: I found a blog post describing this exact method in greater detail: Measuring resistance or voltage with 1 digital I/O, by Moser.
Yes, you can use LDRs(photocells) as an indirect digital input.
You can design a voltage divider circuit, which incorporates your LDR and gives LOW or HIGH digital readings based on your pre-calibrated threshold light values.
Your voltage divider circuit must reach a specific voltage for your wanted light threshold to give you a HIGH reading.
The following are the voltage thresholds guaranteed to be read as HIGH.
When a pin is configured as an INPUT with pinMode(), and read with digitalRead(), the Arduino (Atmega) will report HIGH if:
a voltage greater than 3 volts is present at the pin (5V boards); a voltage greater than 2 volts is present at the pin (3.3V boards);
-
1The numbers you quote are not the voltage thresholds: they are the lowest voltages where the pin is guaranteed to be read as high. On the Uno, more than 3 V is
HIGH
, less than 1.5 V isLOW
, anything in between is not guaranteed. The "typical" thresholds are 2.6 V for theLOW
→HIGH
transition and 2.1 V forHIGH
→LOW
. These are different thresholds because of the hysteresis introduced by the Schmitt trigger at the inputs.Edgar Bonet– Edgar Bonet2016年09月06日 20:45:12 +00:00Commented Sep 6, 2016 at 20:45 -
I'd suggest using a potentiometer, so you can tweak at which light level the pin goes high/low.Gerben– Gerben2016年09月07日 08:04:51 +00:00Commented Sep 7, 2016 at 8:04
-
You wrote: "Your voltage divider should observe this thresholds". No, it should not. If it does, then the pin is guaranteed to read
HIGH
when you expect it to readHIGH
(good), but it will also readHIGH
across a significant range of voltages where you expect it to readLOW
(bad).Edgar Bonet– Edgar Bonet2016年09月07日 09:12:18 +00:00Commented Sep 7, 2016 at 9:12
LDR in a Wheatstone bridge + OpAmp as a comparator
For more (temperature...) stability of your LDR threshold it could be better to use a wheatstone bridge instead of a simple voltage divider.
Then you can send the output of your wheatstone (or your divider) to a simple OpAmp comparator circuit that will output High or Low, which you can plug in any digital port.
To know more on Wheatstone and OpAmp: (you can use directly the last schema by plugging the output of the Opamp to the digital pin of your arduino (instead of sending it to the transistor)
http://www.electronics-tutorials.ws/blog/wheatstone-bridge.html
Hope that can help,
Gaetan
Explore related questions
See similar questions with these tags.