张荣华
Published © GPL3+

Environmental Trend Tracker with M5StickC PLUS 2

Monitor and forecast environmental trends using temperature, humidity, and pressure sensors powered by M5StickC PLUS 2 and Streamlit. Ideal

IntermediateFull instructions provided24 hours162
Environmental Trend Tracker with M5StickC PLUS 2

Things used in this project

Story

Read more

Schematics

M5StickC PLUS 2 + ENV III Connection

Code

M5StickC PLUS 2 Environmental Monitor - Arduino Code

C/C++
This Arduino sketch reads real-time temperature, humidity, and pressure from the ENV III sensor via I2C and displays them on the M5StickC PLUS 2 screen. It also prints data via serial for real-time logging and prediction.
#include <Wire.h>
#include <M5StickCPlus2.h>
#include <Adafruit_SHT31.h>
#include <DFRobot_QMP6988.h>

// 
Adafruit_SHT31 sht30 = Adafruit_SHT31();
DFRobot_QMP6988 qmp;

void setup() {
  M5.begin();
  Wire.begin();  //  SDA/SCL

  Serial.begin(115200);
  delay(1000);
  Serial.println("Initializing sensors...");

  // 
  if (!sht30.begin(0x44)) {
    Serial.println("Couldn't find SHT30 sensor!");
    while (1);
  }

  // 
  if (!qmp.begin()) {
    Serial.println("Couldn't find QMP6988 sensor!");
    while (1);
  }

  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setTextSize(2);
}

void loop() {
  float temperature = sht30.readTemperature();  // 
  float humidity = sht30.readHumidity();        // 
  float pressure = qmp.readPressure();          //  Pa

  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10, 10);
  if (!isnan(temperature)) {
    M5.Lcd.printf("Temp: %.2f C", temperature);
  } else {
    M5.Lcd.println("Temp error");
  }

  M5.Lcd.setCursor(10, 40);
  if (!isnan(humidity)) {
    M5.Lcd.printf("Humi: %.2f %%", humidity);
  } else {
    M5.Lcd.println("Humi error");
  }

  M5.Lcd.setCursor(10, 70);
  if (!isnan(pressure)) {
    M5.Lcd.printf("Pres: %.2f hPa", pressure / 100.0);  //  hPa
  } else {
    M5.Lcd.println("Pres error");
  }

  //   serial_to_csv.py 
  Serial.printf("T: %.2f, H: %.2f, P: %.2f\n", temperature, humidity, pressure / 100.0);

  delay(2000);
}

Serial to CSV Logger

Python
This Python script continuously reads data from the serial port and writes it to a CSV file. It captures time-stamped environmental readings sent from the M5StickC device.
import serial
import pandas as pd
from datetime import datetime

# 
port = 'COM5'
baudrate = 115200

ser = serial.Serial(port, baudrate, timeout=1)
data = []
print(" Receiving data...")

try:
    while len(data) < 100:  # 100
        line = ser.readline().decode(errors='ignore').strip()
        if "T:" in line and "H:" in line and "P:" in line:
            try:
                parts = line.split(",")
                temp = float(parts[0].split(":")[1])
                humi = float(parts[1].split(":")[1])
                pres = float(parts[2].split(":")[1])
                timestamp = datetime.now().strftime("%H:%M:%S")
                data.append([timestamp, temp, humi, pres])
                print(f"{timestamp} | Temp: {temp}C | Humi: {humi}% | Press: {pres}hPa")
            except:
                continue
finally:
    ser.close()
    df = pd.DataFrame(data, columns=["time", "temperature", "humidity", "pressure"])
    df.to_csv("data.csv", index=False, encoding='utf-8')
    print(" Data saved to data.csv")

Streamlit Dashboard for Weather Monitoring

Python
This Streamlit app visualizes the latest temperature, humidity, and pressure data in real-time and provides a simple forecast based on pressure trends. It loads the CSV data generated by the serial logger script.
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates  #  

st.set_page_config(page_title="Environmental Monitoring Dashboard", layout="centered")
st.title(" M5StickC PLUS 2 Environmental Monitor")

