Raspberry Pi DHT22 Sensor with SiliconWit IO
In this tutorial, you will learn how to connect a DHT22 temperature and humidity sensor to a Raspberry Pi, read sensor data using Python, and publish the readings to the SiliconWit IO IoT platform via MQTT over a secure TLS connection.
The Raspberry Pi is a popular choice for IoT projects due to its GPIO pins, built-in WiFi, and ability to run full Python applications. Combined with the DHT22 sensor and SiliconWit IO, you can build a complete environmental monitoring system in minutes.
What You Will Learn
Section titled “What You Will Learn”- How to wire a DHT22 temperature and humidity sensor to a Raspberry Pi
- How to read sensor data using the
adafruit-circuitpython-dhtlibrary - How to establish a secure TLS MQTT connection to SiliconWit IO
- How to publish real sensor readings as JSON telemetry
- How to run the script as a background service using systemd
Prerequisites
Section titled “Prerequisites”Hardware
Section titled “Hardware”| Component | Description |
|---|---|
| Raspberry Pi | Any model with GPIO headers (Pi 3, Pi 4, Pi 5, Pi Zero 2 W) |
| DHT22 Sensor | Also known as AM2302; measures temperature and humidity |
| 10K Ohm Resistor | Pull-up resistor for the data line (some DHT22 modules have this built in) |
| Jumper Wires | Female-to-female or female-to-male depending on your sensor module |
| MicroSD Card | With Raspberry Pi OS installed |
| Power Supply | Appropriate for your Pi model |
| WiFi or Ethernet | Internet connection for MQTT communication |
Software
Section titled “Software”| Software | Purpose |
|---|---|
| Raspberry Pi OS | Bookworm or later (Lite or Desktop) |
| Python 3 | Pre-installed on Raspberry Pi OS |
| SiliconWit IO Account | Free IoT platform account |
SiliconWit IO Credentials
Section titled “SiliconWit IO Credentials”After registering a device on the SiliconWit IO dashboard, note down:
| Credential | Example | Description |
|---|---|---|
| Device ID | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Unique device identifier (MQTT username) |
| Access Token | your_access_token_here | MQTT password |
| Publish Topic | d/{device_id}/t | Topic for sending sensor data (d = device, t = telemetry) |
Keep your access token secure. Never share it publicly or commit it to version control.
Step 1: Wire the DHT22 Sensor to the Raspberry Pi
Section titled “Step 1: Wire the DHT22 Sensor to the Raspberry Pi”The DHT22 sensor has 4 pins (or 3 if using a module with a built-in pull-up resistor):
| DHT22 Pin | Raspberry Pi Pin | Description |
|---|---|---|
| VCC (Pin 1) | 3.3V (Pin 1) | Power supply |
| Data (Pin 2) | GPIO 4 (Pin 7) | Sensor data line |
| NC (Pin 3) | Not connected | Leave unconnected |
| GND (Pin 4) | GND (Pin 6) | Ground |
Raspberry Pi DHT22 Sensor┌──────────────────┐ ┌───────────┐│ │ │ ││ 3.3V (Pin 1) ├─────────────────│ VCC ││ │ ┌───┐ │ ││ GPIO 4 (Pin 7) ├────────┤10K├───│ Data ││ │ └─┬─┘ │ ││ │ │ │ NC ││ │ │ │ ││ GND (Pin 6) ├──────────┴─────│ GND ││ │ │ │└──────────────────┘ └───────────┘
Note: The 10K resistor connects between VCC and the Data line(pull-up). Many DHT22 breakout modules include this resistoron the PCB — check your module before adding an external one.Important notes:
- Use the 3.3V pin, not 5V. The Raspberry Pi GPIO pins are 3.3V logic and the DHT22 works at 3.3V.
- If your DHT22 is on a breakout module (3-pin board), it likely has a built-in pull-up resistor. You can skip the external 10K resistor.
- GPIO 4 is used in this tutorial, but any available GPIO pin will work. Update the pin number in the code if you use a different one.
Step 2: Install Required Libraries
Section titled “Step 2: Install Required Libraries”Update your system and install the necessary packages:
sudo apt updatesudo apt install -y python3-pip python3-venv libgpiod2Create a project directory and virtual environment:
mkdir ~/siliconwit-sensorcd ~/siliconwit-sensorpython3 -m venv venvsource venv/bin/activateInstall the Python libraries:
pip install paho-mqtt adafruit-circuitpython-dht| Library | Purpose |
|---|---|
paho-mqtt | MQTT client for connecting to SiliconWit IO |
adafruit-circuitpython-dht | Read temperature and humidity from the DHT22 sensor |
Step 3: Test the DHT22 Sensor
Section titled “Step 3: Test the DHT22 Sensor”Before writing the full MQTT client, verify that the sensor is working:
import timeimport boardimport adafruit_dht
dht = adafruit_dht.DHT22(board.D4)
for i in range(5): try: temperature = dht.temperature humidity = dht.humidity print(f"Temp: {temperature:.1f}C Humidity: {humidity:.1f}%") except RuntimeError as e: print(f"Sensor read error (normal, retrying): {e}") time.sleep(2)
dht.exit()Save this as test_sensor.py and run it:
python test_sensor.pyThe DHT22 occasionally returns read errors. This is normal behavior for this sensor. The full code below handles these errors gracefully by retrying.
Step 4: Write the Full MQTT Telemetry Script
Section titled “Step 4: Write the Full MQTT Telemetry Script”Create a file called telemetry.py with the following code:
import sslimport jsonimport timeimport boardimport adafruit_dhtimport paho.mqtt.client as mqtt
# ========== SILICONWIT IO MQTT CONFIGURATION ==========MQTT_BROKER = "mqtt.siliconwit.io"MQTT_PORT = 8883DEVICE_ID = "YOUR_DEVICE_ID"ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"PUBLISH_TOPIC = f"d/{DEVICE_ID}/t"
# ========== SENSOR CONFIGURATION ==========DHT_PIN = board.D4 # GPIO 4TELEMETRY_INTERVAL = 30 # seconds
# ========== INITIALIZE SENSOR ==========dht_sensor = adafruit_dht.DHT22(DHT_PIN)
# ========== CALLBACKS ==========def on_connect(client, userdata, flags, reason_code, properties): if reason_code == 0: print("[MQTT] Connected to SiliconWit IO") else: print(f"[MQTT] Connection failed with code: {reason_code}")
def on_disconnect(client, userdata, flags, reason_code, properties): print(f"[MQTT] Disconnected (code: {reason_code}). Reconnecting...")
def on_publish(client, userdata, mid, reason_code, properties): print(f"[MQTT] Message {mid} delivered")
# ========== SENSOR READING ==========def read_dht22(retries=3): """ Read temperature and humidity from the DHT22 sensor. Retries on failure since the DHT22 occasionally returns errors. """ for attempt in range(retries): try: temperature = dht_sensor.temperature humidity = dht_sensor.humidity if temperature is not None and humidity is not None: return { "temperature": round(temperature, 1), "humidity": round(humidity, 1), } except RuntimeError as e: print(f"[SENSOR] Read error (attempt {attempt + 1}/{retries}): {e}") time.sleep(2) return None
# ========== MAIN ==========def main(): print("=== Raspberry Pi DHT22 -> SiliconWit IO ===\n")
# Create MQTT client client = mqtt.Client( callback_api_version=mqtt.CallbackAPIVersion.VERSION2, client_id=DEVICE_ID, protocol=mqtt.MQTTv311, )
# Set authentication client.username_pw_set(DEVICE_ID, ACCESS_TOKEN)
# Configure TLS client.tls_set(tls_version=ssl.PROTOCOL_TLS_CLIENT)
# Set callbacks client.on_connect = on_connect client.on_disconnect = on_disconnect client.on_publish = on_publish
# Enable automatic reconnection client.reconnect_delay_set(min_delay=1, max_delay=60)
# Connect to broker print(f"[MQTT] Connecting to {MQTT_BROKER}:{MQTT_PORT}...") try: client.connect(MQTT_BROKER, MQTT_PORT, keepalive=60) except Exception as e: print(f"[ERROR] Connection failed: {e}") return
# Start the network loop in a background thread client.loop_start()
try: while True: if client.is_connected(): sensor_data = read_dht22() if sensor_data: payload = json.dumps(sensor_data) client.publish(PUBLISH_TOPIC, payload, qos=1) print(f"[TELEMETRY] Sent: {payload}") else: print("[SENSOR] Failed to read after retries, skipping...") else: print("[MQTT] Waiting for connection...")
time.sleep(TELEMETRY_INTERVAL)
except KeyboardInterrupt: print("\n[INFO] Shutting down...") finally: dht_sensor.exit() client.loop_stop() client.disconnect() print("[INFO] Sensor released. Disconnected. Goodbye.")
if __name__ == "__main__": main()Run the script:
python telemetry.pyExpected output:
=== Raspberry Pi DHT22 -> SiliconWit IO ===
[MQTT] Connecting to mqtt.siliconwit.io:8883...[MQTT] Connected to SiliconWit IO[TELEMETRY] Sent: {"temperature": 23.4, "humidity": 58.2}[MQTT] Message 1 delivered[TELEMETRY] Sent: {"temperature": 23.5, "humidity": 57.8}[MQTT] Message 2 deliveredStep 5: Run as a systemd Service
Section titled “Step 5: Run as a systemd Service”To keep the telemetry script running in the background and auto-start on boot, create a systemd service:
sudo nano /etc/systemd/system/siliconwit-sensor.serviceAdd the following content (adjust the User and paths to match your setup):
[Unit]Description=SiliconWit IO DHT22 TelemetryAfter=network-online.targetWants=network-online.target
[Service]Type=simpleUser=piWorkingDirectory=/home/pi/siliconwit-sensorExecStart=/home/pi/siliconwit-sensor/venv/bin/python telemetry.pyRestart=alwaysRestartSec=10
[Install]WantedBy=multi-user.targetEnable and start the service:
sudo systemctl daemon-reloadsudo systemctl enable siliconwit-sensorsudo systemctl start siliconwit-sensorCheck the status:
sudo systemctl status siliconwit-sensorView live logs:
journalctl -u siliconwit-sensor -fStep 6: View Data on SiliconWit IO
Section titled “Step 6: View Data on SiliconWit IO”- Log in to your SiliconWit IO dashboard.
- Navigate to your registered device.
- You should see temperature and humidity readings updating every 30 seconds.
- SiliconWit IO automatically displays charts and a data table for each field.
- You can configure alerts to notify you when values exceed thresholds.
Troubleshooting
Section titled “Troubleshooting”Sensor Issues
Section titled “Sensor Issues”| Symptom | Cause | Solution |
|---|---|---|
RuntimeError: DHT sensor not found | Wrong GPIO pin or bad wiring | Check wiring matches the pin in code. Verify 3.3V and GND connections. |
Constant RuntimeError on every read | Kernel driver conflict | Run sudo apt install libgpiod2 and reboot. |
Readings are None | Sensor not responding | Check the pull-up resistor. Try a different GPIO pin. |
| Temperature reads 0.0 | Defective sensor or loose connection | Re-seat jumper wires. Try a different DHT22 module. |
Permission denied on GPIO | User not in gpio group | Run sudo usermod -aG gpio $USER and log out/in. |
MQTT Connection Issues
Section titled “MQTT Connection Issues”| Symptom | Cause | Solution |
|---|---|---|
Connection refused | Wrong broker address or port | Verify MQTT_BROKER and MQTT_PORT (8883). |
SSL: CERTIFICATE_VERIFY_FAILED | Outdated CA certificates | Run sudo apt update && sudo apt install ca-certificates. |
Connection failed with code: 5 | Invalid credentials | Verify DEVICE_ID and ACCESS_TOKEN from your dashboard. |
Connection timed out | No internet or firewall blocking | Check internet with ping 8.8.8.8. Verify port 8883 is open. |
systemd Service Issues
Section titled “systemd Service Issues”| Symptom | Cause | Solution |
|---|---|---|
| Service fails to start | Wrong path in service file | Verify WorkingDirectory and ExecStart paths exist. |
| Service starts but sensor fails | Permission issue | Ensure the User in the service file has GPIO access. |
| Service restarts repeatedly | Script crashing | Check journalctl -u siliconwit-sensor for error details. |
Summary
Section titled “Summary”In this tutorial, you built a complete environmental monitoring system using:
- Raspberry Pi as the computing platform
- DHT22 sensor for temperature and humidity measurements
- paho-mqtt for secure MQTT communication over TLS
- SiliconWit IO as the cloud dashboard for data visualization and alerts
- systemd for running the script as a reliable background service
The system reads real sensor data every 30 seconds and publishes it to the SiliconWit IO cloud, where you can monitor it from anywhere. This same pattern can be extended with additional sensors (barometric pressure, light level, soil moisture) by adding more fields to the JSON payload.