23 May 2012

The Morse Thermometer - Part 1

Project Features
  • Extremely simple hardware
  • Low-Cost
  • Uses the internal temperature sensor of the ATtiny25 
I used to have one of those electronic thermometers with an outdoor sensor. That sensor transmits its readings through an RF link. Except that it didn't really work. Every now and then I had to reset the thermometer so that it would re-connect to the sensor. This annoyed me and I thought maybe I could make something that actually works.

Well, that was my excuse for this project...

A Minimalistic Concept
I guess the standard solution to this problem would be to take a temperature sensor, read it out with a microcontroller and display the result on some nice display.

For sensors there is a wide selection of analogue devices like a KTY series or LM335 on one hand and digital sensors like an LM75 or DS18S20 on the other hand.

But I knew there were Atmel controllers which have an integrated temperature sensor and I wanted to explore its possibilities. So I went for an ATtiny25, which is relatively cheap and has such a sensor.

For a display, I could have used a nice LCD or a 7-segment display. But I needed something that could be seen from some distance and I wanted it to need as little energy as possible.So why not use just a single LED...

The ATtiny25 Internal Temperature Sensor
For this project I tried to find out, how other people use this internal sensor. But I found only a few projects. And of those, many didn't use the sensor correctly. This is probably to do with the description in the Atmel data sheets. There is very little information how to use it and the existing information is somewhat misleading. It is worth noting, that a lot of additional information on the issue can be found in app note AVR122 / "Calibration of the AVR's internal
temperature reference".

In principle, the usage of this sensor is pretty simple, though. It is connected to the internal ADC via the ADC multiplexer. So all you have to do is to set up the ADC, select the right input channel and read the result. There are however a few pitfalls, which I would like to address:

ADC Clock: The ADC should run at clock speeds between 50 and 200 kHz. Speed is not an issue for this application, so I went for a relatively low CPU clock speed of 128 kHz for this project. Using a divider of 2 results in a clock speed of 64 kHz for the ADC.

ADC Multiplexer Switching: After the analogue multiplexer is switched, it takes some time until the signal is stable on the ADC input. In this project I simply keep the multiplexer switched to the temperature sensor permanently.

Reading the Result: The ADC result is a 10-bit value. So it is stored in two 8-bit registers, ADCL and ADCH. There would be the danger to read wrong data if the result registers were read, while a new result is produced. So there is a latching mechanism built into the ADC. If you read the ADCL register, the ADCH register gets frozen until it is read out. This way no inconsistency can occur. But if you read the ADCH register first, this mechanism would be circumvented. And after reading the ADCL register second, the ADCH register would get latched and therefore give a wrong result when read next time.

Converter Noise: Quite often there is noise on an ADC reading. A couple of things can be done about this. There is a special operating mode for the ATtiny25 called ADC noise reduction mode. In this mode, all unnecessary clock domains are disabled. App note AVR122 shows the effect on the results. It also shows that at low clock speeds, the effect is negligible. So I didn't use it. I did find, however, that noise on the supply lines is very noticeable. I had best results with batteries and horrible results with a switched mode power supply.

ADC Reference: Must be switched to the 1.1 Volts band gap reference. Otherwise readings are nonsense.

Meaning of the Result: The result of the ADC reading is in degrees Kelvin. In order to convert it to Celsius, all you have to do is subtract 273. Some people believe that the result needs to be scaled by a factor of 1.1, but that is not the case. The reference voltage is 1.1 Volt. Divide that by 1024 and you get a step size of 1.07 Volts. And that is exactly the given voltage per degree.

Morse Output
The most basic output of a controller is a single I/O signal. For this project it drives an LED. Because it is a red ultra-bright LED, rated at 1,8 Volt / 20 mA, no series resistor is needed - if the supply voltage of the circuit is less than 3 Volts. The controller simply can't provide enough current to destroy the LED. Instead, its output levels "degrade" somewhat. That is all. Look at the ATtiny's data sheet for details (chapter "Pin Driver Strength").

People have solved the problem to encode 1-bit data in human-readable form about 170 years ago: Morse code. So instead of re-inventing the wheel, I decided to use this code. It is relatively easy to read numbers in Morse code, since they use a regular pattern. And the "+" and "-" signs are not difficult to learn either.

Most of the time, the output has two characters. I suppress the leading zero (if present) and I suppress the sign if the temperature is positive. This makes reading faster and saves some energy. Examples for possible readings would be "32", "24", "8", "0", "-5", "-12" and "-23".

Here is an example, sending a temperature of 12 °C:

Well, since there is no external sensor and only the LED for output, the schematic is almost too simple to actually make a drawing. But here it is anyway:

