Pseudo Analog Input on a Digital Pin

I was using a simple pair of resistors to form a voltage divider to feed bright/dark info from the LED of a USB NiteLite to an ESP-01, and in trying to tweak the design a bit I came across an idea on the Adafruit site: Using a Photocell I’d forgotten about. I’ve used this before on an ESP-12 project, so it’s perfect for those times you don’t have a free analog input pin. The example below is wired to the TX pin (pin 1) of an ESP-01. If this is going to be exposed to bright light an additional resistor before the input pin to limit current flow might be a good idea.

The idea is that by changing the pin state to cause the capacitor to alternately drain or store a charge, and timing the rise to logic-high while it’s charging, you can get an idea of the amount light falling on an LDR (light dependent resistor, or CdS photocell).

A graph from my ‘scope shows what a 10k photocell and a 0.1uF capacitor looks like in moderate light:

The code below does this. Not shown is a delay(1)  to space things out for the scope image which isn’t needed for real use. It returns the counts (not milliseconds) from initialization to logic-high.

int getLDR () {
  // Set and then read an LDR

  int counter = 0;

  // Discharge to initialize
  pinMode(AMB_PIN,OUTPUT);  
  digitalWrite(AMB_PIN,LOW);          

  // Block the pin by setting it to input
  pinMode(AMB_PIN,INPUT);
  while ( digitalRead( AMB_PIN ) == LOW ) {
    counter++;

    if ( counter > 32000 ) {
      break;
    }
  }

  // done
  //Serial.println(counter);
  return counter;
  
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.