Path: Home => AVR overview => Applications => Thermometer ATtiny24 => Thermometer IR/RS232   Diese Seite in Deutsch: Flag DE Logo
Temperature over serial IR Applications of
AVR single chip controllers AT90S, ATtiny, ATmega and ATxmega
Thermometers with serial IR interfaces and ATtiny45
Experimental, incomplete and not tested!
Software under construction!

ATtiny45 thermometers with 2-way infrared RS232 interface

Who doesn't know that? You'd like to have an outdoor thermometer, but you don't want to place your laptop to the outside, because you fear that he won't withstand rain and snow for a longer time. But how to get the data of your thermometer to the warm inside of your living room, without drilling holes in your window frame, to get the cable through those holes?

Here is the solution for this problem: infrared passes through the glass, without any holes in your window frame. The outdoor sensor transmits (and receives), on the inside an infrared-to-serial converter allows to connect to the laptop with an RS232 connection. Here you can receive the regular transmissions of the sensor and display or collect the thermomter's transmissions. Today you need the temperature in Kelvin, tomorrow in °Fahrenheit and the day after tomorrow in °Celsius - no problem: just a short command (1-TK, 1-TF or 1-TC) over the serial RS232 switches temperature sensor number 1 to transmit its temperature in this dimension.

You need an additional temperature sensor, either outside or inside? Just program another ATtiny45 to be number 2 and built another sensor electronic with that. With 2-TK, 2-TF or 2-TC this sensor transmits the temperature in another dimension. With TK, TF or TC alone all connected thermo sensors change their dimension.

And: as long as all sensors see the IR-serial-converter and also all other sensors, a built-in priorization mechanism controls the transmission process. Up to ten sensors can transmit data simultanously.

You'll need to collect this data over days and monthes? No problem, each sensor has a built-in crystal-controlled date-and-time clock and transmits its date and time, together with the sensor number, with each temperature report. Once initiated with D=[Date] and T=[Time] you do not have to care about this for three monthes any more, it is as exact as your crystal is.

The drawings, such as electrical schematics and flow charts, are all in the LibreOffice Draw file here, all calculations are in the LibreOffice Calc file here.

Top Functioning Hardware Mounting Software Algorithms

1 How it functions

1.1 What you need

In any case you'll need:
  1. a computer that runs a terminal program, such as RealTerm, and
  2. an USB-to-serial-converter, that can be configured for 1.2 kBaud, and
  3. the infrared-to-serial-converter device, equipped with a female DB9 D-Sub plug and that can receive serial signals via infrared with a receiver module and can transmit serial signals via an Infrared-LED, which all is controlled with an ATtiny25, a attached transformer power supply provides the 5V for the controller and the 10V for the IR-LED, and
  4. one or more temperature sensors with an ATtiny45, either for rechargeable battery operation outdoor or transformer power supply operation indoor.

1.2 How this works

In a temperature measurement sensor an ATtiny45 measures the temperature, converts it to the desired dimension and to a text string and sends this result in serial RS232 mode with 1,200 Baud over an Infrared-LED. The indoor converter receives these IR signals and converts those to the RS232 signal level. The RS232 signals are outputted to a female D-SUB 9 pin connector, to be received and displayed by the terminal program on the computer.

The ATtiny45 in each temperature sensor has a crystal-driven clock, which starts the temperature measurement of the device in adjustable interval periods between one and 65,535 seconds (65,535 = approx. 18 hours, 0 = temperature measurment off). After measuring, the temperature is send in the desired dimension, started with sensor number and the date&time stamp.

The ATtiny45 has a serial interface, which can receive serial signals over infrared with baud rates up to 1,200 Baud. Via this interface the following can be adjusted:
  1. Date and time, including selection of anglo-saxonian or german date&number format,
  2. the dimension of the temperature (Kelvin, °Celsius, °Fahrenheit),
  3. the three parameters, by which the temperature in Kelvin can be calculated from the ADC's result (with applying the formula T = a * 128ADC2 + b * 128ADC + c), therefore all sensors can be indidually calibrated,
  4. and much more, see for the details below.
All relevant parameters (Temperature dimension, a, b and c) need to be written to the device only once, because those are stored in EEPROM and are read from there on any restart of the device (e. g. after changing the rechargeable battery).

1.3 Details on how this works

The IR-to-serial-converter listens to incoming infrared signals. On detection he sends those to the RXD pin on the female D-SUB plug, formatted as RS232 via a transmitter in the MAX232. Those signals are then received and displayed by the terminal program.

The Serial-to-IR-converter takes up signals from the TXD pin of the female DB9 plug, converts and inverts those in a MAX232 receiver and generates active infrared signals if a binary one is detected. The active-high input pin INT0 of the ATtiny45 starts a rectangle signal with 40 kHz on the OC0A pin, to be converted into a constant-current for the IR LED.

