How to use an led as a sensor.


For this little howto we are going to use an avr to detect light levels using an LED. Thanks to all the sources I stole, er researched information from. er on.
Oh, and thaks to all the people who didn't help, including acidhex who said he would do this with me and RAN AWAY.
eherm...

STEP 1)

Collect the things you need...

CLEAR TABLE SPACE. You need some blooming clear table space.




Your avr microcontroller, this is my Babyboard III, uses an Atmega32



The power supply for your microcontroller


An LED and a resistor for it, this is one of my RCCON LEDs


Your AVR programmer, this is my buffered parallel port one.


Step 2)


Plug the power into your microcontroller.


Step 3)


Next plug in your led.


Step 4)

Load up your avr ide, compile and flash this code to it:

/*******************************************************************************
 Rue's "is it alive" program for avr processors
  also makes a good skel to build your programs form ;)
 
  16Mhz
  Red LED with clear lens.
*******************************************************************************/

/*



1     PB0 <- led
2      PB1
3      PB2 <- led
4      PB3
5      PB4
6     PB5
7     PB6
8     PB7
9     PA0
10    PA1       
11    PA2
12    PA3 
13    PA4  
14    PA5 
15    PA6   
16    PA7
17    PC7
18      PC6
19      PC5
20      PC4
21      PC3
22      PC2
23      PC1
24      PC0
25      PD7
26      PD2
27      PD3
28      PD4
29      PD5
30      PD6


 This example shows one way of using an LED as a light sensor.
 You will need to wire it up like this:

           + port B0
           |
           <
           > 470 ohm resistor
           <
           |
           |
         -----
          / \  5mm red led with a clear lens
         -----
           |
           |
           + port B2

 What we are going to do is apply a positive voltage at port B0 and
 a low voltage at port B2. This is backwards for the LED, current will
 not flow and it will not light, but we will charge up the
 capacitance of the LED junction.

 Then we are going to disconnect the output drivers from PORT B0 and
 count how long it takes to discharge. The brighter the light, the
 lower the capacitance and the faster is will lose its charge.

 The rest of this app here will watch the led and toggle its on/off state
 when it sees a 'dark happen' :)

*/


#include <avr/io.h>

// misc
#define SetBit(BIT, PORT)        PORT |= (1<<BIT)
#define ClearBit(BIT, PORT)      PORT &= ~(1<<BIT)
#define IsHigh(BIT, PORT)       (PORT & (1<<BIT)) != 0
#define IsLow(BIT, PORT)        (PORT & (1<<BIT)) == 0
#define NOP()                    asm volatile ("nop"::)

#define OUTPUT             1
#define INPUT              0
#define HIGH               1
#define LOW                0

#define LED_CATHODE        2
#define LED_ANODE          0
#define LED_PORT           PORTB
#define LED_DDR            DDRB
#define LED_INPUT          PINB

// this determines a 'light level cutoff' if it sees less than 3000 units
// it gives up. this mixes with the contrast delay you will read about later
#define JMAX              3000

void Delay(int delay);
void Delay2(int delay);
int readLED( char onoff );

int main (void) {

  unsigned int val;
 
  char oncount, onoff;

  // set up directions
  DDRA = (INPUT << PA0 | INPUT << PA1 |INPUT << PA2 |INPUT << PA3 |INPUT << PA4 |INPUT << PA5 |INPUT << PA6 |INPUT << PA7);
  DDRB = (OUTPUT << PB0 | OUTPUT << PB1 |OUTPUT << PB2 |OUTPUT << PB3 |OUTPUT << PB4 |OUTPUT << PB5 |OUTPUT << PB6 |OUTPUT << PB7);
  DDRC = (INPUT << PC0 | INPUT << PC1 |INPUT << PC2 |INPUT << PC3 |INPUT << PC4 |INPUT << PC5 |INPUT << PC6 |INPUT << PC7);
  DDRD = (INPUT << PD0 | INPUT << PD1 |INPUT << PD2 |INPUT << PD3 |INPUT << PD4 |INPUT << PD5 |INPUT << PD6 |INPUT << PD7);       

 onoff   = 0;
 oncount = 0;
 val     = 0;
 
  while (1) {
   if (val < 600)  // light level for us to decide to switch, depends on contrast delay
     oncount++;
   else
     oncount = 0;
  
   // 4 counts before we toggle
   if (oncount == 2) {
     if (onoff) onoff = 0;
     else       onoff = 1;
   }
  
   val = readLED(onoff);
  
   // leave it like that for a bit before we do the next reading.
   Delay(15000);
  }
 
}

void Delay(int delay) {
  int x;
  for (x = delay; x != 0; x--) {
    asm volatile ("nop"::);
  }
}
void Delay2(int delay) {
  int x;
  for (x = delay; x != 0; x--) {
    Delay(65000);
  }
}


int readLED(char onoff) {
  unsigned int j;

  // Apply reverse voltage, charge up the pin and led capacitance
  SetBit(LED_CATHODE, LED_DDR ); //  OUTPUT
  SetBit(LED_ANODE,   LED_DDR ); //  OUTPUT
  SetBit(LED_CATHODE, LED_PORT); // HIGH
  ClearBit(LED_ANODE, LED_PORT); // LOW
  Delay(5);
 
  // Isolate the cathode of the LED
  ClearBit(LED_CATHODE, LED_DDR); //  INPUT
  ClearBit(LED_CATHODE, LED_PORT); // turn off internal pull-up resistor

  // Count how long it takes the led to discharge to a logic zero
  // this can take almost like 1/4 second!
  //   In the dark j is lower and takes longer.
  for ( j = JMAX; ((j) && (IsHigh(LED_CATHODE, LED_INPUT))); j--) Delay(45); // this delay controls contrast 

  // leave the led on if they wanted it like that
  if (onoff != 0) {
    SetBit(LED_ANODE,     LED_PORT);  // anode high
    ClearBit(LED_CATHODE, LED_PORT);  // cathode low
    SetBit(LED_ANODE,     LED_DDR);   // output
    SetBit(LED_CATHODE,   LED_DDR);   // output
  }
 
  // return the brightness value
  return j;
}

// find me if you want to know how to read 8 leds with 9 io pins. :)



Step 5)

Play.





Step 6)
Make a better howto and post it!