Arduino reading different voltages than a multimeter

Hello!
I know that LEDs can produce a voltage when light shines on them. First, I connected the cathode (short pin) of my LED to the black lead of the multimeter, and the anode (long pin) to the red lead of the multimeter. I shined a flashlight on a green LED, and the voltage was >0.2V on the multimeter. Next, I connected my LED's cathode to Arduino's GND and anode to analog input A0. I used the default voltage reference, and did this operation on the analogRead() of the pin.

voltage = rawADC * 5.0 / 1024.0;

I shined the same flashlight on the LED and the voltage was >1.5V! I tested it on my multimeter again. Why does the Arduino read the voltage as about 1.5V when the multimeter reads it as about 0.2V?
Thanks!

Perhaps they have different input impedance.

A depending on how directly you shine the light the multimeter definetly has too low impedance, unless you have a good one
Take a peak with an oscilloscope, (1M impedance usually) and add large value resistors in parallel and watch the responses, its pretty cool
the best thing you can do is use an opamp so the measuring impedance doesn't affect it
also use a blue led or white and you'll get 3v full brightness,

What is "input impendance"? Perhaps the LED's cathode potential is at +1.3 and the anode potential is at +1.5? The Arduino GND brings the cathode potential to 0, so the analogRead() result is 1.5V? I don't have an oscilloscope. I don't know how to use op-amps, and which op-amp to use.

Input impedance:
Your multimeter looks like a 100k or 1M resistor to the LED.
The Amalog Input looks like a 10k. correction from mike below.)

Also, you're using such a few number of bits on the a/d you'll have quantization error. You might try using the INTERNAL analogReference() which is 1.1V instead of 5.

Before posting, I also tried the 3.3V reference. The results were the same. But how come the Arduino can measure the voltage of an AA battery properly?

The Amalog Input looks like a 10k.

No you are mixing up the idealise source impedance with the actual input impedance. An arduino is likely to be in the range of 1M or so.

But how come the Arduino can measure the voltage of an AA battery properly?

Because the battery has a very low output impedance. That is it can supply far more current than an LED given the same voltage.
It is rather like the difference between temprature and heat. A spark has a very high temprature but there is very little heat in it. So one can land on your hand with little damage. A cup of boiling water is about 100 times cooler than a spark but has much more heat ( specific heat ) so it burns you far more seriously.

I don't know anything about using LEDs as light sensors... I would guess it's unreliable or it would be done more often...

The simplest way to eliminate the impedance issue is to hook-up the multimeter and the Arduino at the same time.