The thermo sensors
  1. have an individual number between 0 and 9, which they start their messages with, this number also determines the priority of any transmissions of the device (the lower the number the higher the priority,
  2. when switched on, those transmit their identification number and some characeristic text,
  3. wait for incoming strings, which are analyzed like this:
Top Functioning Hardware Mounting Software Algorithms

2 The hardware

The hardware consists of two different types of temperature sensors and of the IR-to-Serial-converter (including a transformer-power-supply).

2.1 The hardware of the sensors

The hardware for Indoor- and Outdoor-sensors is slightly different, the differences are described in the overnext subchapter.

2.1.1 The hardware of Outdoor-temperature-sensors

Schematic of outddoor sensors That is how the sensors for the outside look like. The ATtiny45 is clocked by a crystal (either 7.68 or 4 MHz or any other, see the spreadsheet calculation).

The supply voltage either comes from a rechargeable Lithium-Ion battery with 3.7 Volt or from three stacked rechargeable NiMH batteries with 1.2 Volt each. The current consumption is only elevated during transmission of ones, so adjust the interval as long as possible (e. 60 seconds or 5 minutes) to save battery capacity. On one page of the spreadsheet calculation you can estimate the lifetime of the battery.

The ATtiny45 measures regularly, between 0 - no measurements - and 65.535 seconds - measurement all 18.2 hours - the temperature of its built-in sensor, converts the ADC measurements to the temperature in Kelvin, and from this to the desired dimension, converst this to a string, adds id/date/time and sends this over the infrared diode as serial signal. The converter converts this to RS232 voltage formats and sends this to the computer.

The infrared sensor module TSOP31240 detects, if another sensor currently transmits. If that is the case, it waits until the activity ends. For an id-specific period the sensor then waits until its own specific wait time is over, before it starts to transmit its own string.

If no transmission is active, the infrared sensor waits for signals, reads those in serial mode and stores received characters in a buffer in SRAM. If a linefeed character is received, the line is evaluated. In case the command is valid for the sensor, it executes it.

The infrared diode LD274-3 is driven with a constant-current, if transmit is active and a one is transmitted. Then the ATtiny45 pin OC0A (PB0) generates a 40kHz-rectangle. This turns a red LED on, the LED's forward voltage drives the base of the transistor, which regulates its CE current so that the base voltage is by its B-E forward voltage smaller on its emitter. The emitter resistor so controls the current through the LED.

If the IR-LED is not connected or is defective, the red LED remains dark, because the transistor's base consumes a too high portion of the total available current and the resulting base voltage is smaller than the forward voltage of the red LED.

Measuring the constant current regulator Here, I measured the voltages of the constant-current regulator. Voltages are in blue, resulting currents in red and thermal-power in violet. Note that the thermal power figures are for durable ON of the LED, the 50% ON periods reduce the power figures to half of those listed here.

The constant-current source works from 3.3 Volt operating voltage (and above) very stable and reliable. Only in the case if the IR-LED's anode is driven with 10 Volt (in case of indoor sensors) and the emitter resistor is reduced to 12Ω to use the full power range for the IR-LED, the transistor's thermal power is slightly higher than specified for the BC547 and a larger transistor is necessary. I used a BD439 for that, any other NPN in a TO126 or similar casing can be used.

Why an ATtiny45 and not an ATtiny25? Now, the assembler program is rather large, mainly because of the intensive RS232 communication and the many possible adjustments. This did clearly not fit into the flash memory of an ATtiny25. Of course, an ATtiny85 can also be used, just change the include type on top of the source code.

Top Functioning Hardware Mounting Software Algorithms

2.1.2 The hardware of indoor temperature sensors

Schematic of an indoor-thermosensor Generally any additional thermo-sensors can be added, but to avoid tranmission conflicts all those sensors have to see all sensor's IR signals.

Additional indoor-temperature sensors look similar to outdoor sensors, but the following differences have to be considered:
  1. Operation of indoor sensors uses the same power-supply, batteries are not necessary. The supply of the ATtiny45 is at +5V from the voltage regulator.
  2. Because the operation of the IR-LED uses the unregulated +10V source, the supply needs three connections (+10V, 0V and +5V).
  3. Because the transistor has to handle up to 10V at a constant current of max. 100mA over 50% of the time, which corresponds with 0.5 Watt, a larger type has to be used.
  4. Instead of low-current-LEDs normal LEDs with 20mA can be used.
Each sensor gets his own id, which is used in transmitting and also during reception, so that the sensors can be adjusted individually or as a whole.

Please be aware that because of the low baudrate each sensor needs some time for sending the long strings. So, if you select a very short interval such as one second, and if you use baudrates of 300 Baud and lower, the sensor number 0 blocks all other sensors from transmitting: they still measure, but they can never transmit their result.

2.1.3 Selection of the crystal for temperature sensors

The crystal of the temperature sensor has to allow for the following time-relevant tasks:
  1. The internal clock of the sensor has to be clocked with an exact seconds signal. For this the Counter/Timer TC1 is used, which has comprehensive prescaler variety. The prescaler is maximized for the highest divider rate possible, which results in an as-small-as-possible integer value. This is then divided by a CTC value, which also results in an integer value. This is then divided by a software divider, that leads to one second (without any fractional parts behind).
  2. When sending the IR-diode has to transmit with a defined frequency, by default 40 kHz). Differences from this by +/- 0.5 kHz are tolerable, below or above that is an increasing risk that the IR module doesn't recognize the signal.
  3. When receiving serial signals the baudrate has to be exact enough, so that the nine bits (1 start bit plus 8 data bits) are not missed. The default are 1,200 Baud, so each bit is 833 µs long. The receiver software doesn't use sophistic correction methods, so that the timing error should be less than 9/2 = 4.5% of the baudrate or +/-54 Baud or +/-37µs.
