# Monitor temperature and brightness in a room, a tutorial
###### tags: `IoT`
##### Written by [Benti Zekarias](https://www.linkedin.com/in/bentizekarias)
## Project overview
This is an entry level IoT project that monitors the temperature and brightness in a room. The respective values will be logged between fixed intervals, then sent via Wi-Fi to Datacake where they will be stored and visualized. Approximately 5 hours and $50 will be needed to complete this project.
## Objective
I chose this specific project because I always felt that my room was a tad bit too cold, and too bright during the morning because of the sun rising on my side of the house. Therefore, I decided to actually measure how bright and cold it was in my room to see if it was only my imagination.
The purpose of this project is to measure the temperature and brightness in my room and help others, perhaps not in my exact predicament, create their own such project.
The insights I expect include:
- To learn how to build an IoT device
- To find out at what values I slept the best and the worst. And by extension eventually improve my device to be able to automatically use that data to control my settings during the night to always be at the values I slept the best at.
## Material
1. [ESP32 Microcontroller](https://sizable.se/P.CE9S1/ESP32). I initially had an Heltec ordered, but because of circumstances I could not receive it. So I instead settled for an ESP32 microcontroller, and I found it to be a great choice for a project such as this. Capable of reading the sensor data and sharing it via Wi-Fi, it was more than sufficient enough for me.
2. [DHT11 Tempsensor](https://sizable.se/P.WGXR4/DHT11-Temperatur-och-luftfuktighetssensor ). The DHT11 sensor measured the temperature. It is capable of measuring temperature from 0-50 °C and also the humidity, but the humidity is not of concern for me.
3. [HALJIA Light intensity sensor](https://www.amazon.se/-/en/dp/B01BTGV566). This HALJIA Digital Light Intensity Sensor Module Photo Resistor changes its value depending on the light intensity. That means that when light shines upon it, the value (resistance) decreases. I have used this to detect the brightness and measured the light intensity of my environment.
4. [Breadboard](https://sizable.se/P.SFGYT/Kopplingsdack-med-400-punkter). Helps with the wiring, allowing for components to be removed and replaced easily.
5. Two sets of Jumper cables: [Male-Female](https://sizable.se/P.3V1BE/Dupont-kopplingskablar-Hane-Hona-40-pin) & [Male-Male](https://sizable.se/P.K2HUW/Dupont-kopplingskablar-Hane-Hane-40-pin
). Used for the wiring.
6. Micro USB Cable. Needed to connect the ESP32 microcontroller to the computer, can be bought almost anywhere for a very small sum.
No extra resistors are needed if the materials bought are the same as mine.
## Computer setup
The following steps are only guaranteed to work on a Windows operating system.
### Atom as chosen IDE
This tutorial will be using Atom as the IDE, but Visual Studio is another good choice if you are more comfortable with that.
- **Step 1**: Download and install [Node.js](https://nodejs.org/en/).
- **Step 2**: Download and install [Atom](https://atom.io/).
- **Step 3**: Open Atom and the package manager from: `File >> Settings >> Install`.
- **Step 4**: Locate **Pymakr** under **Install Packages** and install it.
### Uploading code
**Note** that your controller might need to be flashed before you are able to continue. Instructions for doing so can be found [here](https://docs.espressif.com/projects/esp-at/en/latest/esp32/Get_Started/Downloading_guide.html).
Now you can open your Atom IDE and create a folder to store your code in. Add the code you want to run, then click on `Connect device` and choose your COM port as shown in the picture below.

After your microcontroller successfully connects you are now able to upload your code. By pressing on `Upload project to device` the code uploads and can be executed.

## Putting everything together
When connecting everything it is important that no power is running because of the damage it can cause to the devices if something is connected wrong. Again, no extra resistors are needed for this project.
I start by connecting the generic ESP32 microcontroller to the breadboard in such fashion:

The black wire goes from `GND` (ground, 0V) on the microcontroller to the negative rail of the breadboard, while the red one goes from `3V3` (the operating voltage) on the ESP32 to the positive rail. This later gives the two rails on this side power when the microcontroller connects to the micro USB cable. The colors of the cables do not matter, but for the sake of clarity both for myself and for this tutorial the red wires will be connected to the positive rail and the black ones to the negative rail. Make sure to also check that your sensors operate at a voltage of 3.3V and not 5V, as the latter can cause complications.
Two sensors are to be connected, the DHT11 tempsensor and the HALJIA Light Intensity Sensor. Starting with the DHT11, you may connect it like this:

The red cable connects as earlier mentioned to one pin on the positive rail and to one other pin on the same line as the `VCC` (the positive pole of the power supply), located on the DHT11. The black does the same but for the grounding/negative pole. The blue cable meanwhile is responsible for connecting the sensor to the microcontroller. The blue cable connects to `DATA` row of the sensor and to any digital `GPIO` on the ESP32, in my case `GPIO2`.
To make sure that the DHT11 functions as intended, I decided to run a quick test run using the code below.
```python=
from machine import Pin
from time import sleep
import dht
sensor = dht.DHT11(Pin(2))
while True:
try:
sleep(2)
sensor.measure()
temp = sensor.temperature()
temp_f = temp * (9/5) + 32.0
print('Temperature: %3.1f C' %temp)
print('Temperature: %3.1f F' %temp_f)
except OSError as e:
print('Failed to read sensor.')
```
The output is as following, assuring us that it worked:

I iterated the same process for the HALJIA lightsensor.

I connected the blue cable to `GPIO34` on the microcontroller and to `DO` on the lightsensor, and then tested the sensor with:
```python=
from machine import ADC, Pin
import time
class LDR:
def __init__(self, pin, min_value=0, max_value=100):
if min_value >= max_value:
raise Exception('Min value is greater or equal to max value')
self.adc = ADC(Pin(pin))
self.adc.atten(ADC.ATTN_11DB)
self.min_value = min_value
self.max_value = max_value
def read(self):
return self.adc.read()
def value(self):
return (self.max_value - self.min_value) * self.read() / 4095
ldr = LDR(34)
while True:
value = ldr.value()
print('value = {}'.format(value))
time.sleep(3)
```
The result was:

The lower values are when light is detected, meaning that the area around the sensor is bright, and the higher value of a 100 is when it is dark. The lightsensor also turns of one of its otherwise two glowing green led lights when light is not detected. As can be seen in the two pictures below:

When everything is connected, it shall resemble the following when powered up:

Male-Female cables were used when connecting to the microcontroller, while Male-Male cables were used in the other instances.
## Platform
I used the MQTT utilizing [Datacake](https://datacake.co/) as the end-point IoT platform to store and visualize the data sent from the controller. I did so because of these factors:
- Datacake easily receives the data via Wi-Fi
- Your first two devices are free, meaning that you will not have to pay for a subscription when working on this project
- Has great documentation, which helps tremendously
- It features built-in, easy-to-use dashboards.
Using Wi-Fi and Datacake is also a good option if you for example want to expand the project by measuring multiple rooms in your house. Since it gives the users the option to add more devices (but for a fee) you can therefore implement the same code and tools that you already are accustomed to. The use of Wi-Fi keeps it simple to transmit data from inhouse projects like this one even when you include more devices. However, if the device are intented to monitor the temperature and brightness of something outdoors, then I would recommend the use of LoRaWAN which is more suitable for those types of projects. With that said, Wi-Fi together with Datacake's smooth dashboards is best suited for this project in my opinion because of the easy connection to a network I have in my bedroom.
## The code
For this project four files called `boot.py`, `config.py`, `mqtt.py` and `main.py` should be sufficient.
The code in `boot.py` is used to connect the device to Wi-Fi and can resemble the following:
```python=1
import network
import config
sta_if = network.WLAN(network.STA_IF) # Put modem on Station mode
if not sta_if.isconnected(): # Check if already connected
print('connecting to network...')
sta_if.active(True) # Activate network interface
sta_if.connect(config.WIFI_SSID, config.WIFI_PASS) # Your WiFi Credential
# Check if it is connected otherwise wait
while not sta_if.isconnected():
pass
# Print the IP assigned by router
print('network config:', sta_if.ifconfig())
```
The connection is successful if you receive a correct IP-address tuple of four parameters.
`config.py`, is where I store my Wi-Fi credentials such as `WIFI_SSID`, `WIFI_PASS`, and my Datacake credentials. You have to either add a file along these lines or edit some of the code in this project for it to properly execute. For example would line 8 in `boot.py` have to be changed to your Wi-Fi credentials, which is a security and privacy issue if the code is publicly published. A file like `config.py` could therefore look as such:
```python=
# WiFi credentials
WIFI_SSID = 'WIFI_SSID'
WIFI_PASS = 'WIFI_PASS'
# Datacake credentials
SERIAL_NUMBER = 'DEVICE_SERIAL_NUMBER'
MQTT_BROKER = 'mqtt.datacake.co'
TOKEN = 'ACCOUNT_TOKEN'
PORT = 1883
TOPIC = 'TOPIC_TO_PUBLISH_TO'
```
The code for `mqtt.py` can be found and copied from [ESP32-MicroPython](https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/MQTT/umqttsimple.py). The purpose of this file is to import a library which allows the sending of data to the Datacake platform.
`main.py` utilizes the library imported from `mqtt.py` to actually send the data read from the sensors to Datacake. It is therefore in this file that code will differ from the code of other projects that also uses Datacake and MQTT. It consists of:
- Initialization of the sensors
- The planned intervals
- Managing the data read by the sensors
- Publishing the data.
```python=
#Import libraries
from mqtt import MQTTClient
from machine import Pin, ADC
import dht
import time
import ujson
import machine
import config
def sub_cb(topic, msg):
print(msg)
# MQTT Setup
client = MQTTClient(config.SERIAL_NUMBER,
config.MQTT_BROKER,
user=config.TOKEN,
password=config.TOKEN,
port=1883)
client.set_callback(sub_cb)
client.connect()
print('connected')
#Set up the correct topics
my_topic = config.TOPIC
my_topic2 = config.TOPIC2
my_topic3 = config.TOPIC3
#Initialization of the sensors to be read
tempSensor = dht.DHT11(Pin(2))
class LDR:
def __init__(self, pin, min_value=0, max_value=100):
if min_value >= max_value:
raise Exception('Min value is greater or equal to max value')
self.adc = ADC(Pin(pin))
self.adc.atten(ADC.ATTN_11DB)
self.min_value = min_value
self.max_value = max_value
def read(self):
return self.adc.read()
def value(self):
return (self.max_value - self.min_value) * self.read() / 4095
ldr = LDR(34)
while True:
#Measuring and managing the data read from the sensors
tempSensor.measure()
temp = tempSensor.temperature()
temp_f = temp * (9/5) + 32.0
percentDark = ldr.value()
#Publishing of the data to Datacake
client.publish(topic=my_topic, msg=str(temp))
client.publish(topic=my_topic2, msg=str(temp_f))
client.publish(topic=my_topic3, msg=str(percentDark))
client.check_msg()
#The planned intervals
print("Send data to MQTT broker, sleeping for 15 minutes...")
time.sleep(900)
```
## Transmitting the data
I initially had it set up to send the data every 5 minutes but I quickly noticed that it was unnecessary since no noticeable changes were made during those intervals. For that reason, I changed the code to transmit the data every 15 minutes instead.
Wi-Fi is used as the wireless protocol because the generic ESP32 do not support LTE, and the LoRa/LoRaWAN was not needed since the project were intended to be used in my room. The ESP32 implements both TCP- and IP protocols, full 802.11 b/g/n/e/i WLAN MAC protocol, and Wi-Fi Direct specification. Thus, even the generic ESP32 can speak to most of the WiFi Routers out there and is hence more than sufficient enough for my in-house project.
The transport protocol used for this project was the MQTT protocol. I use MQTT because it is a lightweight protocol and is therefore quite quick to implement. The network usage is also low, as is the power usage, making it a good option for this project since I am not transmitting a lot of data.
The code works by first establishing a connection to a Wi-Fi network as can be seen in `boot.py`. The ESP32 then takes sensor-readings every 15 minutes, as stated earlier, and sends them through Wi-Fi to Datacake using the MQTT protocol, where it will be visualized without any need for local storage.
## Presenting the data
I used widgets on Datacake to visualize and monitor the data sent from the device. But I had to add fields before I could do that:

The first two fields describes the two different units of temperature to be read and stored, Celsius and Fahrenheit. As for the ``Darkness`` field, I named it that because of the way the HALJIA Light intensity sensor (LDR) measures its values. When light shines upon it the value decreases, and when it cannot receive any light, it spikes in value [(source)](https://blog.gypsyengineer.com/en/diy-electronics/reading-photoresistor-on-esp32-with-micropython.html). As darkness is lights contrariety it fits to name the field that, with percent as the unit. So if it is bright ``Darkness`` should be at a low percentage, and vice versa when it is dark.
The three fields and their identifiers are then later used to create the dashboard actually used to monitor the data. By utilizing Datacakes ``Value`` widget a clean and easily readible dashboard can be created.

On Datacake you can also read into data other then just the last updated. Under ``History`` you are able to monitor values such as the:
- `CURRENT`
- `AVERAGE`
- `MAXIMUM`
- `MINIMUM`
over a period of time of your liking. Example below:

As can be seen in the graph above, it was particularly bright in my room from 08:30 - 09:15. This confirms my suspicion of me not perhaps setting my blackout curtains up properly.
The data is saved as often as it is sent, which is every 15 minutes. This has not been a problem since I can keep the power of my device on by having it connected to my pc, but having another power source and perhaps readings more often could be more beneficial for you.
## Finalizing the design
Overall, I am quite satisfied with the result of this project even though I did not get my hands on a Heltec microcontroller. An Heltec would allow me to try out more ways to send data than the generic ESP32 did, which could improve the scaling of my project by utilizing other protocols of data sending in different environments. All while still using the same sensors. Designwise, would I liked to get some shorter Male-Male jumper cables since they are a bit too long right now. Putting everything in a neat case would also help with the design and user usability since the only thing the end user would have to think about then is inserting the micro USB cable.

Using Datacake as the platform also fitted my needs quite well, as I did not have any prior experience in the world of IoT and storage of such data, and it gave me the personal answers I was expecting. Further along the line could I use Datacake to add events which would trigger based on the device's readings. Meaning that I in the future could get notified by Datacake via, for example, e-mail if the temperature/brightness gets too high or too low. Looking back, I would also dare say that Datacake is more than suitable enough for more experienced IoT users as well. This is mainly because of its intuitive feel with features for the more advanced users, like creating rules, which I think would be appreciated.