Overview
Build a complete weather station that reads temperature, humidity, pressure, and light level from I2C sensors. Data is published to MQTT for real-time consumption, stored in InfluxDB for historical analysis, and visualized with Grafana dashboards. This intermediate project teaches I2C sensor communication, MQTT publishing, and time-series data management.
What You'll Need
Hardware
- * Raspberry Pi (any model with I2C)
- * BME280 sensor module (temp + humidity + pressure)
- * BH1750 light sensor module
- * Jumper wires (4 wires per sensor, shared I2C bus)
Software
- * EdgeFlow installed on your Pi
- * MQTT broker (Mosquitto recommended)
- * InfluxDB 2.x installed (local or cloud)
- * Grafana (optional, for dashboards)
Wiring Diagram
Both sensors share the same I2C bus (SDA/SCL). They use different I2C addresses so there is no conflict.
BME280 (addr: 0x76)
VCC → 3.3V (Pin 1)
GND → GND (Pin 9)
SDA → GPIO2 / SDA1 (Pin 3)
SCL → GPIO3 / SCL1 (Pin 5)
BH1750 (addr: 0x23)
VCC → 3.3V (Pin 1)
GND → GND (Pin 9)
SDA → GPIO2 / SDA1 (Pin 3)
SCL → GPIO3 / SCL1 (Pin 5)
Enable I2C on Your Pi
I2C must be enabled before the sensors will work. Run these commands:
# Enable I2C interface
sudo raspi-config nonint do_i2c 0
# Verify I2C is enabled
ls /dev/i2c-*
# Scan for connected devices (should show 0x23 and 0x76)
sudo apt install -y i2c-tools
i2cdetect -y 1
You should see addresses 23 and 76 in the i2cdetect output grid.
Importable Flow JSON
Copy this JSON and import it via Menu → Import in the EdgeFlow editor.
{
"name": "Complete Weather Station",
"nodes": [
{
"id": "bme280_1",
"type": "bme280",
"name": "BME280 Sensor",
"address": "0x76",
"interval": 30,
"x": 120,
"y": 160
},
{
"id": "bh1750_1",
"type": "bh1750",
"name": "BH1750 Light",
"address": "0x23",
"interval": 30,
"mode": "continuous_high",
"x": 120,
"y": 320
},
{
"id": "join_sensors",
"type": "join",
"name": "Combine Data",
"mode": "custom",
"count": 2,
"build": "object",
"propertyType": "msg",
"property": "topic",
"x": 340,
"y": 240
},
{
"id": "format_weather",
"type": "function",
"name": "Format Weather Data",
"func": "var bme = msg.payload.bme280 || {};\nvar light = msg.payload.bh1750 || {};\nmsg.payload = {\n temperature: Math.round(bme.temperature * 100) / 100,\n humidity: Math.round(bme.humidity * 100) / 100,\n pressure: Math.round(bme.pressure * 100) / 100,\n light_lux: Math.round(light.lux || 0),\n timestamp: Date.now(),\n station: 'weather-pi-01'\n};\nreturn msg;",
"x": 540,
"y": 240
},
{
"id": "mqtt_weather",
"type": "mqtt-out",
"name": "MQTT Publish",
"broker": "localhost",
"port": 1883,
"topic": "home/weather",
"qos": 1,
"retain": true,
"x": 760,
"y": 180
},
{
"id": "influx_write",
"type": "influxdb",
"name": "Store in InfluxDB",
"url": "http://localhost:8086",
"org": "edgeflow",
"bucket": "weather_data",
"measurement": "weather",
"token": "YOUR_INFLUXDB_TOKEN",
"x": 760,
"y": 300
},
{
"id": "mqtt_temp",
"type": "mqtt-out",
"name": "MQTT Temperature",
"broker": "localhost",
"port": 1883,
"topic": "home/weather/temperature",
"qos": 0,
"x": 760,
"y": 120
},
{
"id": "split_topics",
"type": "function",
"name": "Split to Topics",
"func": "var data = msg.payload;\nvar msgs = [];\nmsgs.push({ payload: data.temperature, topic: 'home/weather/temperature' });\nmsgs.push({ payload: data.humidity, topic: 'home/weather/humidity' });\nmsgs.push({ payload: data.pressure, topic: 'home/weather/pressure' });\nmsgs.push({ payload: data.light_lux, topic: 'home/weather/light' });\nreturn [msgs];",
"outputs": 1,
"x": 540,
"y": 120
},
{
"id": "debug_weather",
"type": "debug",
"name": "Weather Monitor",
"x": 760,
"y": 380
}
],
"connections": [
{ "from": "bme280_1", "to": "join_sensors" },
{ "from": "bh1750_1", "to": "join_sensors" },
{ "from": "join_sensors", "to": "format_weather" },
{ "from": "format_weather", "to": "mqtt_weather" },
{ "from": "format_weather", "to": "influx_write" },
{ "from": "format_weather", "to": "split_topics" },
{ "from": "format_weather", "to": "debug_weather" },
{ "from": "split_topics", "to": "mqtt_temp" }
]
} Step-by-Step Walkthrough
Enable I2C and Wire Sensors
Enable I2C via raspi-config, then wire both sensors to the same I2C bus (SDA on GPIO2, SCL on GPIO3).
Both sensors can share the same 3.3V and GND connections. Run i2cdetect -y 1
to verify both addresses appear.
Install and Configure Mosquitto MQTT Broker
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto
# Test with a quick subscribe/publish
mosquitto_sub -t "test" &
mosquitto_pub -t "test" -m "hello"
# You should see "hello" printed Install InfluxDB 2.x
# Install InfluxDB on Raspberry Pi
wget https://dl.influxdata.com/influxdb/releases/influxdb2_2.7.1-1_arm64.deb
sudo dpkg -i influxdb2_2.7.1-1_arm64.deb
sudo systemctl enable influxdb
sudo systemctl start influxdb
# Open http://YOUR_PI_IP:8086 to complete setup
# Create org: "edgeflow", bucket: "weather_data"
# Copy the generated API token Import Flow and Configure Credentials
Import the flow JSON above into EdgeFlow. Then double-click the InfluxDB node and paste your API token, org name, and bucket name. If your MQTT broker uses authentication, update the MQTT nodes with username and password.
Deploy and Verify Data Flow
Click Deploy. Monitor the Debug panel for combined weather readings every 30 seconds. Verify MQTT messages arrive using a subscriber:
mosquitto_sub -t "home/weather/#" -v Add Grafana Dashboard (Optional)
Install Grafana, add InfluxDB as a data source, and create panels for each measurement. A sample Flux query for the temperature panel:
from(bucket: "weather_data")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "weather")
|> filter(fn: (r) => r._field == "temperature")
|> aggregateWindow(every: 5m, fn: mean, createEmpty: false) Configuration Details
| Parameter | Value | Description |
|---|---|---|
| BME280 Address | 0x76 | I2C address (some modules use 0x77) |
| BH1750 Address | 0x23 | I2C address (ADDR pin LOW) |
| Poll Interval | 30 seconds | Both sensors read simultaneously |
| MQTT Topic | home/weather | Combined JSON payload; subtopics for individual values |
| MQTT QoS | 1 (at least once) | Guaranteed delivery for the combined topic |
| InfluxDB Bucket | weather_data | Measurement name: "weather" |
MQTT Topic Structure
home/weather ← Combined JSON (all readings)
home/weather/temperature ← Float: 22.45
home/weather/humidity ← Float: 58.3
home/weather/pressure ← Float: 1013.25
home/weather/light ← Integer: 4520 Expected Output
The formatted weather data published to MQTT and stored in InfluxDB:
{
"temperature": 22.45,
"humidity": 58.3,
"pressure": 1013.25,
"light_lux": 4520,
"timestamp": 1707750000000,
"station": "weather-pi-01"
} InfluxDB stores each field as a separate column in the "weather" measurement:
| _time | temperature | humidity | pressure | light_lux |
|---|---|---|---|---|
| 2026-02-12T15:00:00Z | 22.45 | 58.3 | 1013.25 | 4520 |
| 2026-02-12T15:00:30Z | 22.51 | 57.9 | 1013.20 | 4485 |
| 2026-02-12T15:01:00Z | 22.48 | 58.1 | 1013.22 | 4510 |
Troubleshooting
i2cdetect shows no devices
- Verify I2C is enabled:
sudo raspi-config nonint do_i2c 0 - Check that SDA is on Pin 3 (GPIO2) and SCL is on Pin 5 (GPIO3)
- Ensure sensors are powered (3.3V, not 5V for most I2C modules)
- Try shorter wires or a different breadboard
MQTT messages are not arriving
- Check Mosquitto is running:
sudo systemctl status mosquitto - Verify the broker address is "localhost" if running on the same Pi
- Test manually:
mosquitto_pub -t test -m hello - Check firewall settings if connecting from another device
InfluxDB write errors
- Verify the API token has write permissions for the bucket
- Check org and bucket names match exactly (case-sensitive)
- Confirm InfluxDB is running:
sudo systemctl status influxdb - Test the API endpoint in a browser: http://localhost:8086
Join node never fires
- Ensure both sensors have the same polling interval (30s)
- Verify each sensor node sets a unique
msg.topic - Check Join node is set to "count: 2" in object mode
- Add a timeout (e.g., 35s) so it fires even if one sensor is slow