1-7 Build Smart Thermostat

The Nest Learning Thermostat was introduced in 2011, and now several companies offer smart thermostats. Smart thermostats can be controlled remotely using a mobile app and offer features like adjusting the temperature, creating temperature schedules, reviewing energy usage, etc.

YOUR TASK

As further practice building and programming IoT devices with your Photon kit, your team will create a prototype of a smart thermostat that can be controlled by a web app.

However for this practice, you will only be given partial instructions. Your team will have to figure out the rest in order to build the device and program its apps.

Your team will need to carefully read through these instructions. Only ask questions if you have first read the instructions.

It might be helpful to have your team members divide up the work:

  • one person could build the device by connecting the parts

  • another person could program the Photon app

  • a third person could program the web app

BUILDING THE DEVICE

System Model

Here is a system model showing how the parts of the smart thermostat prototype are supposed to work together:

System Features

  • Device (and web app) display room temperature, temperature setting, and system status (Off, Heating, Cooling).

  • Device (and web app) allow user to change desired temperature setting using buttons.

  • Device reads current room temperature.

  • Device compares room temperature with temperature setting to control system:

    • If room temperature is lower than temperature setting, device turns on heating system (represented by red LED).

    • If room temperature is higher than temperature setting, device turns on cooling system (represented by blue LED).

    • If room temperature is equal to temperature setting, device turns off heating and cooling systems.

NOTE: To make this device simpler to build and program, this thermostat is designed to run in a dual mode where it may turn on heating or cooling during the same day. For example, people that live in desert climates (such as Arizona, etc.) would want a thermostat that runs in dual mode because it can get very hot during the day but very cool at night.

Most thermostats are designed to be in only one mode at a time: Heat Only, Cool Only, or Off. The "Heat" mode is used during the winter to only run the furnace. The "Cool" mode is used during the summer to only run the air conditioning. The "Off" mode is used during parts of the spring and fall when no heating or cooling is needed. Most thermostats have a separate button to change the system mode.

Picture of Prototype

Here's a picture of a smart thermostat prototype to give you a general sense of how it will look when finished. While it might look complex, each individual part is relatively simple to connect. The instructions provide references that show how to connect each part.

Parts Needed

  • Red LED (to represent heating system, such as furnace)

  • Blue LED (to represent cooling system, such as air conditioner)

  • 2 Resistors (one for each LED)

  • Red Push Button (used to increase temperature setting)

  • Blue Push Button (used to decrease temperature setting)

  • RHT03 Humidity and Temperature Sensor

  • Micro OLED Display Screen

  • 18 Jumper Wires

Arranging Parts

Make sure the parts are arranged in a logical layout that makes it easy for a person to understand and use the device.

Remember that all the parts have to be arranged so their pins are in their own breadboard rows:

  • If different parts are on the same side of the breadboard, the pins of different parts should not be in the same row number.

  • A resistor is an exception because it is supposed to share a row number with a pin of another part (such as LED, etc.).

  • If different parts are on opposite sides of the breadboard (left vs. right), it is perfectly fine if they use the same row numbers because the left-hand rows are not connected to the right-hand rows.

  • Different pins from the same part should not be in the same row number. For example, the OLED display has 8 pins, and each of these pins must be in a different row number on the breadboard.

TIP: Try to place the jumper wires on the side closest to the Photon board, so the wires don't block parts that need to be seen or interacted with.

Connecting Power Supply

You can use one power rail on the breadboard to provide power to all the parts (similar to how a power strip works):

  1. Connect a jumper wire from the 3.3V (+) pin on the Photon board to a pinhole in the positive (+) column of the power rail closest to the Photon board.

  2. Then connect another jumper wire from a pinhole in the negative (-) column of this power rail back to a GND (-) pin on the Photon board.

  3. All other parts that you add to the breadboard can connect to this power rail through their own jumper wires. Some parts will only need to connect to the negative (-) rail because their voltage source (+) will come from a digital pin. Other parts will need to connect to both the positive (+) and negative (-) rails.

IMPORTANT: The OLED display screen can only handle 3.3 volts of power, so be sure to use the 3.3V pin as your voltage source. (Caution: The V-USB pin supplies 5V, which could damage the OLED.)

Connecting Micro OLED Display

The Micro OLED display requires using 7 jumper wires to connect the OLED pins to specific pins on the Photon board. Therefore, you should probably connect the OLED first before adding the other parts.

This reference for the Micro OLED display explains how to connect the OLED and provides example code for displaying text on the OLED screen.

Connecting Other Parts

The other parts can be connected to any of the other digital pins (or analog pins such as A0 or A1) that are not being used by the OLED.

This reference for the RHT03 sensor explains how to connect the RHT03 Humidity and Temperature Sensor and provides example code for taking readings with the RHT03 sensor.

If helpful, there are also references for the LED light and push button that show how to connect them and provide example code for using them.

CODING PHOTON APP

Create a new app in Particle Build titled: SMART-THERMOSTAT

