3

I built this thermometer that reads the sensor value from the temperature sensor and displays it on the LCD display. It basically works fine, but the displayed temperature shows a fluctuation between +/-2 degrees due to varying sensor value and voltage every second. (This is my very first Arduino project and I am pretty new to electronics.) The Arduino gets the power via my Mac through USB.

When I check the sensor value and voltage, it slightly differs each second (or whatever delay interval I use in my code). Sensor value is between 123-125 and voltage usually 0.7, but also changes slightly, which causes the temperature calculation to vary around 2 degrees, which for a "thermometer" is quite a lot.

Is there any way to stabilize it? Should I use a capacitor or another resistor?

enter image description here

enter image description here

Code:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const float powerSupply = 5.0;
const int sensorPin = A0;
const float baselineTemp = 23;

void setup() {
  Serial.begin(9600);   
  lcd.begin(16, 2);
  lcd.print("Temperature:");
}

void loop() {
  int sensorVal = analogRead(sensorPin);
  Serial.print("Sensor Value: ");
  Serial.print(sensorVal);

  float voltage = (sensorVal/1024.0)*powerSupply;
  Serial.print(", Volts: ");
  Serial.print(voltage);

  Serial.print(", degrees C: ");
  float temperature = (voltage - .5)*100;
  Serial.println(temperature);

  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(temperature);      
  // lcd.print(String(sensorVal) + ", " + String(voltage) + ", " + String(temperature));    
  delay(1000);
}
4

What you need to do is take an averaged reading, this is because the sensor is always fluctuating, noise on the 5V line or the signal line. There are possible hardware solutions.

  • Adding a capacitor between Vcc and Gnd near the sensor, 0.1µf
  • Adding a low-pass filter on the signal line of the LM35 to Arduino
  • heatsink on the LM35(they are very sensitive to movement, giving odd readings)

The capacitor on the Vcc and Gnd will lessen the effects of voltage spikes from the rest of the Arduino's circuitry.

The low-pass filter will help give a more filtered output from the sensor with a better response over time.

                2.2k
LM35>---------/\/\/\-0------<Arduino
                     |
                     |
                     |
                    === 1µF
                     |
                     |
                    GND

The heatsink will allow the LM35 to get a better reading of the general temperature and not the temperature of the breeze from a window.

All three of the above solutions will probably give the best results.

What you could do in software too is to have an averaging algorithm/function in your code and actually take the averaged reading across the whole second that you delay the MCU.

An example of this would be:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const float powerSupply = 5.0;
const int sensorPin = A0;
const float baselineTemp = 23;
int sensorVal = 0;

//these are NEW
unsigned long lastTime = 0;     // last time reading taken
unsigned long currTime = 0;     //current time variable intialised
float AverageReading = 0;

float _readingAv = 0;   // static variable for keeping the averaged reading
int _readingsCount = 0;
int _readings = 100;     //the number of readings to take

void setup() {
  Serial.begin(9600);
  //  lcd.begin(16, 2);
  //  lcd.print("Temperature:");
}

void loop() {
  currTime = millis();


  if ((currTime - lastTime) < 1000) {  //checks to see if a second has passed
    sensorVal = analogRead(sensorPin);

    if (_readingsCount < _readings) {
      _readingAv += sensorVal; //add the current value to the last
      _readingsCount++;
    }
    else {
      AverageReading = _readingAv / _readings; //get the average
    }
  }
  else {
    Serial.print("Sensor Value: ");
    Serial.print(sensorVal);

    float voltage = (AverageReading / 1024.0) * powerSupply;
    Serial.print(", Volts: ");
    Serial.print(voltage);

    Serial.print(", degrees C: ");
    float temperature = (voltage - .5) * 100;
    Serial.println(temperature);

    //~ reset the values used by the previous function
    _readingsCount = 0;
    lastTime = currTime;
    _readingAv = 0; //Important to set this back to 0 so not to get odd values

    // set the cursor to column 0, line 1
    // (note: line 1 is the second row, since counting begins with 0):
    lcd.setCursor(0, 1);
   // print the number of seconds since reset:
    lcd.print(temperature);
    // lcd.print(String(sensorVal) + ", " + String(voltage) + ", " + String(temperature));
  }

}

Probably a better version of making filtering code of the LM35.

1

There are a few things you might try to stabilize your readings.

  1. Add a small ceramic capacitor, say 22pF between the analog signal from the temp sensor (green on your example) and ground;

  2. Perform multiple reading from your analog, let's say 10, discard max. and min. values and calculate the average. Use this instead of a single reading;

  3. User the "internal" voltage as reference. It's normally more stable than using the external 5V. Just bear in mind that you might need to use a voltage divider as the "interval" voltage reference max value is 1.1V (https://www.arduino.cc/en/Reference/AnalogReference);

  4. Reduce the wire sizes and make sure all connections are OK.

Probably just by using technique number "2" listed above you'll get much more stable results and don't need any hardware, just a small looping. Also adding the capacitor would be quite simple.

Hope it helps. Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.