I built this project because I had a need for a device like this and I also wanted to learn about web technology. I wanted a way to turn on my garage heater from the house using my smart phone so that I could let it warm up before going in there. I also wanted to see if I could build a nice looking mobile web app that is simple and light-weight enough for the ESP32 web server. This was a learning process for me in using HTML5, Javascript, JSON, Bootstrap, Knockout and other web technologies. I spent most of my time here, doing web research and trial and error. I'll be sharing my debugging setup.
The ESP32 Arduino code uses theESP32 libraries and is not super complicated, letting you see the nuts and bolts of HTML protocols. Although this is a complete working system (except for the enclosure) and a fully functional web application it would also be a good starting point to hack for other applications.
Warnings
Some warnings about this project.
- This project should only be used for low-voltage (24v or less) low-current (2A or less) two wire thermostat applications where a separate relay in the heating unit controls the mains current and the heater unit itself has its own safety systems. It should not be used to control any heater element directly.
- It is up to the builder to use it safely as a thermostat and monitor its operation since it is not designed to any safety standard. If it fails for some reason and stays in an open state and its below freezing outside your room would freeze. If it fails and stays in a closed state the heater could run continuously and generate a high temperature. One option is to put it in series (or in parallel) with an existing thermostat so that there is a backup in case the project gets stuck in a closed (or open) position. This can help avoid one failure mode, but not the other so monitoring is required.
- Familiarity with Arduino environment and board management
- Prototyping practices using jumpers and solderless breadboards
- Basic understanding of web technical concepts
1. Load board definition for ESP32 into Arduino IDE.
2. Edit the Arduino code to configure the WiFi access name, security code, and name of the thermostat.
3. Compile the code and load into the ESP32 board. (Can use the WiFi remote programming)
4. Wire the circuit per the schematic.
5. Locate the IP address and open in web browser
6. Turn on thermostat and change set-point.
How it works - HardwareThe ESP32 board supports the WiFi connectivity and has IO capabilities to interface with the relay board and turn on and off the relay and interface with the DHT22 temperature and humidity sensor. The relay contacts connect to the heating system's 2 wire thermostat terminals. When the relay closes, it completes the 2 wire thermostat circuit and causes the heating system to heat.
The Relay board accepts two inputs that are active-low to control each of the individual relays. This project only uses one relay. The other could be used for other purposes. The relay board handles electrically isolating the sensitive MCU digital I/O pins from the heating system using two stages an opto-isolator and the relay itself. For real-world MCU projects, ensuring isolation is important for reliable and robust operation. Static electricity, AC noise, power supply noise/variability can cause MCUs to get spurious input signals, lock up, or worst of all become permanently destroyed. Debugging these types of problems is a major headache, so isolation is important. The opto-isolator converts the digital output from the MCU into light (via an LED) and then an optical detector picks up the light and turns it into an electrical voltage on an isolated circuit. In this way the MCU pin is electrically insulated from the potential driving the relay. In this circuit the power to drive the relay is still supplied by the same source as the ESP32 board power (the USB power). Using a separate power supply is also possible, that is why there are jumpers on the board. The relay itself, as a mechanical switch, also provides a second stage of electrical isolation between the two-wire heating system thermostat terminals and this project's power source.
The DHT22 temperature and humidity sensor has the measurement range and accuracy needed for our application.
It uses a serial one-wire communication interface to send 5 bytes of data representing the temperature and humidity. For more details, see this link: http://www.ocfreaks.com/basics-interfacing-dht11-dht22-humidity-temperature-sensor-mcu/
During normal operation (after initial programming) the ESP32 board is powered via the 5v USB charger. This 5v power is also distributed to the other boards. In this project, jumpers are used to connect the components, but after the prototyping phase, soldering the connections would increase long term reliability.
How it Works - SoftwareThe ESP32 implements a simple temperature controller and also a web server.
The simple temperaturecontroller does the following functions:
1. Acquire temperature and humidity data serially from the DHT22 sensor via a one wire interface.
2. Turn on and off the relay depending on whether the temperature is below or above the set-point. The controller has some hysterisis so that when the temperature is near the setpoint, the controller does not switch on and off repeatedly due to measurement error.
3. Acquire time data from a server on the internet in order to synchronize the internal ESP32 clock with this internet server to get an official time.
4. Maintains a watchdog timer to detect system locking or malfunction and automatically restart. This timer is constantly reset as long as the main program loop functions normally. If the main loop does not repeat due to some error or failure, the timer counts down and resets the MCU.
The web server can respond to four different types of requests from the client browser:
1. HTTP - When it receives this request, the ESP32 send the HTML file, in the form of a long string to the browser. The HTML file has the javascript that runs on the browser client and makes the other types of requests to the web server.
2. GET - When it receives this request, the ESP32 sends the temperature, humidity, relay status (on/off), set-point, time and other info in the form of a JSON message. In general JSON is a text message with key-value pairs in a hierarchical structure. In this application we keep it simple and do not use any hierarchy.
{ Type: "TH&Relay", Name: "Cave", Temp: "69.44", RelH: "34.60", Tset: "40", Heater: "0", Control: "0", StartTime: "1552185144", CurrentTime: "1552185151", Wifi_ssi: "-42" }
The javascript on the browser client receives this and parses it to update data objects kept in the browser. These can be displayed and manipulated on the client.
3. OPTIONS- This is a required request done before the POST operation to do a security check that the client can post information to the server.
4. POST - When the web server receives this request, it receives a JSON message from the client containing the set-point temperature and whether the temperature control should be active.
{Control: "1", Tset: "72"}
The web server parses this data and sets internal variables for further processing.
Web page Design and DebuggingThis project uses some web technologies and standards that allowed me to keep the HTML file content static and small, while still providing a dynamic and responsive web page. This was the focus of my learning on this project, and where I spent the most time researching the web and learning by trial and error.
Debugging SetupI think the best way to learn the web interface is to use the developer debugging capabilities in a browser. I used Firefox. In the menu there is a selection called 'Web Developer' and then 'Web Console'. This allows you to see the messages being passed to the server, error messages, javascript exceptions, etc. Since the web server on the ESP32 only handles the 4 different requests above, it does not really care what web page is making these requests. It could be the web page loaded using request 1. But it could also be another web page - for example an "index.html" file that you open on your local machine. So this allows you to make small changes to this file in a text editor (I used Notepad++ because it knows html formatting) and then refresh the browser and see what happens to the page rendered, including page layout, formatting, and also requests to the ESP32 server.
Design of web page
The HTML file contains embedded CSS, HTML, and Javascript all in one file. It uses Bootstrap, which is a collection of CSS (Cascading Style Sheets), HTML, and Javascript to design responsive web sites. It uses a javacript library KnockoutJS to dynamically update the browser view when data changes occur. In order to keep the HTML file small, these libraries are not kept in the HTML file itself. They are linked in using what is called a CDN (Content Delivery Network) provider. In addition, the javascript uses the newish native fetch() function, to implement the server calls 2-4. Finally it uses some glyphicon fonts in fontawesome for the reload button (circular arrow), and the flame icon - indicating that the heater is being asked to turn on.
Bootstrap simplifies layout of the web page and the layout can adapt appropriately for mobile screens or larger screens. It has a collection of widgets and styles to assist with making a clean looking web site. There are some good training sources, and examples of code on the web:
- Here is a site that provides explanation of the various parts of Bootstrap as try it yourself tutorials: https://www.w3schools.com/bootstrap4/default.asp
- Here is a site that provides the contents, try changes and see what happens: https://hackerthemes.com/bootstrap-cheatsheet/.
- Here was the starting point for my project web site - does it look similar? https://hackerthemes.com/bootstrap-templates/spur/
KnockoutJS is a lightweight framework in javascript that seems to have fallen out of favor somewhat, but for my requirements seemed perfect. What I learned in my research is that now people use Angular and react, which seem to require their own dev tools and seem to require a lot of learning. The KnockoutJS framework automatically updates the UI when data changes. It is meant to isolate the UI from the underlying data kept in the browser DOM (Data Object Model.) For me this was the most challenging part of the web design, as it depends on many Object Oriented concepts of Javascript. The knockout site provides some tutorials and examples to wade through. Luckily once this was working, I did not have to make any further refinements, as its not tied to UI changes, which is the whole point.
fetch() is a newish function native to javascipt that handles client-server communication for http protocols like GET, OPTIONS, and POST. The alternative is to use additional jQuery AJAX calls or other javascript libraries. Here is some more information. https://davidwalsh.name/fetch
CDNs are used to provide CSS and javascript libraries and code to the browser so that the ESP32 web server does not have to supply these. Content Delivery Networks are a collection of geographically dispersed servers that provide this content, usually for a fee for large volumes or fast response. For this project we use free services which work fine for the volume and response time we need. If you look at the "index.html" file you will see url links to these servers, for example boostrap 4.3.1 is incorporated using the link below.
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
fontawsome is used to add some nice looking glyphicons to the UI to reflect the heater status and for the refresh button. In the HTML, this:
<i class="fas fa-burn" ></i>
produces this in the UI:
Serving a web page from Arduino code- The HTML file was stored a string constant for simplicity of handling it in the web server. However for debugging, I kept the file as "index.html" on my PC's local drive and opened the file in the browser. The browser does not really care how it receives this file (locally or from the ESP32 web server), and so this way I could make HTML changes quickly in this file, refresh the browser, and see the results. Once it was finalized, I used an online tool to convert the index.html to a string. This string is then pasted into the Arduino code.
Enclosure
I designed an enclosure that you can 3D print and attach it to your wall with two screws. The boards can be glued in with hot melt.
ESP32 - https://docs.espressif.com/projects/esp-idf/en/latest/get-started/get-started-devkitc.html
Bootstrap- https://getbootstrap.com/
KnockoutJS -https://knockoutjs.com/
native javascript fetch() - https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
fontawesome - https://fontawesome.com/
Comments