Help with weird analog input problem (unstable analog reference)

Hi. First of all, this is my first post and I'm new to Arduinos and a novice at electronics, but an old hat at programming. My problem I'm having is with the electronics side of things on my Arduino UNO.

Basically, I'm building a simple project to switch a relay on or off depending on the temperature. I have a TMP36 temp sensor on A0 and a small 5v relay with a transistor and 10k resistor on D9. Independently, they work fine. Also, at this point, there is nothing on the other side of the relay (although I have tried it with something) and in fact there is nothing else in the circuit other than that listed here.

Using them together on the same project it 'works' but there's some weirdness happening. As soon as the relay is triggered at say 35 degrees, the temperature jumps up about 5 degrees. After some testing I can see voltages changing on the 5v line (even when using a 9v external supply) and this has lead me to believe that the reference voltage is changing for some reason, making my software calculation for converting the 0-1023 result of analogRead() to a voltage to be incorrect and hence throwing off the temperature result.

I have tried with analogReference(DEFAULT) and calculated for 5v, analogReference(INTERNAL) and calculated for 1.1v, and analogReference(EXTERNAL) and calculated using the result of throwing a multi-meter on the 3.3v line and hooking that into AREF. Nothing works.

Anyone know what's wrong, what's broken or (more likely) what I'm doing wrong? It seems that the more current I pull on the 5v line, the worse things get. Powering an LCD display on it with the backlight turned on drops the voltage from 4.9v down to about 4.55v. Shouldn't this be consistent? How can I make this more consistent? Or even, how can I find out what the reference voltage is and use that in my voltage calculation. I'm kind lost here.

Any help is much appreciated.

Ok, now to make this even more confusing. I have an Arduino Pro Mini 5v 16Mhz that I have now wired up exactly the same and loaded the exact same sketch on to and it works fine. So it's only my UNO that has this problem with the voltage being unstable. The Pro Mini even works with the LCD screen turned on with it's backlight and seems to output a clean 5.05 volts.

Still a problem? Busted UNO?

Test the input voltage, if it is a 9V battery then it is likely it is sagging and can't provide the voltage under load. Use a wall wart and I guess it will be fine.

Here are a few suggestions:

  1. You need to get a stable voltage reference. Using the 3.3v output should give you a stable reference even if the 5v line varies a bit. You may need to put a load resistor (say 10K) between the 3.3v pin and ground to make it stable.

  2. Use separate analog and digital grounds. Dedicate one of the Arduino ground pins to be analog ground and use it to connect only the ground side of analog sensors and any associated filtering capacitors (in your case, use it to connect the ground side of the TMP36 only). Use the other ground pins to connect power and any output devices. Even better is to use the Agnd pin of the mcu of mcu socket as analog ground, but you probably don't need to go that far.

  3. If you are using a 9v supply to power the whole thing, you can make the 5v supply more stable and also reduce the power dissipation in the regulator by powering the lcd backlight and the relay from 9v instead of 5v, with a suitable series resistor in each case.

Thank you dc42! While I'd already tried 1. and 2. myself, I hadn't thought about the shared ground being an issue. Simply unplugging the ground from the temp sensor and plugging it into the 2nd ground pin on the UNO has fixed the problem.

For posterity. @dc42 Your reply also helped me with a seemingly unstable UV sensor:

The DFRobot UV Sensor module uses the GUVA-S12SD chip. Detects UV light in the wavelength range 200-370nm. Linear analog voltage signal output from 0 to 1 volt. Can go above 1 volt for very strong UV intensity. Now, with its own ground connection it reads rock solid regardless of the 16x2 LCD backlight being on or off.

I had fairly unstable readings from my TMP36's until I used shielded cable and a capacitor from +5v to GND at each sensor.
Also, putting a resistor from 3.3v to AREF will produce a voltage much lower at AREF because you are making a voltage divider with the resistors already built in to AREF. I use a 20K and that makes 2.04v at the AREF pin, which is perfect because the most the TMP will put out is 1.75v @ 125C.
To make your readings very precise, divide 2.04 by 1023 to get 1.992mV per step. At -40C, we should see an output reading of 100mV. Divide 100 by 1.992 to get 50. This means at -40C, you should see an analog reading of 50. at 125C, you would take 1750mV and divide by 1.992 to get 882, so at 125C, you should see 882 as an analog reading.
Then map the analog reading : tempC = map(analogRead(0), 50, 882, -40, 125.

See my thermostat sketch for more info and ideas. I take readings every 100ms and average them in a matrix.

Also, I have my thermostat set up so the relay stays on or off for quite a while to keep it from firing the heater on too often as the room temp teeters on the hold temp. Make sure you do something like this unless its an electric heater or you will burn out your ignitor.