The conclusion is, that the most relevant accuracy-driver is the clock. If you don't want to manually reset the time daily, your crystal should provide a stable and reliable clock signal.

Because the outdoor sensor works with a 3.6 or 3.7 V battery, you can not use crystals with 10 MHz or higher: the tiny needs 4,5 V to work at that frequency. And we'd like to save as-much-as-possible operating current.

Table with crystals for clocking The crystals in the spreadsheet "clocking_thermometer" of the LibreOffice-Calc file here shows all commercially available crystals in column G. Column I calculates the resulting IR-LED frequency in Hz, column K the resulting baudrate in Bd.

As we see, many crystals can generate an exact IR frequency, those who result in fractions are not very far away and within the acceptable tolerance.

The correct baudrate can also be reached with many crystals. All are within the tolerable bounds.

Columns J and L calculate the squared deviations from the target values, to get a freeling, which crystals are how near to the target. The minimum deviations (zero) are for the 7.68 MHz crystal and for 9.6 MHz (which is not a crystal but the default RC oscillator of an ATtiny13).

The message here is: you can use what you like, anything goes, only only is perfect for all.

Calculating the seconds Another part of the sheet, A56 to B65, calculates the optimal divider values for the seconds. For the selected crystal in dropdown cell B2, here 4 MHz, and for a selected blink duration in B57, here 1 fifth of a second,
  1. B59 calculates the prescaler value for TC1 (here: 256), and
  2. B62 determines the CTC divider (here: 125), and
  3. B64 calculates the soft counter
for the seconds signal. 4,000,000 / 256 / 125 / 25 yields exactly 5, by which the blink rhythm can be generated and the seconds can be derived from (see in the software section below the flow chart of the blinking LED).

To copy all those settings to the assembler source code, the yellow area in the sheet collects all those informations. Just select the yellow area, copy it with Ctrl-C and paste it into the source code file with Ctrl-V.

Top Functioning Hardware Mounting Software Algorithms

2.2 The hardware of the IR-to-Serial-converter

The IR-to-Serial-converter receives the IR signals of the sensors and converts those to serial signals on the RS232 voltage levels. On the other way, serial transmissions from the RS232 transmit line are converted into IR signals and send via IR LED to the sensors.

2.2.1 Schematic of the IR-Serial-converter

Schematic of the IR-to-Serial-converter The IR-to-Serial-converter constists of
  1. a female DB9 plug, which serves as two-way-communication port,
  2. a MAX232, which converts signal levels from 5V to the RS232 level,
  3. the Infrared-Receiver-module TSOP31240, which receives Infrared signals, filters those by frequency and outputs those on its sig pin,
  4. a crystal-driven ATtiny25, which switches an IR-LED on and off at 40 kHz, if ones come over the DB9's transmit pin, the IR-LED is driven by a constant current supplied by a BD439 transistor and the LED, with its anode, is tied to the unregulated +10V supply voltage,
  5. a 6-pin male ISP-Interface, over which the ATtiny25 can be programmed within the system.
Within the converter only the 40-kHz-signal of the IR-diode is time-critical. That can be achieved by nearly any crystal. I used a 4 MHz, which fits exactly for my 40-kHz-signal. Without a crystal, only with the internal RC oscillator of the ATtiny25, I measured 43 kHz. That is too far away from my target frequency, so the help of the crystal is justified.

Top Functioning Hardware Mounting Software Algorithms

2.2.2 Transformer power supply for the IR-to-Serial-converter

Schematic of the converter's power supply This is the power supply for the converter. It provides unregulated +10V for the IR-LED's anode as well as regulated +5V for the ATtiny25 and the MAX232.

The power supply under 110 mA load current In the ON phase of the IR-LED the power supply needs to feed 110 mA load current. The analysis of the power supply shows that this maximum load is permanently fine. As the LED has a duty cycle of 50%, the really consumed load current is much smaller than this.

This reserve capacity of the power supply can be used to supply additional indoor sensors. As their IR-LED is active only, if the converter's LED is quiet, several additional sensors can be supplied in a row, without overloading the power supply. Only if you supply more than five sensors, the +5V regulator comes to his limits, due to the many blink LEDs, which are always active in indoor sensors. In that case it makes sense to program those for the outdoor mode, where the LED is normally off and only consumes current when blinking.

Top Functioning Hardware Mounting Software Algorithms

3 Mounting

I have mounted all devices on prototyping boards and did not design any PCBs for those. As all schematics are rather simple, it should not be a problem to design those when needed.

3.1 Mounting the thermo sensors

That is how a sensor looks during active transmit periods.

Outdoor sensor mounted Thermosensor on a prototyping board This is the mounting of the outdoor sensor. The indoor version is similar, the following differences between out- and indoor sensors are:
  1. Indoor sensors have their IR-LED-anode on separate +5V and +10V supply pins, the re-chargeable batteries and their casing are unnecessary.
  2. Due to the higher thermal power of the transistor a BD439 (or eq.) is used instead of the BC547.
  3. The two resistors driving the green and the red LED and the emitter resistor that controls the constant current are slightly smaller.
  4. Blinking is now reversed: the green LED is permanently on and is switched off during blinks.