Remember that the structure and order of the code for a Photon app is:

  1. libraries (if needed for certain inputs or outputs)

  2. global variables

  3. setup() function (can only have one)

  4. loop() function (can only have one)

  5. custom functions (as many as needed)

If helpful, here is additional information (and references) for coding Photon apps.

Libraries

Be sure that you include the libraries for the Micro OLED display and the RHT03 sensor. The code examples in the Micro OLED reference and the RHT03 sensor reference explain how to include the library for each part.

Global Variables

Your app should declare global variables for each part's pin numbers (OLED, RHT03, both LEDs, both buttons) and declare objects for the OLED display and RHT03 sensor. The code examples in the references for the parts can help with this.

Be sure the pin numbers (such as: D0, D1, etc.) you list in your code match the actual pin that each part's jumper wire is connected to on the Photon board. If they don't match, it is usually easiest to fix it by changing your code (rather than moving your wire).

In addition, your app should also include these other global variables:

// add global variables for OLED display, RHT03 sensor, LEDs, and buttons

// other global variables
String systemStatus = "Off"; // values = Off, Heating, Cooling
int setTemp = 70; // initial temperature setting (degrees F)
int minTemp = 50; // minimum allowed temperature setting
int maxTemp = 90; // maximum allowed temperature setting
int roomTemp; // reading from temperature sensor

setup( )

In your setup() function, be sure to:

  • set the pin modes for your LEDs and buttons

  • turn off the LEDs at the start

  • start the OLED display and RHT03 sensor

  • include Particle.variable statements to share these three variables with your web app: setTemp, roomTemp, systemStatus

  • include Particle.function statements to allow your web app to call these two custom functions: tempUp, tempDown

The code examples in the references for the parts can help with figuring out the pin modes, turning off the LEDs, and starting the OLED display and RHT03 sensor.

This Particle Cloud reference can help with the Particle.variable and Particle.function statements.

You can also refer back to the setup() function in the final version of the Photon app for your Smart Lightbulb.

NOTE: If you have added the Particle.function statements but haven't yet added the custom functions for tempUp and tempDown, Particle Build will say your app has errors when you try to verify the code. To avoid this, you can type two forward slashes directly before each Particle.function statement to temporarily make them into comments. Later, you will need to remove these slashes once you've added the custom functions to your Photon app.

loop( )

Good news – here is the entire code for your loop() function:

void loop() {
    checkButtons();
    readTemp();
    compareTemp();
    displayTemp();
    delay(200);
} // end of loop()

However, you will have to create custom functions for: checkButtons(), readTemp(), compareTemp(), displayTemp() (as well as tempUp and tempDown)

NOTE: Until you create these custom functions, Particle Build will say your app has errors when you try to verify the code if you include the names of these functions inside your loop() function. So in the meantime, you can either leave the loop() function empty, or you can type two forward slashes directly before the name of each custom function listed inside the loop() function to temporarily make them into comments. You will need to revise the loop() function to match the code above once you've created the custom functions.

Custom Functions

You will need to create the following custom functions:

  • checkButtons() should read each button and call tempUp() function if red button pushed and call tempDown() function if blue button pushed

  • readTemp() should update roomTemp with new reading from RHT03 sensor

  • compareTemp() should compare roomTemp with setTemp to decide whether system should be heating, cooling, or off (be sure to update systemStatus and turn correct LEDs on or off)

  • displayTemp() should use Micro OLED to display roomTemp, setTemp, and systemStatus (add other text and adjust font size if needed to make information clear and easy to read)

  • tempUp() should increase setTemp by 1 but not allow it to go higher than maxTemp

  • tempDown() should decrease setTemp by 1 but not allow it to go lower than minTemp

Here is part of the code for your checkButtons() function:

void checkButtons() {
    int redButtonStatus = digitalRead(redButton);
    // LOW means button is pushed
    if (redButtonStatus == LOW) {
        tempUp("adjust");
    }

    // add code for checking blue button

} // end of checkButtons()

For help with your readTemp() function, look at the code examples in the RHT03 sensor reference.

void readTemp() {
    // add code to update roomTemp with new reading

} // end of readTemp()

Here is part of the code for your compareTemp() function:

void compareTemp() {
    if (roomTemp < setTemp) {
        // add code to change systemStatus and turn on/off LEDs

    } else if (roomTemp > setTemp) {
        // add code to change systemStatus and turn on/off LEDs

    } else {
        systemStatus = "Off";        
        digitalWrite(redLed, LOW);
        digitalWrite(blueLed, LOW);
    }
} // end of compareTemp()

For help with your displayTemp() function, look at the code examples in the Micro OLED reference.

void displayTemp() {
    // add code to update OLED with thermostat information

} // end of displayTemp()

Remember that tempUp() and tempDown() are functions that your web app can call, so the code for these two functions is slightly different (they must return an integer value and accept a String value).

As an example, here is the complete code for your tempUp() function:

int tempUp(String command) {
    if (command == "adjust") {
        setTemp = setTemp + 1;
        if (setTemp > maxTemp) {
            setTemp = maxTemp;
        }
        return 1;
    } else {
        return 0;
    }
} // end of tempUp()

