noob question on analogRead fluctuations

Having recently acquired a smiley micros kit (Arduino Duemilanov ATMega 328) I'm playing around with the examples. I have a LM35 temperature sensor on analogue A0 and a light sensor on A1. I'm using analogRead in the loop (with 500mS delay) to read the values from A0 and A1 and serial.print to write them back to my computer (baud rate 19200 connected through USB cable).

The light sensor on A1 seems to return a rock solid value but the temperature sensor on A0 seems to fluctuate between a reading of 37 and 41 and yet my volt meter on the LM35 output is rock steady at 205mV.

Interestingly, if I stop calling analogRead(A1) for the light sensor the fluctuations on A0 temp sensor are far less (39/40).

Can anyone explain this?

Thanks

Post the actual code you are using.

Do you have the delay between reads

analogRead(A0)
delay(500)
analogRead(A1)

or elsewhere like

analogRead(A0)
analogRead(A1)
delay(500)

It's possible the LM35 has a high output impendance so the sample & hold cap is not getting charged properly.

What happens if you swap the reads around, does the problem follow the LM35?

Either way post your code.


Rob

Code below.

I tried swapping the light sensor and temp sensor around on A0/A1.

If I comment out the readAnalog on the light sensor the readings on the temp sensor seen less erratic.

The commented out code was when I was trying to send a reading only when a switch was pressed.

#define LEDPIN 9
#define BUTTONPIN 8
#define DEBOUNCE 10
#define LIGHTPIN A1
#define TEMPPIN A0

int reading = 0;
int count = 0;
boolean ledstate = false; //state of LED
int lightvalue = 0;  // light sensor value
int tempvalue = 0; // temperature sensor value

void setup()
{
      pinMode(BUTTONPIN, INPUT);
      pinMode(LEDPIN, OUTPUT);
        pinMode(LIGHTPIN, INPUT);
        pinMode(TEMPPIN, INPUT);
      Serial.begin(19200);      // opens serial port, sets data rate to 19200 bps

}

void loop() 
{
      //while (count < DEBOUNCE) {
      //      checkButton();
      //}
      count = 0;
      //if (ledstate == true) {
      //      Serial.println("switching led off");
      //      digitalWrite(LEDPIN, LOW);
      //      ledstate = false;
      //} else {
      //      Serial.println("switching led on");
      //      digitalWrite(LEDPIN, HIGH);
      //      ledstate = true;
      //}
      lightvalue = analogRead(LIGHTPIN);
      Serial.print("light value: ");
      Serial.println(lightvalue, DEC);
        delay(500);
      output_temperature(TEMPPIN);

      
}

void output_temperature(int pin)
{
    int whole;
    int fractions;
    
      // ADC range is 0 to 5v returning a number 0 to 1023
      // so it is 5/1024 = 0.0049V/ADCunit or 4.9mV/ADCunit

      // LM35 guarantees 0.5% accuracy at at 25C
      // LM35 outputs 10mV per degree C

      // so if we read N from the port the temperature is
      // N*4.9/10 
      tempvalue = analogRead(pin);
        Serial.println(tempvalue, DEC);
        whole = tempvalue * 49 / 100;
        fractions = (tempvalue * 49) % 100;
      Serial.print("temperature: ");
      Serial.print(whole, DEC);
        Serial.print(".");
        Serial.println(fractions, DEC);
}

void checkButton()
{
      reading = digitalRead(BUTTONPIN);
      if ((reading == LOW) && (count < DEBOUNCE)) {
            count++;
      } else {
            if (count > 0) count--;
      }
}

Nothing to do with the fluctuations but I noticed the following: void output_temperature(int pin) contains two ints whole and fraction. As an int (16 bit) can hold only +- 16384 as value. The reading * 49 causes an overflow. Define whole as a long (32 bit) and the math would go right.

You could also define a float for temperature, try this:

float tempvalue = analogRead(pin);
tempvalue = tempvalue * 4.9 / 10;
Serial.print("temperature: ");
Serial.print(tempvalue , 2);   // 2 decimals

robtillaart, thanks but the sensor is sat on my desk so I'm not that worried about integer overflow as the temperature would have to be so hot I would not be here. The LM35 outputs 10mV for 1 degree. 25 degrees is 250mv = 51 ADC units. 51 * 49 = 2891. I' need 330 odd ADC units to overflow and that would be 330 * 4.9mV = 1617 mv = 161 degrees centigrade.

Your point is taken though and I was rather blindly followed the arduino workshop book. I knew about floats but hadn't noticed the arduino supported them.

Thanks

Try to ground the unused analog pins, this have sometimes helped others with similar problems.

Haven't changed a thing and this morning the same setup is showing values from the ADC of 21 to 63 yet my multimeter shows 162mV constant.

I tried grounding the remaining analogue inputs and it does not help.

A second look at your code doesn't show serious error in the SW, so time to scrutinize the HW. Can you make a drawing or photo of how you connected the LM35 and lightsensor to the Arduino?

The LM35 pinout in the arduino workshop book (looking from the front with the flat face facing me) is:

v+
out
gnd

The v+ I connected to the +5 rail.
The out is connected to A0
The gnd is connected to gnd

The picture of the setup is at http://www.martin-evans.me.uk/P1030925.JPG

and

http://www.martin-evans.me.uk/P1030927_cropped.jpg

Are you using long wires from the sensors to the Arduino board ?

Wires are no more than 10cm.

I would try to strip the circuit so only the temp. sensor is attached to Arduino and the see how the readings look.

10 cm. wires should be ok

If the input is too high impedance the input sample and hold capacitor won't have time to charge. Try taking tow readings of the same analogue input in succession and only use the second one. If that helps but does not completely cure the problem try putting a small delay between the first and second reading of the same pin.

I'll come back to Grumpy_Mike's suggestion.

I've disconnected everything from the arduino except the LM35 and disconnected everything on my breadboard (see picture) from the +5 and gnd.

At ambient temp in my room I get values from 29 to 34 jumping around all the time (representing 14.21 degrees C to 16.66 degrees C) and also this seems a little low, I'd expect it was around 18/19 degrees C and this represents around 180mV (18 degrees C).

Interestingly if I put my fingers over the LM35 it rises to an adc value of 57 and is consistent then when I remove fingers it steadily drops (no jumping around by more than 1) back to 38 or so then the jumping around starts again.

From here:
http://www.ladyada.net/learn/sensors/tmp36.html

Problems you may encounter with multiple sensors...

If, when adding more sensors, you find that the temperature is inconsistant, this indicates that the sensors are interfering with each other when switching the analog reading circuit from one pin to the other. You can fix this by doing two delayed readings and tossing out the first one

The link:

A user in the customer forums had a problem with multiplexing analog signals, they seemed to be very noisy and inconsistent. Turns out it was because the sensors are high impedance. This means that if there is capacitance on the ADC line or on any sort of sample&hold capacitor, it may take a while for it to charge up. Read these threads for some great analysis! View here and here?

Hope this helps...

Hope this helps.

well it's just what I said isn't it?

well it's just what I said isn't it?

Yes, of course. Additionally the second link has link to forum threads with example code too.

Just in case: I've found this while struggling somewhat similar problem with analog sensor on a breadboard: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1291144300

But mine works ok if connected without anything directly to Arduino. Have you tried to eliminate breadboard?

well it's just what I said

As did I back in reply #2. However the spec sheet does say "low-impedance output", whatever that means.


Rob

As did I back in reply #2.

Well not quite, you were saying:-
analogRead(A0)
delay(500)
analogRead(A1)

where as I was saying:-
analogRead(A0)
delay(500)
analogRead(A0)