Introduction: Arduino Based House Heater Controler With SMS User Interface

The project provides instructions and code to build a heating controller for your home or remote country house, which can be controlled and monitored by GSM via SMS commands. I started to design it as we needed a reliable and remotely accessible heating controller for our country home, which is in deep in the countryside where temperatures fall down to -30°C in wintertime and where there is no reliable (and affordable) internet connection. Commercially available controllers either did not offer GSM control, or did not have the safety features nor the relative ease of comparably plain-text command operation we required.

Step 1: Description & Partslist

The device is built around an Arduino compatible Freeduino ATMega328, has a rather simple customs shield for timing, temperature measurement and interfacing and communicates via RS232 with a tc35i Siemens GSM modem. It is housed in a picture frame and unobtrusively hangs on the wall. Most important, it has been working flawlessly for a year now. It offers the following functionality:

- on/off control (as opposed to more advanced control algorithms like PID or control protocols like Opentherm) of heater (gas central heating), which is switched via a simple relay
- interactive control through 3 button keyboard and simple large LCD with plaintext menu system
- 6 operating modes:
    o manual temperature control
    o comfort (daytime) or economy (night) temperature regimes
    o cycle: switches to programmable comfort level in the morning, and to reduced night temperature level in the evening
    o profile: freely programmable temperature profile per day or group of days for selected days of week
    o antifreeze: keep temperature at low programmable temperature (e.g. 8 °C)
- real time clock with battery buffer
- inside and outside (optional) temperature measurement
- control of all operations and parameters by plaintext SMS (e.g. “antifreeze on”, “time set 09:20” …)
- editable phonebook for up to five registered users
- status return SMS by a call to the device (left unanswered, so at no cost for caller)
- regular daily logging by SMS to 1 user to monitor operations
- SMS alerts for crossing temperature limits and suspected heater malfunction
- all parameters are stored in non-volatile memory to safeguard against power outages

So typically during wintertime, the house is kept in antifreeze mode. Several hours before arrival, we send a SMS to start heating up to a comfortable temperature level. We switch to ‘cycle’ mode and the device switches between 20°C during daytime and 17°C at night. In addition, every morning the device reports about the current status by SMS to my mobile. If we reliably know our schedule, we program the device to heat up automatically before our new arrival.

The challenges in design were threefold: apart from the basic requirements for functionality and GSM interfacing, space on the ATMega has been a major limitation. Finally the rather rustic and traditional log house required some nice and aesthetically appealing casing. The golden picture frame fits well.

As a general disclaimer, I urge caution when modifying existing heating systems, as this may result in major damage. Also, the typical precautions when handling high voltages must be applied. Finally, I do not assume any responsibility on the working of the device or code. Suggestions or improvements are welcome.

What you need:

• 1 Freeduino Serial V1.2 from Fundamental Logics (ATMega 328) any Duemilia compatible will do, however, it requires a serial port (or an adaptor circuit) to interface with the GSM Modem
• 1 Siemens tci35 or mc35i GSM Modem
• 1 antenna for Siemens (in my case a simple wire would do)
• 2 D-Sub 9-pole male connectors for soldering the RS232 cable
• 1 LCD Display 20x4 or 16x4 characters preferably with backlight (e.g. 20x4 with large 9mm characters: HITECH DISPLAYS, Model: HMC020487SY-LY, 146.00 x 57.30mm)
• 1 power supply (12V, 2.0 A) with 2.1 mm center postive plug
• 1 female 2.1 mm connector
• 1 male 2.1 mm connector
• 1 Western 6 pole male connector for connecting to the GSM Modem
• 1 (inside only) or 2 (inside+outside) Dallas DS18B20 temp. sensors TO92
• 1 capacitor 100nF for the outside temperature sensor (solder between +5V & GND to increase one-wire bus stability at longer cable lenghts)
• 3 push buttons (2 black, 1 different color)
• 1 capacitor 10uF / 16V
• 1 capacitor 150nF  / 16V
• 3 diodes 1N4148
• 1 battery CR2032H
• 1 battery holder for CR2032H
• 2 pinheads 1X08 2.54 mm, 19mm pins (for stacking onto Arduino)
• 1 pinhead 1X06 2.54 mm, 19mm pins (for stacking onto Arduino)
• 1 pinhead 1X06 2.54 mm
• 1 pinhead 1X04 2.54 mm
• 1 pinhead 1X09 2.54 mm (depends on LCD pinout, particularly backlight)
• 2 connectors 2.54 mm to solder to LCD
• 1 Relay Omron G6C-2117P
• 1 Quartz 32.768kHz
• 2 resistors 10k
• 1 trimmer 10k
• 1 resistor 1k5
• 2 transistors BC547 TO92
• 1 timer chip Dallas DS2417 TSOC6
• 1 connector  3 contact phoenix-350 – may take 220V if required
• 2 connectors  3 contact phoenix-254 – 5V only for one wire temp sensors
• a suitable casing (in my case a 30cm x 40cm picture frame with thick passe-partout to hold the components)
• two aluminum angels (to accomodate pushbuttons), screws
• PCB (eagle files attached)
• some wires
• glue or hotmelt
• 4 screws 2.5 mm x 10 mm plus nuts to fix the LCD
• some velcro