Then you can copy and modify the code above to create your tempDown() function.

IMPORTANT: If necessary, go back to your setup() function to make sure your Particle.function statements do not have two slashes before them. Also be sure that your loop() function matches the code provided earlier.

CODING WEB APP

Create a new HTML file (index.html), CSS file (style.css), and JavaScript file (code.js) using a code editor (such as Editey in Google Drive, etc.). Make sure the files are blank. Rename the folder containing the files as: Smart Thermostat

The pictures show screenshots for how the web app could possibly look (during four different states: connecting, cooling, off, heating). However, your web app doesn't have to look exactly like this – you can design your own screen layout as long as the necessary information and functions are present.

If necessary, refer to the System Features towards the top of this page to verify what the web app should do.

HTML for index.html

You should copy and modify the HTML used in the Smart Lightbulb web app.

In the <body>, you should have a <div> element to display the current thermostat information. Assign id="thermostat" and class="off" to this <div> element.

This <div> should contain <p> elements to list the room temperature, temperature setting, and system status (Off, Heating, Cooling). Be sure to give each <p> element a unique id name, so you can update their HTML using jQuery statements in your code.js and change their style using CSS declarations in your style.css

Be sure to include two <button> elements to allow the user to increase and decrease the temperature setting: one should have onclick="raiseTemp();" and the other should have onclick="lowerTemp();" (these will run custom functions that you'll create in your code.js)

If necessary, here is a HTML reference for additional help on HTML element tags.

CSS for style.css

If you want, you can borrow and modify some of the CSS used in the Smart Lightbulb web app.

Add CSS declarations to style properties for your #thermostat. For example, the CSS below will make it into a circle (by setting border-radius: 50%).

#thermostat {
    /* you can change these or add other properties */
    width: 300px;
    height: 300px;
    margin: 20px auto;
    border: 1px solid black;
    border-radius: 50%;

}

Create a class for each system status: .off, .heating, .cooling

Each of these classes should set a background-color that represents the system status.

You can add CSS declarations for other elements or id names to customize the layout and appearance of your web app, so it is easier and more enjoyable to use.

If necessary, here is a CSS reference for additional help on CSS syntax to declare style properties.

JavaScript for code.js

You should copy and modify the JavaScript used in the Smart Lightbulb web app.

It may be helpful to use the information and code examples in this Particle Cloud reference.

IMPORTANT: Remember to assign your Photon device id and access token to the JavaScript global variables for myDevice and myToken

Be sure the webpage window is set to run the checkThermostat function at an interval of every 200 milliseconds.

Your JavaScript code should have the following custom functions:

  • raiseTemp() function should contain particle.callFunction statement to call "tempUp" function (with argument of "adjust") on your Photon device

  • lowerTemp() function should contain particle.callFunction statement to call "tempDown" function (with argument of "adjust") on your Photon device

  • checkThermostat() function should contain three separate particle.getVariable statements to get current values for setTemp, roomTemp, and systemStatus and use these to update the content and appearance of your web app

In each particle.getVariable statement, the value of the requested Photon variable gets temporarily stored in a local variable called data.body.result that you can use.

By referring to id names, jQuery statements (which always start with $) can easily change the text inside an HTML element. For example, if the webpage contained <p id="#set-temp"> element, you could update its content with jQuery to display the word "Set " followed by the value stored in data.body.result:

$("#set-temp").html("Set " + data.body.result);

Here's how that jQuery statement would be used inside a particle.getVariable statement:

particle.getVariable({ deviceId: myDevice, name: "setTemp", auth: myToken }).then(function(data) {
    $("#set-temp").html("Set " + data.body.result);
}, function(err) {
    console.log("An error occurred retrieving data:", err);
});

You can also use if and else if statements to check the data.body.result value, and then use jQuery statements to easily add or remove CSS classes:

particle.getVariable({ deviceId: myDevice, name: "systemStatus", auth: myToken }).then(function(data) {
    if (data.body.result == "Heating") {
        $("#system-status").html(data.body.result);
        $("#thermostat").removeClass("off");
        $("#thermostat").removeClass("cooling");
        $("#thermostat").addClass("heating");
    }
    // add code to check if data.body.result is "Cooling"

    // add code to check if data.body.result is "Off"

}, function(err) {
    console.log("An error occurred retrieving data:", err);
});

If necessary, here is a JavaScript reference and a jQuery reference for additional help on their syntax and functions. Because jQuery is a JavaScript library, JavaScript statements can be combined together with jQuery statements.

After creating the code for the other custom functions in your JavaScript, test your web app with your Photon device. If everything is working, then congratulations...

You've just created your second IoT device!

GOING FURTHER

If you have time, add a third button to the device and web app that allows the user to change the system mode (Off, Heat, Cool). For example, in the "Heat" mode, only the heating system (red LED) should be turned on or off by the device. You will have to modify your Photon app to make the device operate properly in each mode. Your device and web app should display both the system mode and system status. For example, the mode might be "Heat" but the status would be "Heat OFF" if the current room temperature is at or above the desired temperature setting.

Last updated