# Load CSV data
df = pd.read_csv("data.csv")
df['time'] = pd.to_datetime(df['time'])  #   time  datetime 

# Show latest data preview
st.subheader(" Latest Data Preview")
st.dataframe(df.tail(10))

# Temperature trend
st.subheader(" Temperature Trend")
fig1, ax1 = plt.subplots(figsize=(6, 3))
ax1.plot(df['time'], df['temperature'], color='orange', label='Temperature (C)')
ax1.set_xlabel("Time")
ax1.set_ylabel("Temperature (C)")
ax1.xaxis.set_major_locator(mdates.AutoDateLocator())  #  
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))  #  
ax1.tick_params(axis='x', rotation=45)
ax1.legend()
st.pyplot(fig1)

# Humidity trend
st.subheader(" Humidity Trend")
fig2, ax2 = plt.subplots(figsize=(6, 3))
ax2.plot(df['time'], df['humidity'], color='blue', label='Humidity (%)')
ax2.set_xlabel("Time")
ax2.set_ylabel("Humidity (%)")
ax2.xaxis.set_major_locator(mdates.AutoDateLocator())
ax2.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
ax2.tick_params(axis='x', rotation=45)
ax2.legend()
st.pyplot(fig2)

# Pressure trend
st.subheader(" Pressure Trend")
fig3, ax3 = plt.subplots(figsize=(6, 3))
ax3.plot(df['time'], df['pressure'], color='green', label='Pressure (hPa)')
ax3.set_xlabel("Time")
ax3.set_ylabel("Pressure (hPa)")
ax3.xaxis.set_major_locator(mdates.AutoDateLocator())
ax3.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
ax3.tick_params(axis='x', rotation=45)
ax3.legend()
st.pyplot(fig3)

# Weather prediction
st.subheader(" Weather Forecast")
if len(df) >= 2:
    # 
    t_now, h_now, p_now = df[['temperature', 'humidity', 'pressure']].iloc[-1]
    t_prev, h_prev, p_prev = df[['temperature', 'humidity', 'pressure']].iloc[-2]

    dt = t_now - t_prev
    dh = h_now - h_prev
    dp = p_now - p_prev

    # 
    st.markdown(f"**Pressure :** `{dp:.2f} hPa`**Humidity :** `{dh:.2f} %`**Temp :** `{dt:.2f} C`")

    # 
    if dp < -1.0 and dh > 1.0 and dt < -0.3:
        forecast = " Likely rain or overcast  pressure dropping, humidity rising"
    elif dp > 1.0 and dh < -1.0 and dt > 0.3:
        forecast = " Clear or improving  pressure rising and drier"
    elif abs(dp) < 0.5 and abs(dh) < 2 and abs(dt) < 0.5:
        forecast = " Stable weather  no major changes"
    else:
        forecast = " Fluctuating  unclear, possibly humid or cloudy"

    st.markdown(f"**Forecast:** {forecast}")
else:
    st.write("Not enough data to predict weather.")


st.markdown("""
---
 This dashboard visualizes real-time environmental data (temperature, humidity, and pressure) collected by the M5StickC PLUS 2 + ENV III module.  
Data is sampled every 2 seconds and can support basic weather trend predictions.
""")

Sample Data File (data.csv)

