As a result of the questions from lekirst  on this ible of my hand: LED-as-lightsensor-on-the-arduino/ and the cleaner code made by hansc44 at:  Arduino-Use-LED-as-a-light-sensor/ it was time to come with a better Ible. So here it is. (I didn't solve lekirst's problems yet so she probably is open for suggestions)

What is the idea?

You might know that a LED emits light when you put the right amount of volts on the right leads. The funny thing is that it also works the other way around. Not the leads, it doesn't work when you put the leads the other way around. But what does work is that when you shine light on a LED it will GIVE current. It is a very small current but just enough for an Arduino to detect.

What will it do?

When you darken the sensor led, for instance by covering it with your hand, it will turn on the other LED.

Does this work with any LED?

As far as I know, it works with any LED, but not with any LED as good.
green and red LEDs seem to work best.
If trough experimenting you find out that other colors even work better, let me know.

Does it work with any light?

This sketch works very reliable with normal daylight. It is not fully tested in dark rooms or bright sunlight yet.

Step 1: You Will Need

You will need
  • an Arduino board (Uno, Duemilanove or something like that)
  • two LEDs
And really that's it! (you could even do it with just one LED and use the SMD-LED on the Arduino board as the second LED)

You will need no tools.

You do need a computer with the Arduino software installed and a USB-cable to connect the Arduino board. (But if you have an Arduino board, you probably have that sorted already)

Step 2: Setting Everything Up

To set this project up, you just need to put the two LED's in the Arduino.
  • Put the LED that you want to use as the sensor with the long lead (this is the anode and positive lead) in pin analog 3 in the Arduino. This could also be an other analog pin, but then you need to change this in the sketch later on.
    Put the other, short lead in the GND.
  • Put the other LED with the long lead in pin (digital) 13 in the Arduino. Put the short lead in the GND that is next to pin 13.

Now you just need to hook up the Arduino board with the computer and the fun can begin.

Step 3: Uploading the Sketch

//Copy the following sketch in your Arduino software and upload it to the Arduino board. (be sure to select the right board and com-port in the Arduino software)

int led = 13;                                        // the pin where you will put the LED
int sensorpin = A3;                           // the analog pin where you put your sensorLED
int resetteller = 0;                              // the rest are counters and variables to calculate with
int sens = 0;
int teller = 0;
int basis = 1024;
int test = 1024;
int test2 = 1024;
int test3 = 1024;

// this are the values to play with to get better (or worse) results
int marge = 5;                         // the space between a positive and negative reading
int vertraging = 1;                  // the speed of the readings; a lower number is a higher speed
int samples = 70;                   // the amount of samples to compare to make one reading
int resetsamples = 30;          // how many cycles to run the light on before you don't trust the value anymore

