Raspberry Pi

Monitor de Qualidade do Ar com Raspberry Pi, BME680 e MQTT

Ligue um BME680 a um Raspberry Pi, calibre uma linha de base de gás, calcule um índice simples de qualidade do ar interno e envie tudo para um broker MQTT que você acompanha de qualquer lugar.

Monitor de qualidade do ar com Raspberry Pi e placa sensora BME680 enviando leituras de gás, umidade e temperatura para um dashboard MQTT
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

Um monitor de qualidade do ar com Raspberry Pi construído em torno do Bosch BME680 é um dos projetos de sensor pequenos mais úteis que você pode colocar em um escritório, oficina ou quarto. Neste tutorial você vai ligar o sensor, ler temperatura, umidade, pressão e resistência de gás em Python, transformar esses valores brutos em uma estimativa simples de qualidade do ar interno (IAQ) e publicar tudo via MQTT para que qualquer dashboard ou celular acompanhe ao vivo.

O que o BME680 realmente mede

O BME680 combina quatro medições em um encapsulamento minúsculo: temperatura, umidade relativa, pressão barométrica e a resistência de uma camada aquecida de óxido metálico sensível a gases. As três primeiras são grandezas físicas diretas. A quarta é a interessante, e também a mais mal compreendida.

O sensor de gás não informa um gás específico nem uma concentração em ppm. Compostos orgânicos voláteis (VOCs) de produtos de limpeza, cozinha, tinta, pessoas e móveis reagem com a camada sensora aquecida e reduzem sua resistência. Ar limpo dá resistência alta; ar poluído, uma mais baixa. Isso torna o valor bruto um indicador relativo: ótimo para perceber tendências e eventos ("alguém começou a cozinhar", "o ambiente precisa de ventilação"), não uma medição de laboratório.

A Bosch distribui uma biblioteca de código fechado chamada BSEC que converte essas leituras em um índice IAQ calibrado de 0 a 500 e em equivalentes estimados de CO2. Ela funciona bem, mas é um binário fechado com licença e esforço de integração próprios. Para um monitor de hobby ou de laboratório, um índice transparente baseado em linha de base costuma bastar, e é isso que vamos construir aqui. Se mais tarde você precisar da BSEC, o lado MQTT deste projeto continua exatamente igual.

Leitura Unidade Faixa interna típica O que indica
Temperatura °C 18 a 26 Conforto, e um fator de correção para a camada de gás
Umidade relativa % 30 a 60 Conforto, risco de mofo, parte do índice IAQ
Pressão hPa 950 a 1050 Tendência do tempo, não qualidade do ar
Resistência de gás Ohm Dezenas a centenas de kOhm Nível relativo de VOCs; quanto maior, mais limpo

Peças e ligações

Você precisa de:

  1. Qualquer Raspberry Pi com header de 40 pinos (Zero 2 W, 3, 4 ou 5) rodando Raspberry Pi OS.
  2. Uma placa breakout BME680. Adafruit, Pimoroni e muitas placas genéricas funcionam; verifique se a sua usa o endereço I2C 0x76 ou 0x77.
  3. Quatro jumpers.

Ligue a breakout ao Pi via I2C:

Pino do BME680 Pino do Raspberry Pi
VIN / 3V3 Pino 1 (3,3 V)
GND Pino 6 (GND)
SDA / SDI Pino 3 (GPIO 2, SDA)
SCL / SCK Pino 5 (GPIO 3, SCL)

Monte o sensor longe do próprio Pi. A CPU e o regulador de tensão aquecem a placa, e um sensor posicionado logo acima do SoC vai ler vários graus a mais e empurrar a umidade para baixo. Um cabo de 10 a 15 cm ou um pequeno espaçador faz uma diferença perceptível.

Preparando o Raspberry Pi

Ative o I2C, confirme que o sensor está visível e crie um ambiente virtual Python (o Raspberry Pi OS Bookworm e versões posteriores exigem um para instalações com pip):

