I'm trying to build thermostat with Arduino. I want to power it using mobile phone battery/charger which makes system voltage quite variable. Right now I use Arduino Uno, but once it is complete I will port it to Lilypad.

First I tried to use TMP36 temperature sensor. So far it was complete failure. While the sensor itself appears to be very stable, I can't figure a way to accurately measure its voltage.

Using built-in 5v reference for analog sensors isn't working at all -- even powered from USB arduino's +5V are actually +4.8V (which shifts measured temperature by few degrees). When the board is powered from the battery, voltage drops to about 4V and measured temperature sky-rockets. I also tried to use +3.3V from the board as a reference. It seems to be more stable when the board is powered from USB, but its voltage drops when running off the battery.

Is there any other way to reliably measure sensor output voltage?

For the second stage I'm planning to use thermistors. Just ordered a couple of these 20K thermistors.

From what I understand, these should be easier to measure accurately if I build voltage divider and use V_in as reference voltage for ADC.

A couple of questions about them:

  • Does it make sense to use few voltage dividers with different fixed resistor to increase accuracy?
  • I can use programmable pin as V_in, and measure temperature using few different voltage levels. Though its not clear to me whether this will actually increase accuracy.
  • \$\begingroup\$ Please post your temperature conversion code. \$\endgroup\$ – geometrikal Dec 23 '13 at 7:52
  • 1
    \$\begingroup\$ Please define what you mean by "accurately". What sort of temperature resolution and absolute accuracy are you trying to achieve? \$\endgroup\$ – Joe Hass Dec 23 '13 at 12:27
  • \$\begingroup\$ I hope to get resolution of about 1-2 degrees. Absolute calibration error of 1-2 degrees should be fine too. From what I understand its relatively easy to get a reference point at 0C, and I guess I can get second (much more rough) point at room temperature by cross-calibrating sensors. \$\endgroup\$ – Usov Dec 24 '13 at 2:43
  • \$\begingroup\$ 1-2 degrees for temperatures in the 5-25C range. \$\endgroup\$ – Usov Dec 24 '13 at 2:59
  • \$\begingroup\$ @geometrikal I don't have it at hand right now, but its basically the same as everybody's else: drop first sample, wait few millis, sample a couple more times and average samples. Then rescale by what you believe your reference voltage is. \$\endgroup\$ – Usov Dec 24 '13 at 3:41

It seems you are aware of the problem with the reference voltage changing and if you use a device like the TMP36 (fixed 10mV/degC) there is nothing you can do other than use a voltage reference from a chip to stabilize things.

However, if you are using an RTD or a thermistor then the problem won't arise. You ADC is making a ratiometric measurement - it compares the ADC input to its reference voltage BUT, if you power the RTD or thermistor (via a suitable resistor) from the same ref voltage it won't affect readings. If the ref goes up 10% then so does the voltage into the ADC.


I think you should consider using a digital temperature sensor like DS18B20/ DS18S20 because it does not depend on the accuracy of your ATmega ADC to measure an anaolg signal, it uses 1-wire digital protocol to report temperature.

Refer to the following tutorials

  • 2
    \$\begingroup\$ This answer isn't very helpful unless you explain why the OP should shift to a different sensor, and you've given no justification for that. Just providing links in an answer is not a good idea because they often go dead and the content of the answer is lost. \$\endgroup\$ – Joe Hass Dec 23 '13 at 12:25
  • \$\begingroup\$ Rather than write my own answer along the same lines, I've edited this A to address the concern raised by Joe. \$\endgroup\$ – RedGrittyBrick Dec 23 '13 at 13:22
  • \$\begingroup\$ @JoeHass The only alternative than linking to external articles is to attach the code in the reply but I don't have my own code to attach and it wouldn't be vary fair to attach someone elses code without their consent. Even if the links go dead a library for Arduino can be easily found using google and DS18B20 as keyword. Regarding the explanation, it was my mistake, I thought that mentioning that the sensor is digital would have explained my point. \$\endgroup\$ – alexan_e Dec 23 '13 at 16:05
  • \$\begingroup\$ Thanks for the comment. For some reason digital sensors are quite difficult to find. Neither local suppliers (Maplin) nor cheap(er) online guys (I used Spiraltronics) don't sell any. £3 a pop + delivery still makes it relatively costly option. \$\endgroup\$ – Usov Dec 24 '13 at 3:09
  • \$\begingroup\$ @Usov Judging from the links you have provided I assume you live in the UK. I usually buy these components cheap from China but I also found them in ebay.uk for £1.49 , maybe they suit you \$\endgroup\$ – alexan_e Dec 24 '13 at 7:26

