Generic heating / cooling controller

This article describes a generic heating / cooling controller implemented in a AVR ATTiny25 microcontroller (MCU).

The controller is an on-off or bang-bang type controller with programmable hysteresis (or differential) and minimum on and off times.

The controller logic is contained in program stored in flash memory, and parameters that control its operation are stored in EEPROM. This means that the same flash module can be used for a range of applications, and operation tailored by field programming of the EEPROM with appropriate data.



The controller acts on an analogue signal impressed on ADC1 pin of the MCU. The voltage must be in the range 0-1.1V for accurate conversion. The ADC has 10bit resolution, so 1024 steps from 0V to the chosen reference voltage. When using the internal ADC, the source impedance of the sensor should not be less than about 10kΩ.

A wide range of sensors can be used, with or without a voltage divider, to develop a voltage in this range for the required temperature range, for example:

To use a very low voltage sensor (eg a thermocouple) requires an external amplifier. For example, the AD595 amplifier with cold junction compensation for a K type thermocouple could be used with this controller. Another option is a 4-20mA transducer (very low cost on eBay).

The design does not include an 'anticipator'. Anticipators used in mechanical thermostats help to prevent overshoot caused by delay in the control loop, particularly evident on the initial run. More sensitive temperature sensing and faster response help to avoid the need for the open loop anticipator action. It is often (incorrectly IMHO) held that an anticipator is merely to shorten the cycle time, this design includes facility for minimum on and off times to prevent short cycling which can be suboptimal or even damaging to equipment, suitable values can be chosen to suit the type of equipment being controlled.


Control output

The main control output is to operate the heating or cooling appliance and is a logic output which will require a driver to operate the final load. The driver might for example be a FET relay driver, a SSR.


There are two alarm outputs:

Either of these outputs could be buffered to drive higher current loads.


The EEPROM layout is version dependent. The current flash program will ignore EEPROM data that does not match its EEPROM version level.

Table 1: EEPROM structure
Variable Bytes Comment
ver 1 EEPROM version (2)
opt 1 Options, see Table 2.
offset 2 offset temperature specified in ADC units
alarm 2 alarm temperature specified in ADC units
setpoint 2 setpoint specified in ADC units
differential 2 differential temperature specified in ADC units
ion 2 minimum on time in s/4
ioff 2 minimum off time in s/4
msk 2 mask anded with SPI read

Table 1 shows the EEPROM variables, their size and usage. All variables are unsigned binary integers. The temperature equivalent of ADC units depends on the sensor used, and in some sensors (eg thermistors), the relationship may be moderately complex.

Differential is the difference between the set point and the maximum allowed deviation from set point before the system calls for heating or cooling.

For conversion from V1 EEPROM format, setpoint=ton+differential for H mode, setpoint=ton-differential for C mode.

Table 2: Option bits - V1 EEPROM
Option Bit Comment
OPTHEAT 0 Heating mode for up/up control loop (ie non-inverting temperature sensor).
OPTHR 1 1.1/2.5V reference
OPTEXT 2  external sensor on ADC1
OPTPOT 3 Use pot to set turn on temperature.
OPTAII 4 Inhibit alarm until first off cycle.
  7:5 Reserved.


Table 2: Option bits - V2 EEPROM
Option Bit Comment
OPTHEAT 0 Heating mode for up/up control loop (ie non-inverting temperature sensor).
OPTEXT 2:1 0: internal sensor (ADC4/8)
1: external sensor on SPI
2: external sensor on ADC1
3: DS18B20
OPTPOT 3 Use pot to set turn on temperature.
OPTAII 4 Inhibit alarm until first off cycle.
  7:5 Reserved.

Table 2 shows the use of the bits in the Option byte of EEPROM

Table 2: Option bits - V3 EEPROM
Option Bit Comment
OPTEXT 3:0 0: internal sensor (ADC4/8)
1: external sensor on SPI
2: external sensor on ADC1
3: DS18B20
4: DHT22 temperature
5: DHT22 humidity
OPTHEAT 4 Heating mode for up/up control loop (ie non-inverting temperature sensor).
OPTPOT 5 Use pot to set turn on temperature.
OPTAII 6 Inhibit alarm until first off cycle.
  7 Reserved.

Table 2 shows the use of the bits in the Option byte of EEPROM

The DS18B20 is used in 10bit mode, and values specified in the EEPROM for setpoint and alarm is temperature*4+512. The DS18B20 must be the only sensor on the bus, must be powered (ie parasitic power), and the full temperature range is supported

