Problem on starter kit project 3 Love-O-Meter

Hello.
I’m new to arduino and electronic.
I was doing a starter kit project 3 Love-O-Meter and expanded the project from 3 LED to 6 LED.
3 Red LED is to measure the hot environment and 3 Blue Led is to measure the cold environment.
But, i am facing a problems during this project and i would like to ask a few question.
My question is :

  1. Why the temperature shown in the serial monitor is sometimes unstable ?

But when i touch the sensor, the temperature increase and it become stable.

  1. Why the temperature shown the in serial monitor changed drastically when i shake or move the breadboard or arduino for a few cm ?

  1. Is the code i write to measure the cold environment is the simplest one or are there more simplest than this ?
const int sensorPin = A0;
const float baselineTemp = 27.0;

void setup()
{
  Serial.begin(9600);
  for(int pinNumber = 2; pinNumber < 8; pinNumber ++)
  {
    pinMode(pinNumber, OUTPUT);
    digitalWrite(pinNumber, LOW);
  }
}

void loop()
{
  int sensorVal = analogRead(sensorPin);

  Serial.print("Sensor Value : ");
  Serial.print(sensorVal);
  
  float voltage = (sensorVal/1024.0)*5.0;

  Serial.print("Volts : ");
  Serial.print(voltage);
  Serial.print("Degrees C : ");

  float temperature = (voltage-.5)*100;

  Serial.println(temperature); 

  if(temperature >= baselineTemp+2 && temperature < baselineTemp+4)
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }

  else if(temperature >= baselineTemp+4 && temperature < baselineTemp+6)
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }

  else if(temperature >= baselineTemp+6)
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }

  else if (temperature < baselineTemp && temperature >= baselineTemp-2)
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }

  else if (temperature < baselineTemp-2 && temperature >= baselineTemp-4)
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
  }

  else if (temperature < baselineTemp-4)
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, HIGH);
  }

  else
  {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
  }

  delay(1);
}

Thank you very much.

Hi,

Its a combination of several things.

First the sensor is very sensitive, even a slight draft can change the temperature quickly.

The power supply needs to be very stable to be very accurate.

The components in the breadboard are always a source of poor connection , hence why touching the board causes the signals to change.

The long wires from the Uno to the breadboard are also a source open to interference.

If you built the circuit onto some soldered board with short leads you should get much better results.

Because sensors like this can be prone to such problems , it often better to take several readings ,then average them to produce an actual result.

If you see the data sheet of the tmp36 they suggest you fit a 100nf acfross the +5v and 0v rails as close to the TMP36 as possible.

As for your code, then that is probably contributing to the problem.

You main loop time just has a delay of 1ms, + the few instructions, however during that loop, lets say 20ms in total, you can be turning several leds on and off, this can affect the stability of the main 5v rail ( depending on the current the leds take) and if the 5v rails changes slightly, then so will the voltages for the TMP36 and the ADC reading.

Also, and without getting too technical, the ADC section needs a little time to settle between each reading, which its not getting, so sugest you increase your delay at the end of the loop or just before your read the sensor, to at least 100ms.

No reason you cannot increase it to 1 second, then you will get a more readable result on the serial monitor instead of them zooming past.

Hello ricky101, thanks for replying :slight_smile:

I see, so the problem comes from sensor, wire, and breadboard. But if the sensor is very sensitive, does it categorized as good sensor ?

Why soldered board is better than solderless breadboard ?

I tried to changed the delay to 100, 1000 and it gives me difference result. The 1000 is more stable than 100 :slight_smile:

Im planning to applicate this project to measure my room temperature in the future, should i keep using the TMP36 or should i change it to other sensor ?

Thanks ! :slight_smile:

Hi,

There is nothing wrong with the sensor, its that the connection within the breadboard can lead to problems as they do not always make a good contact with the component,

Is your breadboard new ? an old or dusty one can olny make the contact problem worse.

The signal from the sensor only has to loose a few millivolt to affect your displayed temperature.

Thats why a soldered joint is always better.

Try cutting some breadboard wires down to about 25mm /1 " and soldering the cut ends of three wires to the TMP36 and then plug the other ends directly into the Arduino connectors.

That should improve your results.

If soldering is not possible, then use the shortest wires between the sensor and Arduino.

You can leave your leds on the breadboard as the are not affected in the same way as the sensor.

Here’s a nifty way to average your readings, to make them even MORE stable.

  int sensorVal = analogRead(sensorPin);

// INSERT THESE LINES

  int i; //Create variable for loop
  for (i = 0; i < 10; i++){
    sensorVal = sensorVal + analogRead(sensorPin);    // Read analog pin ten times, adding them
  }
  sensorVal = sensorVal / 10;    // Divide by 10 to get the average (Stabilizes the display a lot!)

// YOUR CODE CONTINUES

float voltage = (sensorVal/1024.0)*5.0;


  Serial.print("Sensor Value : ");
  Serial.print(sensorVal);

This will take 10 samples and average them, resulting in a much more stable reading. Since the max value from an analog pin is 1023, an integer variable will hold 10203 (the max times ten)

I used this in a simple voltmeter system I was working on, and it helped a LOT. :slight_smile:

A bigger problem with the code is the use of default Aref.

An LM35 with default Aref only gives an A/D value of about 40 at a temp of 20C.
A ~0.5C step size.
The code prints this with two decimal places. 40 A/D values to 20.00 (2000 values).
That will give will be huge gaps in the readout. See the first screenshot.
26.17 jumps to 25.68 (as expected, a 0.49C granularity).

A ~5x improvement is possible by using 1.1volt Aref.
And throw in some averaging ofcourse.
Example sketch attached.
Leo…

// LM35 temp sensor connected A0

unsigned int total; // A/D readings
float tempC; // Celcius
float tempF; // Fahrenheit

void setup() {
  analogReference(INTERNAL); // use the internal ~1.1volt reference | change to (INTERNAL1V1) for a Mega
  Serial.begin(9600);
}

void loop() {
  // read the sensor
  for (int x = 0; x < 64; x++) { // 64(max) analogue readings for averaging
    total = total + analogRead(A0); // add each value
  }
  // temp conversion
  tempC = total * 0.001632; // Calibrate by slightly changing 0.0016xx
  tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit

  Serial.print("The temperature is  ");
  Serial.print(tempC, 1); // one decimal place
  Serial.print(" Celcius  ");
  Serial.print(tempF, 0); // no decimal places
  Serial.println(" Fahrenheit");

  total = 0; // reset total
  delay(1000); // slows readings
}