owned this note
owned this note
Published
Linked with GitHub
Hi! Welcome to this tutorial. My name is Emil Larsson and I have chosen to name my project "PicoClima". My LNU student username is **el225ju**.
## Overview
As a person who enjoys having indoor plants but forget to take care of them, I often struggle to provide consistent and optimal care. Overwatering, underwatering, and incorrect temperature exposure frequently occur due to forgetfulness or lack of time.
The challenge is to create an automated, user-friendly system that maintains optimal plant health by monitoring soil moisture and indoor temperature and humidity. This tool would not only benefit my personal plant care routine but also assist other plant owners facing similar challenges. There should also be a system for sending notifications via SMS should the soil moisture drop.
#### Time to complete
This project will take approximately 3 hours to get up and running, provided that you own the necessary hardware and have some experience within IT, more specifically coding in Python and setting up databases.
## Objective
The primary objective of this project is to develop an IoT device that allows for consistent monitoring of indoor and plant soil conditions.
I aim to use this device to gather data on humidity, temperature (both indoor and in the soil), which will provide timely and accurate information about the plant's needs. By automating the process, the device serves the purpose of reducing manual checks and potential human error.
The collected data will first be sent to an MQTT broker. The data will then be transferred and stored in a local MySQL database and presented in a dashboard using Node-RED. There will also be a service that sends an SMS at a given interval if the soil moisture drops below a specified threshold value.
Finally, there will be an automated service that sends SMS reminders on a regular basis if the plant needs my attention.
#### Why I chose the project:
This project combines my interest for indoor plants and their well-being with my interest in IoT technology. Due to my busy lifestyle, I have often forgotten to water my plants or adjust their location to cater to their temperature needs. This device will serve as a reminder and guide, making plant care more manageable and effective, and ensuring a healthier indoor environment.
#### What insights it will give:
Through this project, I expect to gain actionable insights into the specific care routines of my plant. Understanding the optimal soil moisture levels and temperature conditions will allow me to provide targeted care. Additionally, by monitoring the indoor humidity and temperature, I can also make adjustments to ensure a more comfortable living environment for both myself and my plants. This information could also be useful for other indoor plant enthusiasts, potentially providing a benchmark for plant care in different indoor environments.
#### Flowchart
Below is the flowchart for the project. The arrows represent the data that is being sent, starting from the sensors connected to the Raspberry Pi Pico W.
Note that the arrow from the Node-RED container to the Twilio SMS service is dotted, meaning that the data will only be sent if certain conditions are met.

---
## Material
1.

The Raspberry Pi Pico W. It is a simple yet powerful microcontroller that has a lot of connections for different sensors. It also has WiFi connectivity. This model has pres-soldered header pins.
---
2.

The DHT11 temperature and humidity sensor. It has a humidity accuracy of ±5%RH and a temperature accuracy of ±2℃.
This is a cheap but high quality sensor.
---
3.

The Adafruit STEMMA soil sensor. It is capacitive, meaning that the sensor is oscillating the charge it is storing and measuring the effect soil moisture has on that oscillation. The moisture values that are returned from the sensor is from 200 (very dry) to 2000 (very wet).
I chose this sensor because it is better and more reliable than the cheaper, non-capacitive sensors on the market.
---
4.

An 840 point breadboard. The breadboard has a grid of holes into which electronic components like resistors, capacitors, and integrated circuits can be inserted.
This is a great tool for experimenting with different sensors and connections without having to solder anything.
---
5.

A USB to micro USB cable. This cable is used for connecting the Raspberry Pi Pico W to a computer for powering the microcontroller, but also for uploading files, flashing the firmware and to be able to program the microcontroller. It can also be connected to a power source such as a powerbank.
---
6.

A JST-PH cable, needed for connecting the Adafruit STEMMA soil sensor to the Raspberry Pi Pico W over the I2C bus.
---
7.

Lab cables that I used to connect the microcontroller to the different points of the breadboard, and also connecting the breadboard to the sensors.
---
| Image | Name | Supplier | Link | Price |
|:-----:|:--------------------------------------:|:-----------:|:-------------------------------------------------------------------------------------------:| ------- |
| 1 | Raspberry Pi Pico WH | electro:kit | [Click](https://www.electrokit.com/produkt/raspberry-pi-pico-wh/) | 98 SEK |
| 2 | DHT11 humidity and temperature sensor | electro:kit | [Click](https://www.electrokit.com/produkt/digital-temperatur-och-fuktsensor-dht11/ ) | 49 SEK |
| 3 | Adafruit STEMMA capacitive soil sensor | electro:kit | [Click](https://www.electrokit.com/produkt/jordfuktighetssensor-kapacitiv-i2c) | 115 SEK |
| 4 | Breadboard, 840 pins | electro:kit | [Click](https://www.electrokit.com/produkt/kopplingsdack-840-anslutningar/) | 69 SEK |
| 5 | USB to micro USB 1.8M | electro:kit | [Click](https://www.electrokit.com/produkt/usb-kabel-a-hane-micro-b-5p-hane-1-8m/) | 39 SEK |
| 6 | JST-PH 2.0MM 4-pin female cable 200mm | electro:kit | [Click](https://www.electrokit.com/produkt/kabel-med-jst-ph-4-pol-hona-0-64mm-stift-200mm/) | 24 SEK |
| 7 | Lab cable 40-pin 30cm male/male | electro:kit | [Click](https://www.electrokit.com/produkt/labbsladd-40-pin-30cm-hane-hane/) | 49 SEK |
| | **Total price:** | | | 443 SEK |
---
## Computer setup
#### Updating firmware
The first thing you need to do is to update the firmware of your Raspberry Pi Pico W. Go to https://projects.raspberrypi.org/en/projects/get-started-pico-w/1 and follow the instructions on that webpage.
#### Installing an IDE
I suggest you install **Visual Studio Code** (also called VS Code). You can, however, use another IDE such as **Thonny**. I tried both in this project and the two of them work fine. Thonny seems a bit more stable than using PyMakr and Visual Studio Code, however, neither the IDE functionality such as code completion nor the visual appearance is as good as VS Code.
To install Visual Studio Code, go to: https://code.visualstudio.com/ and follow the download instructions.
To install Thonny, go to https://thonny.org/ and download the version that is compatible with your computer.
#### Installing PyMakr
If you choose to install Visual Studio Code, I highly recommend you to install the **PyMakr** plugin. PyMakr makes it easy to setup a project for writing and running MicroPython code on your Raspberry Pi Pico W. To install PyMakr, click the "Extensions" button in Visual Studio Code. Then search for "PyMakr" and click the "Install" button for the first search result as shown in the screenshot below.
---

---
Once you have installed PyMakr, the PyMakr extension button will be available in the lower left side of Visual Studio Code. If you click on it, you will have a couple of useful links to get you started with PyMakr and setting up your project.

---
#### Signing up for an Adafruit IO account and creating feeds
To be able to send data read by the sensors, you will need an MQTT broker. For this project, I chose the Adafruit IO. The service is very easy to setup and use and is completely free, with some limitations.
Go to https://io.adafruit.com/ and register your account.
Once you have registered for an account and you have logged in, click "IO" on the top menu bar. Then click "Feeds" which will bring you the the Feeds page. Here, you can click "New group" to create a group for your feeds.

Once you have created the group, create 4 feeds called
* Humidity
* Soil humidity
* Soil temperature
* Temperature
When you are done, your "Feeds" page should look similar to mine:

*Please note that my different feeds have recorded values. Your feeds will not have any values until you start sending data to your feeds.*
---
#### Node-RED
Node-RED is an open-source programming tool developed by IBM for wiring together hardware devices, APIs, and online services. It lets you create flows by dragging and dropping "nodes" which can be used to read data, insert data into a database, create visual representations of your data and much more. The data can also be presented and interacted with using a web interface.
I chose Node-RED for this project because it is free, easy to use, and highly customizable. It can also be scaled so that new sensors, feeds and nodes can easily be added to the flows. Furthermore, there are a lot of modules that can be downloaded that lets you interact with many different services and protocols.
To install Node-RED, please follow the instructions on this website: https://nodered.org/docs/getting-started/local
As stated on the website, you will need a compatible version of **Node.js**, which you can read more about on this page: https://nodered.org/docs/faq/node-versions
---
#### MySQL
To store the data, you will need a database management system. For this project I chose MySQL. It is one of the most commonly used RDBMS (Relational database management systems) today. It is completely free, highly scalable and is also compatible with Node-RED. For this project, I chose to store the data on my local computer.
The MySQL Installer, which includes MySQL Server and MySQL Workbench can be downloaded and installed from https://dev.mysql.com/downloads/installer/
Once you have downloaded and installed MySQL, download the file db_script.sql from my GitHub repository: https://github.com/emillarsson1/PicoClima/tree/main/database
You will then need to create a new schema. In the MySQL Workbench Navigator pane, select **Schemas**. Then, right click in the pane and choose **Create Schema...**

---
Enter "temp_and_humidity" as the Name:

Click "Apply".

A window will appear that asks you to review the SQL Script that will be applied. Click "Apply" in this window also.

---
After that, you should be able to see your newly created schema in the Navigator pane:
Double click the schema to select it. You will notice that the schema name will be highlighted in bold.

---
You can now start the import process of the database tables by clicking **Server** and then **Data Import** in the MySQL Workbench application.

You then choose **Import from Self-Contained File** and click the button with the three dots to choose the db_script.sql that you downloaded.
Also select the temp_and_humidity schema you created as the Default Target Schema:

After you have selected the file and the schema, click the **Start Import** button in the lower right corner.

---
You will get a message saying that the import has completed:

You can verify that the tables were added to the schema by clicking the refresh button in the upper right corner of the Navigator pane:

---
#### Signing up for a Twilio account
I used Twilio for sending SMS notifications. Go to https://www.twilio.com/ and register for an account. You will then need to enter your phone number and verify it. After that, you can use the service for free until your sign up credits run out.
---
## Putting everything together
#### Connecting the sensors
In the below image you can see how I wired the Microcontroller (in the lower left), the DHT11 sensor (the blue sensor on the breadboard), and the Adafruit STEMMA soil sensor together using the breadboard.
Please note that the soil sensor needs the JST-PH cable that is listed in the [Material](#Material) section to work. This cable consists of 4 cables pinned together.

---
#### Downloading the MicroPython code and connecting the microcontroller
After you have connected the sensors, and double checked that everything is correctly wired, it is time to run the code to verify that everything works. Plug the micro USB end of your USB to micro USB cable gently into the microcontroller, and the USB end to your computer. Run PyMakr in Visual Studio or Thonny to upload the below Python files to your microcontroller.
All the code I have used in this project, including the database script and Node-RED JSON files, is available in the following GitHub repository: https://github.com/emillarsson1/PicoClima
---
#### Code snippets
sensors.py
This file contains the functions that retrieves the values from the two sensors. Please make sure to change the Pin values if needed, so that they match your connected sensors. For the DHT11 I have used pin 27 and for the soil sensor, pin 17 for SCL and pin 16 for SDA.
```
import dht
import seesaw
import stemma_soil_sensor
from machine import Pin, I2C
'''
Function that retrieves indoor humidity and temperature
from the DHT11 sensor
'''
def get_temperature_and_humidity():
sensor = dht.DHT11(Pin(27))
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
return(temp,hum)
'''
Function that retrieves soil moisture and temperature
from the Adafruit STEMMA soil sensor
'''
def get_soil_temperature_and_humidity():
i2c = I2C(0, scl=Pin(17), sda=Pin(16))
SENSOR_ADDR = 0x36
seesaw2 = stemma_soil_sensor.StemmaSoilSensor(i2c)
moisture = seesaw2.get_moisture()
temperature = seesaw2.get_temp()
return(temperature,moisture)
```
---
MQTT.py
The Python file that contains the MQTT broker details, including credentials, is this one. Ensure that you update this information, such as the credentials, feed names, and so on, to align with your specific preferences.
```
import time
import ubinascii
import machine
from umqtt.simple import MQTTClient
import sensors
# Insert MQTT information below
CLIENT_ID = ubinascii.hexlify(machine.unique_id())
MQTT_BROKER ="io.adafruit.com"
PORT = 1883
ADAFRUIT_USERNAME = "USERNAME HERE"
ADAFRUIT_PASSWORD ="PASSWORD HERE"
TEMPERATURE_TOPIC = b"TEMPERATURE TOPIC HERE"
HUMIDITY_TOPIC = b"HUMIDITY TOPIC HERE"
SOIL_TEMPERATURE_TOPIC=b"SOIL TEMPERATURE TOPIC HERE"
SOIL_HUMIDITY_TOPIC=b"SOIL HUMIDITY TOPIC HERE"
# Set the publish interval (in seconds)
publish_interval=600
last_publish=time.time()
# Function that will reset the hardware if needed
def reset():
print("Resetting...")
time.sleep(5)
machine.reset()
# Connect to the MQTT broker
def start_mqtt():
print(f"Starting connection with MQTT Broker :: {MQTT_BROKER}")
mqttClient = MQTTClient(CLIENT_ID, MQTT_BROKER, PORT, ADAFRUIT_USERNAME, ADAFRUIT_PASSWORD, keepalive=700)
try:
mqttClient.connect()
print(f"Connected to MQTT Broker :: {MQTT_BROKER}")
# Reset the Raspberry Pi Pico W if the connection failed
except OSError:
print("Failed to connect to MQTT Broker, resetting...")
reset()
# Loop for publishing to the MQTT broker starts here
while True:
global last_publish
# Check if it is time to publish according to the set interval
if(time.time() - last_publish) >= publish_interval:
# Get the indoor temperature and humidity and save the two values in a list
temp_and_humidity = sensors.get_temperature_and_humidity()
# Get the soil temperature and humidity and save the two values in a list
temp_and_moisture = sensors.get_soil_temperature_and_humidity()
# Save the temp and humidity in two different variables
temp = temp_and_humidity[0]
humidity = temp_and_humidity[1]
# Save the soil temp and humidity in two different variables
soil_temp=temp_and_moisture[0]
soil_moisture=temp_and_moisture[1]
# Publish to the four different feeds
mqttClient.publish(TEMPERATURE_TOPIC, str(temp))
mqttClient.publish(HUMIDITY_TOPIC, str(humidity))
mqttClient.publish(SOIL_TEMPERATURE_TOPIC, str(soil_temp))
mqttClient.publish(SOIL_HUMIDITY_TOPIC, str(soil_moisture))
# Set the last publish time to the current time
last_publish=time.time()
# Get current time and change it to a readable format
local_time = time.localtime()
date_time_str = "{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(
local_time[0], # year
local_time[1], # month
local_time[2], # day
local_time[3], # hour
local_time[4], # minute
local_time[5] # second
)
# Print out confirmation that the data was sent
print("The data was sent at " + str(date_time_str))
# Wait 10 seconds
time.sleep(10)
```
---
boot.py
This is run every time you reboot your Raspberry Pi Pico W. The code connects to your Wifi, verifies your Internet connection and prints out the results. Make sure to change the YOUR_SSID_HERE and YOUR_WIFI_PASSWORD_HERE values to match the settings of your WiFi.
**Kindly be aware that the Raspberry Pi Pico W is designed to support only the 2.4GHz WiFi frequency band.**
```
# Function that connects to WiFi
def do_connect():
import network
from time import sleep
import machine
wlan = network.WLAN(network.STA_IF) # Put modem on Station mode
if not wlan.isconnected(): # Check if already connected
print('connecting to network...')
wlan.active(True) # Activate network interface
# set power mode to get WiFi power-saving off (if needed)
wlan.config(pm = 0xa11140)
wlan.connect('YOUR_SSID_HERE', 'YOUR_WIFI_PASSWORD_HERE') # Your WiFi Credential
print('Waiting for connection...', end='')
# Check if it is connected otherwise wait
while not wlan.isconnected() and wlan.status() >= 0:
print('.', end='')
print('Status:', wlan.status())
sleep(1)
# Print the IP assigned by router
ip = wlan.ifconfig()[0]
print('\nConnected on {}'.format(ip))
return ip
# Function that verifies Internet connectivity
def http_get(url = 'http://detectportal.firefox.com/'):
import socket # Used by HTML get request
import time # Used for delay
_, _, host, path = url.split('/', 3) # Separate URL request
addr = socket.getaddrinfo(host, 80)[0][-1] # Get IP address of host
s = socket.socket() # Initialise the socket
s.connect(addr) # Try connecting to host address
# Send HTTP request to the host with specific path
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
time.sleep(1) # Sleep for a second
rec_bytes = s.recv(10000) # Receve response
print(rec_bytes) # Print the response
s.close() # Close connection
# WiFi Connection
try:
ip = do_connect()
except KeyboardInterrupt:
print("Keyboard interrupt")
# HTTP request
try:
http_get()
except Exception as err:
print("Exception", err)
```
---
main.py
This is the main file that runs after boot.py. It calls the start_mqtt() function.
```
import MQTT
MQTT.start_mqtt()
```
---
The rest of the files that contains the code for the seesaw library MicroPython port can be found on the GitHub repository for this project, which is https://github.com/emillarsson1/PicoClima/tree/main/code
You should not have to make any changes to those files in order to run the application.
*Please note that I am not the author of the seesaw port. The author and license information can be found in the seesaw.py and stemma_soil_sensor.py*
---
## Transmitting data and connectivity
In this project I have chosen to use WiFi connectivity. Although this technology can be quite energy consuming relative to other options, since this is an indoor project where there is access to wall outlets and a wireless router, I decided WiFi to be the most pragmatic choice.
I chose Adafruit IO as the MQTT broker. It has an easy to use interface and supports both MQTT and HTTP which gives great flexibility. It is also free under some restrictions.
The script will send the data to the MQTT broker every 10 minutes. You can change this setting by changing the value of the "publish_interval" variable in the MQTT.py file.

*Example screenshot of what the output will be in the Thonny IDE (should look similar in Visual Studio Code) when a connection is successfully made to the Adafruit IO MQTT broker.*
---
#### Running Node-RED
When you have successfully installed and started Node-RED, you can import the configuration files from the GitHub repository I mentioned earlier (https://github.com/emillarsson1/PicoClima)
For information on how to import flows, go to this website: https://nodered.org/docs/user-guide/editor/workspace/import-export
After a successful import, the flows should like below.


You need to configure the 4 purple nodes so that the information matches your Adafruit IO MQTT broker password and feed names. Double click each of the nodes and enter your credentials.
---

*A text message alerting me that the soil in my plant is dry and that the plant needs to be watered.*
---
## Presenting the data
Below is a screenshot of what the dashboard presenting the live data looks like. The different gauges display the indoor temperature and humidity (which is coming from the DHT11 sensor), and also the plant soil moisture level and the temperature (data coming from the Adafruit STEMMA soil sensor).
In the bottom right corner there is a summary that displays different messages depending on the measured values.

Below is the historic data for the humidity and temperature in the room. This data is pulled from the MySQL database and shows the data for 3 weeks back.

---
## Finalizing the design

#### Current state and future improvements
This photo is an example of how what the finished product might look like. Given that this is not a finalized setting, there's considerable scope for enhancements. One such possibility is to forgo the use of a breadboard by soldering the sensors directly to the Raspberry Pi Pico W. Furthermore, housing the microcontroller in a protective enclosure could shield it from any water spill when watering the plant.
All in all, I am happy with the results of my project. I think I made good choices regarding what software and services to use. I could have implemented a cloud solution where I put the database and the Node-RED server on a virtual machine hosted in Azure or AWS, but as I wanted a cheap solution, this was not an option.
---