How to Build a Raspberry Pi Sensor Dashboard with DHT22 and Grafana
In this project you will wire a DHT22 temperature and humidity sensor to your Raspberry Pi, write a Python script to read data from it, store the readings in InfluxDB, and visualize everything on a Grafana dashboard.
Prerequisites
- Raspberry Pi 3 or newer running Raspberry Pi OS (64-bit)
- Docker and Docker Compose installed (see our Docker setup guide)
- A DHT22 sensor module (the 3-pin breakout board with a built-in pull-up resistor)
- Three jumper wires (female-to-female)
- Python 3 and pip installed (included with Raspberry Pi OS)
Step 1: Wire the DHT22 to the Raspberry Pi
The DHT22 breakout module has three pins. Connect them as follows:
| DHT22 Pin | Raspberry Pi Pin | |-----------|-------------------------| | VCC (+) | Pin 1 (3.3V Power) | | DATA | Pin 7 (GPIO 4) | | GND (-) | Pin 9 (Ground) |
If you are using the 4-pin raw DHT22 sensor (without a breakout board), you will also need a 10K ohm pull-up resistor between the VCC and DATA lines.
Step 2: Install Python Dependencies
Install the Adafruit CircuitPython DHT library and the InfluxDB client:
sudo apt install -y libgpiod2
pip install adafruit-circuitpython-dht influxdb-client
Step 3: Deploy InfluxDB and Grafana with Docker Compose
Create a project directory and compose file:
mkdir -p ~/sensor-dashboard
cd ~/sensor-dashboard
Create docker-compose.yml:
services:
influxdb:
image: influxdb:2
container_name: influxdb
restart: unless-stopped
ports:
- "8086:8086"
volumes:
- influxdb-data:/var/lib/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=changeme123
- DOCKER_INFLUXDB_INIT_ORG=homelab
- DOCKER_INFLUXDB_INIT_BUCKET=sensors
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=my-super-secret-token
grafana:
image: grafana/grafana
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- influxdb
volumes:
influxdb-data:
grafana-data:
Start the stack:
docker compose up -d
Verify both containers are running with docker ps.
Step 4: Create the Python Sensor Script
Create ~/sensor-dashboard/sensor.py:
import time
import board
import adafruit_dht
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
# DHT22 sensor on GPIO 4
dht_device = adafruit_dht.DHT22(board.D4)
# InfluxDB connection
client = InfluxDBClient(
url="http://localhost:8086",
token="my-super-secret-token",
org="homelab"
)
write_api = client.write_api(write_options=SYNCHRONOUS)
BUCKET = "sensors"
INTERVAL_SECONDS = 30
print("Starting sensor readings...")
while True:
try:
temperature_c = dht_device.temperature
humidity = dht_device.humidity
if temperature_c is not None and humidity is not None:
temperature_f = temperature_c * 9.0 / 5.0 + 32.0
print(f"Temp: {temperature_c:.1f}C ({temperature_f:.1f}F) Humidity: {humidity:.1f}%")
point = (
Point("environment")
.tag("location", "room1")
.field("temperature_c", temperature_c)
.field("temperature_f", temperature_f)
.field("humidity", humidity)
)
write_api.write(bucket=BUCKET, record=point)
else:
print("Sensor returned None, retrying...")
except RuntimeError as e:
# DHT sensors occasionally fail reads; just retry
print(f"Read error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
dht_device.exit()
raise
time.sleep(INTERVAL_SECONDS)
Run the script to verify it reads data and writes to InfluxDB:
python3 ~/sensor-dashboard/sensor.py
You should see temperature and humidity readings printed every 30 seconds.
Step 5: Set Up Grafana
- Open Grafana in your browser at
http://<your-pi-ip>:3000 - Log in with the default credentials: admin / admin (you will be prompted to change the password)
- Navigate to Connections > Data Sources > Add data source
- Select InfluxDB
- Configure the data source:
- Query language: Flux
- URL:
http://influxdb:8086 - Organization:
homelab - Token:
my-super-secret-token - Default bucket:
sensors
- Click Save & Test to verify the connection
Step 6: Create a Dashboard
- Go to Dashboards > New Dashboard > Add visualization
- Select your InfluxDB data source
- Use this Flux query to display temperature:
from(bucket: "sensors")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "environment")
|> filter(fn: (r) => r._field == "temperature_c")
|> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
- Add another panel for humidity by changing the
_fieldfilter to"humidity" - Save the dashboard
Step 7: Run the Script on Boot
Create a systemd service to start the sensor script automatically:
sudo tee /etc/systemd/system/sensor.service > /dev/null <<EOF
[Unit]
Description=DHT22 Sensor Logger
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/python3 /home/$USER/sensor-dashboard/sensor.py
Restart=always
RestartSec=10
User=$USER
[Install]
WantedBy=multi-user.target
EOF
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable sensor.service
sudo systemctl start sensor.service
Troubleshooting
- Sensor returns None or RuntimeError: DHT22 sensors are unreliable over long wires. Keep the wire length under 1 meter. The script already retries on RuntimeError.
- Permission denied on GPIO: Run the script with
sudoor add your user to thegpiogroup:sudo usermod -aG gpio $USER. - InfluxDB connection refused: Make sure the InfluxDB container is running and port 8086 is accessible.
- Grafana shows no data: Double-check the Flux query, especially the bucket name and field names. Make sure the time range covers a period when data was being collected.
- libgpiod errors: Ensure you installed
libgpiod2with apt. This is required by the Adafruit CircuitPython DHT library.
Conclusion
You now have a complete IoT sensor pipeline running on a Raspberry Pi: a DHT22 sensor feeding data through Python into InfluxDB, with Grafana providing beautiful real-time dashboards. From here, you can add more sensors, set up alerts in Grafana, or push the data to an MQTT broker for other services to consume.