Textile
This CSV file contains sample environmental data collected via the M5StickC PLUS 2. It can be used to preview the dashboard functionality.
time,temperature,humidity,pressure
18:38:25,24.69,69.83,10.13
18:38:27,24.69,69.71,10.13
18:38:29,24.69,69.61,10.13
18:38:31,24.7,69.86,10.13
18:38:33,24.73,69.99,10.13
18:38:35,24.73,70.14,10.13
18:38:37,24.77,70.09,10.13
18:38:39,24.74,69.96,10.13
18:38:41,24.74,69.92,10.13
18:38:43,24.76,69.88,10.13
18:38:45,24.76,69.81,10.13
18:38:47,24.79,69.74,10.13
18:38:49,24.77,69.7,10.13
18:38:51,24.77,69.66,10.13
18:38:54,24.79,69.62,10.13
18:38:56,24.79,69.57,10.13
18:38:58,24.79,69.57,10.13
18:39:00,24.83,69.56,10.13
18:39:02,24.81,69.63,10.13
18:39:04,24.8,69.76,10.13
18:39:06,24.8,69.86,10.13
18:39:08,24.83,69.94,10.13
18:39:10,24.81,69.94,10.13
18:39:12,24.84,69.96,10.13
18:39:14,24.83,69.92,10.13
18:39:16,24.81,69.9,10.13
18:39:18,24.83,69.96,10.13
18:39:20,24.84,70.21,10.13
18:39:22,24.86,70.41,10.13
18:39:25,24.83,70.51,10.13
18:39:27,24.87,70.65,10.13
18:39:29,24.84,70.74,10.13
18:39:31,24.86,70.72,10.13
18:39:33,24.87,70.89,10.13
18:39:35,24.87,71.08,10.13
18:39:37,24.87,71.24,10.13
18:39:39,24.88,71.33,10.13
18:39:41,24.87,71.51,10.13
18:39:43,24.87,71.67,10.13
18:39:45,24.88,71.86,10.13
18:39:47,24.87,71.98,10.13
18:39:49,24.91,72.07,10.13
18:39:51,24.88,72.12,10.13
18:39:53,24.9,72.2,10.13
18:39:56,24.88,72.35,10.13
18:39:58,24.9,72.45,10.13
18:40:00,24.91,72.52,10.13
18:40:02,24.9,72.55,10.13
18:40:04,24.9,72.58,10.13
18:40:06,24.9,72.6,10.13
18:40:08,24.91,72.58,10.13
18:40:10,24.92,72.57,10.13
18:40:12,24.91,72.53,10.13
18:40:14,24.91,72.39,10.13
18:40:16,24.91,72.19,10.13
18:40:18,24.92,72.05,10.13
18:40:20,24.91,71.95,10.13
18:40:22,24.92,71.81,10.13
18:40:24,24.95,71.74,10.13
18:40:26,24.92,71.63,10.13
18:40:29,24.92,71.61,10.13
18:40:31,24.92,71.59,10.13
18:40:33,24.92,71.57,10.13
18:40:35,24.95,71.68,10.13
18:40:37,24.92,71.85,10.13
18:40:39,24.97,71.96,10.13
18:40:41,24.97,72.11,10.13
18:40:43,24.95,72.34,10.13
18:40:45,24.97,72.52,10.13
18:40:47,24.95,72.62,10.13
18:40:49,24.95,72.65,10.13
18:40:51,24.97,72.68,10.13
18:40:53,24.97,72.74,10.13
18:40:55,24.95,72.86,10.13
18:40:57,24.97,72.89,10.13
18:41:00,24.98,72.95,10.13
18:41:02,24.95,72.98,10.13
18:41:04,24.97,73.01,10.13
18:41:06,24.97,72.97,10.13
18:41:08,24.97,72.95,10.13
18:41:10,24.97,72.93,10.13
18:41:12,24.98,72.94,10.13
18:41:14,24.99,72.92,10.13
18:41:16,24.99,72.91,10.13
18:41:18,24.98,72.88,10.13
18:41:20,24.98,72.81,10.13
18:41:22,24.97,72.78,10.13
18:41:24,24.98,72.68,10.13
18:41:26,24.98,72.58,10.13
18:41:28,24.99,72.54,10.13
18:41:31,24.98,72.45,10.13
18:41:33,24.99,72.44,10.13
18:41:35,24.98,72.36,10.13
18:41:37,24.97,72.29,10.13
18:41:39,25.01,72.27,10.13
18:41:41,24.99,72.27,10.13
18:41:43,24.99,72.31,10.13
18:41:45,24.99,72.33,10.13
18:41:47,25.01,72.32,10.13
18:41:49,25.01,72.32,10.13

Credits

张荣华
1 project • 0 followers

Comments