The only remarkable thing might be that the LED is connected with both pins to controller ports. I did this, because like this it can also be used as a light sensor. I thought this might be useful, e.g. for day/night detection. There is some code in the firmware (#defined out), to make use of this feature. It works, but I didn't actually use it in the end. I left it in as a base for further experiments.
Power Consumption
Since this device is meant to be used as an outdoor thermometer, it will have to be battery operated. So it shouldn't use more energy than absolutely necessary. The controller runs off the internal watchdog RC oscillator at 128kHz, so it needs next to now power. At 128kHz and 2,7 Volts the supply current was measured at under 70 µA. The LED actually draws 10mA - with no resistor in series. So this is quite safe for the LED.

And how long would a set of batteries last? Let's assume they have got a capacity of 2000mAh. Then at 10mA of continuous current consumption, they would last 2000mAh / 10mA = 200h, about 8 days. But the LED is not active continuously. While it flashes, it is approximately on for 2/3 of the time. If we assume that one digit needs about 3 seconds for transmission, then the LED would be active for 2 seconds per digit. The result is send out twice per display cycle (= 4 digits / 8 seconds). A cycle is about 50 seconds long. So the LED is on for 1/6th of the time and the battery works for 6 times 200h, about two months

Of course, a lot of variation is possible. E.g. the cycle time and flashing speed could be increased, leading to a longer battery life.

Unfortunately, during an outdoor test I found that my rechargeable batteries were fully discharged after two weeks. I am not sure why that was, but my guess is that the batteries didn't last longer because of the very low temperature. At the time the night time temperatures were down to about -14°C.

This was actually more difficult to judge than I thought. I have several digital thermometers, some of which show the temperature at up to 1/10th of a degree. But if you place them next to each other, they never show the same temperature. Usually they deviate from each other by 1 - 2 degrees.

The most accurate thermometer I have is probably my multimeter with its k-type thermocouple. So I used it to calculate an offset at room temperature. But when I placed this multimeter outdoors, I got a surprise: Although it was deep winter with temperatures at around -6 °C it displayed positive values. After a bit of research I found that this is due to the way a thermocouple works.

But what I can say is that my temperature readings were always very close to the weather reports for  the region. Sometimes they were 1-2 °C higher, sometimes lower.


In order to improve current consumption I devised a new code as an alternative to Morse code.

Morse code has to provide not only for numbers, but also for letters, of course. And this isn't the case for a thermometer. A very simple code (for digits only) therefore would be one which just flashes the LED for the number of times that the digit shows, i.e. once for a '1', five times for a '5' and nine times for a '9'. This is actually not bad as far as energy consumption is concerned. E.g. for a '1' you would only flash the  LED once, whereas in Morse code you would send ". - - - -", which is equivalent to 13 dots. So it's a huge reduction in that case. But higher numbers get a bit difficult to understand, because you would have to count the flashes. So in order to make this a bit easier, I use a scheme where four dots are replaced by a single dash.

This means, that the '9' looks like this: "--." (4 + 4 + 1 = 9), which is not only easier to decode, but also more energy efficient (it is the equivalent of seven dots).

It is also worth considering, that for outdoor temperatures, the most frequent range is between + and - 30 degrees. So the first digit is always between 0 and 3 dots. I think, in general, that code reduces energy consumption by at least 50%. And for many people it is easier to decode than Morse code.

Here is an example, sending a temperature of 12 °C with the alternative code:

And that is it - not
Of course I could have ended here. But since I was not quite satisfied with the fact that I had to recharge the thermometer's battery ever couple of weeks or months, I looked at other means to power it. And the most obvious source of electrical energy outdoors is a solar cell. So the story continues in part 2. Stay tuned...


  1. I have been messing with the Tiny85 internal temp sensor and cannot make it give me any useful information. Would you be inclined to post you code for this project?

  2. Right, I meant do do this with part 3 of this post. But the weather is too nice at the moment. So here is a preliminary version of the code.

    This is probably not the final version, because I might modify the output routine. But temperature reading works.

    Also, it is in AVR Studio assembler. But it should be readable anyway. Hope it helps!

  3. Ahm - the code is available through the "Downloads" page in case you were wondering - right side under the Labels gadget.

  4. You rock, thank you so much. I have you book marked and look forward to your next installment. I intend to use a few CPC1824 solar panels with a a supercap to have a tinyTemp logger. This should be enough to get me over the hump.
    T. Bradley

  5. I find that using the Arduino platform with the ATtiny works well. There are several demo programs for using the ATtiny's internal temperature sensor, just Google "attiny85 arduino internal temperature"

    - Ray