• Standard electronics tools
• a crimping tool for Western 6 pole connector
• soldering iron, additionally a flat soldering tip for soldering the 2417 SMD
• PCB etching equipment & supplies (e.g. for toner transfer method)
• Arduino IDE (> 1.0.5, may work with earlier versions)
• Arduino standard libraries
• USB to RS232 cable to program the ATMega, alternatively a programmer, recommended in any case for testing GSM-Arduino communications
• Program code and custom libraries (attached)

Operations (optional):
• GSM SIM card, startup PIN request switched off

Step 2: Overview

The figure depicts the major functional blocks of my design.

All is controlled by the ATMega on a Freeduino board. As RAM space is rather limited (it compiles into 30602 of 30720 available bytes) I chose to make use of the one wire bus for both DS18B20 temperature sensor and to effect time keeping via a DS2417 chip. This device only counts seconds, so I added a small library modeled after the DS1307 functionality to allow for proper timekeeping and calendar functionality. Irrespective, this setup is more economical on ram compared to a combination of DS18B20 and DS1307. The time chip is buffered by a CR3202 battery, which will maintain operation in the event of power loss.

The ATMega communicates to the GSM modem via RS232 (crossed pair cable). On the hardware side I therefore employed an Freeduino with RS232 interface on board, which avoids additional driver hardware. The modem is controlled by a library allowing for a straightforward use of its AT command set, basic text parsing capabilities as well as SMS and incoming call handling. Phone numbers for up to 5 users are managed by a phone book library.

The user interface consists of a 3 button keyboard for menu navigation (up/enter/down) and number/data entry as well as a 20x4 LCD display. As I wanted the data to be readable from afar, I chose a display with large 9mm letters and backlight. You can use smaller displays and also 16x4 or smaller sizes (modify the compiler switches in the sketch). Keyboard and display are controlled by the uC's digital I/O pins via a modified standard Arduino liquid crystal library (adapted to drive both 20x4 and 16x4 displays) and a library for menu navigation and event handling.

The ATMega controls the boiler via a small 5V relay and its transistor driver, which can handle up to 220V at low currents. This typically is sufficient for driving boiler on/off contacts. The software components for heater control are a controller library managing set points, minim run times and temperature limits, an alert library which is used to communicate warning messages as well as a library providing functionality for temperature profiles and their management.

All data (1wire bus addresses, heater control parameters and state as well as phonebook settings etc.) are stored in non-volatile EEPROM to safeguard against power losses.
All electronics are placed on a custom shield, which is stacked onto the Freeduino. The custom shield also contains sockets for the LCD and holds its contrast trimmer and backlight driver.

One temperature sensor is directly attached to the shield for the inside temperature, a second for measuring the outdoor temperature can also be connected by a 3 wire cable. Power is provided by a 12V 2A supply.

Step 3: Building the Shield

The custom shield is fairly simple and is assembled on a single sided PCB. Beginners in electronics should have not too many problems building it. Eagle files are attached, so is the PCB etching pattern.

The PCB can most easily be prepared with the toner transfer method. You will find ample references for this on the net. Once it is etched and holes are drilled, all devices but the 2417 chip can be soldered. The 2417 Chip is a surface mounted device. It is soldered on the print side of the PCB, i.e. on the side with the copper patches. This is a bit more tricky – the result is shown in the picture, and it is not one of my best. You will find a number of descriptions on how to solder SMD chips on the net.

If your relay needs to switch 220V, you may want to cut a 1 mm slit into the PCB thereby separating the 220V relay contacts from the low voltage part. This will increase insulation. In this case you can no longer use an open design and all contacts need to be covered. You should employ an insulating housing, properly grounded, for the entire device. In my case I only had to switch 12 V coming from the heater, so this was not necessary.

While the dimensions and contacts for the Arduino are fairly standardized, the location of the contacts for the LCD display need to be modified for your particular choice of display.

Finally solder the contacts to the LCD, which should match the LCD contacts on the shield. You can and should test with the shield and the Arduino before mechanical assembly.

Step 4: Building the User Interface

Next comes the keyboard and the LCD display. For my particular choice of housing, a picture frame this was fairly straightforward choice, which was acceptable also to my family.

For the LCD Display, I cut a corresponding rectangular hole into the passe-partout. This should fit pretty tightly in order to provide extra mechanical stability. Next fit in the LCD and mark the center of its mounting holes on the back of the passe-partout. Then either use hotmelt or - as I did - 2 component polymer glue to fix 4 screws to hold the LCD. The LCD can then be screwed onto the screws and is firmly held in place.

If you are a good at woodworking, you could install the 3 pushbuttons into the frame body. I had some space as the frame would hang between two logs and there was ample space behind it, so I fixed the buttons on a small piece of aluminum metal, which was screwed to the frame. The pushbuttons are switching to a common ground. There should be four wires coming from this keyboard to the port on the right hand side of the custom shield depicted above.

Step 5: Connecting Things

In order to connect the components, the following cabling needs to be prepared:

Power Supply: the power supply with the 2.1 mm connector drives both Freeduino and the Siemens Modem. The lines are connected 1:1 to the Freeduino plug. The Siemens Western plug needs to be connected along the pinout described in the Siemens manual p. 18 ff. The PD_IN pin is connected to ground, the IGT_IN goes to +12V.

For the RS232 cable, only 3 lines are required, pin 5 on both ends are connected, lines to pins 2 and 3 are crossed.
The last 4 line cable connects the keyboard to the custom shield. Common ground is the yellow line on the pictures followed by up, enter and down.

For the antenna, I simply took a 15 cm wire, which I wrapped around a 1.5 mm drill bit. This fits firmly on to the center pin on the Siemens and is sufficient for the location.

Step 6: Assembly

First attach the LCD display to the picture frame by sliding it over the screws and fix it. Then plug the keyboard cable onto the custom shield, attach the indoor temperature sensor and the outdoor sensor, if available as shown in the pictures. The two lines to the boiler are attached at the relay port. Then you can plug the custom shield onto the LCD, which provides mechanical support for the entire structure. The custom shield is then attached to the Freeduino and both are connected to the LCD.

The modem is easily fixed onto the back of the passe-partout with two Velcro strips.  Next, connect the Freeduino to the modem by the RS232 cable and do not forget to connect the antenna.

Finally, connect the power supply cable to modem and Fredduino, and power up. If the display does not show anything, adjust the contract first with the trimmer on the shield.

Step 7: Compilation and Upload, Libraries

Depending on your operating system, place the supplied libraries into the designated folder and save the program into your Arduino sketches folder. In order to program the Freeduino, you can either program the ATMega on a programmer, on your Arduino, or via a RS232-USB cable on the Freeduino.

