Making your own smart ‘machine learning’ thermostat using Arduino, AWS, HBase, Spark, Raspberry PI and XBee

Previous part:
4. Storing data in the Amazon Cloud (HBase)

5. Turning the boiler on and off at the right time (Arduino)

5.1 Six boiler on/off intervals per hour (understanding how a thermostat works part II)

After finishing the previous part, I collected the temperature sensor data and the data from the photo resistor for a couple of weeks (when the normal thermostat would turn the boiler on and off).

The next step was to turn the Arduino into an actuator and let the Arduino turn the boiler on and off, Thus turning the Arduino into a thermostat.

Looking at the collected information I noticed that regardless of the temperature and difference between the set and actual temperature the thermostat would never turn the boiler on and off more than 6 times per hour. Regular intervals can be distinguished between every moment the thermostat turns the boiler on. Looking at the data in more detail I saw that when the temperature difference between the set and the actual temperature was smaller it would turn the boiler on for a fewer number of minutes than with a bigger difference, as can be seen in figure 9.

Figure 9: six boiler on/off intervals per hour

Knowing now what to search for, I searched the Internet for the interval value of a thermostat. And this was exactly how a thermostat worked. For most thermostats the interval per hour is a setting, ranging from 3 to 12 intervals per hour. Unless you have a system that does not have gas fired furnace, for example a heating system that uses excess heat from a power plant (something that is common in Amsterdam), you are supposed to turn your boiler on and off only a couple of times per hour. The first reason is for this is that if you constantly turn your boiler on and off you would break it. The second reason is that it takes a while before the room temperature increases after the boiler turns on the heat. This depends on the distance between the boiler and the thermostat and how long it takes for the room to absorb the heat form the radiators. This also explains why my normal thermostat sometimes overshoots and the room gets a lot warmer than the set temperature. In figure 9 you can see it actually takes 10 minutes before the room gets warmer after the boiler is turned on.

5.2 Thermostat Hardware (final breadboard layout schematic)

The hardware to turn the boiler on and off is the simple relay schematic from the ARDX starter kit . The relay was added on a separate breadboard, which was added to the setup explained in part 2 of this blog post. The final breadboard layout and schematic for this project are shown in figure 11 and 12.

5.3 Arduino thermostat code

To control the boiler with the Arduino I used the same interval pattern. I created three run levels and three functions. The run levels are in the main loop()of the arduino.

The first run level (level 0) is the off state. In this level it checks, with the function frunScen(), weather it is necessary to go into on mode. If the temperature difference is more 3,5 degrees Celsius it goes to the second run level.

In the second run level (level 1) the Arduino decides for how long it should turn the boiler on. For this it uses the function fscenLenght() that takes the temperature difference as input. It then proceeds to the third and last run level.

The third run level (level 2) always runs for 10 minutes. This level takes the ‘duration the boiler has to be on’ as input. Every cycle in the third run level, the Arduino checks if the boiler should still be on, using the fboilerStat() function. If the amount of on time or the desired temperature has been reached in turns the boiler off. The fboilerStat() function ads 3.5 degrees Celsius to the set temperature to allow for a temperature decrease when the boiler is turned off. After ten minutes the run level goes back to 0.

To monitor the Arduino thermostat, the set boiler state and the time the Arduino decides the boiler should be on are also send to the Raspberry PI and subsequently forwarded to the Cloud server. Allowing analysis of the workings of the thermostat. The result can be seen in figure 10, showing that the Arduino perfectly mimics my normal Honeywell thermostat.

Figure 10: Arduino thermostat

Thermostat main loop

