---
# System prepended metadata

title: The Greenhouse Thermometer
tags: [raspberry pi pico, wifi, thermometer]

---

**Project made by:** Wictor Rindebrant
**Student credentials** (wr222bp)

Overview
---
It's pretty common that we want to know what temperature there is in our greenhouse, for our plants to not die from the heat or the cold. So most people use a thermometer for this reason. But always having to go to the greenhouse can be pretty time consuming and unnecessary.

So for this reason I decided to make an IOT device that is a simple thermometer that is connected to a website, so that you can check the temperature in the greenhouse from anywhere.

**Estimated time to set up:** 2-4 hours


Objective
---
My father wanted a way to see the temperature in the greenhouse without having to go out there and check the thermometer all the time. So the reason I choose this for my project is so that my father can check the temperature in the greenhouse without having to go out there and check the thermometer. It also shows with led lights what the temperature is, this is so that he does not need any extra thermometer in the greenhouse and can fast and easy just check the led lights to see the temperature.

The possible insight that this will give is I think this IoT thermometer will save my father some time and might even reduce the stress around always having to think about going out to the greenhouse to check the temperature.



Material
---


| Component | Description | Amount |
| -------- | -------- | -------- |
| Raspberry Pi Pico WH| The micro computer where all the code will be executed and stored | 1 |
| Breadboard| A place to connect everything with the pico | 1 |
| USB-cable A-male – micro B 5p male| To be able to connect the computer to the pico, to send over the code to be executed by the pico| 1 |
| Digital temperature and humidity sensor DHT11| The device that gathers all the information about the temperature and humidity | 1 |
| Resistor 330 ohm | Used to lower the power of the circuit for the led lights since they need lower power | 1 |
| Led lights (2v) | Used to indicate what the temperature it is with just looking at what light is lighted up | 3-7 |
| Jumper Wires| Used to connect everything on the breadboard | 10 |

I did buy all of the materials from here:


| Kit Name | Website | Price |
| -------- | -------- | -------- |
| Start Kit – Applied IoT at Linnaeus University (2023)     | https://www.electrokit.com     | 36.31 £|

