A while back I was reading about bidirectional led sensing. Basically, the idea is that you light the LED, and then switch the potential across it, setting the anode to low, and the cathode to high. Since it's a diode, the LED pulls the cathode low. Apparently, the time it takes for the cathode to fall low is dependent on the amount of ambient light -- if we measure that time, then we have a rudimentary sensor.
I tried coding it, and no matter what, it didn't work. I came across a Benoit Rousseau's post on the arduino forum about this. It turns out that there are pullup resistors built-into the Atmega168, and I believe this means that it'll interfere by pulling the cathode high, while sensing with the cathode...? I may be wrong. Anyhow, the solution is to disable those pull-up resistors with the code:
_SFR_IO8(0x35) |= 4; _SFR_IO8(0x35) |= (1<<4);
The final code was:
/* LED sensor -- photodiode.
*/
int anodePin = 2;
int cathodePin = 8;
int wait = 10;
int value;
void setup()
{
//deactivates pullup resistors?
_SFR_IO8(0x35) |= 4;
_SFR_IO8(0x35) |= (1<<4);
pinMode(anodePin, OUTPUT); // sets the digital pin as output
pinMode(cathodePin, OUTPUT); // sets the digital pin as output
Serial.begin(9600);
}
void loop()
{
value = 0;
//emit light
digitalWrite(anodePin, HIGH);
digitalWrite(cathodePin, LOW);
delay(50);
//switch potentials -- charge LED to -5V
digitalWrite(anodePin, LOW);
digitalWrite(cathodePin, HIGH);
//measure time for potential to equalize (for cathode to be LOW)
//switch pinmode
pinMode(cathodePin, INPUT);
//measure time it takes for cathodePin to go to zero
//this value probably depends on the chip clock or something
while(digitalRead(cathodePin) != 0)
value++;
pinMode(cathodePin, OUTPUT);
digitalWrite(anodePin, HIGH);
digitalWrite(cathodePin, LOW);
Serial.println(value, DEC);
}
Success! I also added code later to light a separate LED when the time for the LED sensor's cathode to drop to low would be higher than a certain threshold: