How to Build a Raspberry Pi Sensor Dashboard with DHT22 and Grafana

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:

Bash
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:

Bash
mkdir -p ~/sensor-dashboard
cd ~/sensor-dashboard

Create docker-compose.yml:

YAML
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:

Bash
docker compose up -d

Verify both containers are running with docker ps.


Step 4: Create the Python Sensor Script

Create ~/sensor-dashboard/sensor.py:

Python
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:

Bash
python3 ~/sensor-dashboard/sensor.py

You should see temperature and humidity readings printed every 30 seconds.


Step 5: Set Up Grafana

  1. Open Grafana in your browser at http://<your-pi-ip>:3000
  2. Log in with the default credentials: admin / admin (you will be prompted to change the password)
  3. Navigate to Connections > Data Sources > Add data source
  4. Select InfluxDB
  5. Configure the data source:
    • Query language: Flux
    • URL: http://influxdb:8086
    • Organization: homelab
    • Token: my-super-secret-token
    • Default bucket: sensors
  6. Click Save & Test to verify the connection

Step 6: Create a Dashboard

  1. Go to Dashboards > New Dashboard > Add visualization
  2. Select your InfluxDB data source
  3. Use this Flux query to display temperature:
Code
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)
  1. Add another panel for humidity by changing the _field filter to "humidity"
  2. Save the dashboard

Step 7: Run the Script on Boot

Create a systemd service to start the sensor script automatically:

Bash
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:

Bash
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 sudo or add your user to the gpio group: 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 libgpiod2 with 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.