The values for the DHT22 Temp and Humidity are a signed integer in tenths of degrees or tenths of one percent RH. hcctl should be compatible with other sensors compatible with the DHT22.


Table 3: AtTiny pinout
Signal ATtiny25 pin DIP8 pin ATtiny24 pin DIP14 pin Comment
Sensor ADC1 7 ADC1 12 Voltage from external temperature sensor.
Output PB4 3 PB2 5 Output to control heating / cooling appliance (active pullup / pulldown).
/Button PB1 6 PB1 3 Button input with weak pullup, external 10kΩ pullup compatible with ATB).
/Alarm PB0 5 PB0 2 Alarm output for over/under temperature (open collector with weak pullup).
Pot ADC3 2 ADC3 10 0-1.1V to set setpoint if option selected.
/CS     PA7 6 Weak pullup.
SCK     PA4 9 Weak pullup.
DO     PA5 8 Weak pullup.
DI     PA6 7 Weak pullup.
Vcc Vcc 8 Vcc 1 +5V
Gnd Gnd 4 Gnd 14 Ground

Table 3 shows the use of the MCU pins. Use of some pins is optional, depending on the selected option bits.

Self calibration

Some sensors may give a quite predictable slope to their characteristic, but need calibration at some temperature to improve absolute accuracy.

The controller contains a feature to store the 'current temperature' into offset. If offset=0xffff when the MCU is reset (using /RST), it will read the external sensor and store the ADC output into offset then stop.

To use this feature, specify setpoint relative to the ambient temperature at which the EEPROM will be programmed, and offset=0xffff. Reset the MCU and it will write the 'current temperature' equivalent to offset in EEPROM. Reset the MCU again and offset will be subtracted from the output of the ADC at each measurement.



Fig 1: 

Fig 1 shows the prototype built for code testing. It is complex in having hardware for testing of all of the controller's features, and it uses a TC427 dual driver for the control and alarm outputs.

Other implementations

Fig 2: 

Fig 2 shows the controller module fitted to a power supply to control a 12V muffin fan for supplementary cooling. See Fan controller for Manson EP-613 / Jaytech MP-3082 with fan for more information on that application.


The controller could be used as a thermostatic controller for a heating for cooling appliance, with or without alarms.

The alarm feature alone, contact closure and/or audible alarm could be used separately as a stand alone monitor of some system.

Example 1 - monitor for excessive heat sink temperature

This example design uses an off the shelf LM35 temperature sensor which has 0.5° accuracy without adjustment to alarm heat sink temperature in excess of 100°. The LM35 produces a voltage of 10mV/°, so it produces 1V at 100°. The LM35 would be connected by three wires to the contoller board, and could be attached to the heatsink with thermally conductive adhesive.

he critical ADC output at 100° will be 1.0/2.1*1024=931=0x03a3. So Alarm=0x03a3. We do not wish to use the offset feature, so Offset=0.

If setpoint is set to 0x3ff, the value should never be reached and that part of the code ignored. The alarm works quite independently of the controlling function, but it does share offset.

Putting the options together, this is a cooling controller with an up/up sensor, so the options bits will be 0x04.

Fig 3: 

Fig 3 shows the binary EEPROM image in Hex Editor Neo. Hex Editor Neo Professional contains a really useful facility to bind a structure definition to the binary file contents, allowing exploration of the structure using the structure element types, sizes, labels etc. The cursor hint in Fig 3 shows that the word containing 0x0190 is the alarm variable with a value of 400 decimal. Isn't that clever!

The alarm output can be used to light a LED (with a series resistor as required) to show over-temperature, and a buzzer can provide an audible alert. Pressing the button will cancel the alarm, and pressing it again will undo the cancel.



Version Date Description
1.01 16/03/2013 Initial.
1.02 01/05/2015 Added OPTAII.
1.03 13/05/2015 Added SPI sensor read.
1.04 06/06/2015 Setpoint terminology.
1.05 27/06/2016 Sense of alarm changed to /ALARM, function moved to old spkr pin, alarm cancel added.
1.06 03/03/2017 v2.03: added DS18B20 support.
1.07 01/04/2017 v2.04: added DHT22 support, V3 EEPROM.
1.08 10/09/2017 v2.05: fixed initialisation of ADC.

© Copyright: Owen Duffy 1995, 2021. All rights reserved. Disclaimer.