Here is a picture of all the things i bought and all the things i used:
![](https://hackmd.io/_uploads/BJxz7F3d2.jpg)


Computer setup
---
The first thing you need to do is install some programs listed below:



| Program | Download link |
| -------- | -------- |
| VSCode latest version | https://code.visualstudio.com/download |
| Python 3.9 or newer | https://www.python.org/downloads/ |
| MicroPython firmware | https://micropython.org/download/rp2-pico-w/ |
| Pico-w-go version 2 (not 3) | https://github.com/paulober/Pico-W-Go/releases/tag/v2.1.8 |
| Pytlance | Found on VSCode extensions |

When all of these programs/files are installed we can start with putting the micropython firmware on the pico, we are doing this by holding the bootsel button on the pico while putting in the cable from the pico to the computer. This will open up a folder on our computer where we drag and drop the file that we downloaded from micropython.org. When we have done that the folder should disappear and the micropython should now be installed on the pico.

After that we can open up VSCode (our IDE) and create a new folder that we will store all the files in. Then we can install the pico-w-go extension to visual studio code by going in to the extension tab, press the 3 dots (views and more actions) and then on press on Install from VSIX... as shown in the image below:
![](https://hackmd.io/_uploads/H144G1cO2.png)
When we have done that, we choose the file that we downloaded from the github link provided above for the pico-w-go version 2 file. Then the extension should be installed. And while we are at the extension tab in VSCode we can also go ahead and search for "Pylance" and install that as well.

The next step will be to press Ctrl+Shift+P to open the command pallet and type in Pico-W-Go > Configure project. If everything worked as it should then it should look like this in your created folder:
![](https://hackmd.io/_uploads/SkjKmJ5Oh.png)

When we have got this far, we are finally ready to type some code and send it to the pico to be executed. We do this by first creating a main.py in the folder that we just created. Then we type some code in the main.py file that we want the pico to execute. Then to upload the code to the pico we hold Ctrl+Shift+P again to open the command pallet, but this time we first type Pico-W-Go > Connect (to connect to the pico). And then we type Pico-W-Go > Upload project (to upload our folder with the main.py file to the pico).

A main.py test code is provided in the image below just to test that everything is working:
![](https://hackmd.io/_uploads/HyZ7PJcOn.png)
If everything is working the little led light on the pico should blink.

Putting everything together
---
Now it's time to put everything together on the breadboard. And to show this I used the program Fritzing. It's not exactly the same as i did in reality but it's the same connections and same things used, just in different positions to make it easier to see how everything is connected.
![](https://hackmd.io/_uploads/Byw3fOhuh.png)

![](https://hackmd.io/_uploads/S1oD4_3Oh.png)

![](https://hackmd.io/_uploads/r11tXgqun.png)

All the 7 blue jumper wires are connected from the picos GP0 - GP6 to one side of all of the Led lights. The other side of the Led lights are connected to the same connected row on the breadboard that goes back to the picos GND through the resistor with 330 ohm to make a circuit. From this we can decide on what GP0 - GP6 we want to send out power, and depending on that, the different led lights will light up.

Then the Digital temperature and humidity sensor (DHT11) needs to be connected with 3 jumper wires to the pico. The red jumper wires are connected from the DHT11 VCC to the 3v3(OUT) on the pico to get some power, then the black jump wires are connected from the DHT11 GND back to the picos GND to make a circuit. And then last we have the yellow jumper wires that are used for transferring data from the DHT11 that is connected from the DHT11 Data out to the picos GP28 for input of the data.

Calculating the resistors needed:
**DHT11** 
The DHT11 has originally 4 pins where one of the pins serves as an resistor between the VCC and the GND, so for this reason we don't need any resistor for  the DHT11.

**Led light** 
The led lights can only handle 2.1v, and the picos GP power out is 3.3v. So for this reason we will need a resistor to the led lights. I used this website "https://kitronik.co.uk/blogs/resources/led-resistor-value-calculator" to calculate how big a resistor I would need for the led light. And after putting in all of the variables needed to calculate the resistor, it said that I needed a resistor that has at least 68 ohm. When checking what different resistors i had, i did see that my smallest one was 330 ohm, so i went for that one. The website I provided is using ohms law to calculate the resistance needed in the circuit (R = V / I). And below is an image i did draw on all the different resistors i had, that i got from the starter kit:
![](https://hackmd.io/_uploads/Sk2xPt2_3.png)

Platform
---
**Adafruit IO**
The platform I decided to use for this project was the cloud service adafruit IO. I decided to use adafruit IO since I'm pretty new to IOT and I found a lot of guides and information about how to connect your IOT device to adafruit. I think it's a perfect cloud service for IOT since it's really simple to set up and use, the only downside with adafruit is that the free version has some limits as I show in the picture below.
![](https://hackmd.io/_uploads/SkhQAe9_h.png)

But if you are willing to pay for the paid version of adafruit IO, it gives a lot more. So if you want to use more devices or just larger projects then the paid version is the way to go. But for smaller projects like this one, I think it worked really well.

Adafruit IO lets you connect your IOT device to their cloud service. There you can set up different groups for your different IOT devices and inside those groups you can set up feeds. The feeds lets you communicate with your different sensors and things on your IOT device to the Adafruit IO cloud, so that you can directly link information from a sensor to a diagram on adafruit IO cloud service. On the Adafruit IO website, you can link different diagrams, tables, buttons and so much more directly to your IOT device inside a really user-friendly dashboard.

The code
---
```
# Pins used on the Pico.
led1 = machine.Pin("GP0", machine.Pin.OUT)
led2 = machine.Pin("GP1", machine.Pin.OUT)
led3 = machine.Pin("GP2", machine.Pin.OUT)
led4 = machine.Pin("GP3", machine.Pin.OUT)
led5 = machine.Pin("GP4", machine.Pin.OUT)
led6 = machine.Pin("GP5", machine.Pin.OUT)
led7 = machine.Pin("GP6", machine.Pin.OUT)
tempSensor = DHT11(machine.Pin(28))

# Status of the light (start as ON).
light_status = "ON"
```

```
# Handles the functionality when pressing the light button on the website.
def light_button_cb(topic, msg):
    global light_status         
    if msg == b"ON":             
        ledOn()
        light_status = "ON"      
    elif msg == b"OFF":          
        allLedOff()
        light_status = "OFF"         
    else:                        
        print("Unknown message")
    print("Light Status:", light_status)
    
# Sends the infromation about the temperature to the website every x ms.
def send_temp():
    global publish_time_interval
    global last_sent_ticks
    last_publish = time.ticks_ms()

    if ((last_publish - last_sent_ticks) < publish_time_interval):
        return; 

    temp = get_temp()
    print("Publishing: {0} Celsius to {1}      ".format(temp, AIO_TEMP_FEED), end='')
    try:
        client.publish(topic=AIO_TEMP_FEED, msg=str(temp))
        print("[DONE]")
    except Exception as e:
        print("[FAILED]")
    finally:
        last_sent_ticks = time.ticks_ms()

# Gets the temperature and returns it.
def get_temp():
    tempSensor.measure()
    return tempSensor.temperature()

# Turns all the led lights off.
def allLedOff():
    led1.off()
    led2.off()
    led3.off()
    led4.off()
    led5.off()
    led6.off()
    led7.off()

# Turns one of the led light on depending on temperature.
def ledOn():
    temp = get_temp()

    if (temp <= 23):
        allLedOff()
        led1.on()
    elif (temp <= 24):
        allLedOff()
        led2.on()
    elif (temp <= 25):
        allLedOff()
        led3.on()
    elif (temp <= 26):
        allLedOff()
        led4.on()
    elif (temp <= 27):
        allLedOff()
        led5.on()
    elif (temp <= 28):
        allLedOff()
        led6.on()
    else:
        allLedOff()
        led7.on()


# Tries to connect to the WiFi.
try:
    ip = connect()
except KeyboardInterrupt:
    print("Keyboard interrupt")

# Use the MQTT protocol to connect to the website.
client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY)

# Subscribed messages will be delivered to this callback
client.set_callback(light_button_cb)
client.connect()
client.subscribe(AIO_LIGHTS_FEED)
print("Connected to %s, subscribed to %s topic" % (AIO_SERVER, AIO_LIGHTS_FEED))

# Infinity while loop that updates the status of the temperature and light.
try:                               
    while True:
        client.check_msg()
        send_temp()
        if light_status == "ON":
            ledOn()
        elif light_status == "OFF":
            allLedOff()
```

What this code does is that it first tries to connect the pico to the wifi. If that works it will try to connect the pico to the website. Then when the pico is connected to the wifi and the website, it will get stuck in a while loop that will check incoming msg from the server and call for the function that sends the temperature to the website if the interval timer is reached. Then in the while loop it will also check if the light status has been changed from the client.check_msg() function in the start of the while loop that in that case would change the light_status variable in the function light_button_cb(). And if it's changed from "ON'' to "OFF" it will call for the function allLedOff() that will just turn off all the led lights. And if it's changed from "OFF" to "ON" it will call for the function ledOn(), that will turn on one of the led lights depending on the temperature and that will keep getting updated since it will always calls for that function in the while loop if the light_status is "ON" and not "OFF" 

Transmitting the data / connectivity
---
I did choose the MQTT protocol to transfer the data from my pico to the website. The reason why I decided to use MQTT is because I found a really detailed guide on how to connect my pico wireless to the Adafruit IO website using MQTT. Here is the guide i did follow: 
https://hackmd.io/@lnu-iot/r1yEtcs55

The first thing I did was create an account on the website Adafruit IO, then I created a group for my IOT device named Raspberry Pi Pico W. After that I created two different feeds in that group I just made, one for the thermometer and one for the lights. When that was done I made a dashboard, and in that dashboard I did create two new blocks, one button that I connected to the lights feed and one gauge that I connected to the thermometer feed. All of this is showed below:
![](https://hackmd.io/_uploads/SkKZ1c3_3.png)
![](https://hackmd.io/_uploads/ryRWyq2O3.png)
![](https://hackmd.io/_uploads/Hk7zk92Oh.png)

The next thing I did was to download the mqtt.py file (from the link provided above) that i added to my pico folder in VSCode, then I checked the main.py file (from the link provided above) for what I would need to import and apply to my code to make it work with the MQTT file. So I added all of that and structured my code so that it would work with MQTT. The most important thing i needed to change to connect to the Adafruit IO website was the following:

```
WIFI_SSID = "Rindebrant"
WIFI_PASS = "**********"

AIO_SERVER = "io.adafruit.com"
AIO_PORT = 1883
AIO_USER = "wr222bp"
AIO_KEY = "aio_Zkti82CnqDAJhNHHlqh2YZ0sq6jG"
AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id())
AIO_LIGHTS_FEED = "wr222bp/feeds/lights"
AIO_TEMP_FEED = "wr222bp/feeds/temp"
```
So as we see in the code above, it's also in this part of the code where we link the different feeds to the code that is executed in the pico. After all of that was done, my pico was connected to the Adafruit IO website.

The temperature is updated to the website depending on this code:
```
# How often information is updated to the website.
publish_time_interval = 60000    # ms
last_sent_ticks = 0  # ms

# Sends the infromation about the temperature to the website every x ms.
def send_temp():
    global publish_time_interval
    global last_sent_ticks
    last_publish = time.ticks_ms()

    if ((last_publish - last_sent_ticks) < publish_time_interval):
        return; 

    temp = get_temp()
    print("Publishing: {0} Celsius to {1}      ".format(temp, AIO_TEMP_FEED), end='')
    try:
        client.publish(topic=AIO_TEMP_FEED, msg=str(temp))
        print("[DONE]")
    except Exception as e:
        print("[FAILED]")
    finally:
        last_sent_ticks = time.ticks_ms()
```
So right now it's set to update the temperature to the website every minute.
I decided to use WiFi for the wireless connection since the WiFi is really close to the greenhouse.
The transport protocol that was used was MQTT as mentioned above.

Presenting the data
---
![](https://hackmd.io/_uploads/HyTZt-5u2.png)
Clean and simple Dashboard. It lets the user view the current temperature in the greenhouse and has the function to turn off or on the lights depending if the user wants them on or not.

The two blocks that we see here are connected to two different feeds that the code in the pico is connected to. And because of that, it will send and receive information from the pico. The light switch will send information to the pico that will trigger the lights to go on or off. And the temperature will update depending on the information it gets from the DHT11 temperature that is connected to the pico.

The data will be saved 30 times every minute to the database if you have the free plan, and 60 times every minute to the database if you have the paid plan.
The data will be stored for 30 days in the database before it gets removed if you have the free plan, and 60 days if you have the paid plan.

Finalizing the design
---
I think the project was really fun to do, and I learned a lot by doing this. Was expecting it to take longer than it did take to make all of this, but it was probably because I have worked with raspberry pi pico before in assembly and taking a course in python as well. I don't think I would have changed anything, it was really fun and learning to start with an easy IOT project, as my first time working with IOT. And since my father needed this type of thermometer for his greenhouse, I'm happy that I could kill 2 birds with one stone. But next time I'm doing an IOT project I will try to make something more complicated than this. Down below we can see the final result:
![](https://hackmd.io/_uploads/ryiX7K2un.jpg)
![](https://hackmd.io/_uploads/H1bVmK2Oh.jpg)