As the menu strings are residing in the processor's EEPROM memory, they have to be loaded there first. This is done by a small program (streeng.ino) that has to be loaded and launched prior to compiling and installing the main controller program (steuerung.ino). The streeng program as well as the controler make use of the streeng class library, which allows for saving and accessing character strings in EEPROM.

A few words on the libraries:

Menu System

The functionality of the device requires a structured user interface. I developed the menu system with three objectives: simplicity, flexibility and low memory footprint. The menus are hierarchical down to 4 levels. Menu entries can be modified at runtime and the system also provides functionality for the entry of alphanumeric and time data. For the input only three buttons (up/enter/down) are required. Button push time is also used for additional functionality.

The LCD shows a header panel line (status information, time, temperature, operating mode and boiler state) as well as 3 lines of menu. Depending on display size, this can be more or less (e.g. header plus 1 line for a small 16x2 display). Menu navigation does not affect the header panel. The current menu position can be seen on the left most side and is indicated by a '>'. The text for the menu entry is seen at screen center. In case that there are submenus for a menu entry, a '>' is displayed on the rightmost side. Menu items are selected by pressing the enter key, up and down navigates correspondingly within the menu tree. Pushing enter for longer returns to the menu root, pushing 'up' longer navigates one menu level up.

Strings are edited by changing the value under the highlighted cursor using the up/down keys. Holding them longer will move the cursor. The enter key terminates editing with the new value taken over, holding it longer will also terminate, but restores the original string value.

The menu class library provides for three ways of storing the menu item text: 1) program memory, 2) EEPROM, 3) for both of the above dynamic calculation by a function provided. At program start the menu tree needs to be built up using the entry function. In this example due to memory limitations EEPROM is used mostly for storage (phone books are dynamic and thus use dynamic menu entry creation). Menu entries are identified by an index number (index to position in EEPROM, or function argument) and a number coding their position in the menu tree (4 hex digits indicating a level each). So 0x1000 would signify the first menu entry on the top level, 0x2000 the second top level menu, while 0x1400 would denote the fourth submenu to the first top-level menu entry. The index number allows for a change of menu text during runtime by repeated calls to the entry function (e.g. On/Off toggling).

The main function called from the user program is an event handler, which returns menu items selected and handles all menu navigation, display update and scrolling. While waiting for menu events, the event handler allows the calling program to use processor time via a custom service routine, which has to be supplied.

Command Line Interface

One essential feature of the user interface is the command line interface, which allows for input of plain text commands. While it is used for input from SMS, it can also be used and adapted for other command syntax and purposes (e.g. input via IP).
Essentially the command line is parsed for keywords (residing in program space), which are then translated to a compact intermediate code, which is then easily checked for syntax. Arguments such as time and temperature information are expected in a particular form (hh:mm for time, tt.t for temperature). In case that a syntax error be detected, an error message is produced.

Phone book

The phonebook manages phonebook entries and stores them in the controller’s EEPROM. The library heavily depends on the menu library, which supplies edit functions as well as the backbone of the phonebook menu structure.
The Phonebook library creates a menu structure with dynamic menu entries, which each have submenus for editing and deleting. Routines for editing and deletion are provided by the menu library. Generally, phone numbers may have 16 digits and are stored in international format commencing with a starting ‘+’ and the country code.


The boiler’s on/off contact is controlled by the controller software. The library switches the heater depending on the relevant setpoint, which is either manually set (via the Temperature menu entry), uses default values (Comfort, Economy or Antifreeze, which in turn are set by the Settings menu item) or is determined by the schedules programmed by the user. The schedules can be programmed with one minute time resolution. Up to five time intervals with individual temperature settings can be programmed.
While controlling the boiler, the library takes care not to run the heater for less than the pre set minimum runtime, and also checks for possible malfunctions, i.e. when the room temperature does not increase during heater operation. In case that a malfunction is encountered or the temperature falls below (Alert 0) or exceeds (Alert 1) programmed setpoints, alert messages are sent by SMS. Finally the controller attempts to assure at all times that the measured temperature never falls below the antifreeze level defined.