The shown board is relatively large for the few components. I used a Euro standard size for that. If you need it in smaller sizes, no problem.

If the sensor needs a weather protection, if operated on the outside, and if you use a plastic box for that: be aware that the temperature reaches the ATtiny45 device a little bit delayed. Even though the thermal power of the active IR-LED and the battery is not influencing your temperature readings to a relevant extent, you can place the IR-sensor and the IR-LED outside of the box (by that increasing their visibility for the converter and other sensors) and you can protect their pins with water-resistant glue from rain and snow.

3.2 Parts list for the sensors

Parts list for an outdoor sensor This is the parts list for all components of an outdoor sensor. Three quarters of the total costs of 23€ are for the rechargeable Lithium cell and its casing. If you are not as rich as I am, you can save a lot here. I got the cell and the battery case for free (or as we in Southern Hesse say: for "umme"), so do not comment on the faked 9,800 mAh capacity of my cell: dont look a gift horse into the mouth.

3.3 Mounting the converter

Mounting of the converter on an experimental board This is the component placement of the converter. It includes the power supply part. The external connections to the IR-sensor-module and the IR-LED are made with screw terminals, so you can use whatever casing you like, and you can place the receiver module and the IR-LED outside of the plastic case to increase their sensitivity. If you use a plastic box with a size of 60-by-120-by-40 mm, it is not a good idea to use angled pin connectors for the 6-pin and 10-pin connectors, because those are not accessible within the box. The connections for the three-pin power supply to indoor sensors are also made with screw terminals, use three 2mm plugs when installing it into a box (not included in the parts list). The wall cable is also on a screw terminal for easy mounting into a box.

3.4 Parts list for converter and transformer power supply

Parts list for converter with power supply This here is the complete parts list for the converter, including the power supply parts. Parts for placing this converter into a plastic box are not included, so please add the box and three 2mm plugs for the power supply of additional indoor sensors to it, if you need it.

Top Functioning Hardware Mounting Software Algorithms

4 Software

The software for the converter and the sensors is still under construction. I will post the source code here when it is working and has been tested.

The software of the sensors is optimized for the ATtiny45. The flash memory of an ATtiny25 proved as too small, due to the extensive RS232 communication. So I changed to an ATtiny45 later on.

Do not forget to burn the fuses of the ATtiny25 and ATtiny45 so their clock comes from an external crystal. Otherwise the complete timing is confused.

Top Functioning Hardware Mounting Software Algorithms

5 Built-in hardware and algorithms used

The following chapters describe the internal hardware of the controller, which is used, as well as the algorithms that the software uses. It might be used to better understand the internals of this and it might be useful, if you want to design alternatives.

5.1 Hardware and algorithms used in the converter

Clocking the transmission The converter works with an ATtiny25. Its task is rather simple: to detect signals that come from the transmit pin of the female DB9 and, after inversion in the MAX232, to transmit with 40 kHz over the IR-LED, when the input pin is high, and to switch the LED off if low.

The scheme on the right shows the clocks when transmitting a single character.

Responsible for the detection is the INT0 interrupt. This executes on every transition of the INT0 pin. If the ISR finds a zero on the PB2 input pin, it switches the TC0's OC0A output pin to clear, the constant current gets zero and the IR-LED is off (CLR). If a high input is detected, the timer TC0's OC0A pin is set to toggle (TGL), the constant current driver and the LED are switched on and off.

Flow diagram of the blink mechanism For the green LED, that is connected to the PB1 pin, I have invented a nice mode. As the serial baudrate is 1,200 Baud, just switching it on at high bits from the serial transmit pin is nearly invisibly short. So I decided to blink the LED with two different frequencies: a slow blinking when the input pin is inactive (by default: 2 Hz), and a fast blinking if signals come in (by default: 5 Hz). The number of blinks after the last activity on the input pin can be selected by software.

The blink mechanism uses TC1's output pin OC1A on pin PB1. This output is set to toggle in any case, the toggle speed is adjusted with the OCR1C comparer in TC1. In inactive times the prescaler of TC1 divides the clock signal by 4,096 and OCR1C's compare value is set to 243. That yields a toggle frequency of 4,000,000 / 4,096 / (243 + 1) or 4 Hz. The blink frequency is half the toggle frequency.

If the INT0 input pin PB2 detects high signals, it changes the prescaler to 2,048 and writes 194 to OCR1C. Now the OC1A output pin toggles faster, with 4,000,000 / 2,048 / (194 + 1) or 10 Hz. A toggle counter in rTgl is set to the number of toggles (by default: 10). It further enables the OCIE1B interrupt, which counts the number of blinks down whenever the counter restarts (right side of the flow diagram). This activated state also sets the T flag, by which further incoming positive signals on the input pin do not restart the blink mechanism any more.

If the blink counter reaches zero,
  1. it clears the T flag, and
  2. the OCIE1B interrupt is disabled, and
  3. the prescaler and the OCR1C value are set to slow blinking.
