# Tutorial on how to build a temperature and light sensor
**By Christoffer Wrigmar, cw222vn**
## Project overview
The aim of this project is to easily set up a sensor that monitors temperature and light intensity in any given physical space.
The steps of this guide will take approximately 2 hours or less (depending on previous experience).
### Objective
This project was chosen because of its possible utilizations: the data that is given by the sensor can be used to either optimize the placement of indoor plants, a "plant placer" if you will, or because of its day and night cycle tracking, be part of a home automation system. By reading temperature and brightness, one can determine whether a location is optimal for a given plant in terms of enough light and/or temperature, or by connecting the sensor to an automation system, the data can be used to control lighting and regulate indoor climate.
Hopefully this will work as a good introductory project using programming and hardware parts, and learn how to use the former to control the latter in a simple project.
## Material
The materials used in this project was bought as a bundled kit from Electrokit exclusive for this course (which can be found [here](https://www.electrokit.com/produkt/lnu-1dt305-tillampad-iot-lopy4-and-sensors-bundle/) for a total of 949 SEK (~€93)), but the costs listed below are based on prices for each part from Pycom and Electrokit.
| Material | Description | Cost |
| -------- | -------- | -------- |
| LoPy4 | Programmable microprocessor that supports different networks for transmitting data. Will read input from the sensors, control the LEDs and use WIFI to transmit data to a cloud platform | [€38.45](https://pycom.io/product/lopy4/) |
| Pycom Expansion Board 3.0 | An expansion board for the LoPy4 that enables USB-charging and easily connecting the components | [€17.60](https://pycom.io/product/expansion-board-3-0/) |
| Breadboard | Used for experimenting with electronics to place components without soldering | [€6.31](https://www.electrokit.com/produkt/kopplingsdack-400-anslutningar/) |
| Wires | Jumper wires to connect the components from the breadboard to the expansion board | [€4.17](https://www.electrokit.com/en/product/hook-up-wires-w-pins-for-breadboard-smooth-65-pcs/) |
| Micro-USB cable | To connect the microprocessor to your computer and power your device (can be used with a USB charger and/or battery bank for mobile use) | [€5.24](https://www.electrokit.com/en/product/usb-cable-a-male-micro-b-male-3m/) |
| Temperature sensor | Used to read the temperature, and sends an analog signal based on voltage that is interpreted by the microprocessor | [€0.86](https://www.electrokit.com/produkt/mcp9700-e-to-to-92-temperaturgivare/) |
| Photo resistor | Used to measure light intensity, by sending an analog signal based on voltage in a similar way as the temperature sensor | [€2.57](https://www.amazon.se/Fotomotst%C3%A5nd-Dependent-Resistor-sensor-Motst%C3%A5nd/dp/B07JNDVTZV/ref=sr_1_5?dchild=1&keywords=ldr&qid=1627893702&sr=8-5) |
| 1 x 10kΩ Resistor | Used for the photoresistor to lower the voltage| [€0.32](https://www.electrokit.com/produkt/motstand-metallfilm-0-6w-1-10kohm-10k/) |
| 1 x 330Ω Resistor | Used for the LEDs for the same reason as above | [€0.32](https://www.electrokit.com/produkt/motstand-metallfilm-0-6w-1-330ohm-330r/)|
|LED Red | Used to indicate temperatures above 30°C | [€0.54](https://www.electrokit.com/en/product/led-3mm-rod-diffus-1300mcd/) |
|LED Orange | Used to indicate temperatures between 25 and 30°C | [€0.54](https://www.electrokit.com/en/product/led-3mm-orange-diffus-600mcd/) |
|LED Green | Used to indicate temperatures below 25°C | [€0.54](https://www.electrokit.com/en/product/led-3mm-gron-diffus-70mcd/) |
## Computer setup
This project was set up using [**Microsoft's Visual Studio Code**](https://code.visualstudio.com/) (but there are other IDEs that will work as well). To get started you need to install the **Pymakr REPL console**, which supports MicroPython and connects to the Pycom board, and also enables you to upload program files to it. This is done by going to `Extensions`, search for `Pymakr`, select it and then click `Install`.

*Figure 1: Installing the Pymakr plugin*
A prerequisite for Pymakr is **Node.js** (6.9.5 or higher) installed on the computer, which can be downloaded from https://nodejs.org/en/, and then follow the instructions for your operating system.
When the installation is done a command bar should appear on the bottom of you IDE that contains different tools, with which you can control your attached Pycom board. To load your project onto the microprocessor you just press the `Upload` button from within the project.

*Figure 2: The Pymakr toolbar and terminal*
Sometimes this won't work because Safe Booting is disabled, and if that's the case you'll have to open the `Project settings` from the `All commands` menu and change `safe_boot_on_upload: false` to `true`:

*Figure 3: Enable safe boot on upload*
Before you start putting your project together, make sure to check if your expansion board needs a firmware update by plugging it in with the USB-cable and follow [these](https://docs.pycom.io/updatefirmware/expansionboard/) steps.
When everything is installed and ready, you should create a new folder (`File > Open folder... > Create folder`) in which you'll store the code, and then create a new folder called `lib` (by right-clicking the file space and click `New folder`). This is where some of the code will end up later. Then you need to create two files in the root folder (either by clicking `File > New file`, or `Ctrl + N`):
* `boot.py`, the first script file that is run when the device is booted up and is used for decluttering the main file
* `main.py`, the main file where you tell the device what to do
The generated data from the device will be uploaded to the cloud based platform **Pybytes**, which anyone with a Pycom board can use, so the next step is to connect the device to this service. You need to create a new account on their website https://pybytes.pycom.io/ and then follow the steps for [getting started](https://docs.pycom.io/pybytes/gettingstarted/) (make sure you set up WiFi as well, since this will be the wireless protocol used in this project). After the device is set up, you'll need to create two new signals (the steps for doing so is found [here](https://docs.pycom.io/pybytes/dashboard/)):
* **Signal 1** will be used for temperature, so you can name it `Temperature` and use the unit `°C`
* **Signal 2** is used for measuring sunlight, so a reasonable name could be `Brightness` or `Sunlight` and the unit `%` (this will be the percentage of the maximum value that can be recorded by the photo resistor)
## Putting everything together
The following picture is a circuit diagram with all the hardware used in this project, and the color scheme that is used in this case is:
* Red for voltage and outputs (i.e. 3V3 for sensors and pins 10-12 for LEDs)
* White between LEDs and resistor
* Black for ground
* Yellow for analog input from sensors
*You can use whatever colors you'd like, but it's recommended to be consistent with the different types of connections*

*Figure 4: Project circuit scheme*
Some notes about the design:
* The two bottom lines on the breadboard are +/- rails, which means that you can connect them to 3V3 and ground respectively and then connect your other parts to them collectively
* Only one 330Ω resistor is used for the LEDs since there never is more than one that is turned on at any given time, and therefore the resistance won't become too great. Although, you could use one resistor per LED as well, for safety measure
* The temperature sensor is marked TMP36, which is another sensor than the one that's being used, but works the same
*Make sure you unplug the device before you connect any parts to the Pycom board.*
## Platform
As is mentioned earlier, the platform used in this project is Pybytes. This is a cloud based storage provider that lets you to visualize different data from a Pycom device in a simple manner through a dashboard. There are other platforms that you can use as well, but since Pybytes is both supported by the device and easy to use they weren't considered for this project.
The different widgets in the dashboard that is used are:
* The amount of data that is recieved from the device both minute-wise and hourly, to monitor that the data flow is even, which otherwise could indicate some problems with the device (as unfortunately is seen below, more on that later)
* Temperatures recorded every minute from the last 21 hours
* The amount of light every minute from the last 21 hours (if only sunlight is recorded there should be a wave-like shape, as indicated below)
* The location of the device, if there is a future need to use the corelation between the recorded data and location

*Figure 4: The Pybytes Dashboard*
## The code
The code for this project is divided into four different files (`boot.py` is empty), as is shown in the following picture:

*Figure 5: The file structure of the project*
**lib/light_sensor.py:**
```
from machine import ADC, Pin
light_adc = ADC(bits=10) # makes the light value range 0-1024
LightSensorPin = 'P13' #Photo resistor signal wire on pin 13
light_apin = light_adc.channel(attn=ADC.ATTN_11DB, pin=LightSensorPin)
lightPin = Pin(LightSensorPin, mode=Pin.IN)
# takes the value from the sensor and returns a percentage of maximum value
def light_read():
return light_apin() / 1024
```
**lib/temp_sensor.py:**
```
from machine import ADC
temp_adc = ADC()
temp_apin = temp_adc.channel(pin='P16') #temperature sensor signal on pin 16
# reads the voltage from the sensor, calculates
# and return the temperature in celsius
def temp_read():
millivolts = temp_apin.voltage()
return (millivolts - 500.0) / 10.0
```
**lib/leds.py:**
```
from machine import Pin
red = Pin('P12', Pin.OUT, pull = Pin.PULL_DOWN)
ylw = Pin('P11', Pin.OUT, pull = Pin.PULL_DOWN)
grn = Pin('P10', Pin.OUT, pull = Pin.PULL_DOWN)
# takes the temperature and decides what LED to turn on based on value
def led(temp):
if temp <= 25:
red.value(0)
ylw.value(0)
grn.value(1)
elif temp > 25 and temp < 30:
grn.value(0)
red.value(0)
ylw.value(1)
elif temp >= 30:
grn.value(0)
ylw.value(0)
red.value(1)
else:
grn.value(0)
ylw.value(0)
red.value(0)
```
**/main.py:**
```
import pycom
import time
from temp_sensor import temp_read
from light_sensor import light_read
from leds import led
pycom.heartbeat(False) #turns of the RBG LED on the LoPy4
while True:
celsius = temp_read()
light_val = light_read()
led(celsius)
pybytes.send_signal(1, celsius)
pybytes.send_signal(2, light_val)
print("Temp: " + str(celsius) + "°C | Light: " + str(light_val)) + "%"
time.sleep(60)
```
## Connectivity
The data is sent every 60 seconds to make sure that fluctuations in temperature and light is recorded. An alternative would be to send data less often with an average reading, e.g. the average of every 5-10 minutes or less often, if there were an internet pricing plan or another wireless protocol in use. This also goes for the power supply: if the device is intended to be mobile and is connected to a battery bank instead of a power socket with a charger, then sending less data would also be preferred to use less power.
In this case the device is stationary and uses WiFi as wireless protocol, which is why the current data flow was chosen. The project is using MQTT as transport protocol to send data to Pybytes, since it's by default when using WiFi.
A free Pybytes account includes 5 MB of storage and about 1kB is recieved every hour, which means the storage will run out after about 208 days. This should be taken into consideration when deciding how often the device should send data.
## Presenting the data
In the pictures below you can see how the data readings are presented on the Pybytes Dashboard. Unfortunately something went wrong with the project during the time this tutorial was made, which led to some distorted data and scaling (as is seen in the end of the curves and scales).

*Figure 6: The Pybytes widget visualizing temperature data*

*Figure 7: The Pybytes widget visualizing sunlight data*
The data is also printed in the terminal in the following format:
```
Temperature: Temp: 23.3°C | Light: 22,1%
```
This can be useful while connected to a computer, but as a stand-alone device this serves no meaningful purpose as of now.
## Final design

*Figure 8: The final result, monitoring the temperature and sunlight conditions for a Coleus plant on a window sill*

*Figure 9: Close-up on the setup*
Some final thoughts about the project and its design:
* As for the looks, it would be nice to either make a case for the device as is, so the wires, breadboard and microprocessor are hidden, or solder the components onto a circuit board and make a more permanent installation
* There have been some problems during the project, i.e. the distorted data, and also uploading the project onto the Pycom board (described in the "Computer setup" section), which took me way too long to figure out. But I'd like to think that I learned a lot from these hickups.
* Last but not least, this has been a fun project to develop, and hopefully someone else will enjoy it as well!