sudo raspi-config nonint do_i2c 0
sudo apt update && sudo apt install -y i2c-tools python3-venv
i2cdetect -y 1          # espere ver 76 ou 77 na grade

python3 -m venv ~/aq-env
source ~/aq-env/bin/activate
pip install adafruit-circuitpython-bme680 paho-mqtt

Se o i2cdetect mostrar uma grade vazia, confira de novo SDA e SCL (é fácil inverter) e verifique se a placa está alimentada com 3,3 V. A documentação oficial de configuração do Raspberry Pi cobre a configuração do I2C em mais detalhes caso você use uma imagem não padrão.

Construindo o script do monitor de qualidade do ar com Raspberry Pi

O script abaixo faz quatro coisas: lê o sensor a cada dez segundos, executa um aquecimento (burn-in) de cinco minutos para estabelecer uma linha de base de gás, calcula uma estimativa de IAQ a partir do gás e da umidade e publica uma mensagem JSON no servidor MQTT público gratuito em broker.connectmq.com. Ele também define um Last Will para que os subscribers saibam quando o monitor fica offline.

#!/usr/bin/env python3
"""Raspberry Pi air quality monitor: BME680 -> MQTT."""
import json
import time
import uuid

import board
import adafruit_bme680
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
PORT = 1883
DEVICE_ID = "pi-aq-" + uuid.uuid4().hex[:6]
BASE_TOPIC = f"connectmq/demo/{DEVICE_ID}/air"
I2C_ADDRESS = 0x77          # troque para 0x76 em placas estilo Pimoroni
INTERVAL = 10               # segundos entre leituras
BURN_IN = 300               # segundos usados para aprender a linha de base de ar limpo
HUM_BASELINE = 40.0         # umidade interna ideal em porcentagem
HUM_WEIGHT = 0.25           # parcela do índice vinda da umidade


def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.publish(f"{BASE_TOPIC}/status", "online", qos=1, retain=True)


def iaq_score(gas, hum, gas_baseline):
    """0-100, higher is better. Simple, transparent estimate, not Bosch BSEC."""
    hum_offset = hum - HUM_BASELINE
    if hum_offset > 0:
        hum_score = (100 - HUM_BASELINE - hum_offset) / (100 - HUM_BASELINE)
    else:
        hum_score = (HUM_BASELINE + hum_offset) / HUM_BASELINE
    hum_score *= HUM_WEIGHT * 100

    gas_offset = gas_baseline - gas
    if gas_offset > 0:
        gas_score = (gas / gas_baseline) * (100 - HUM_WEIGHT * 100)
    else:
        gas_score = 100 - HUM_WEIGHT * 100
    return round(max(0.0, min(100.0, hum_score + gas_score)), 1)


def main():
    i2c = board.I2C()
    sensor = adafruit_bme680.Adafruit_BME680_I2C(i2c, address=I2C_ADDRESS)
    sensor.sea_level_pressure = 1013.25

    client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=DEVICE_ID)
    client.will_set(f"{BASE_TOPIC}/status", "offline", qos=1, retain=True)
    client.on_connect = on_connect
    client.connect(BROKER, PORT, keepalive=60)
    client.loop_start()

    print(f"Burn-in for {BURN_IN} s, publishing to {BASE_TOPIC}/#")
    samples = []
    start = time.time()
    while time.time() - start < BURN_IN:
        samples.append(sensor.gas)
        time.sleep(1)
    gas_baseline = sum(samples[-50:]) / len(samples[-50:])
    print(f"Gas baseline: {gas_baseline:.0f} Ohm")

    while True:
        gas = sensor.gas
        hum = sensor.relative_humidity
        payload = {
            "ts": int(time.time()),
            "temperature_c": round(sensor.temperature, 2),
            "humidity_pct": round(hum, 1),
            "pressure_hpa": round(sensor.pressure, 1),
            "gas_ohm": int(gas),
            "iaq_score": iaq_score(gas, hum, gas_baseline),
        }
        client.publish(f"{BASE_TOPIC}/telemetry", json.dumps(payload), qos=1)
        print(payload)
        time.sleep(INTERVAL)


