MSP430 Launchpad: LED as PhotoDiode

Posted by on February 28, 2011

Story:

I’ve been meaning to build a “line seeker” robot for a while now, however I can’t source LDRs (Light Dependent Resistor) due to RoHS nonsense, so I decided to use plain old LEDs instead. While you could use a couple analog amplifiers and comparators to do this I thought it would be a fun little microcontroller project.

Right now we’re just exploring how to utilize a regular LED as a photo-diode, ie. an input sensor.

There are a couple ways to accomplish this – I chose the simplest for the time being – The idea is to sample the voltage present on the LED anode (or cathode!) by using the ADC on the MSP430, this voltage will be relative to the ambient light. You could picture the LED as a solar cell in this case.

The code:

We’re going to use the on-board LEDs on the LaunchPad to simplify things. The Red LED will be our “sense” input and the Green LED will be used to depict the current state of the sensor.

You’ll have to modify the header (and your project target) depending on which MCU you’re using, I happen to have a G2452 currently populated for another project I’m working on, but you can use any value-line MCU as long as it’s got an ADC.

/* LED as Photo-Sensor
 / By: Gustavo J. Fiorenza (GuShH - info@gushh.net)
 / No external components required, simply shine a light to the RED onboard LED!
 /
 / Note: Tested on a G2452 only, should also work with other value-line MCUs.
*/

#include "msp430g2452.h"	// Change the header to "msp430x20x2.h" if you're using the default MCU bundled with the LaunchPad.

#define LED_SENSE INCH_0 	// LED 1 (Red LED from LaunchPad).

unsigned int adcval = 0;

unsigned int analogRead(unsigned int pin) {

  ADC10CTL0 = ADC10ON + ADC10SHT_2 + SREF_1 + REFON + REF2_5V;
  ADC10CTL1 = ADC10SSEL_0 + pin;

  ADC10CTL0 |= ENC + ADC10SC;

  while (1) {
    if ((ADC10CTL1 ^ ADC10BUSY) & ((ADC10CTL0 & ADC10IFG)==ADC10IFG)) {
      ADC10CTL0 &= ~(ADC10IFG +ENC);
      break;
    }
  }

  return ADC10MEM;
}

void main(void) {
	unsigned int i, delay;

	WDTCTL = WDTPW + WDTHOLD;	// Hold the watchdog.
	P1DIR = BIT6; // LED 2 (Green LED from LaunchPad).

	while (1){

		// Multi-sampling (8 samples with delay for stability).
		adcval = 0;
		for ( i=0; i < 8; i++ ) {
			adcval += analogRead( LED_SENSE );	// Read the analog input.
			delay = 1000;
			while (--delay);
		}
		adcval >>= 3; // division by 8

		// Interpret the result
		if ( adcval < 500 ){
			P1OUT |= BIT6;	// Turn on the onboard Green LED.
		}else{
			P1OUT = 0x00;	// Turn off the entire Port 1, thus turning off the LED as well.
		}

	}

}

Why so vague?

Lately I've been suffering a serious mental block, I would really like to explain the theory behind all this but not only am I uninspired I also can't focus on writing... I would however recommend you Google "LED Sensor" (or similar query) to learn more about the subject.

Have fun.