//variables for calculating avarage temperature at Arduino
int avgTotalTemp = 0;
int avgTemp = 0;
int avgNumSamp = 0;
int avgMaxSamp =10;
//control variables
int startup = 0; //initial delay before temparature is set
int controllPin = 9; //pin connected to relay
int runScen = 0; //temperature run level 0 ,1 or 2
unsigned long startScen = 0; //scenario started
unsigned long scenLength = 0; //minutes on
unsigned long maxScen = 600000; //10 minutes
int boilerStat = 0; //boiler status
//variables of inital check if arduino has been running long enough
int vrunl = 0; //
unsigned long startArdMillis = 0; //start millis
unsigned long nextRunl = 10000; //milisecond arduino has to be running
void loop() {
unsigned long currentMillis = millis();
//vrunl is used to see of Arduino has been running for x number of second to make sure a viable actual temperature has been received or measured
if (vrunl == 0) {
startArdMillis = currentMillis;
vrunl = 1;
} else if (vrunl == 1) {
if (currentMillis – startArdMillis > nextRunl ){
vrunl = 2;
// calculating avarage temperature using thermistor 1 value
avgNumSamp = avgNumSamp + 1;
if(avgNumSamp > avgMaxSamp) {
avgNumSamp = 1;
avgTotalTemp = 0;
avgTotalTemp = avgTotalTemp + thermistorValue;
if(avgNumSamp == avgMaxSamp){
avgTemp = (int) round(avgTotalTemp/avgNumSamp);
startup = 1;
//main boiler controll loop.
//3 run levels.
// run level 0 = initial,
// run level 1 = determine how many mintues boier shoudl be on,
// run level 2 = continuesly check of boier should be on for 10 minutes
if(runScen == 0) { //no scenario running
if(startup > 0 && vrunl ==2) { //wait for a time delay to make sure there is correctly measured avarage temperature
//check if controll should go to runlevel 1
runScen = frunScen(avgTemp,sensorValue);
} else if (runScen == 1) { //start scenario run level 1
startScen = currentMillis;
scenLength = fscenLength(avgTemp,sensorValue); //check how many seconds boiler should be on in 10 minute interval
runScen = 2;
boilerStat = 1; //turn boiler on
//sending minutes boiler on time to Rapsberry PI for monitoring purposses
unsigned long scenLengthCalc = (scenLength/(1000UL));
int sendScenLength = (int) scenLengthCalc;
} else if (runScen == 2) { //runlevel 2 always runs for 10 minutes
if (boilerStat == 1 ) { //onley check boiler stat if boiler is on this to prevent on/off fluctuation af ter overshoot
boilerStat = fboilerStat(startScen,scenLength,currentMillis,avgTemp,sensorValue); //continuesly check if boiler should be on
if (boilerStat == 1 ) { //turn relay to on of boiler should be on
digitalWrite(controllPin, HIGH);
} else {
digitalWrite(controllPin, LOW);
//after 10 minutes go back to run level 0
if(currentMillis – startScen > maxScen) {
runScen = 0;

Thermostat functions

//function to determine if boiler controll loop should go to run level 1
int frunScen (int actTemp, int setTemp) {
if ( (setTemp*10) – actTemp > 35) {
return 1;
} else {
return 0;
//function to determine how many seconds boiler should go on within 10 minute interval
unsigned long fscenLength(int actTemp, int setTemp) {
unsigned long scnel;
// int iscnel = 0;
if ( (setTemp*10) – actTemp > 260) {
scnel = (6UL*60UL*1000UL);
} else if ( (setTemp*10) – actTemp > 160) {
scnel = (5UL*60UL*1000UL);
} else if ( (setTemp*10) – actTemp > 70) {
scnel = (4UL*60UL*1000UL);
} else if ( (setTemp*10) – actTemp > 40) {
scnel = (3UL*60UL*1000UL);
} else {
scnel = (2UL*60UL*1000UL);
return scnel;
//function to check if boiler should stay on or go off
int fboilerStat(unsigned long starts,unsigned long scenl,unsigned long cur ,int actTemp, int setTemp) {
if (actTemp – (setTemp*10) < 35){ //criteria 1: only say on if act temperature is below set temperature + margin
if (cur – starts < scenl) { //criteria 2: only stay on of boiler has not been on for the number of seconds determined by fscenLength
return 1; //stay on
} else {
return 0; //go off (because boiler was on for number of minues determined by fscenLength
} else {
return 2; //go off (2 is used to monitor overflow)

Figure 11: Final breadboard layout

Figure 12: Final schematic

Next part:
6. Using outside temperature and scenarios to control an Arduino from a Raspberry PI


2 thoughts on “Making your own smart ‘machine learning’ thermostat using Arduino, AWS, HBase, Spark, Raspberry PI and XBee

  1. Pingback: Enabling technologies: how to build your own NEST | SmartDomus

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s