If the LED is acting like a high-impedance voltage source (like I said, I don't know), you could be picking-up noise. (The noise should be about the same with the light shining on it or not.)

It's likely that the multimeter has some filtering to smooth-out noisy readings. So with a noisy signal, the meter reading could be lower and more stable even if they are both reading the exact same voltage at the exact same time. (If you had an oscilloscope you could see if there is noise.)

and note if the Arduino's response changes, should you measure a different voltage with the Arduino connected you will have your answer...

Doc

Unless you are shining a light directly into it very brightly the led will only put out 4mv with ambient light
kinda cool you can see the switching frequency of flourescent bulbs with an led detecting ambient light and an oscilloscope

winner10920:
kinda cool you can see the switching frequency of flourescent bulbs with an led detecting ambient light and an oscilloscope

I'm not sure if the LED responds fast enough. Another way to to measure light with an LED is to hook it up backwards (anode to GND, cathode to digital pin). First, the digital pin turns into output and HIGH. That will charge up the LED's "parasitic capacitor". Then, the pin switches to input, and the Arduino times how long the "parasitic capacitor" takes to discharge. In complete darkness, it can be more than a second, but in direct bright light, it takes only about 0.02 seconds. I got that from http://provideyourown.com/2011/cheap-alternative-for-hard-to-find-cds-light-sensor/. This is the code:

class AmbientLightSensor {
public:
  AmbientLightSensor(int ledPin) : mLedPin(ledPin), mMeasureAnalog(false) {}
 
  void setAnalogMeasurement(int thresholdLevel); // measure from an analog pin
  void setDigitalMeasurement(); // measure from a digital pin (default)
 
  int measure();

protected:
  int mLedPin;
  bool mMeasureAnalog;
  int mAnalogThresholdLevel; // (0 to 1023)
 
  void charge();
  void discharge();
 
  int measureUsingAnalogPin();
  int measureUsingDigitalPin();
};
 
void AmbientLightSensor::setAnalogMeasurement(int thresholdLevel)
{
  mAnalogThresholdLevel = thresholdLevel;
  mMeasureAnalog = true;
}
 
void AmbientLightSensor::setDigitalMeasurement()
{
  mMeasureAnalog = false;
}
 
void AmbientLightSensor::charge() {
  // Apply reverse voltage, charge up the pin and led capacitance
  pinMode(mLedPin, OUTPUT);
  digitalWrite(mLedPin, HIGH);
}
 
void AmbientLightSensor::discharge() {
  // Isolate the diode
  pinMode(mLedPin, INPUT);
  digitalWrite(mLedPin, LOW); // turn off internal pull-up resistor, see http://arduino.cc/en/Tutorial/DigitalPins
}
 
int AmbientLightSensor::measure() {
  charge();
  delay(1); // charge it up
  discharge();
  return (mMeasureAnalog)? measureUsingAnalogPin() : measureUsingDigitalPin();
}
 
int AmbientLightSensor::measureUsingDigitalPin() {
  long startTime = millis();
  // Time how long it takes the diode to bleed back down to a logic zero
  while ((millis() - startTime) < 2000) { // max time we allow is 2000 ms
    if ( digitalRead(mLedPin)==0) break;
  }
  return millis() - startTime;
}
 
int AmbientLightSensor::measureUsingAnalogPin() {
  long startTime = millis();
  // Time how long it takes the diode to bleed back down to a logic zero
  while ((millis() - startTime) < 2000) { // max time we allow is 2000 ms
    if ( analogRead(mLedPin) < mAnalogThresholdLevel) break;
  }
  return millis() - startTime;
}
AmbientLightSensor led(12); // LED is hooked up to digital pin 12
 
int led2 = 9; // led to indicate darkness is hooked up to digital pin 9
 
void setup()
{
  Serial.begin(9600);
  pinMode(led2, OUTPUT);
}

void loop()
{
  analogWrite(led2, map(constrain(led.measure(),0, 400), 0, 400, 0, 255));
  Serial.println(led.measure());
}

This way is more sensitive, but slow responding

Docedison:
and note if the Arduino's response changes, should you measure a different voltage with the Arduino connected you will have your answer...

What?

Yeah it is also an issue as the Fluorescent Lights actually turn off and on 60 times a second and this has to be filtered for some light detection schemes. My employer was an engineer, he came to me one day and explained that a photo detector he made "Hummed" but only at night and when I got through chuckling I told him to put a 100 uf cap on the output of the detector switch and add a diode and resistor to discharge the cap.... I made a color detector 25 years ago that fit in a hollow cane (aluminum tubing) for the blind... It would work nicely at night to detect which traffic light was on, Red, Yellow or Green. I used the 60 hz signal on the led's output to detect the traffic light but it was easily "Falsed" by Neon signs. LED's are much higher in intensity and sensitivity is much better now. I have a night light that uses 170uA and works well on a 2032 Lithium coin cell so I don't kill myself going to the WC at night. But with 35 - 40 mA driving it it makes a great blue flashlight... too bright for me to sleep. 20 Candela's advertised (20,000 milli candelas) and about $0.10 each. An LMC6022 and a couple of resistors makes a nice, Very low current photo-detector that will swing rail to rail from a 9V battery. Great @ 5V too I used them a lot.

Doc

Well I know the led responds fast enoughbecause I've seen it, lol not only the 60hz but the multiple Khz switching frequency, which we would never see fluctuating with our eyes but the led can see

winner10920:
Well I know the led responds fast enoughbecause I've seen it, lol not only the 60hz but the multiple Khz switching frequency, which we would never see fluctuating with our eyes but the led can see

I meant detecting light, not lighting up.

Well yeah, I mean with just an led hooked up to an oscope, you can see the switching frequency of the flourescent, from that led detecting it

voltage = rawADC * 5.0 / 1024.0;

That formula is wrong for a start.

There are two things wrong with it:

  1. You should be dividing by 1023.0 not 1024.0
  2. It will only be accurate if your Vcc is actually 5V. It rarely is, so you might want to measure it and change the 5.0 to the real value.

Better still, check out my how to make accurate ADC readings on the Arduino posting:

winner10920:
Well yeah, I mean with just an led hooked up to an oscope, you can see the switching frequency of the flourescent, from that led detecting it

Okay. But I don't have any oscilloscope. The LED is sensitive enough? Some old computers have flickering screens.
Is the Arduino correct, or the multimeter correct on the voltage the LED produces?

Grumpy_Mike:
A spark has a very high temprature but there is very little heat in it.

And it is very quick and small. The heat energy is very packed. But the boiling water has more heat energy overall.

The Arduino ADC input is CMOS, its DC input impedance will be very high (>10 thousand megohms perhaps, common for CMOS inputs), much more than the multimeters which is likely to be 10M or so for a modern meter.

The only clue I could find from the datasheet is that the analog comparator input leakage is <= 50nA, which indicates 100M ohms or more (the ADC block diagram indicates that an analog comparator is also used there).

An LED with a light shined on it is an almost perfect current source until its voltage gets high enough for the LED to start conducting (about 1.5V in fact). The voltage across its terminals will depend directly on the resistance placed across them (up to the point when
it starts to conduct). (This is the action of a photo-voltaic cell).

The higher the input resistance the better a voltmeter - the only reason multimeters don't have the same extremely high input impedance as a CMOS ADC is the network of voltage dividers on the input that allows range-selection and the protection circuitry.

So the Arduino is acting as a much better voltmeter for high impedance sources than your multimeter!

majenko:
You should be dividing by 1023.0 not 1024.0

Arduino Playground - Thermistor2 Elaborate Code is wrong then. I was using 3.3V reference (actually 3.27V) with no difference,

MarkT:
An LED with a light shined on it is an almost perfect current source until its voltage gets high enough for the LED to start conducting (about 1.5V in fact). The voltage across its terminals will depend directly on the resistance placed across them (up to the point when
it starts to conduct). (This is the action of a photo-voltaic cell).

So what resistor should I place across the leads? So if I connect many LEDs in series, it can act as a solar cell? What do you mean by the first sentence in this quote?

  1. You should be dividing by 1023.0 not 1024.0

I disagree, it is a 10 bit A/D, so there are 1024 divisions it can use. 1023 is the top number sure but when mapping a continuous value to a digital value using 1024 will put the true value in the middle of the digital increments. Using 1023 will put the true value at the transition of the digital value.

He means that once the voltage gets above a certain point then the LED stats to short it out.