The GSM library performs the communication between Freeduino and Modem. The library performs basic IO with the modem, provides a method to send AT commands to the modem and provides for basic functionality to monitor incoming calls and manage incoming SMS messages as well as initiating outgoing SMS messages.

Step 8: Using It

After startup the device will check for availability of a Modem and issue appropriate commands for initialization. In the absence of a modem, the device will be restricted to manual operation. The GSM relevant menu entries will then be disabled.

During first the first run the device will look for temperature sensors and allocate them arbitrarily to inside and outside sensors. The user may change that arbitrary choice by later swapping inside and outside sensors (settings -> swap sensors). This setting will be stored in non-volatile EEPROM and are available upon reboot. During the first run (and in case temperature sensors are changed) the device will notify the user to check the sensor allocation.

Thereafter, the display will show at the top line from left to right: time, day of week, inside temperature, outside temperature, operating mode. For operating mode, the device displays the following characters in the upper right corner:

A – Antifreeze (reduce temperature to preset antifreeze level, but never fall below)
C – Comfort (maintain preset comfort level – default: 20°C)
E – Economy (maintain present economy level – default: 17°C)
O – Cycle (cycle between comfort (during day) and economy (during night)
P – Programmable Profile
M – Manual Temperature (maintain manually entered, fixed temperature)

The operating mode will alternate in one seconds intervals with the heater run indicator, which is the asterisk (‘*’) for a boiler operation.

The programmable profile consists of up to 5 temperature regimes starting with 00:00 and ending at 24:00. Each profile can be declared valid for individual days or groups of days (e.g. weekdays, weekends – or only on a thursday).

Manual Operation

The user can scroll in the menu tree as described above and can switch between operating modes and modify settings. All changes are saved in EEPROM to prevent data loss due to blackouts.

GSM Operation

If a GSM modem is available, the user can also send commands via GSM and receive status information. In general, all manually available functions can also be effected by GSM. For that, the user’s telephone number has to be registered with the device (SMS -> phonebook) and the calling user must have caller number transmission enabled on his phone. Upon completion of the SMS command, the device will typically issue a status message, which summarizes the current operation followed by an ‘OK’ or ‘Error’ message.

List of SMS Commands:

cycle on  // economy at night, comfort during day
cycle off  // switch off cycle mode, back to antifreeze
cycle set hh:mm tmp1 hh:mm tmp2 // set switch time and temperature value for cycle
economy on // switch on economy temperature
economy off // switch off economy mode, back to antifreeze
economy set tmp // set economy temperature to value
comfort on // switch on comfort temperature
comfort off // switch off comfort mode, back to antifreeze
comfort set tmp // set comfort temperature to value
temperature on // switch on manual temperature mode
temperature set temp // set manual temperature level to value
antifreeze on // switch on antifreeze mode
antifreeze set temp // set antifreeze temperature level to value
profile nr mode // switch on profile nr to mode (see below)
profile nr set hh:mm temp // set in profile nr temperature value at time
profile nr reset // reset profile nr
time set hh:mm // set device time to hh:mm
date set dd mm yy // set device date to dd mm yy
alert  // enquire status of alerts
alert nr on // activate alert nr (0/1)
alert nr off // deactivate alert nr (0/1)
alert nr set tmp // set trigger level of alert nr to temperature
status log set hh:mm // set device log time to hh:mm
status log on // switch on daily logging at programmed time
status log off // switch off daily logging
status // send status SMS to sender

Temperature and Time formats:

Temperature format:  tt.t  (decimal and fraction is mandatory)
Time format:   hh:mm  (two digits for hrs and min mandatory)

Temperature Profile Mode:

The controller can operate temperature schedules for various time periods and days:

Never   0 (= switched off)
sunday   1
monday  2
tuesday  3
wednesday  4
thursday  5
friday   6
saturday  7
weekday  8 (mon – fri)
weekend  9 (sat – sun)
first half of week 10 (mon – wed)
second half of week 11 (thu – fri)
always   12

Microcontroller Contest

Participated in the
Microcontroller Contest