All those settings (the desired crystal, the IR frequency, the baud rate, the normal and active blink frequency, the number of blinks) can be changed using the spreadsheet "IR-over-serial-converter" in the LibreOffice Calc file here and fill in all desired values in the cells with a green background. Then copy the yellow cells to the right of the sheet and paste those to the assembler source code. This configures anything at once.

Top Functioning Hardware Mounting Software Algorithms

5.2 Algoriths used in sensors

The software of the sensors is rather complex. This is demonstrated with the active interrupt-vectors, which look like that:

; **********************************
; R E S E T  &  I N T - V E C T O R S
; **********************************
	rjmp Main ; Reset vector
	rjmp Int0Isr ; INT0
	reti ; PCI0
	rjmp Oc1aIsr ; OC1A
	reti ; OVF1
	reti ; OVF0
	rjmp ErdyIsr ; ERDY
	reti ; ACI
	rjmp AdccIsr ; ADCC
	reti ; OC1B
	rjmp Oc0aIsr ; OC0A
	reti ; OC0B
	reti ; WDT
	reti ; USI_START
	reti ; USI_OVF

Six of the 15 vektors are in use, behind Oc0aIsr in reality are three different sections, depending from the current sub-tasks tranmitting, receiving and waiting for transmitting.

The single components of the sensors are described in more detail in the following sub chapters.

Top Functioning Hardware Mounting Software Algorithms

5.2.1 The clock in the sensor

Flow diagram of the seconds blinker Each thermo sensor has a programmed crystal clock. That makes it possible to add the date&time stamp to any temperature measurement. The date can be initiated via the command (over the serial transmitter) "D=2/26/23", which sets all dates in all sensors. The time can be initiated by sending "T=12:34:56" over the transmitter. Following that, all sensors have the same date and time.

For clocking the clock, the Timer TC1 divides the crystal-controlled controller clock by a prescaler and, in CTC mode, by the Compare-A value (plus one). On reaching the Compare-A value, the OC1A interrupt is triggered.

To enable the use of many different crystals, a down-counter in the ISR can divide the clock either by one, or by an 8-bit- or by a 16-bit-value. The type of down-counter is in the constant cTc1Bits (0, 8 or 16). Within the respective Interrupt-Service-Routine the following, depending from the state of the constant cTc1Bits, is executed:
  1. cTc1Bits = 0: The flag bSec in the flag register is set.
  2. cTc1Bits = 8: An 8-bit counter in SRAM, sTc1Cnt, is decreased. If that reaches zero, the flag bSec is set and the timer is re-started with cTc1Cnt.
  3. cTc1Bits > 8: A 16-bit-counter in SRAM, sTc1Cnt+1:sTc1Cnt, is decreased by one. If both bytes reach zero, the flag bSec is set and the counter is re-started with cTc1Cnt.
Hence, the crystal clock frequency is divided by the prescaler, by the CTC-Compare value and the 0-/8-/16-bit counter. This all yields not a second, but the clock frequency by which the green LED shall be toggled. Depending from the setting of constants, this can be one second, a halve second, a quarter second or what-so-ever, depending from the cell B57 of the spreadsheet "clocking_thermometer".

The flag bSec causes to further handle the clock info in the routine HdlSec: outside the ISR.

The clocking of the green LED does the following. The flag bBlk indicates if blinking is currently active. If this the case, the PINB port register of the green LED is set, by that toggling the PORTB bit. The blink counter is decreased, and, if zero, the bBlk flag is cleared.

One basic rule with handling the SRAM bytes within the routine is that the Z pointer points to the beginning of that structure in SRAM. Instead of LDS and STS, that needs two words per instruction, the routines often use single-word LDD and STD instructions by temporarily adding displacements to Z's address. This saves a lot of flash memory, because date and time handling requires many different byte accesses to SRAM locations. The displacements have defined constants, their names all start with "d".

In the counter at Z+dBlink always an even value has to be written, so that after the end of blinking the default state of the LED is reached again. This state can be ON (in indoor sensors, powered by the transformer power supply) or OFF (in outdoor sensors, powered from batteries).

The 8-bit-counter in Z+dSecCnt counts down the number of blinks (multiplied by two), and, at the end, reaches one second.

Increasing the clock by one second starts with the test, if the measuring interval has a value of zero. If that is not the case, the 16-bit interval counter in sMeasCnt+1:sMeasCnt is decreased and, on zero, the next measurement is started.

The measurement start takes 128 single ADC measurements, sums those up, calculates the temperature in Kelvin and, if desired in °Celsius or °Fahrenheit, forms a string from that and sends this over the serial interface. The measurement algorithm is independant from further time and date handling, see the three sub-chapters below for details.

Adding a second to time/date Increasing the clock by one second includes increasing the date, if the time is at 23:59:59.

This is the algorithm to add one second to time and date. To the left, the time increases by one. At the end of the day, the date is increased by one day, the flow on the right. The major part to the flow on the right is the correct detection if the next month starts. A complicated algorithm, but any complains about that go back to Pope Gregor in the 15th century, which needed that complication due to earth's crazy circular movements around the sun.

