2

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.

1
  • 1
    You 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, Sep 7, 2016 at 15:29

3 Answers 3

1

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:

  1. Every digital input is fitted with a Schmitt trigger which makes it hysteretic, meaning the voltage threshold for switching from LOW to HIGH is higher than the threshold for switching from HIGH to LOW. If the pin voltage is between the two thresholds, it will read either HIGH or LOW, 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.

  2. 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.

1

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);

Source of Quote

3
  • 1
    The 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 is LOW, anything in between is not guaranteed. The “typical” thresholds are 2.6 V for the LOWHIGH transition and 2.1 V for HIGHLOW. These are different thresholds because of the hysteresis introduced by the Schmitt trigger at the inputs. 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
    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 read HIGH (good), but it will also read HIGH across a significant range of voltages where you expect it to read LOW (bad). Sep 7, 2016 at 9:12
0

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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.