# Creating an indoor Temperature and Humidity monitor
> Author: Philip Hilding (ph223ae)
This tutorial goes through the process of creating an indoor temperature and humidity monitor. In other words, displaying the temperature and humidity in your room or an area of your appartment/ house in seperate graphs.
The approximate time for this project is 3-4 hours.
## Objective
Having an interest in learning IoT has made me curious to create an IoT device for quite some time. Thus this project is a huge step towards learning the concepts of IoT as well as diving even deeper. During the time of imagining what project to create, I started to notice that my appartment had gotten noticeably warmer. Then it struck me, that creating a IoT device to measure the temperature and humidity inside my home was the best of both worlds, for I will understand the concepts of that technology whilst also see if it's actually getting warmer or if it's just placebo.
The project would naturally give me an insight into how the first layer, sensing and sending data, of an smart home with automatic air conditioning works.
## Material
|Product | Price and link |
|---|---|
|Arduino MKR1000 | [$43.93](https://www.amazon.com/Arduino-MKR1000-WiFi-ABX00004-Headers/dp/B01M1H83WB)
|DHT11 moisture sensor | [$43.93](https://www.amazon.com/Arduino-MKR1000-WiFi-ABX00004-Headers/dp/B01M1H83WB)
|1x Red LED | [$9.99](https://www.amazon.com/Gikfun-Assorted-Arduino-100pcs-EK8437/dp/B01ER728F6/ref=sr_1_12?keywords=Arduino+led&qid=1656966554&sr=8-12)
|1x Green LED | [$9.99](https://www.amazon.com/Gikfun-Assorted-Arduino-100pcs-EK8437/dp/B01ER728F6/ref=sr_1_12?keywords=Arduino+led&qid=1656966554&sr=8-12)
|10x Jumper Wires|[$9.99](https://www.amazon.com/MCIGICM-Breadboard-Jumper-Cables-Arduino/dp/B081GMJVPB/ref=sr_1_2_sspa?keywords=jumper+wires&qid=1656966504&sr=8-2-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzRVpNUzQ4U042SUJBJmVuY3J5cHRlZElkPUEwNDI0MzI2Mkc1SkwwSUs3QVJQNiZlbmNyeXB0ZWRBZElkPUEwNDI5NzA4M0VNTzVHWDdBNVFQMyZ3aWRnZXROYW1lPXNwX2F0ZiZhY3Rpb249Y2xpY2tSZWRpcmVjdCZkb05vdExvZ0NsaWNrPXRydWU=)
|Breadboard | [$2.61](https://www.artekit.eu/products/prototyping/breadboarding/breadboard-mini-white/)
|2x 220 ohm resistors | [$5.99](https://www.amazon.com/EDGELEC-Resistor-Tolerance-Multiple-Resistance/dp/B07QK9ZBVZ/ref=sr_1_1_sspa?keywords=220+ohm+resistor&qid=1656966680&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExVFNJWlNLNDlSUzFIJmVuY3J5cHRlZElkPUEwMjc1NDkzMUpSTFpJVFJLN0ZORyZlbmNyeXB0ZWRBZElkPUEwMDI5ODE4MlpQVlNZSVRXSlBRMyZ3aWRnZXROYW1lPXNwX2F0ZiZhY3Rpb249Y2xpY2tSZWRpcmVjdCZkb05vdExvZ0NsaWNrPXRydWU=)
|USB to micro usb cable | [$8.03](https://www.amazon.com/AmazonBasics-Male-Micro-Cable-Black/dp/B071S5NTDR/ref=sr_1_1_sspa?crid=Y8IKJXDT64TF&keywords=usb+cable+micro&qid=1656966734&sprefix=usb+cable+micro%2Caps%2C146&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUE3SU0xTU1VUlNRU1gmZW5jcnlwdGVkSWQ9QTAzNDEwMjYzMDRGMTkzM08wTTZHJmVuY3J5cHRlZEFkSWQ9QTAzNzAwNTYyWTc2Qk9HTVdWU0JZJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==)
* The arduino MKR1000 is optional, as the products above will work with most microcontrollers, but if you wanna follow this tutorial, the Arduino MKR1000 is recommended. This is used to connect all components, providing power and is the brain of the whole device, controlling it all by the code uploaded.
* DHT11 is the sensor which is used to read the temperature and humidity in the room. Another good choice with more functionality would be the DHT22 sensor, althought it is more expensive. It has a range of 0-50°C.
* The breadboard is used as a form of extension for easily connecting the jump wires (which provides power, grounding and/ or inputs and outputs) with the LEDs and sensors.
* The resistors at 220 are there to make sure that the LEDs are provided with the correct voltage, and not recive a voltage that will break them.
* The USB cable is used to upload the code, but will also work as a powercable for the Arduino.
## Computer setup
### Setting up the IDE
The first thing you want to do is installing the Arduino IDE 2.0. This is arduinos own IDE, which is built for development with arduino microcontrollers. If you prefer using any other IDE like VS code, that's totally up to you, but for development with arduino microcontrollers, the arduino IDE is recommended thanks to it's library manager and tools.
You can download the it [here](https://www.arduino.cc/en/software#experimental-software).
Having downloaded the IDE, what you want to do first is choosing your board. You do that by clicking on the Tools button in the top right of the window > Boards > Arduino SAMD Boards > Arduino MKR1000.

You're also going to install a few libraries, which are used to connect to your wifi, accessing DHT data and sending the data with a HTTP request.
To add a library to your project, click ont the 3rd button from in the vertical menu on the left side of the application, as to shown in the picture below.

There after you're gonna search for the library you want, click on it, and press install.
For this project, you want to install:
* Wifi101 by Arduino
* ArduinoHttpClient by Arduino
* DHT sensor library by ADAFRUIT
### Uploading the code
The code will be uploaded with the USB cable. Make sure to connect it to your pc and microcontroller. When you want to upload the code from the IDE to the Arduino, click on the button as shown in the picture below.

### Setting up node red
Node red is a flow based development tool, used to controll the flow of data that comes in but also sending out data to the device. It's the tool we will use to display our data.
First of all, you will want to download NodeJS [here](https://nodejs.org/en/download/).
After installning node, you will want to check if the installation was successful. Do so by opening up your command prompt and type "npm". 
Now onto the installation of node red. To download node red, we can use the command prompt we have open and type the following code:
```console
sudo npm install -g --unsafe-perm node-red
```
If you're a windows user like me, you will not use "sudo", so remove that from the code above when executing the installation.
Now, restart your command prompt by closing the window open a new command prompt, and run:
```console
node-red
```
And just like that, you can search for 127.0.0.1:1880 in your browser and the node red dashboard will show up. If you're woundering, 127.0.0.1 is a localhost on your computer, and it's running on port 1880. It's fully possible to run node red on a seperate server instead of a localhost one, for example on a raspberry pi.
### Node red setup
Having node red open, we are going to want to install two palettes, one for connecting to our database, and one for getting dashboards options.
* node-red-contrib-mongodb-aleph
* node-red-dashboard
You can install them by clicking on the hamburger menu on the top right, next to the "Deploy" button.

Thereafter, click on the "Install" tab, search for one of the palettes from the list above, and install. For the nodes to show up on the node list on the left, you can reload the webpage by clicking F5 on your keyboard. If that doe not work, try restarting the node red server by closing your command prompt, opening a new command prompt, and run "node red".
In node red, we are going to want to setup our flow so it looks like the picture below.

By clicking on the "Detalis" button below, you can get the JSON code for the same flow with the same configuration. You can copy that code, and in node red press CTRL + i on your keyboard to import it by pasting the JSON code in, and clicking on the "Import" button.
<details>
[{"id":"7b64ba7b704416df","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"388c61d4c4634e8a","type":"http in","z":"7b64ba7b704416df","name":"","url":"/temp","method":"post","upload":false,"swaggerDoc":"","x":210,"y":380,"wires":[["1d236f7509d9f364","f44bae1350cc349f","8580ad9e6b4bb4b8"]]},{"id":"1d236f7509d9f364","type":"ui_chart","z":"7b64ba7b704416df","name":"","group":"2a1da0889c1eabd3","order":2,"width":"0","height":"0","label":"Temperature in Celcius","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"50","removeOlder":"20","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":480,"y":380,"wires":[[]]},{"id":"f44bae1350cc349f","type":"debug","z":"7b64ba7b704416df","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":430,"y":480,"wires":[]},{"id":"ebe4af7b066da27b","type":"http in","z":"7b64ba7b704416df","name":"","url":"/hum","method":"post","upload":false,"swaggerDoc":"","x":200,"y":200,"wires":[["b37caa37c1796dde","ec766217fe5da67c","3f84badb9608ca6b"]]},{"id":"b37caa37c1796dde","type":"ui_chart","z":"7b64ba7b704416df","name":"","group":"2a1da0889c1eabd3","order":2,"width":"0","height":"0","label":"Humidity in percent","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":"20","removeOlderPoints":"","removeOlderUnit":"60","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#7cbce9","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":470,"y":200,"wires":[[]]},{"id":"ec766217fe5da67c","type":"debug","z":"7b64ba7b704416df","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":430,"y":300,"wires":[]},{"id":"1787991d25c50854","type":"http in","z":"7b64ba7b704416df","name":"","url":"/sensorStatus","method":"post","upload":false,"swaggerDoc":"","x":230,"y":600,"wires":[["6cf4420395840947","8d4b3d2d91666dfd","928b35d0912ab57d"]]},{"id":"6cf4420395840947","type":"debug","z":"7b64ba7b704416df","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":430,"y":700,"wires":[]},{"id":"8d4b3d2d91666dfd","type":"ui_text","z":"7b64ba7b704416df","group":"2a1da0889c1eabd3","order":3,"width":0,"height":0,"name":"","label":"Sensor status:","format":"{{msg.payload}}","layout":"row-center","className":"","x":460,"y":600,"wires":[]},{"id":"7e7475900d731627","type":"mongodb-aleph-out","z":"7b64ba7b704416df","mongodb":"cadc73c977e7c32e","name":"","collection":"Temp","payonly":false,"upsert":false,"multi":false,"operation":"insert","x":920,"y":440,"wires":[[]]},{"id":"8580ad9e6b4bb4b8","type":"function","z":"7b64ba7b704416df","name":"","func":"msg.payload = msg.req.body;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":440,"wires":[["7e7475900d731627"]]},{"id":"178dd987d1ab0220","type":"mongodb-aleph-out","z":"7b64ba7b704416df","mongodb":"cadc73c977e7c32e","name":"","collection":"Errors","payonly":false,"upsert":false,"multi":false,"operation":"insert","x":920,"y":640,"wires":[[]]},{"id":"928b35d0912ab57d","type":"function","z":"7b64ba7b704416df","name":"","func":"msg.payload = msg.req.body;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":640,"wires":[["178dd987d1ab0220"]]},{"id":"3a97a9ca85a1e159","type":"mongodb-aleph-out","z":"7b64ba7b704416df","mongodb":"cadc73c977e7c32e","name":"","collection":"Humidity","payonly":false,"upsert":false,"multi":false,"operation":"insert","x":930,"y":260,"wires":[[]]},{"id":"3f84badb9608ca6b","type":"function","z":"7b64ba7b704416df","name":"","func":"msg.payload = msg.req.body;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":260,"wires":[["3a97a9ca85a1e159"]]},{"id":"2a1da0889c1eabd3","type":"ui_group","name":"Temperature and Humidity","tab":"af0f0aa66ad6d3bc","order":1,"disp":true,"width":"13","collapse":false,"className":""},{"id":"cadc73c977e7c32e","type":"mongodb-aleph-config","hostname":"cluster0.aa6ci.mongodb.net","topology":"dnscluster","connectOptions":"","port":"27017","db":"IOT-project","name":""},{"id":"af0f0aa66ad6d3bc","type":"ui_tab","name":"Test","icon":"dashboard","disabled":false,"hidden":false}]
</details>
### Quick guide on setting up MongoDB
First of all, we need to go to [The mongoDB website](https://cloud.mongodb.com/) and signup to setup the database.
Setting up a database, you need to choose localhost connection and paste your public IP address, and also choose a username and a password, which you need to input in the mongoDB node in node red, to get connectivity to work.
Thereafter you can create a database named "IOT-project" and 3 collections:
* Temp
* Humidity
* Errors
If you have set it up correctly, it should look like this:

## Putting everything together
Below, you can see a drawing of the circuit diagram, as well as an picture of how it looks in person.


What's happening here is that we have one GND connection with a jump wire from our Arduino to the negative horizontal line on the breadboard, and another one from the 5V pin to the positive horizontal line on the breadboard.
There are also three jump wires connected from the digital pins, 1, 2 and 3 on the arduino, which are connected to the DHT sensor and LED diods. Since the max output of the digitalpin is less than 5V and enough for the DHT11 sensor to handle (since it can handle up to 5 volts ), we don't need any resistors. Althought, while the LED diods can handle the output from the digital pins signal, it's better to be safe and use a fairly low (220 ohm) resistor that we connect to their positive pin (the long leg of the LED).
The small green jump wires are used for negative grounding and the white one used for positive current.
The great part of this setup is that it can be used in both development and production.
## Platform
The chosen platform that we are going to use, which was also mentioned above, is Node red. The reason I used this platform, is that it's free, can be run locally, but also on a raspberry pi if you want to host it on your own server. It's also very easy to use and beginner friendly, and has lots of palettes that you can install, which gives you more freedom and extra functionality.
Since it's running locally, you don't have to creat an account and you can manage all of it on your own. On top of that, node red gives you the opinion to have different flow tabs, giving you the posibility to structure your project and supports scaling of your project.
If you have any experience with front end programming like me, you can also write your own javascript and css to add extra functionality, but that's something we are not going to go over in the tutorial
## The code
So let's go over the core functionality and structure of our code. Since we are using a Arduino, the language that is used is c/c++ (with a tweak of Arduinos own version of it). I've decided to split up the different core functions in different files, which are shown below:

The .ino file is the main file, and is where you want to put your setup() and loop() function.
In our main file (.ino), is where we read the data from the sensor, thus is where we are connecting to it as shown below.
```c++
#include "DHT.h"
#include "wifi_connection.h"
#include "HTTP_requests.h"
#define DHTPIN 1
#define DHTTYPE DHT11
int greenLed = 2;
int redLed = 3;
int retry = 0;
DHT dht(DHTPIN, DHTTYPE);
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
pinMode(greenLed, OUTPUT); // Declare the LED as an output
pinMode(redLed, OUTPUT); // Declare the LED as an output
//Call function for Wifi connectivity
setup_wifi();
Serial.println(F("Starting DHT sensor!"));
dht.begin();
}
```
You can also notice that we have a setup_wifi() function, which is not declared in the .ino file. That's because we are grabbing it through the wifi_connection.h header file, which grabs is from the wifi_connection.cpp file:
```c++
#include "wifi_connection.h"
#include "arduino_secrets.h"
#include <WiFi101.h>
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup_wifi() {
while (!Serial);
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to network: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network:
status = WiFi.begin(ssid, pass);
delay(1);
}
// you're connected now, so print out the data:
Serial.println("You're connected to the network");
Serial.println("----------------------------------------");
printData();
Serial.println("----------------------------------------");
}
```
Here, we are importing the Wifi101 library which is used to connect to your LAN, and connect by using our routers SSID and password, stored in arduino_secrets.h.
\
Another important part of our code is the http POST requests. These are used to send data to node-red, which can then display it in our graphs:
```c++
#include <ArduinoHttpClient.h>
#include <WiFi101.h>
const char* server = "192.168.1.220";
int port = 1880;
WiFiClient client;
HttpClient httpClient = HttpClient(client, server, port);
void httpRequestTemp(String temp) {
// if there's a successful connection:
if (client.connect(server, 1880)) {
client.println("POST /temp HTTP/1.1");
client.println("Host: 192.168.1.220");
client.println("User-Agent: Arduino/1.0");
client.println("Connection: close");
client.print("Content-Length: ");
client.println(temp.length());
client.println();
client.println(temp);
} else {
Serial.println("Connection failed");
}
client.stop();
}
```
Here is one example of how we are creating an HTTP POST request to node-red. First of all, we are setting the server to our computers IP address on the network, and the port that node red is running on. Then, we check if we are still connected to the network, and if we are, we send the request to node red. Be sure to change the IP that is stored in the variable "server", and don't pull a misstake like me where you write the localhost address on the computer, and not the actual computers IP address, since the arduino does not exist in the computers local scope.
## Transmitting the data / connectivity
### Wireless protocol
The sensor data is sent to node red every 10 seconds over a wifi connection, which is the wireless protocol used. The reason for picking wifi, is that it's very simple to setup, especially since we are trying to connect to our own local server instead of an external server over the internet. This means that every device in our home connects to the router, creating a small "closed" network only accessable within the local area network (LAN), by giving every network device their own private IP which is used to talk to eachother by sending packets, whether they are connected wireless or through an ethernet cable.
\
Looking from an power consumption perspective, using a wifi connection will require a fair amount of energy. There are better options if you are looking at a environmental perspective, such as LoRa or Sigfox, but it's still better compared to celluar connectivity for example.
But since we are only measuring the temperature and humidity in our home, this device does not need to be active 24/7, meaning we can save a lot of energy having it turned of when we are asleep or away (unless we also want to record that data).
### Transport protocol
But just having the devices connected to the same network is not enough, for we need a way to send the data that we want to the other device(s). This is where transport protocols come in.
In this project, the transport protocol that is used is HTTP (Hyper text transfer protocol). You've probably seen or heard of this before, for it is the protocol that the world wide web uses, in other words the protocol used when you go onto a website, like the very one you are on right now for example.
\
How we have it set up, is that we in our code have a function that is called whenever we have gotten the data from our sensor, which you can find in the code section of this tutorial. This particular request is a POST request, meaning that the device, which is also called the client, send a request to post data to the server (our computer). The server then processes the request, sends a status code depending on if the POST request was successful or not (which you can read more about over at [mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status), a website with documentations on web development topics).
Thereafter, the server will act upon that data, depending on how the code is written (for example storing it in a database, displaying on the screen, printing it out to the console etc.). There are of course also other types of requests that can be used, such as GET, where the client wants to reretrieve data from the server instead of posting data to it.
## Presenting the data
### Dashboard
In the final product, the dashboard, there are two graphs, one for the temperature (measured in celcius) and one for humidity (measured in percent), which shows the data from the last 20 minutes. We also have a text in the button of the page, which tells us if there are any problems, either with connection to the LAN or sensor. One thing worth mentioning again is that the DHT11 sensor has a accuracy of +- 2, so the temperature and humidity is not 100% accurate, but close enough in this project to present an accurate result.

### Database
As mentioned in the computer setup section, the data comming from the microcontroller with the POST request sends the data to the dashboard, and at the same time sends it to the mongoDB server, in other words, every 10 seconds.
The reason for picking MongoDB is that is very free (although the free version has limited space), runs on the cloud, giving the option not to set up your own database, is very easy to get started with, and is very easy to implement with node red. Having over 2 years of experience in web development, I've also stumbled across MongoDB before, thus I have some experience using it, which is why it was a no brainer to use that as the database for storing data.
## Finalizing the design
Starting up the Arduino, if you have done it successfully, the green LED should light up and you will see the data in the dashboard updating.

\
\

You could even try pulling out one of the jumper wires connected to the DHT11 sensor to see if your error HTTP POST request works:
<iframe width="100%" height="500" src="https://www.youtube.com/embed/W0BPTM4sFy8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
### Conclusion
I think the project went very well considering it was my first IoT project, especially since I learned a lot, now knowing how the basics of IoT works and how to go from idea to project. Jumping into IoT I was kinda scared that it was going to end up in a mess, even if I am familiar with programming, hosting and network concepts. But it went better than expected and I will most likely continue learning more about IoT and creating more advanced devices and systems connected to the devices.
Of course, there are always going to be things that you could have done better and in another way. For example, having a sensor for measuring air quality would've been a really fun addon, but also implementing the functionality to control the IoT device in someway through node red. But if I had more time, or had to do it again, I would love to explore with the MQTT protocol, and add a node to a fan, so if my temperature sensor reaches a value over a set limit, the server automatically turns on the fan with that added device, in a publisher, broker, subscriber design.
I would also want to explore the energy options a bit more than just connecting my device to my computer, thy that makes it very limited where I could keep it (unless I have and want a long USB cable).
## References
HTTP response status codes. (2022, July 3). Retrieved from https://developer.mozilla.org/en-US/docs/Web/HTTP/Status