As the measuring has been initiated already at the beginning, it is a question whether this measurement uses the previous or the next time stamp (which can have a difference of up to one year). As this routine executes until all Gregorian complications have been finally considered, and as the set bAdc flag after 128 measurements is only seen from the controller after the next wake-up from sleep, the next measurement uses the next date/time stamp in any case and as a whole, so no protection has to be added to prevent from incomplete time&date settings.

Top Functioning Hardware Mounting Software Algorithms

5.2.2 Measuring the temperature in the sensor

The built-in temperature sensor in the ATtiny45 is available at the multiplex address 0b1111 in port register ADMUX. As measuring the sensor requires that the voltage source of the internal 1.1V is used as reference, the VREF bits in ADMUX are to be set according to this. As no other ADC channels need to be measured, this channel can be fixed at start-up.

Linear funktions ADC-to-T The handbook of the ATtiny45 gives the following relationship of the ADC value at three temperatures:


Behind that is not a simple linear function, how the diagram to the right demonstrates: neither the ascending slope nor the constant adder are nearly the same below and above 25°Celsius. On such a rough basis, a temperature calculation is rather rough, it allows resolutions of +/-1° only, a resolution of +/-0.2 or +/-0.1 is impossible with that.

Squared function for ADC-to-T As already used in another project on this webpage (see here) I devellopped a squared function to better interpolate those: T = a * ADC2 + b * ADC + c. T is the temperature in Kelvin, of course. With the original values of ATMEL, the three parameters of this function are as follows.

The parameter a, the squared part, is negative, which means: the curve is slightly reducing its slope with increasing ADC values. The linear parameter b is anything else than 1.0, which is ATMEL's interpolation suggestion.

Now, the multiplication with 0.000510 or with 1.198980 does not feel good for an assembler programmer: I hear a loud cry for the floating math library here. And that does not fit into the flash memory of an ATtiny45. But, in contrast to C-dependents, the assembler programmer knows better and much faster ways to come around this. Here is how he resolves this task.

The resulting temperature shall have a resolution of 0.1°. If we multiply the temperature T with 10, we'll get an integer. If we convert this to decimal, we just smuggle a dot into that, right before we issue the last digit of the decimal. That is already it to get rid from the floating number lib.

And, of course we'll have to measure the temperature repeatedly, to get rid of the unavoidable toggling of the last bit in the ADC. In order to get more exact results, we can add the results from 128 measurements, without having to fear an overflow of a 16-bit integer for the sum value. This would only happen if the temperature exceeds 191°Celsius, by which the ATtiny45's silicon chip would not work correct any more and is on way towards melting.

The summing of several ADC measurements increases the resolution, not by the 128-fold but allows for at least a +/-0.2° resolution. The formula now is:
10*T = a * 128*ADC2 + b * 128*ADC + c

In the spreadsheet "temp-scaling" of the LibreOffice-Calc file here we'll get a, b and c calculated. Use this sheet to calculate your own parameters from your calibration run data.

Contribution of the three parts in the squared interpolation This diagram shows the contribution of all three components in the squared function. The linear part contributes the highest, but the other two factors are on remarkably high values. The slopes of the a- and b-contribution are rather low, and cannot be really seen in that diagram. Note that the opposite function, ADC = a * T2 + b * T + c, has been used here instead of the above formula.

Difference between linear and squared interpolation How large are the differences between this squared function compared to a linear interpolation? Now, as the differences at 25°Celsius are small, I have calculated that for a range from 45 to 50°Celsius. The differences are around 0.5°. We'll never had reached an accuracy of +/-0.2° with a linear function, and we can be sure that displaying +/-0.1° has a solid base with the square function.

Top Functioning Hardware Mounting Software Algorithms

5.2.3 Converting measuring results to temperatures

Another hurdle in calculating temperatures from ADC values is the multiplication with 3.114E-07 and with 0.093670. To do that, we'll use another trick: we'll multiply the 3,114E-7 simply with 65,536 * 65,536, which results in 1.337, and we'll skip the lowest four bytes of the result. The same with 0.093670: here we multiply by 65,536, which yields rounded 6139, and skip the lower two bytes of the multiplication result.

This results in the column L in three assembler code lines:

; Parameters, export from spreadsheet to source code
  .equ cParA = 1337 ; 65536*65536*a in 10*T=-a*128ADC*128ADC+b*128ADC-c
  .equ cParB = 6139 ; 65536*b in 10*T=-a*128ADC*128ADC+b*128ADC-c
  .equ cParC = 156 ; c in 10*T=-a*128ADC*128ADC+b*128ADC-c

With those generic values the temperature sensor converts its ADC results to temperatures, right until the serial interface transmits other values for a, b and c.

The ADC sum of 128 measurements as well the parameters fit well into 16 bits. We can now
  1. multiply parameter b with the 128-sum and store the 4-byte result in SRAM, and then
  2. multiply parameter a with the 128-sum, divide the four bytes by 65.536 (by skipping the two lower bytes) and subtract this from the stored value, and
  3. subtract parameter c from bytes 3 and 4 of previous result, and
  4. we use the lower two bytes of the result to round the result in the upper two bytes.
What comes out is the 10-fold of the temperature in K, which also fits into 16 result bits.