Your measurement will be as good as reference voltage for ADC is good. Arduino by default uses supply voltage as reference voltage, but in your case the right way to do it would be to use Aref pin of arduino. You have to get a special chip called "Voltage reference" and connect it to Aref pin, then set ADC to use the external reference in Arduino code (analogReference(EXTERNAL))

The voltage of the reference has to be selected so that the full swing of your temperature sensor will fit into referece voltage. TMP36 will output ~1.5V @ 100C, so you would have to use reference above 1.5V for measuring temperature up to 100C. You want your reference as close to the maximum voltage measured as possible to get as much resolution as possible.

Atmega328p has two internal references that can be used without any external components. One is 1.1V, another 2.56V. They usually are a bit worse accuracy than what you would get by using external dedicated component. Check Arduino documentation for analogReference and Atmega328p datasheet for internal reference accuracy.

If you really want to get nuts with different ranges, you can use several external references and switch them by using an analog switch like 74hc4051. Or you can switch between two internal references.

With thermistors you will have better results if you set up a constant current source instead using a dumb resistor. On another hand - a dumb resistor powered from a stable voltage reference would work ok.

When choosing an external reference, make sure you have enough voltage to accomodate for it's drop out voltage when powering from batteries and the batteries are flat. Vref+Vdropout < Vbat-min.

  • \$\begingroup\$ Thanks for your comment. This is basically the same comment I got today -- build my own ref voltage on zener diode or get dedicated low-voltage regulator for AREF. \$\endgroup\$ – Usov Dec 24 '13 at 3:50
  • \$\begingroup\$ Why better results with constant current and a thermistor? \$\endgroup\$ – geometrikal Dec 24 '13 at 4:49

Not having a stable ADC reference is actually a symptom of a another problem in your circuit: you are not supplying a high enough voltage to the board. This is indicated by the 5V supply dropping to 4V and the 3.3V dropping as well.

The voltage regulator (MC33269D-5.0 IIRC) on the Arduino board has a dropout voltage of ~1.0V, therefore you need to supply it with at least 6V to get a stable 5V output. AA batteries start off at 1.5-1.6V and are almost dead at 1.1V so you must power the board with at least 6 AA batteries for a stable output over the entire battery life.

Powered correctly, you may either use the internal ADC reference or either the 5V or 3.3V lines. Since the temperature sensor varies by around 10mV per degree Celcius, you could use a voltage divider to set the reference voltage equivalent to the maximum expected sensor output voltage (e.g. for 50 degree C). This will give a more precise measurement.

If you want to use fewer than 6 AA batteries, try a DC-DC boost converter, e.g. https://www.sparkfun.com/products/10968. The linked example takes 1V - 4V and makes 5V. The output would be fed directly into the 5V pin of the Arduino, bypassing its regulator.

To get the board to run longer on batteries, put the MCU to sleep between sensor reads. The rocketscream low power library is great for this purpose. But it is only really useful when using an efficient regulator / DC-DC converter as the standard Arduino regulator uses 10mA just by itself!


Answer for the question Is there any other way to reliably measure sensor output voltage?

ADC uses the reference voltage for the conversion from analog to digital. So if there is a change in the reference voltage, the converted values(i.e digital value) will change. The digital value will be different for the same analog input if the reference voltage changes.

One easy option is to use the internal reference voltage inside the Arduino(i.e Atmega controller).

See the below link where a sample code is provided to use the internal ADC (Arduino function name - analogReference(DEFAULT) )


I think this will solve your issue and there no need to switch towards thermistors.

  • \$\begingroup\$ I'm not sure how "Hacking Wifi finder" is relevant -- I can't find there anything of relevance. Regarding internal ADC reference -- I wrote about it. It's not working even when Arduino is powered from USB. And when the board is powered from cell phone battery (3.7 - 4.5V) its even worse. \$\endgroup\$ – Usov Dec 23 '13 at 4:36
  • \$\begingroup\$ Sorry its a copy/paste mistake. Will correct the link soon! \$\endgroup\$ – robomon Dec 23 '13 at 4:37
  • \$\begingroup\$ @Usov link corrected! \$\endgroup\$ – robomon Dec 23 '13 at 4:39
  • 1
    \$\begingroup\$ 1.1V internal has can float by over 10% according to atmega328 spec. This doesn't seem to be very reliable reference either. \$\endgroup\$ – Usov Dec 24 '13 at 3:34

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.