PDA

View Full Version : Using LEDs as light sensors



skimask
- 30th December 2006, 09:54
Has anybody ever done this? Used an LED to sense light, basically use it as a touch panel?
I was doing some reading in the good book (otherwise known as 'The Art of Electronics') and found a section talking about this, so I figured I'd try it out.
I ended up with a string of 7 IR LEDs, anodes to a common pin, cathodes to different pins on a PIC18F4620, all pins are schmidt trigger types (PortD, PortC, PortA.4, etc. The TTL inputs draw too much current and don't give a decent reading). I've also got an LCD hooked up for a display of whatever was going on.

Jist of the story, the software runs, I've got the LEDs lined up in a row, I run my finger over (but not touching) the IR LEDs, I set up a block on the LCD to basically follow my finger running over the IR LEDs! This is neat.

To read the IR LEDs, set 2 pins as output. You first forward bias the IR LED (one pin high, one pin low) for about 1ms. Next you reverse bias (high goes low, and low goes high) to essentially 'charge' them up for another 1ms or so (every diode has a certain amount of capacitance when reverse biased. Then you set the pin that's high when the LED is reverse biased to an input. Immediately after that you set up a counter inside a tight if/then. When the input changes from a 1 to a 0 (because the voltage 'stored' in the LEDs capacitor is decaying), you save the count and exit the if/then. The count you get when you exit the if/then is inversely proportional to the amount of light hitting the IR LED, the lower the number, the more the light; the higher, the darker. I then compare all of the numbers, looking for the lowest number and display a solid block in that character position.

Here's a snippet of example code (without the generic sections like LCD defines, config settings, etc. oh, and my PIC is running at 40mhz, I don't know how well it'll work at slower speeds, if at all.):


looper var byte : anode var porta.1 'common anode of all IR LEDs
t1 var portc.5 : t2 var portc.4 : t3 var portc.1 : t4 var portc.0 : t5 var porte.2 : t6 var porte.1 : t7 var porta.4 'all IR LEDs cathodes pins

touchval var word[7] : touchmin var word[7] : touchmax var word[7] : touchrange var word[7] : touchpos var word[7] : touchaverage var word[7]
touchmidpoint var word[7] : maxval var byte : maxtemp var word

skipsubs: 'generic setup I use for all my programs, YMMV
flags=0 : pause 1000 : intcon=0 : intcon.7=1 : intcon.6=1 : intcon.5=1 : intcon2=0 : intcon2.2=1 : intco3=0 : pir1=0 : pir2=0 : pie1=0 : pie1.5=1 : pie1.4=1 : pie2=0 : t0con=0 : t0con.7=1 : t0con.6=1
t0con=t0con+2 : t1con=0 : t2con=0 : t3con=0 : ccp1con=0 : ccp2con=0 : pwm1con=0 : eccp1as=0 : sspstat=0 : sspcon1=0 : sspcon2=0 : txsta=0 : txsta.6=0 : txsta.5=1 : txsta.4=0 : txsta.2=1 : rcsta=0
rcsta.7=1 : rcsta.6=0 : rcsta.4=1 : baudcon=0 : baudcon.3=1 : spbrgh=4 : spbrg=16 : adcon0=0 : adcon1=$f : adcon2=$ff : cmcon=7 : cvrcon=0 : hlvdcon=0 : trisa=0 : porta=0 : trisb=0 : portb=0 : trisc=0
portc=0 : trisd=0 : portd=0 : trise=0 : porte=0 : input switch1 : input switch2 : output led1 : led1=1 : led1=0 :pause 200 : led1=1 : pause 200 : led1=0 : pause 200 : led1=1 : pause 200 : led1=0 : pause 200
led1=1 : pause 200 : led1=0 : pause 200 : led1=1 : pause 200 : led1=0 : pause 200 : lcdout $fe,1 : switchignorecount=0 : menu=1 : switchdelay=1000 : output serialdataoutputpin : input serialdatainputpin

touchmin = 65000 : touchmax = 100

loop2:
led1 = counter.0
for looper = 1 to 7 'light an LED, even though you can't see it
output anode : anode=1 : input t1 : t1=0 : input t2 : t2=0 : input t3 : t3=0 : input t4 : t4=0 : input t5 : t5=0 : input t6 : t6=0 : input t7 : t7=0
select case looper
case 1
output t1 : t1 = 0
case 2
output t2 : t2 = 0
case 3
output t3 : t3 = 0
case 4
output t4 : t4 = 0
case 5
output t5 : t5 = 0
case 6
output t6 : t6 = 0
case 7
output t7 : t7 = 0
end select
pause 1 : anode = 0
select case looper 'reverse bias that same LED
case 1
output t1 : t1 = 1
case 2
output t2 : t2 = 1
case 3
output t3 : t3 = 1
case 4
output t4 : t4 = 1
case 5
output t5 : t5 = 1
case 6
output t6 : t6 = 1
case 7
output t7 : t7 = 1
end select
pause 1
select case looper 'switch that LED to an input to read it
case 1
input t1
case 2
input t2
case 3
input t3
case 4
input t4
case 5
input t5
case 6
input t6
case 7
input t7
end select
loop3a:
'run a counter in a tight loop (loop3a) and keep checking and waiting for the particular LED input to drop from a logic 1 to a logic 0 because the voltage sitting on the LED due to the internal capacitance drops 'slowly'
touchval[ looper ] = touchval[ looper ] + 1 : if touchval[ looper ] > 65000 then goto kickoutloop3a
'if we wait too long or the pin is stuck, we'll never get out of the loop
select case looper
case 1
if t1 = 1 then goto loop3a
case 2
if t2 = 1 then goto loop3a
case 3
if t3 = 1 then goto loop3a
case 4
if t4 = 1 then goto loop3a
case 5
if t5 = 1 then goto loop3a
case 6
if t6 = 1 then goto loop3a
case 7
if t7 = 1 then goto loop3a
end select
kickoutloop3a:
counter = counter + 1 'just a counter to show a 'heartbeat'
next looper

maxval = 0 : maxtemp = 0 'maxval keeps track of which led had the lowest value, maxtemp keeps track of the lowest value

for looper = 1 to 7 'check al 7 LEDs to find the lowest one
if touchval[ looper ] > maxtemp then
maxtemp = touchval[ looper ] : maxval = looper
endif
next looper

'clear out the line, then display the number of the darkest LED
lcdout $fe,$80," ":lcdout $fe,$80+(7-maxval),DEC1 (7-maxval ) : lcdout $fe,$c0," ":lcdout $fe,$c0+(7-maxval),$ff
for looper = 1 to 7 : touchval[ looper ] = 0 : next looper
goto loop2
END


For some reason, this only seems to work with the IR LEDs I have on hand. That might be because they are all cheap LEDs. Somebody might get this to work with visible light LEDs, I don't know. Then I wonder if this will work with those bargraph LEDs. You could do something silly like those slider thingies on Star Trek where they run their fingers up a panel and the lights follow.
As soon as I get some more ambition, I'm going to post this little project on my webpage along with a short clip of it in action, some schematics, etc.etc.

Like I said, I'm getting a kick out of this....
Maybe somebody else will too...

bbarney
- 30th December 2006, 16:53
have a look at this post
http://www.picbasic.co.uk/forum/showthread.php?t=3624

Dave
- 30th December 2006, 17:16
skimask, I have built a version of a solar tracker about 2 or 3 years ago using Green Led's as light sensors with great success. Here is a link to a site I found about 2 years ago with some circuits for an interface. I have since gone over to using the TSL-230 light to frequency sensors as they have a wider light to dark ratio. I hope this helps.....
http://www.redrok.com/electron.htm#chaceshadow

Dave Purola
N8NTA

skimask
- 30th December 2006, 23:19
have a look at this post
http://www.picbasic.co.uk/forum/showthread.php?t=3624


skimask, I have built a version of a solar tracker about 2 or 3 years ago using Green Led's as light sensors with great success. Here is a link to a site I found about 2 years ago with some circuits for an interface. I have since gone over to using the TSL-230 light to frequency sensors as they have a wider light to dark ratio. I hope this helps.....
http://www.redrok.com/electron.htm#chaceshadow

Dave Purola
N8NTA


Shucks...and I thought I might be 'first' (in a relative way of thinking) at something.
Oh well.... :(
I'm whipping up a small page on my site right now. The code works great, and it's neat to watch at any rate.
Thanks for the link guys. I've got a bit more info to work with now.

Video/writeup posted to my web page.