Depending from the states of the two flags bTC and bTF we'll have to calculate the °Celsius and °Fahrenheit from this. The Celsius * 10 comes out, if we subtract 273.15 * 10 from the Kelvin. The Fahrenheit comes out if we multiply the Celsius with 1.8 * 10 and add 32 * 10 to that. In both cases the result can be negative, so we'll have to set a flag and to calculate 65.536 minus degrees from that to get it positive. The 16-bit value is the temperature in the desired dimension, multiplied by 10.

Top Functioning Hardware Mounting Software Algorithms

5.2.4 Converting the temperature to decimal in the tranmit buffer

The rest now is simple hand-crafting:
  1. to set the transmit pointer X to the beginning of the transmit buffer in SRAM,
  2. .
  3. add the id of the sensor (0 to 9) and a minus-character,
  4. to write the date in the correct format (english or german) to the transmit buffer, followed by a minus,
  5. add the time, separated with ":", to the tranmsit buffer, followed by an "=",
  6. if the temperature flag signals negative, add another minus,
  7. add the temperatur as positive integer with a dot (english) or a komma (german) prior to the last digit,
  8. add carriage return, line-feed and the cursor character as well as the final null character to it,
  9. point the pointer X back to the start, and
  10. set the wait flag to transmit the buffer, when no other transmission is active any more.
From now on the transmitter is busy for 250 ms long, as he transmits the result over the serial interface (see next sub-chapter).

Top Functioning Hardware Mounting Software Algorithms

5.2.5 Sending the transmit buffer

A serial startbit is transmitted at 1200 Baud If the flag bTx is set, the sensor transmits. In transmit mode, TC0 is clocked with 80 kHz (at 4 MHz: CTC = 50, Compare A = 49, time slice = 12.5 µs) and either toggles the output pin OC0A (when transmitting the start bit or a one-bit) or clears it (when sending stop bits or a zero-bit).

The example to the right shows the toggling 0C0A with 40 kHz for the duration of a start bit at 1,200 Baud.

Flow diagram of transmission During transmission the X pointer points to the next character, that is to be send, in the SRAM transmit buffer. The buffer is null-terminated, when reaching null the transmission stops.

The tranmsit algorithm is driven by the TC0-Compare-A interrupt. As this interrupt also serves other tasks (see overnext sub-chapter), the first check in this interrupt is if the bTx flag is set. If that is the case, the algorithm continues in the send section. The 16-bit counter rCntH:rCntL, which counts the number of toggles of the CTC in TC0 and controls the duration of transmitted bits (by default at 1k2Baud: 67 toggles).

If the counter reaches zero, the 16-bit counter is reloaded with its start value. Now the number of bits to be transmitted is decreased. If that reaches zero, the next character is read from the X buffer, which is auto-incremented. If the character is a null, the transmission is ending, with the following operations:
  1. the transmit flag bTx is cleared, and
  2. the timer-interrupt enable for TC0 is cleared, (the interrupt for TC1 is kept to keep the clock active), and
  3. the OC0A-pin is set to clear.
If the character wasn't a null, the number of bits to be transmitted in register rBit is set to 11 (1 start bit, 8 data bits, 2 stop bits) and OC0A is set to toggle (which sends the start bit of the character).

If rBit was zero after decrementing it, register rimp is set to clear the OC0A output pin. If the number of bits to be send is smaller than two, the stop bits are send. If not, the character is shifted left and, if carry is set, rimp is set to toggle OC0A. The value of rimp is written to the control port register A of TC0.

For all instructions to be executed the required clock cycles are added in red in the flow diagram. All remain below a level of 38 clock cycles, after which, at a crystal frequency of 3 MHz and an IR frequency of 40 kHz, the next interrupt comes in. Only in the case that the wait cycle has just finished and transmission of the first character starts, this limit is reached. Because the next interrupt initiation requires five clock cycles to get active (the rjmp in the vector is executed), the limit is not exceeded. The case of a loss of an interrupt only occurs if another such interrupt remains untreated, the limit is twice the 38 clock cycles long. Even if another interrupt occurs in between and has a higher priority would occur (e.g. an INT0), this doesn't cause a loss, because such interrupts are disabled during the transmit period.

At 4 MHz or higher the execution is even faster, so that losses of interrupts are not possible.

Toggling the OC0A output when sending the start bit and 0b0101 This here shows the toggling of the OC0A output pin during the transmission of a start bit and of the upper nibble of 0x5x with 1,200 Baud. The transmit frequency of 40 kHz is exact, the LED is 50% of the time on. All signal durations are of equal duration, that's what an IR receiver likes.

Toggling the OC0A output when sending 0x55 This here is the transmitter output for the whole 0x55 byte and for the beginning of the next start bit. The stop bits in 8N2 are twice as long.

Toggling the OC0A output when sending 0x55 twice The same for sending 0x55 twice. The double space of the two stop bits yields - roughly - a 600 Hz signal.

Top Functioning Hardware Mounting Software Algorithms

5.2.6 Wait time prior to transmit

In order to avoid sensor tranmission conflicts, the controller waits for a certain time period, during which no other sensor is transmitting. The wait time period restarts if another sensor transmits, so that all sensors are transmitting in a fixed row.

Each sensor has an indivual time period, which guarantees that a priority chain gets active.