if __name__ == "__main__":
    main()

Execute com python aq_monitor.py. Durante o burn-in o aquecedor se estabiliza; um sensor novo deriva nos primeiros um ou dois dias, então não confie na linha de base da primeiríssima execução. Um hábito prático é iniciar o script com ar fresco (abra uma janela nos primeiros cinco minutos), porque a linha de base define o que significa "limpo" pelo resto da sessão.

Interpretando a estimativa de IAQ

O índice é invertido em relação ao da Bosch: 100 significa ar tão limpo quanto a linha de base com umidade ideal, e valores menores são piores. Um guia aproximado de leitura:

Índice Significado Ação típica
80 a 100 Próximo da linha de base Nada a fazer
60 a 80 VOCs perceptíveis ou umidade fora do ideal Fique de olho
40 a 60 Claramente pior que a linha de base Ventile o ambiente
Abaixo de 40 Fonte forte por perto Encontre a fonte e ventile agora

Como a linha de base é relativa, compare os índices ao longo do tempo no mesmo ambiente, e não entre dispositivos diferentes.

Acompanhando os dados ao vivo

Abra um segundo terminal (no Pi ou no seu notebook) e faça a assinatura com o cliente Mosquitto. Troque o device ID pelo que o seu script imprimiu:

mosquitto_sub -h broker.connectmq.com -p 1883 -i aq-viewer-$RANDOM \
  -t "connectmq/demo/pi-aq-1a2b3c/air/#" -v

Você deve ver primeiro o status retido online e depois uma mensagem de telemetria a cada dez segundos. Pare o script Python com Ctrl+C e, quando o keepalive expirar, o broker entrega o Last Will offline. Lembre-se de que o servidor MQTT público de testes pode ser lido por qualquer pessoa que conheça o topic, então dados de ar de um ambiente tudo bem, mas nada pessoal deve ir para lá.

Rodando o monitor sem supervisão

Um sensor que para quando você fecha a sessão SSH não é bem um monitor. Crie uma unit do systemd para que o script inicie no boot e reinicie após falhas:

# /etc/systemd/system/aq-monitor.service
[Unit]
Description=BME680 air quality monitor
After=network-online.target
Wants=network-online.target

[Service]
User=pi
ExecStart=/home/pi/aq-env/bin/python /home/pi/aq_monitor.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now aq-monitor
journalctl -u aq-monitor -f

Ajuste o nome de usuário e os caminhos conforme a sua instalação. O mesmo padrão é explicado com mais profundidade para outros sensores no projeto de temperatura com DS18B20 e no tutorial de umidade com DHT22, que você pode combinar com este em um único Pi.

Migrando para um broker privado

Para qualquer coisa além de experimentos, publique no seu próprio broker com credenciais e TLS. No ConnectMQ você se cadastra, cria um broker e recebe usuário, senha e client ID gerados. Depois, altere o bloco de conexão:

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set()                       # o repositório de CAs do sistema valida o certificado Let's Encrypt
client.will_set(f"{BASE_TOPIC}/status", "offline", qos=1, retain=True)
client.connect("broker.connectmq.com", 8883, keepalive=60)

Com um broker MQTT gerenciado você não precisa manter uma instância Mosquitto atualizada e acessível por conta própria, e o explorador de topics ao vivo do portal mostra a telemetria chegando sem ferramentas extras. Você também pode adicionar uma regra de alerta por limite em iaq_score ou humidity_pct para que o log de alertas do portal registre cada vez que o ambiente ultrapassar um limite.