void setup() {
  pinMode(led, OUTPUT);
  Serial.begin(9600);                                   // no real part of the program, just for debugging
  for(teller =0; teller < samples; teller++) {// remember the lowest value out of many readings
   sens = analogRead(sensorpin);
   if (sens < basis){basis = sens;}
   delay(vertraging);                                     // the sensor needs a delay here to catch its breath

void loop() {                                            
for(teller =0; teller < samples; teller++) {// remember the lowest value out of many readings
   sens = analogRead(sensorpin);
   delay(vertraging);                                   // the sensor needs a delay here to catch its breath
   if (sens < test){
   test3 = sens;                                            // remember the 3 lowest readings
   test2 = test3;
   test = test2;}
  if (test < basis-marge && test2 < basis-marge && test3 < basis-marge){//all 3 low readings mus be < the basis reading
    digitalWrite(led, HIGH);
    resetteller++;                                         // count how long the LED stays on
      digitalWrite(led, LOW);
      basis = test;                                         // if the lowest test reading is higher than the basis, basis will be reset
      resetteller = 0;
    if (resetteller > resetsamples){basis = test;}//if LED stays on to long, we don't trust it and reset basis
    Serial.print(basis);Serial.print("  ");Serial.print(test);Serial.print("  ");Serial.println(sens);//just for debugging
    test = 1024;

Step 4: About the Sketch

What does it do?

When you darken the sensor led, for instance by covering it with your hand, it will turn on the other LED.

Why is this one better?

This sketch works much more reliable than the previous version.
This sketch has the serial monitor functionality.
All the tweaking is done in the top of the sketch with four variables.
I did put a lot more explanations in the sketch

Is this sketch perfect?

No, it is far from perfect, but is works great most of the time. Sometimes it doesn't work at all for no apparent reason. But when it works, it will keep on working for hours.
Besides that does it still not do what lekirst wants it to do: The LED sensor is also the emitting sensor that stays on as long as it is touched.
I'm sorry that I use Dutch names for the variables some of the time, but that is because Dutch isn't Dutch to me.

How to tweak

You can change the "marge". This will set how sensitive the sketch will be for light changes. A low value is a high sensitivity.

When you change the "vertraging" you can set the speed of the sensor. A low value is a high speed. My Arduino doesn't work when I set it al the way to 0, but with 1 it works most of the time. Somehow the Arduino needs a short rest in-between sensing.

With the "samples" you change the accuracy of the sketch. More samples is a higher accuracy, but with a higher value it will also react slower.

The last value you can tweak is the "resetsamples". This value sets how long the sketch will accept a low reading on the sensor (and turn on the LED) until it doesn't trust it anymore and reset the sensor back to zero.

What else?

Well if you want to put your emitting LED in an other pin, you should change the value of "led" to the number of the pin you want to use.
The same goes for the value of "sensorpin" if you want to use an other analog pin for your sensor LED.

You might notice that the LED turns off after a short time when I keep my hand over the sensor. This is because of the "resetsamples" value. When you increase this value, the LED will stay on longer. But when the sensor makes a mistake because of changing light or something, it also takes longer for the sketch to correct this.
<p>Use code below for real light sensing with LED.</p><p>Connections: LED's cathode to GND pin, LED's anode to A0 pin (Anode is smaller part in LED)</p><p>you can see result on pin13 arduino's built in led, also serial terminal</p><p>Green or red classic 5mm LEDs gives best result</p><p>--------------------------------------------------------------------------------------------</p><p>// the setup routine runs once when you press reset:</p><p>void setup() {</p><p> // initialize serial communication at 9600 bits per second:</p><p> pinMode(13, OUTPUT);</p><p> Serial.begin(9600);</p><p>}</p><p>// the loop routine runs over and over again forever:</p><p>void loop() {</p><p> // read the input on analog pin 0:</p><p> int sensorValue = analogRead(A0);</p><p>Serial.println(sensorValue);</p><p> if (sensorValue &lt; 50) { digitalWrite(13, HIGH);}</p><p>else if (sensorValue &gt;= 50) { digitalWrite(13, LOW);}</p><p>else { // digitalWrite(led, HIGH);</p><p>delay(500);</p><p>digitalWrite(13, LOW);}</p><p>}</p>
<p>This does not use the LED as a light sensor but rather an antenna. It picks up 50/60Hz noise from the grid. If you put your hand close to the LED without changing the incident light you will see the thing still &quot;working&quot;. If you remove the LED and replace it with a small wire it will continue &quot;working&quot;.</p>
<p>Any elaboration on how it should be done?</p>
<p>Search for an article (and a video) from Scott E. Hudson: &quot;Using Light Emitting Diode Arrays as Touch-Sensitive Input and Output Devices&quot;. He reverse biases the LED and then waits for the LED capacitance to discharge. The discharge rate is correlated to the leakage current and thus is light dependent. </p>
<p>I found your description on my search for building a &quot;reactive light&quot; for geocaching and I'm very happy since most examples I had were for ATTINY in BASCOM. (google for the german &quot;Reaktivlicht&quot;). But it seems there is a small error in your code (which doesn't make any problems but it will not work as intended according to your comments. Look here:</p><blockquote>if (sens &lt; test){<br> test3 = sens; // remember the 3 lowest readings<br> test2 = test3;<br> test = test2;}<br> }<br><br> if (test &lt; basis-marge &amp;&amp; test2 &lt; basis-marge <br>&amp;&amp; test3 &lt; basis-marge){//all 3 low readings mus be &lt; the <br>basis reading</blockquote><p>After </p><blockquote>test3 = sens; // remember the 3 lowest readings<br> test2 = test3;<br> test = test2;}</blockquote><p>test, test2 and test3 will have the same value (sens), therefore your if statement will just compare the lowest reading.</p><p>So you could just use </p><blockquote>if (sens&lt;test) test=sense;</blockquote><blockquote>}<br></blockquote><blockquote>if (test &lt; basis-marge &amp;&amp; test2 &lt; basis-marge &amp;&amp; <br>test3 &lt; basis-marge){//all 3 low readings mus be &lt; the basis <br>reading</blockquote><blockquote>...<br></blockquote><p>instead.</p><p>If you want to be less tolerant and require that all three lowest values stay below basis - merge you could use the following:</p><p>for ....{ ...</p><p>if(sens &lt; test3) {</p><p>if(sens &lt; test2) {</p><p>if(sens &lt; test) { // sens is smaller than all three test values</p><p>test3 = test2;</p><p>test2 = test;</p><p>test = sens;</p><p>} else { // sens is smaller than test3 and test2 but not than test</p><p>test3 = test2;</p><p>test2 = sens;</p><p>}</p><p>} else { // sense is smaller than test3 but not smaller than test2 and test</p><p>test3 = sens;</p><p>}</p><p>} // after this you have test &lt; test2 &lt; test3!</p><p>}</p><p>if (test3 &lt; basis-marge){//all 3 low readings mus be &lt; the basis <br>reading</p><p>digitalWrite(led, HIGH);</p><p>resetteller++; // count how long the LED stays on</p><p>}</p><p>Since nobody complained so far this discussion may be purely academical. Somaybe you should just use the version from my comment to keep your code shorter.</p>
<p>Hello Dirk,</p><p>Yes I see what you mean. That's what happens when you are writing code at night :), but somehow it works very reliable for me. It looks like one reading might be enough.</p><p>Thank you for looking into the code.</p>
<p>What you made is some sort of antenna (in this case EM detector) on the A0 pin. Try to put your hand near the sensor LED but not between the LED and the light and you will see. BTW is true LED can act like light sensors but you will need an amplifier.</p><p>To see that i'm right take off the LED and pass your hand over the Arduino A0 pin ;)</p><p>And if you put a wire on this port the effect will be amplified.</p>
I know how to use the A0 port as an EM detector, but this is not it. You will see that it value changes with light changes and for my 4x4x4 interactive led-cube I used the same methode with shielded wires.
Can you put the link to the video or put the video?<br>Thank you.
<p><a href="https://www.instructables.com/id/4x4x4-interactive-LED-cube-with-Arduino/" rel="nofollow">https://www.instructables.com/id/4x4x4-interactive-LED-cube-with-Arduino/</a></p>
<p>I will try again the circuit but i'm sure that it is the same problem. A0 allways give these values and reacts to small charge changes. Thank you btw.</p>
Can you put the link to the video or put the video?<br>Thank you.
<p>used to work ,now not working</p>
That's strange? what is different? Other LED? longer leads?
<p>Great enhancment </p><p>please keep going further </p><p>can you tell me how can i make it sense more than one LED like putting 2 more sensing leds and operate the same ? </p><p>thanks a lot</p>
<p>You can use as many sensing led's as you have analog ports at your disposal. Just be sure to use shielded wire to connect them. If you don't use shielded wire the interference in the air might confuse the Arduino.</p>
<p>Thanks for fast replay.</p><p>What i mean is that the code will be different, i tried to add more LEDs and modify the code in the Arduino software but i cannot make it for 2 more led sensors please help me doing it for total of 3 leds and 3 digital output(each LED sensor has its own digital output).</p><p>Thanks again</p>
<p>Can you send me the code you wrote? So I can see what went wrong. You might use personal mail for that.</p>
<p>kindly waiting for your email</p><p>have a good day</p>
<p>I can't find where you send the code.</p>
<p>nice! i made it and is working nice!</p>
cool! are you using it for something special?
I do not know what happened, but when I back anywhere on the board until the blue side and the LED flashes
What do you mean with &quot;when I back anywhere on the board until the blue side&quot;?
Using an Arduino for this is a waste of a million transistors. Use the LED to turn on another transistor used as a simple switch. That could cost less than $1. Add a relay or higher current transistor, SCR, Triac or whatever for higher current.
To get this working for less than 1,- and without all the code, that would be really great. If you get it working, please post the schematics and/or write an Ible about it. I would be really interested in that schematic. (I do know that I can easily do this with an ATTINY45, but that is still the same as this, just with a cheaper IC)
I have tried to post a reply with a schematic attached, but every time I attempt to upload the schematic (a .jpg file) it deletes my explanatory comments, as it is failing to upload the file. <br>I decided to use an op-amp instead of a transistor because of the enormous gain and other features available with op-amps, and their ridiculous low price ($0.13 for an LM358AN, for example). The circuit also requires 3 resistors, and that's all. I'll try again another day.
Amazing project! Good job. <br>The setup is so sensitive that it works off the electrical pulses off my hand when I touch the analog pin.
That would be a nice follow-up project :)
Clear LEDs will usually work better than colored or frosted ones. Also avoid the white ones. The phosphor will produce higher losses. While it is interesting that LEDs can be used as light detectors, for practical designs it is best to use a photodiode.
Hi Kenyer; <br>Pretty much all LED work as Photo Voltaic sensors. All the way from InfraRed to UltraViolet. <br> <br>Nick Holonyak, http://en.wikipedia.org/wiki/Nick_Holonyak, <br>and Oleg Losev, http://en.wikipedia.org/wiki/Oleg_Losev, <br>who invented LEDs understood their PV action, but it was generally not know in the industry. <br>Later, Forrest Mims, http://en.wikipedia.org/wiki/Forrest_Mims, <br>is credited with the &ldquo;Mims Effect&rdquo;. <br> <br>My own work is with using LEDs in solar trackers. <br> <br>redrok <br>
Thank you for this info and links. I didn't know this about Mims. Do you have a link to the solar trackers you work with?<br><br>I did know that all LEDs (that I tested) work, but not all LEDs give the same result. Some LEDs give a much higher range than others. Until now, green is my personal favorite.
LEDs work by having a band gap corresponding to the wavelength of light that they emit. Electrons drop from higher potential (caused by applying a voltage) to a lower potential, the 'height' determined by the band gap, they lose this energy by emitting a photon. No electrons can exist in an intermediary energy level so you get a single wavelength of light emitted (formula wise, band gap energy = planck's const. x light frequency ). The reason we've only had certain colour LEDs more recently, blue, for instance is due to better understanding of semiconductors and how to fabricate them. <br> <br>The inverse is also true - when you shine light on an LED, you're exciting electrons in the valence band. If you give them sufficient energy to jump the band gap, then they will and you'll see the effect as a current. The caveat is that only photons with energy greater than the band gap will cause conduction. You'll probably find that infrared LEDs work best due to their smaller band gap compared to say UV. <br> <br>This is identical to the way that a standard silicon (or whatever) photodiode can produce a current from incident light. The difference is that the bandgaps involved in these semiconductors are non-radiative - they don't emit light when you put a potential difference across them. <br> <br>And of course this means you can never get a truly white LED. You have to mix different band gap semiconductors to approximate the light. Tungsten, by comparison has a very broad spectral output, but this is simply due to black body radiation (and therefore has a main peak that roughly correlates with its temperature, so you can make 'cool' or 'warm' lighting easily).
Numbers wise, a GaAs red led has a bandgap of around 1.4eV, corresponding to 875nm, or 'red'. A silicon photodiode has a bandgap of 1.1eV which goes to 1100nm. So any light 'redder' than this won't be absorbed because the electrons can't be raised to a high enough energy level (think about jumping next to a cliff, if you jump high enough from the ground you can reach the top, but there's nowhere to stop inbetween). <br> <br>There'a an upper limit too, due to the quantum efficiency of the material. This tells you how many electrons are produced per incoming photon. As you go shorter, the response of the detector gets worse. This is a pretty good diagram for a silicon solar cell: <br> <br>http://pvcdrom.pveducation.org/CELLOPER/Images/QE.gif
Very good work. Maybe it could enhance if you isolate visually both LEDs, because the red light incides on the white LED when you darken it.
Forrest Mims, let me give you a lot of credit for my early interest in LEDs all those years ago. <br>An interest that now builds the mother of all mother, futuristic LED displays. <br>https://www.facebook.com/#!/wayne.masters.35
I can see someone creating a solar panel made of LEDs. Great instructable.
Nice Job man ! <br> <br>P.S: Doing Electronics was ad are my best friend in my whole age , It is also my job for more than 10 years <br>Enjoy electronics my friend for ever ! <br> <br>Take Care .... Mohammad
Connecting an LED to a digital output port, without an added series current-limiting resistor, will stress and potentially damage the output port. In engineering terms, it violates Kirchoff's voltage law, particularly for LEDs with a lower forward voltage (like red). For a short-term experiment, you can probably get by with it. But in the long term, add the resistor to keep the Arduino (and your LED) within their designed safe operating region.
This is very true! Pin 13 on the Arduino is the exemption on this rule because it has a resistor build in what makes it very handy for easy experiments like these: http://playground.arduino.cc/uploads/Main/arduino_notebook_v1-1.pdf<br><br>Still it is very good that you mention this.
Your LED is going to pull too much current. Put in a 330 ohm or larger resistor to decrease the current.
Nice project! I've read orange LEDs are the best as light sensors.
Thank you for the info, I will try that.

About This Instructable




Bio: I'm a social-worker, working with 12 - 23 year-olds. I used to be a printer and I worked voluntarily in Romania for a couple of ... More »
More by kenyer:Stop Motion Puppet Armature Life-size Hamster Ball Dodecahedron Deodorant Powder 
Add instructable to: