owned this note
owned this note
Published
Linked with GitHub
# Introduction
Nelly's flower/vegetables monitor 🌸🥕🥒🫛
Nelly Olofsson (no222hh)
**View code here:** https://github.com/nellyolofsson/SummerProject2024
**View project video here:** https://youtu.be/Zt8Pav2uU20
I haven't counted the exact number of hours spent on the project, but it involved some challenging parts and required a fair amount of research. I estimate it took about 10-12 hours to complete.
# Objective
The idea for this project came from my love for gardening. I have a large garden with many flowers and vegetables, and I often struggle to keep track of each plant's needs, such as water, sunlight, and nutrients.
This inspired me to create a plant monitor that not only tracks these factors but the user (myself) can access the data through a user-friendly interface. If a plant needs more sunlight or water, the owner will be alerted via email. Additionally, an email will be sent daily summarizing the monitor's measurements for the day.
# Material
#### Additional Components
In addition to the components listed below, you will also need a USB cable and a power bank to run the system. These items were not included in the material list as I already had them at home.
|Images| Name | Price | Supplier |
|------- | -------- | -------- | -------- |
|  |Raspberry Pi Pico WH | 109 sek | [Electrokit](https://www.electrokit.com/raspberry-pi-pico-wh) |
| |Digital temperatur- och fuktsensor DHT11 | 49 sek | [Electrokit](https://www.electrokit.com/digital-temperatur-och-fuktsensor-dht11) |
| |Jordfuktighetssensor kapacitiv I2C |115 sek |[Electrokit](https://www.electrokit.com/jordfuktighetssensor-kapacitiv-i2c) |
|  | Ljussensor |39 sek | [Electrokit](https://www.electrokit.com/ljussensor)|
| |Kopplingsdäck 840 anslutningar |69 sek | [Electrokit](https://www.electrokit.com/kopplingsdack-840-anslutningar) |
| |Labbsladd 40-pin 30cm hane/hane | 49 sek | [Electrokit](https://www.electrokit.com/labbsladd-40-pin-30cm-hane/hane) |
| | Labbsladd 20-pin 15cm hona/hane |29 sek |[Electrokit](https://www.electrokit.com/labbsladd-20-pin-15cm-hona/hane) |
| |Kabel med JST-PH 2.0mm 4-pol hona / 0.64mm hylsor 200mm |24 sek | [Electrokit](https://www.electrokit.com/kabel-med-jst-ph-4-pol-hona-/-0.64mm-hylsor-200mm)|
| |Rörelsedetektor PIR mini SR602 | 59 sek| [Electrokit](https://www.electrokit.com/rorelsedetektor-pir-mini-sr602)|
| | | Total 542 sek| |
# Computer setup
The project was developed on a computer running Windows 11, computer setup may differ on different operating systems.
1. Install Preferred IDE:
- I used [Visual Studio Code](https://code.visualstudio.com/) (VS Code) for this project.
- You can also use [Thonny](https://projects.raspberrypi.org/en/projects/getting-started-with-the-pico/2), which is a simple Python IDE.
2. Install Node.js (only for VS Code):
- Download and install [Node.js](https://nodejs.org/en)
3. Install Extensions in VS Code:
- Open VS Code.
- Go to the Extensions view by clicking on the Extensions icon in the Activity Bar on the side of the window.
- Search for "Pymakr" or "MicroPico" and install the extension.
4. Download the latest firmware for your Raspberry Pi Pico WH from [firmware](https://micropython.org/download/RPI_PICO_W/).
- Follow this guide if needed: [Firmware Guide](https://hackmd.io/@lnu-iot/rkFw7gao_).
5. Flashing the Firmware
- Connect your Raspberry Pi Pico to your computer while holding the BOOTSEL button to enter USB mass storage mode.
- Drag and drop the downloaded firmware (.uf2 file) onto the Pico's USB drive. The Pico will reboot automatically into MicroPython.
6. Getting Started with Your First Project
- Create a new folder for your project in VS code.
- Click on Use this folder to select it as your project directory.
<img src="https://hackmd.io/_uploads/BkTY6ezU0.png" alt="Create Folder" width="300"/>
Ensure your Pico or any other compatible device is connected to your computer and then click on the connect device.
<img src="https://hackmd.io/_uploads/B17IRxM8A.png" alt="connect" width="300"/>
You can also press the Start Development Mode button. This ensures that any changes to your files are automatically saved, deleted files are removed, and the device is restarted accordingly.
<img src="https://hackmd.io/_uploads/r1fDAlGUR.png" alt="connect" width="300"/>
7. Version Control with GitHub
- Create an account on GitHub if you don't have one.
- Create a new repository for your project.
- Clone the repository to your local machine.
After cloning, you can start writing your code. Use the following Git commands to save your changes:
**git add .** - This command stages all the files or changes you have made.
**git commit -m "your message"** - This command commits your changes with a descriptive message.
**git push** - This command pushes your commits to your repository on GitHub.
By following these steps, all your changes will be saved in GitHub. This guide ensures that a beginner can set up the development environment, flash the firmware, and start coding with a Raspberry Pi Pico.
### Circuit diagram

As you can see, my Motion Detector PIR Mini SR602 is not included in the circuit diagram because I'm currently not using it. However, if you decide to integrate it, it adds an additional layer of functionality to the project by allowing you to detect motion and trigger actions based on movement. Below are the wiring instructions and potential use cases for incorporating it into your setup:
**Motion Detector PIR Mini SR602:**
VCC (Red Wire): Connect to the 3.3V pin on the Pico.
GND (Black Wire): Connect to a GND pin on the Pico.
Data (Orange Wire): Connect to GPIO 26 on the Pico.
My initial idea was to track the movements of my cats near the cucumber plant 🐈 and send an email whenever motion was detected. However, I found it somewhat overwhelming to receive numerous emails, so I temporarily commented out that code.
**Wiring Instructions:**
In this project, we are connecting a DHT11 temperature/humidity sensor, a photoresistor (light sensor), and a capacitive soil moisture sensor to a Raspberry Pi Pico. Below are detailed wiring instructions, including the necessary connections.
**DHT11 sensor:**
VCC (Red Wire): Connect to the 3.3V pin on the Pico.
GND (Black Wire): Connect to a GND pin on the Pico.
Data (Yellow Wire): Connet to GIPO 17 on the Pico.
**Photoresistor:**
VCC (Red wire): Connect to the 3.3V pin on the Pico.
GND (Black Wire): Connect to a GND pin on the Pico.
Data (Yellow Wire): Connet to GIPO 27 on the Pico.
**Capacitive Soil Moisture Sensor (I2C):**
VCC (Red wire): Connect to the 3.3V pin on the Pico.
GND (Black Wire): Connect to a GND pin on the Pico.
SDA (White Wire): Connect to GPIO 4 (I2C0 SDA) on the Pico.
SCL (Green Wire): Connect to GPIO 5 (I2C0 SCL) on the Pico.
**What is I2C? A Brief Overview**
I2C (Inter-Integrated Circuit) is a serial communication protocol invented by Philips. It is commonly referred to as I2C or IIC. I2C uses two bidirectional lines:
- SDA (Serial Data): This line carries the data.
- SCL (Serial Clock): This line carries the clock signal.
### Electrical calculations
| Component | W|
| -------- | -------- |
|Capacitive Soil Moisture Sensor (I2C) | ~0.001089 |
|DHT11 |~0.01089|
|Raspberry Pi Pico WH |~1.65|
|Photoresistor | ~0.00165 |
| Total| 1.663629 |
P = effect, watt
U = voltage, volt
I = current, ampere
R = resistance, ohm
Power Calculation Formula: P = $\frac{U^2}{R}$
Power Calculation: P = $U * I$
**Capacitive Soil Moisture Sensor (I2C):**
Voltage and Resistance: $3.3 \cdot 3.3 \over 10000$ = 0.001089 W
**DHT11:**
Voltage and Resistance: $3.3 \cdot 3.3 \over 1000$ = 0,01089 W
**Rasberry Pi Pico WH:**
Voltage and Current: $3.3*0.5$ = 1.65 W
**Photoresistor:**
Voltage and Current: $3.3 * 0,0005$ = 0,00165 W
A power bank with a capacity of 20,000 mAh is equivalent to a power bank with a capacity of 66 Wh. Here's how it's calculated:
To find out how long the power bank can last, divide the total capacity in Wh by the power consumption of the system in watts (W). If the system uses 1.663629 W continuously, the calculation is $66 Wh/1.663629 W$ = 39.67 hours.
The Raspberry Pi Pico WH sends data every 10 minutes, we need to consider the power consumption during the active period (when it sends data) and the deep sleep period in between. Therefore, the system can run much longer than 40 hours. Here is a quick calculation:
**Active Period Duration: 30 seconds (0.00833 hours)**
1.663629W * 0.00833 hours = 0.0138580296Wh
**Deep Sleep Period Duration: 570 seconds (9.5 minutes or 0.1583 hours)**
0.00000429W * 0.1583 hours = 0.000000679Wh
**Total Energy Consumed in One Cycle (10 minutes):**
0.0138580296Wh + 0.000000679Wh = 0.0138587086Wh
**Since each cycle is 10 minutes (or 1/6 of an hour):**
0.0138587086Wh * 6 = 0.0831522516W
**Using the battery capacity (66 Wh):**
66 Wh / 0.0831522516W = 793,424 hours with is ~33 days.
# Platform
I have chosen a self-hosted approach to manage my data collection and visualization infrastructure, utilizing InfluxDB for data storage, Grafana for data visualization, and Adafruit IO as an MQTT broker for seamless data collection from IoT devices. Telegraf serves as the middleware that subscribes to MQTT topics on Adafruit IO, facilitating the transfer of sensor data to InfluxDB for storage and analysis through Grafana.
I have created a flowchart illustrating how the data is transferred.

My platform is currently based on a local installation where I self-host my data collection and visualization infrastructure using InfluxDB and Grafana on my own server. To enable remote access, I utilize ngrok, which provides a public URL to access Grafana securely from anywhere.
I followed this guide to set up the [tig-stack](https://github.com/iot-lnu/tig-stack). Additionally, you need to have [docker desktop](https://www.docker.com/products/docker-desktop/) downloaded and installed.
If you don't want to use Adafruit, you can also try out [Mosquitto](https://hackmd.io/@lnu-iot/BkwDAimvn) as your MQTT broker. I wanted to try it but haven't had the time to test it out yet. Or you can use Adafruit dashboards to create simple visualizations, but the TIG stack offers more advanced features.
### Why I Chose This Platform
I chose to implement this platform for several reasons, based on both curiosity and the specific benefits it offers. I had previous experience using Adafruit for data collection and visualization, and I wanted to try something new and potentially more powerful. The TIG stack (Telegraf, InfluxDB, and Grafana) provided an opportunity to explore advanced features and capabilities that Adafruit does not offer. The setup process for the TIG stack was straightforward and well-documented, making it easy to follow and implement. This was important as it allowed me to quickly get the platform up and running without encountering significant obstacles.
Grafana, as part of the TIG stack, offers robust and advanced visualization options. This enables me to create more detailed and interactive dashboards for analyzing the data collected from my IoT device.
[Ngrok](https://ngrok.com/docs/guides/getting-started/) was an easy way to access my Grafana dashboard from anywhere. However, it only works as long as I have the HTTP tunnel open, and typically, an ngrok session on the free plan lasts up to 8 hours. After this period, the tunnel will be closed, and you'll need to restart it to get a new public URL. This works fine for me for now, but if you want to keep the tunnel open all the time, you would need to sign up for their paid plans, which allow you to keep the tunnel open indefinitely without a time limit.
# The code
The [main.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/main.py) script is designed to collect sensor data from various environmental sensors and transmit this data to an MQTT broker. Additionally, it includes functionalities for handling WiFi connectivity, reading sensors, formatting data into JSON, and sending MQTT messages. For additional code details, please refer to the GitHub repository.
**Defining sensors**
```python=
# Defining sensors
i2c = machine.I2C(0, sda=machine.Pin(4), scl=machine.Pin(5), freq=400000)
# Light sensor
light_sensor = LightSensor(27)
# DHT temp and humidity
temp_humidity_sensor = TempHumiditySensor(17)
# Movement sensor
movement_sensor = MovementSensor(26)
# LED Lamp
led = Pin("LED", Pin.OUT)
# Soil sensor
moisture_sensor = StemmaSoilSensor(i2c)
```
**Sensor Reading and Data Transmission**
```python=
def read_sensors():
try:
temp_humidity_sensor.measure()
temperature = temp_humidity_sensor.temperature()
humidity = temp_humidity_sensor.humidity()
light_value = light_sensor.read_value()
darkness = round(light_value / 65535 * 1000, 2)
raw_moisture = moisture_sensor.get_moisture()
moisture_percentage = round((raw_moisture - MIN_MOISTURE_VALUE) / (MAX_MOISTURE_VALUE - MIN_MOISTURE_VALUE) * 100, 2)
return {
"temperature": temperature,
"humidity": humidity,
"light": darkness,
"moisture": moisture_percentage
}
except Exception as e:
print(f"Error reading sensors: {e}")
return None
def send_sensor_data(sensor_data):
temp_json = build_json("temperature", sensor_data["temperature"])
humidity_json = build_json("humidity", sensor_data["humidity"])
light_json = build_json("light", sensor_data["light"])
soil_json = build_json("soil", sensor_data["moisture"])
if temp_json:
send_topic(temp_json, secrets["MQTT_TEMPERATURE_FEED"])
if humidity_json:
send_topic(humidity_json, secrets["MQTT_HUMIDITY_FEED"])
if light_json:
send_topic(light_json, secrets["MQTT_LIGHT_FEED"])
if soil_json:
send_topic(soil_json, secrets["MQTT_SOIL_FEED"])
```
**Sending Emails with Micropython using Umail**
I implemented email sending functionality in my project using the [Umail library](https://github.com/shawwwn/uMail/blob/master/umail.py). This library enables sending emails directly from devices running Micropython, such as my Raspberry Pi Pico. Initially, I followed this [guide](https://randomnerdtutorials.com/raspberry-pi-pico-w-send-email-micropython/) to set up the email functionality.
**Key Points to Note:**
Library Usage: Umail simplifies the process of sending emails but requires adjustments when using Micropython due to the absence of the ussl library, necessitating the use of ssl instead.
Configuration: Before using Umail, it's essential to generate an app-specific password for your email account, as outlined in the guide linked above.

[SendEmail.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/lib/SendEmail.py) is utilizes the umail libary to send formatted HTML emails witch sensor data.
#### Email code:
```python=
def email(dayvalues, nightvalues, eveningvalues):
daytemp = dayvalues["temp"]
dayhumid = dayvalues["humidity"]
daygroundmoist = dayvalues["groundmoist"]
daylight = dayvalues["light"]
daytime = dayvalues["time"]
eveningtemp = eveningvalues["temp"]
eveninghumid = eveningvalues["humidity"]
eveninggroundmoist = eveningvalues["groundmoist"]
eveninglight = eveningvalues["light"]
eveningtime = eveningvalues["time"]
nighttemp = nightvalues["temp"]
nighthumid = nightvalues["humidity"]
nightgroundmoist = nightvalues["groundmoist"]
nightlight = nightvalues["light"]
nighttime = nightvalues["time"]
email_body = f"""
<html>
<head></head>
<body>
<h2>Dagvärden ({daytime}):</h2>
<p>Temperatur: {daytemp}°C</p>
<p>Fuktighet: {dayhumid}%</p>
<p>Jordfuktighet: {daygroundmoist}%</p>
<p>Ljusnivå: {daylight}lm</p>
<h2>Kvällsvärden ({eveningtime}):</h2>
<p>Temperatur: {eveningtemp}°C</p>
<p>Fuktighet: {eveninghumid}%</p>
<p>Jordfuktighet: {eveninggroundmoist}%</p>
<p>Ljusnivå: {eveninglight}lm</p>
<h2>Nattvärden ({nighttime}):</h2>
<p>Temperatur: {nighttemp}°C</p>
<p>Fuktighet: {nighthumid}%</p>
<p>Jordfuktighet: {nightgroundmoist}%</p>
<p>Ljusnivå: {nightlight}lm</p>
</body>
</html>
"""
return email_body
```
```python=
def send_email(subject, dayvalues, nightvalues, eveningvalues):
smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True)
smtp.login(sender_email, sender_app_password)
smtp.to(subject)
smtp.write(f"Subject: {email_subject}\n")
smtp.write("Content-Type: text/html\n")
smtp.write("\n")
smtp.write(email(dayvalues, nightvalues, eveningvalues))
smtp.send()
smtp.quit()
```
In [main.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/main.py), an email containing sensor data saved at 03:10, 13:10, and 17:10 each day is sent automatically. The script manages sensor readings, formats data, and triggers email notifications using the [umail.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/umail.py) script for email functionality.

In [boot.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/boot.py) I handle the WiFi connection. 
Don't forget to create a secret file named mysecrets.py. An example of how it should look is provided below:
```python=
secrets = {
# WIFI
'WIFI_SSID': "ssid",
'WIFI_PASSWORD': "password",
# MQTT Configuration
'MQTT_SERVER': "io.adafruit.com",
'MQTT_PORT': 1883,
'MQTT_USER': "username",
'MQTT_KEY': "password",
'MQTT_TEMPERATURE_FEED': b"username/feeds/temperature",
'MQTT_HUMIDITY_FEED': b"username/feeds/humidity",
'MQTT_LIGHT_FEED': b"username/feeds/light",
'MQTT_SOIL_FEED': b"username/feeds/soil",
# Email
'SENDER_EMAIL': "example@gmail.com",
'GOOGLE_APP_PASS': "password"
}
```
I also have two additional classes that you can explore on my GitHub repository:
[seesaw.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/lib/seesaw.py) : This class contains functionalities related to the Seesaw sensor interface, providing methods for interacting with sensors connected via I2C.
[stemma_soil_sensor.py](https://github.com/nellyolofsson/SummerProject2024/blob/main/lib/stemma_soil_sensor.py): This class encapsulates interactions with the Stemma soil sensor, offering methods to read and interpret soil moisture levels.
# Transmitting the data / connectivity
For this project, I am currently using a WiFi connection. Initially, I considered using LoRa technology, which is known for its long-range wireless communication capabilities and low power consumption. However, LoRaWAN wasn't feasible due to the limited range in my area. It typically operates with networks like [The Things Network](https://www.thethingsnetwork.org/).
At present, WiFi suffices for my needs. I've opted to use a mobile network connection temporarily, but i can also use my home network. Currently, the data is sent every 10 minutes to the MQTT broker Adafruit IO. It is also saved in InfluxDB, and from the Grafana dashboards, I can fetch and display the data.
To subscribe to our readings in Adafruit, I am using Telegraf as mentioned before. This is done in the Telegraf configuration file.
**Example of subscribing to feeds in Adafruit:**
```python=
[[inputs.mqtt_consumer]]
name_override = "adafruit"
servers = ["tcp://io.adafruit.com:1883"]
topics = ["nellyolofsson/feeds/#"]
qos = 0
connection_timeout = "30s"
username= "username"
password= "password"
data_format = "json"
```
Right now, my choices affect the device range and battery consumption significantly. Using WiFi results in higher power usage due to continuous connection maintenance and higher data rates, which can shorten battery life. On the other hand, LoRa offers significantly lower power consumption and longer range, making it a more efficient choice for battery-operated devices in remote areas. However, the current lack of LoRaWAN coverage in my area led me to choose WiFi temporarily, despite its higher power demands.
# Presenting the data
### Dashboard Presentation
The data is saved every 10 minutes in the InfluxDB database. First, you need to connect your database to Grafana by setting up a new data source. This involves configuring the database connection settings, such as the database type, host, database name, username, and password. To do that, you can follow this guide as I mentioned before: [(Setting up Grafana).](https://hackmd.io/@lnu-iot/BkwDAimvn) To fetch and display this data on the Grafana dashboard, an SQL-like query is used to retrieve the relevant information. Alternatively, you can use Flux. Flux is an open-source functional data scripting language designed for querying, analyzing, and acting on data.



### Choice of Database
I chose InfluxDB due to its efficient handling of time-series data, which is ideal for storing sensor readings. It provides high performance for both writing and querying data, making it suitable for real-time analytics and monitoring.
### Automation/Triggers
**Email updates**
The email automation sends an email every day at around 17:00, providing a clear view of the values during the night and day.
**Here are some pictures of how an email update looks:**

**And the Motion Detector that i'm not using but an email did look like this:**

# Finalizing the design
Overall, the project was a success. However, if I were to change something, I would use Mosquitto as the MQTT broker instead of Adafruit IO, as it might provide more flexibility and potentially better performance for handling data transmission. I could also have done the wiring more neatly. Additionally, if I plan to use it outside in the future, I would need to protect all the components in a safe way.
One more thing is that i didn't get the chance to try out LoRa, so I hope that I could try it out in the future.
**View project video here:**
https://youtu.be/Zt8Pav2uU20
**Here is a picture when I have it outside, I only tried it out once:**

**Here you can see that my cucumber plant has grown compared to the video:**