Solução de problemas

  1. ValueError: No I2C device at address: o endereço está errado. Use o que o i2cdetect mostra (0x76 ou 0x77).
  2. Resistência de gás travada muito baixa e sem subir: o sensor ainda está em condicionamento. Deixe-o ligado por várias horas; a deriva no primeiro uso é normal.
  3. Temperatura vários graus acima: calor do Pi ou do próprio aquecedor do sensor. Afaste o sensor da placa ou aplique um offset fixo após comparar com um termômetro de referência.
  4. Conexão recusada no broker privado: verifique se o client ID corresponde exatamente às credenciais emitidas; o ConnectMQ vincula client IDs às credenciais.
  5. As mensagens param após uma oscilação de rede: o paho reconecta automaticamente enquanto loop_start() está rodando, mas mensagens QoS 1 publicadas offline ficam apenas em fila na memória. Para quedas longas, adicione um buffer local.

Ideias para expandir o projeto

Depois que os dados estiverem fluindo, o resto é MQTT puro. O Node-RED pode assinar e acionar um exaustor por meio de um relé. O Telegraf pode gravar o JSON no InfluxDB para gráficos de longo prazo. Um segundo Pi em outro cômodo pode publicar com seu próprio device ID para você comparar ambientes lado a lado. Se a plataforma for nova para você, o tutorial de MQTT com Raspberry Pi cobre o básico de clientes, topics e QoS em que este projeto se apoia.

Comece com o ConnectMQ

Leve seu monitor de qualidade do ar com Raspberry Pi do servidor público de testes para um broker privado protegido por TLS em poucos minutos. O ConnectMQ oferece um broker gerenciado com cliente MQTT no navegador, explorador de topics ao vivo e alertas por limite. Crie um broker Serverless gratuito, sem cartão de crédito, e aponte seu script para ele.

Perguntas frequentes

O valor IAQ do BME680 é o mesmo que o índice BSEC da Bosch?

Não. O índice deste tutorial é uma estimativa transparente baseada em uma linha de base de gás e na umidade. A biblioteca BSEC da Bosch produz um índice calibrado de 0 a 500 com acompanhamento automático da linha de base, e pode ser adotada depois sem mudar os topics MQTT.

Quanto tempo o BME680 precisa para aquecer?

O aquecedor se estabiliza em minutos, e é por isso que o script usa um burn-in de cinco minutos. Um sensor novo continua derivando nos primeiros um ou dois dias de operação, e as leituras ficam mais consistentes depois disso.

Posso medir CO2 com um BME680?

Não diretamente. O BME680 reage a VOCs, e qualquer valor de CO2 derivado dele é uma estimativa. Para medir CO2 de verdade, use um sensor NDIR como o SCD40 ou SCD41 e publique-o junto com os dados do BME680.

Qual broker MQTT devo usar para um monitor de qualidade do ar doméstico?

O servidor público de testes serve para experimentar, mas todos podem lê-lo. Para uso permanente, um broker privado com credenciais e TLS, como um broker ConnectMQ Serverless gratuito, mantém seus dados privados.

Artigos relacionados

Registro de Acessos Raspberry Pi RFID MQTT com o Leitor RC522

Ligue um leitor RFID RC522 a um Raspberry Pi, leia tags em Python, confira-as em uma lista de permissões local e publique cada tentativa de acesso como um evento MQTT que loggers, dashboards e ferramentas de alerta podem consumir.

8 min de leitura

Confiabilidade do Raspberry Pi: Rodando um Pi 24/7 como Gateway IoT

Um guia prático para manter um gateway MQTT com Raspberry Pi rodando por meses: desgaste do armazenamento, sistemas de arquivos somente leitura, alimentação, refrigeração, watchdogs de hardware e software e monitoramento remoto de saúde.

9 min de leitura

Pico W vs Pico 2 W para MQTT: Desempenho, Memória e TLS do RP2040 vs RP2350

O Pico 2 W mantém o formato e o chip Wi-Fi do Pico W, mas troca o RP2040 pelo RP2350, mais rápido. Esta comparação mostra o que isso significa para dispositivos MQTT: CPU, memória, TLS, recursos de segurança, suporte de software e qual placa comprar para cada projeto.

9 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.