Flow diagram of the wait period This is the flow of the wait cycles. This is added as a further part of the OCR0A interrupt service routine and gets active if the bTx and bRx flag is low anfd the bRq flag is active (Rq = Request TX). If all three flags are inactive, the OCR0A interrupt is disabled.

During the wait period, the INT0 interrupt is disabled. The INT0 input pin is checked during the wait period, if active (low) another sensor transmits and the counter is restarted.

If not, the counter is decreased by one. If not yet zero, waiting continues.

If the counter reaches zero, transmission starts:
  1. the Tx-Request-flag is cleared, and
  2. the transmit flag is set, and
  3. the X-pointer is set to the text buffer start, and
  4. the first character in the buffer is read to register rTx, and
  5. the INT0-interrupt is disabled, and
  6. the counter for the number of IR signals is set to 1 and the number of bits to be transmitted is set to 11, and
  7. the compare-A-value of TC0 is set to the IR-transmit-value, and
  8. the prescaler of TC0 is set to one.
Then the first start bit is transmitted. For this a jump to the respective routine within the transmit algorithm is executed.

All further bits of the first character as well as all other characters of the string are send with the bTx flag set.

Top Functioning Hardware Mounting Software Algorithms

5.2.7 Serial reception to the receive buffer

Clocking the reception during receive During receiving serial signals, the flag bRx in the flag register is set. That is initated by the INT0 interrupt, when a falling edge occurs. In receive mode the TC0 compare match A interrupt senses the IR input pin on INT0 for the next bit. The period between the time that the start bit started and the center of the bit 7 (one-plus-one-half bit length) is written to the compare A port register, the prescaler is written to be 64 (in the default case).

The IR-to-serial-converter transmits the signals that are sent by over the interface. Normally the converter's receiver module is close to the transmit LED, and so loops back the received signal over the receive pin on the serial interface. So, the thermosensor does not need to loop back the incoming signals, which simplifies the sensor's program.

Prior to reception the IR-receiver module TSOP31240 waits for incoming signals. After roughly 10 IR-pulses the module activates its output pin by pulling it low. The output pin is attached to the PB2 = INT0 pin. The falling edge initiates an INT0-interrupt. This switches the INT0 interrupt enable off, sets the bRx flag in the flag register, sets the bit counter rBits to 9 and starts TC0 with the following settings:
Flow diagram for receiving Now the following happens:
  1. The counter rBit is decreased by one. If it gets zero, the recption of one byte is finished. If not, the following happens.
  2. Always, when the time of the TC0 is over, the input pin is sensed. If low, a zero is shifted into the byte in register rRx to the left. If high, a one is shifted into rRx.
  3. The compare A port register is set to the cTc0Rx period, which is the time between two bits (at 4 MHz and 1200 Baud this is 52, because 4,000,000 / 64 / 1200 = 52, the delay of 10 signals in the receiver module is also inserted here.
If the reception of an 8 bit character is finalized, which occurs in the middle of the first stop bit, the following happens:
  1. The received character is written to the SRAM receiver buffer in sRx, to which the Y pointer points.
  2. It is tested, if the pointer now points to beyond the receiver buffer (buffer overflow). If that is the case, the Y pointer is set back to the beginning of the buffer area. An undefined command code is written to this location to provoke an error message.
  3. After that, a null-terminating byte is written to the next location.
  4. Further interrupts from TC0-Compare-A are disabled, only the clock interrupts of TC1 are kept active.
  5. The bRx flag is cleared, the further reception is disabled. This is enabled again, if the next start bit arrives.
  6. Then it is tested, if the received character is a linefeed. If that is the case, the flag bRxL (received line) is set, initiating analysis of the received line.
  7. If the character is not a linefeed, INT0 interrupts are enabled again and the controller waits for the next start bit.
The number of clock cycles, even though part of the diagram in red, is not very relevant here, because the serial transmission speed is low and the prescaler of the TC0 is 64. Even with higher speeds the number of clock cycles, where interrupts would get lost, is never reached.

Top Functioning Hardware Mounting Software Algorithms

5.2.8 Analysis and execution of the received line

Commands for thermosensors If the controller detects, after executing interrupts, that the flag bit bRxL is set, the received line has to be analyzed and, if the sensor is the receiver of a message, the received command has to be executed.

First of all, the received line is re-formatted:
  1. All ASCII control characters, blanks and minus symbols are removed from the line.
  2. All small letters are converted to upper-case.
The remaining content is analyzed:
  1. If only a linefeed has been received (the first character is a null character), immediate measurement is initiated.
  2. If the first character is a decimal digit between 0 and 9, it is checked whether this matches the own ID. If that isn't the case, the command is ignored.
  3. This or the next character is checked for being in "D, T, M, K, C, F, A, B, ?, H". If the character is in "D, T, M, A, B, C", a "=" can follow. If that is the case, the following is done:
  4. If an error occurs, a meaningful error message is transmitted and the green LED of the sensor blinks once. Otherwise ID, date, time, temperature and its dimension are send back, and the green LED blinks three times.
Please note, that changing the settings for "TK/TC/TF, M, A, B, C" are written to the EEPROM and read from there on the controller's start-up. These commands do not have to be repeated when starting, only date and time need an update.

Many success when communicating with those devices.

Top Functioning Hardware Mounting Software Algorithms

©2023 by