BME280 com Arduino: temperatura, umidade, pressão e altitude
Ligue um BME280 ou BMP280 ao Arduino: endereço I2C 0x76/0x77, biblioteca da Adafruit, altitude pela pressão ao nível do mar, aviso de 3,3 V, estação meteorológica com ESP32 e Pico.
O BME280 é um sensor ambiental digital fabricado pela Bosch que mede temperatura, umidade relativa e pressão do ar em um único chip minúsculo. Para usá-lo com um Arduino, você só precisa de quatro fios (VCC, GND, SDA, SCL) e da biblioteca Adafruit BME280; poucas linhas de código mostram leituras em °C, % e hPa no Monitor Serial. Como mede pressão, ele também consegue calcular a sua altura acima do nível do mar, ou seja, a altitude. O irmão dele, o BMP280, parece quase idêntico, mas não mede umidade; ele só dá temperatura e pressão.
Neste guia você vai aprender a diferença entre os dois sensores, por que o endereço I2C às vezes é 0x76 e às vezes 0x77, como ligá-los a um Arduino Uno, a um ESP32 e a um Raspberry Pi Pico, como funciona a fórmula da altitude e como escolher a pressão ao nível do mar certa. Depois você vai montar uma miniestação meteorológica com ESP32 que abre no celular, rodar no Pico um driver MicroPython sem biblioteca e ver como um único sketch revela o problema muito comum do “BMP280 vendido como BME280”.

O que é o BME280 e como ele funciona?
O BME280 tem três elementos sensores. O sensor de pressão mede o quanto uma fina membrana de silício se flexiona sob o ar que a pressiona, usando o efeito piezorresistivo. O sensor de umidade é uma camada de polímero cuja capacitância muda conforme ela absorve a umidade do ar. O sensor de temperatura informa a temperatura ambiente e também é usado para corrigir as outras duas medições. Cada chip é calibrado individualmente na fábrica e os coeficientes ficam guardados na memória interna dele; a biblioteca os lê na inicialização e converte os números brutos em unidades reais com as fórmulas do datasheet. O pequeno furo na tampa metálica deixa o ar chegar ao sensor, então nunca o cubra com fita ou cola.
| Característica | BME280 | BMP280 |
|---|---|---|
| Mede | Temperatura, umidade, pressão | Temperatura, pressão |
| Temperatura | -40…+85 °C, ±1 °C (±0,5 °C a 25 °C) | -40…+85 °C, ±1 °C (±0,5 °C a 25 °C) |
| Umidade relativa | 0–100%, ±3% | Nenhuma |
| Faixa de pressão | 300–1100 hPa | 300–1100 hPa |
| Precisão da pressão | Absoluta ±1 hPa, relativa ±0,12 hPa (≈ ±1 m) | Absoluta ±1 hPa, relativa ±0,12 hPa (≈ ±1 m) |
| Tensão de alimentação do chip | 1,71–3,6 V | 1,71–3,6 V |
| Corrente (1 leitura por segundo) | 3,6 µA (as três medições) | 2,7 µA |
| Corrente em sleep | 0,1 µA | 0,1 µA |
| Interface | I2C (até 3,4 MHz) e SPI (até 10 MHz) | I2C e SPI |
| ID do chip (registrador 0xD0) | 0x60 | 0x58 |
| Tamanho do chip | 2,5 × 2,5 mm (quadrado) | 2,0 × 2,5 mm (retangular) |
Resumindo, o BMP280 é um BME280 um pouco mais barato, sem o sensor de umidade; as leituras de pressão e temperatura dele são igualmente boas. Se você só precisa de altitude ou de pressão do ar, um BMP280 basta. Para projetos em que a umidade importa, como uma estação meteorológica, uma estufa ou o monitoramento do clima de um cômodo, escolha o BME280. Um degrau acima na família, o BME680/BME688 acrescenta um sensor de gás que detecta compostos orgânicos voláteis (COVs) no ar, mas custa várias vezes mais.
BME280 ou DHT11/DHT22?
| Característica | DHT11 | DHT22 | BME280 |
|---|---|---|---|
| Faixa e precisão de temperatura | 0–50 °C, ±2 °C | -40…+80 °C, ±0,5 °C | -40…+85 °C, ±1 °C |
| Precisão de umidade | ±5% | ±2–5% | ±3% |
| Pressão e altitude | Não | Não | Sim |
| Leitura mais rápida | Uma vez por segundo | Uma vez a cada 2 segundos | Dezenas por segundo |
| Ligação | Um único fio de dados | Um único fio de dados | I2C ou SPI |
| Corrente (medindo) | ≈ 1 mA | ≈ 1,5 mA | Abaixo de 1 mA |
Os sensores DHT são baratos e simples, mas são lentos, de vez em quando dão erros de leitura e não medem pressão. O BME280 divide o mesmo barramento I2C com outros dispositivos, como um display, quase não consome corrente em sleep e é ideal para projetos que funcionam com bateria por meses. Para os detalhes do DHT11, veja sensor de temperatura e umidade DHT11 e, para ver todas as opções lado a lado, leia a comparação de sensores de temperatura.
Tipos de módulo e o aviso de 3,3 V
O chip sozinho é tão pequeno que sempre é usado em uma placa breakout, e dois tipos são comuns. Os módulos de 6 pinos (normalmente roxos e vendidos como GY-BME280-3.3 ou GY-BMP280-3.3) têm os pinos VCC, GND, SCL, SDA, CSB e SDO; a maioria não tem regulador, e o 3.3 do nome diz justamente isso: alimente-os só com 3,3 V. Os módulos de 4 pinos (VIN, GND, SCL, SDA) normalmente têm um pequeno regulador de 3,3 V e, muitas vezes, transistores de conversão de nível para as linhas I2C, então podem ir no pino 5V do Arduino Uno. Se não tiver certeza de qual tipo você tem, procure na placa um minúsculo chip regulador de três pernas; se não houver, use 3,3 V.
Ligação do BME280: Arduino Uno, ESP32 e Pico
| Pino do BME280 | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC / VIN | 3.3V (6 pinos) ou 5V (4 pinos, com regulador) | 3V3 | 3V3(OUT), pino 36 |
| GND | GND | GND | GND, pino 38 |
| SCL | A5 | GPIO 22 | GP5, pino 7 |
| SDA | A4 | GPIO 21 | GP4, pino 6 |
| CSB (6 pinos) | 3.3V (seleciona I2C) | 3V3 | 3V3 |
| SDO (6 pinos) | Aberto ou GND: 0x76, 3.3V: 0x77 | Aberto ou GND: 0x76, 3V3: 0x77 | Aberto ou GND: 0x76, 3V3: 0x77 |
O endereço é onde a maioria das pessoas empaca. Se o pino SDO do chip estiver no GND, o endereço é 0x76; se estiver em 3,3 V, é 0x77. A maioria dos módulos baratos puxa o SDO para o GND com um resistor, então o endereço deles é 0x76, enquanto as placas da própria Adafruit usam 0x77, e a biblioteca tenta 0x77 por padrão. Por isso você deve escrever o endereço explicitamente no código. Se o pino CSB estiver no GND na inicialização, o chip passa para o modo SPI e não responde no I2C; se você usa I2C, ligue o CSB em 3,3 V ou confira se o módulo já o puxa para cima. Você encontra os pinos I2C da sua placa na ferramenta Pinagem e a lógica do barramento I2C em O que é I2C?.
Se você quer dois sensores no mesmo barramento, ligue o pino SDO de um deles em 3,3 V para mudar o endereço para 0x77; nos módulos de 4 pinos, isso normalmente se faz com um jumper de solda no verso. Para mais de dois sensores, o SPI é mais adequado: o SCL vai no SCK (13 no Uno), o SDA no MOSI (11), o SDO no MISO (12), e o pino CSB de cada sensor vai em um pino digital próprio; no código, basta declarar o objeto como Adafruit_BME280 bme(10);. Como o Uno de 5 V aciona as linhas SPI diretamente, você precisa colocar um conversor de nível entre ele e um módulo de 3,3 V.
Instalando a biblioteca Adafruit BME280
- No Arduino IDE, abra Ferramentas > Gerenciar Bibliotecas e busque Adafruit BME280.
- Ao clicar em Instalar, escolha Instalar tudo na janela que pergunta sobre as dependências, para que a Adafruit Unified Sensor e a Adafruit BusIO também sejam instaladas.
- Se o seu sensor for um BMP280, instale do mesmo jeito a biblioteca Adafruit BMP280; a biblioteca do BME280 não reconhece o BMP280.
- Se quiser, abra Arquivo > Exemplos > Adafruit BME280 Library > bme280test, mas não se esqueça de colocar o endereço (0x76) na linha begin().
Primeiro sketch: lendo temperatura, umidade e pressão com o BME280
1#include <Wire.h>
2#include <Adafruit_Sensor.h>
3#include <Adafruit_BME280.h>
4
5#define DENIZ_SEVIYESI_HPA 1013.25 // bugünkü deniz seviyesi basıncı / today's sea-level pressure
6
7Adafruit_BME280 bme;
8
9void setup() {
10 Serial.begin(9600);
11 // Önce 0x76, olmazsa 0x77 dene / try 0x76 first, then 0x77
12 if (!bme.begin(0x76) && !bme.begin(0x77)) {
13 Serial.println(F("BME280 bulunamadi! Kablolari ve adresi kontrol et."));
14 Serial.print(F("Chip ID: 0x"));
15 Serial.println(bme.sensorID(), HEX); // 0x58 ise bu bir BMP280 / 0x58 means BMP280
16 while (true) delay(10);
17 }
18 Serial.println(F("BME280 hazir"));
19}
20
21void loop() {
22 float sicaklik = bme.readTemperature(); // °C
23 float nem = bme.readHumidity(); // % bağıl nem / % relative humidity
24 float basinc = bme.readPressure() / 100.0F; // Pa -> hPa
25 float irtifa = bme.readAltitude(DENIZ_SEVIYESI_HPA); // metre / meters
26
27 Serial.print(F("Sicaklik: ")); Serial.print(sicaklik, 1); Serial.println(F(" C"));
28 Serial.print(F("Nem: ")); Serial.print(nem, 1); Serial.println(F(" %"));
29 Serial.print(F("Basinc: ")); Serial.print(basinc, 1); Serial.println(F(" hPa"));
30 Serial.print(F("Irtifa: ")); Serial.print(irtifa, 0); Serial.println(F(" m"));
31 Serial.println();
32 delay(2000);
33}| Função | O que faz |
|---|---|
| bme.begin(0x76) | Inicia o sensor; retorna true se um dispositivo responder no endereço e o ID do chip for 0x60 |
| readTemperature() | Temperatura, °C |
| readHumidity() | Umidade relativa, % |
| readPressure() | Pressão, Pa (divida por 100 para hPa) |
| readAltitude(P0) | Altura em relação à pressão ao nível do mar P0 (hPa), em metros |
| seaLevelForAltitude(altitude, P) | Pressão ao nível do mar a partir de uma altitude conhecida, hPa |
| sensorID() | O ID do chip lido: 0x60 BME280, 0x58 BMP280 |
| setTemperatureCompensation(x) | Soma x °C a cada leitura de temperatura; umidade e pressão são corrigidas de acordo |
Quando você carrega o sketch e abre o Monitor Serial em 9600 baud, vê valores de mais ou menos 23,4 °C, 45% de umidade e 1009,8 hPa nas condições de um cômodo. A pressão muda devagar, ao longo de horas; sopre no sensor e você verá a umidade subir em segundos, toque nele com um dedo e a temperatura sobe. Por padrão, a biblioteca mede continuamente no modo normal com a maior sobreamostragem (x16); isso é ideal para um primeiro teste, mas, como você vai ver abaixo, outra configuração dá resultados mais precisos para medições meteorológicas de longo prazo.
Modos de medição: forced, normal e as configurações certas
O BME280 tem três modos. No modo sleep, ele não mede e consome 0,1 µA. No modo forced, ele faz uma única medição e volta a dormir; para cada valor novo, você chama takeForcedMeasurement(). No modo normal, ele continua medindo sozinho com o tempo de espera que você definir. A sobreamostragem (oversampling) mede o mesmo valor várias vezes e tira a média para reduzir o ruído, e o filtro IIR suaviza picos súbitos de pressão (uma porta batendo, uma rajada de vento). No datasheet, a Bosch recomenda estas configurações conforme o uso:
| Uso | Modo | Sobreamostragem (pressão / temperatura / umidade) | Filtro IIR | Corrente média |
|---|---|---|---|---|
| Monitoramento do tempo | Forced, 1 leitura por minuto | x1 / x1 / x1 | Desligado | ≈ 0,16 µA |
| Medição de umidade | Forced, 1 leitura por segundo | Pulada / x1 / x1 | Desligado | ≈ 2,9 µA |
| Navegação em ambientes internos (andares, elevadores) | Normal, espera de 0,5 ms | x16 / x2 / x1 | 16 | ≈ 633 µA |
Pressão ao nível do mar e cálculo da altitude
A pressão do ar cai conforme você sobe, então a altitude pode ser calculada a partir da pressão medida. A biblioteca usa esta fórmula barométrica: h = 44330 × (1 − (P / P0)^0,1903). Aqui, P é a pressão que você mede e P0 é a pressão atual ao nível do mar (as duas em hPa). A atmosfera padrão considera P0 = 1013,25 hPa, e perto do nível do mar uma diferença de 1 hPa corresponde a cerca de 8,3 metros.
O problema é que o P0 não é fixo; ele varia mais ou menos entre 990 e 1035 hPa conforme o tempo. Se o valor real hoje for 1023 hPa e você deixar 1013,25 no código, o sensor vai mostrar uma altitude cerca de 80 metros baixa demais. Para ter resultados precisos, você precisa manter o P0 atualizado: use o valor de “pressão ao nível do mar” informado pelos serviços de meteorologia ou o valor Q do boletim METAR do aeroporto mais próximo (por exemplo, Q1018, que significa 1018 hPa). Também dá para fazer o caminho inverso: se você sabe a altitude do seu local, calcule o P0 com seaLevelForAltitude(altitude, pressure). Por exemplo, se o sensor ler 905 hPa em Ancara (cerca de 938 m), a pressão reduzida ao nível do mar fica em cerca de 1012,6 hPa, que é o número que você vê nos apps de previsão do tempo.
Para a altitude absoluta, a precisão absoluta de ±1 hPa significa uma incerteza de cerca de ±8 metros. Nas medições relativas, porém, o sensor é muito melhor: ±0,12 hPa ≈ ±1 m. Um andar de prédio tem cerca de 3 metros, ou 0,36 hPa, então o BME280 consegue dizer com facilidade em que andar você está ou detectar um elevador em movimento. O sketch abaixo tira a média de 20 leituras na inicialização como referência e depois mostra a altura em relação a esse ponto e a pressão ao nível do mar calculada a partir de uma altitude conhecida:
1#include <Wire.h>
2#include <Adafruit_Sensor.h>
3#include <Adafruit_BME280.h>
4
5#define BILINEN_IRTIFA 938.0 // bulunduğun yerin rakımı (m), örnek Ankara / your altitude (m), e.g. Ankara
6
7Adafruit_BME280 bme;
8float referansHpa; // açılıştaki basınç / pressure at start-up
9
10void setup() {
11 Serial.begin(9600);
12 if (!bme.begin(0x76)) {
13 Serial.println(F("BME280 bulunamadi!"));
14 while (true) delay(10);
15 }
16 // İç mekan navigasyonu ayarı: düşük gürültü / indoor navigation preset: low noise
17 bme.setSampling(Adafruit_BME280::MODE_NORMAL,
18 Adafruit_BME280::SAMPLING_X2, // sıcaklık / temperature
19 Adafruit_BME280::SAMPLING_X16, // basınç / pressure
20 Adafruit_BME280::SAMPLING_X1, // nem / humidity
21 Adafruit_BME280::FILTER_X16, // IIR filtre / IIR filter
22 Adafruit_BME280::STANDBY_MS_0_5);
23 delay(1000); // filtre otursun / let the filter settle
24
25 float toplam = 0;
26 for (int i = 0; i < 20; i++) { // 20 ölçümün ortalaması / average of 20 readings
27 toplam += bme.readPressure() / 100.0F;
28 delay(50);
29 }
30 referansHpa = toplam / 20;
31}
32
33void loop() {
34 float basinc = bme.readPressure() / 100.0F; // istasyon basıncı / station pressure
35 float denizSeviyesi = bme.seaLevelForAltitude(BILINEN_IRTIFA, basinc); // hPa
36 float bagilYukseklik = bme.readAltitude(referansHpa); // başlangıca göre / relative to start
37
38 Serial.print(F("Istasyon basinci: ")); Serial.print(basinc, 2); Serial.println(F(" hPa"));
39 Serial.print(F("Deniz seviyesi (QNH): ")); Serial.print(denizSeviyesi, 1); Serial.println(F(" hPa"));
40 Serial.print(F("Baslangica gore: ")); Serial.print(bagilYukseklik, 2); Serial.println(F(" m"));
41 Serial.println();
42 delay(1000);
43}Se você pegar a placa do chão e levantá-la acima da cabeça, verá o valor “Baslangica gore” (em relação ao início) subir cerca de 2 metros. Como a pressão do ar muda alguns hPa ao longo do dia, essa leitura relativa deriva depois de algumas horas, então, no uso de longo prazo, você precisa atualizar a referência de vez em quando. Para acalmar ainda mais as leituras, você pode acrescentar a média móvel de filtragem de dados de sensores.
Miniestação meteorológica com ESP32: uma página web que você abre no celular
Graças ao Wi-Fi do ESP32, você pode ver as leituras do BME280 em uma página web de qualquer celular ou computador na mesma rede. O sketch abaixo usa a biblioteca WebServer que vem com o core do ESP32, então não precisa de biblioteca extra. A página principal carrega uma vez e, depois, um pequeno trecho de JavaScript dentro dela busca um JSON em /veri a cada 5 segundos e atualiza os valores sem recarregar a página. O sensor funciona no modo forced, então só faz uma medição quando alguém está olhando a página, e a pressão é mostrada reduzida ao nível do mar para você comparar com a previsão do tempo. Se é a sua primeira vez com o ESP32, comece por O que é o ESP32?.
- Ligue o BME280 como na tabela: VCC no 3V3, SDA no GPIO 21, SCL no GPIO 22.
- Coloque os dados da sua rede nos campos WIFI_ADI (nome da rede) e WIFI_SIFRE (senha) do código, e a altitude do seu local em RAKIM_M.
- Selecione ESP32 Dev Module como placa e carregue o sketch.
- Abra o Monitor Serial a 115200 baud; depois de conectado, ele mostra o endereço IP.
- Digite esse endereço (por exemplo, 192.168.1.42) no navegador de um celular na mesma rede Wi-Fi; aparecem cartões com temperatura, umidade e pressão.
1#include <WiFi.h>
2#include <WebServer.h>
3#include <Wire.h>
4#include <Adafruit_Sensor.h>
5#include <Adafruit_BME280.h>
6
7const char* WIFI_ADI = "WiFiAdin"; // kendi ağ adın / your network name
8const char* WIFI_SIFRE = "WiFiSifren"; // kendi şifren / your password
9const float RAKIM_M = 938.0; // bulunduğun yerin rakımı / your local altitude
10
11Adafruit_BME280 bme;
12WebServer server(80);
13
14// Telefonda açılan sayfa, 5 sn'de bir /veri'yi okur / phone page, reads /veri every 5 s
15const char SAYFA[] PROGMEM = R"rawliteral(
16<!DOCTYPE html><html><head><meta charset="utf-8">
17<meta name="viewport" content="width=device-width,initial-scale=1">
18<title>Mini Hava İstasyonu</title>
19<style>
20body{font-family:sans-serif;text-align:center;background:#0f172a;color:#e2e8f0;margin:0;padding:16px}
21.k{display:inline-block;min-width:140px;margin:8px;padding:16px;border-radius:14px;background:#1e293b}
22.d{font-size:2.2em;font-weight:bold;margin:6px 0}
23</style></head><body>
24<h2>Mini Hava İstasyonu</h2>
25<div class="k">Sıcaklık<div class="d" id="t">--</div>°C</div>
26<div class="k">Nem<div class="d" id="h">--</div>%</div>
27<div class="k">Basınç<div class="d" id="p">--</div>hPa</div>
28<script>
29async function guncelle() {
30 const v = await (await fetch('/veri')).json();
31 document.getElementById('t').textContent = v.t.toFixed(1);
32 document.getElementById('h').textContent = v.h.toFixed(0);
33 document.getElementById('p').textContent = v.p.toFixed(1);
34}
35guncelle();
36setInterval(guncelle, 5000);
37</script>
38</body></html>
39)rawliteral";
40
41void anaSayfa() {
42 server.send(200, "text/html", SAYFA);
43}
44
45void veriGonder() {
46 bme.takeForcedMeasurement(); // tek ölçüm al, sonra uyu / one measurement, then sleep
47 float p = bme.readPressure() / 100.0F;
48 String json = "{\"t\":" + String(bme.readTemperature(), 2) +
49 ",\"h\":" + String(bme.readHumidity(), 1) +
50 ",\"p\":" + String(bme.seaLevelForAltitude(RAKIM_M, p), 1) + "}";
51 server.send(200, "application/json", json);
52}
53
54void setup() {
55 Serial.begin(115200);
56 Wire.begin(21, 22); // SDA, SCL
57 if (!bme.begin(0x76)) {
58 Serial.println("BME280 bulunamadi!");
59 while (true) delay(10);
60 }
61 // Hava durumu izleme ayarı: kendi kendini ısıtmayı azaltır / weather monitoring preset: less self-heating
62 bme.setSampling(Adafruit_BME280::MODE_FORCED,
63 Adafruit_BME280::SAMPLING_X1, // sıcaklık / temperature
64 Adafruit_BME280::SAMPLING_X1, // basınç / pressure
65 Adafruit_BME280::SAMPLING_X1, // nem / humidity
66 Adafruit_BME280::FILTER_OFF);
67
68 WiFi.mode(WIFI_STA);
69 WiFi.begin(WIFI_ADI, WIFI_SIFRE);
70 while (WiFi.status() != WL_CONNECTED) {
71 delay(500);
72 Serial.print(".");
73 }
74 Serial.print("\nTarayicida ac / open in browser: http://");
75 Serial.println(WiFi.localIP());
76
77 server.on("/", anaSayfa);
78 server.on("/veri", veriGonder);
79 server.begin();
80}
81
82void loop() {
83 server.handleClient();
84}BME280 com o Raspberry Pi Pico (MicroPython)
O MicroPython não tem módulo embutido para o BME280. Em vez de baixar um arquivo de driver, o código abaixo traz um pequeno driver dentro dele: lê os coeficientes de calibração, faz o sensor tirar uma única medição no modo forced e calcula o resultado com as fórmulas do datasheet. Como ele verifica o ID do chip, também funciona com o BMP280 e pula sozinho a linha de umidade. Ligue o sensor no GP4 (SDA), no GP5 (SCL) e no 3V3(OUT) e salve o código no Pico pelo Thonny como main.py. Se o Pico é novidade para você, O que é o Raspberry Pi Pico? e fundamentos do MicroPython vão facilitar as coisas.
1from machine import Pin, I2C
2import struct, time
3
4i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
5ADR = 0x76 # olmazsa 0x77 dene / try 0x77 if it fails
6P0 = 1013.25 # deniz seviyesi basıncı (hPa) / sea-level pressure (hPa)
7
8def s8(x): # işaretli 8 bit / signed 8-bit
9 return x - 256 if x > 127 else x
10
11chip = i2c.readfrom_mem(ADR, 0xD0, 1)[0]
12BME = chip == 0x60 # 0x60 BME280, 0x58 BMP280
13print("Chip ID:", hex(chip), "BME280" if BME else "BMP280 (nem yok / no humidity)")
14
15# Fabrika kalibrasyon katsayıları / factory calibration coefficients
16T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9 = struct.unpack("<HhhHhhhhhhhh", i2c.readfrom_mem(ADR, 0x88, 24))
17if BME:
18 H1 = i2c.readfrom_mem(ADR, 0xA1, 1)[0]
19 e = i2c.readfrom_mem(ADR, 0xE1, 7)
20 H2 = struct.unpack("<h", e[0:2])[0]
21 H3 = e[2]
22 H4 = (s8(e[3]) << 4) | (e[4] & 0x0F)
23 H5 = (s8(e[5]) << 4) | (e[4] >> 4)
24 H6 = s8(e[6])
25 i2c.writeto_mem(ADR, 0xF2, b"\x01") # nem x1 (ctrl_meas'tan önce) / humidity x1 (before ctrl_meas)
26
27def oku():
28 i2c.writeto_mem(ADR, 0xF4, b"\x25") # sıcaklık x1, basınç x1, forced mod / temp x1, press x1, forced mode
29 time.sleep_ms(15) # ölçümün bitmesini bekle / wait for the measurement
30 d = i2c.readfrom_mem(ADR, 0xF7, 8 if BME else 6)
31 adc_p = (d[0] << 12) | (d[1] << 4) | (d[2] >> 4)
32 adc_t = (d[3] << 12) | (d[4] << 4) | (d[5] >> 4)
33
34 # Sıcaklık (datasheet formülü) / temperature (datasheet formula)
35 v1 = (adc_t / 16384 - T1 / 1024) * T2
36 v2 = (adc_t / 131072 - T1 / 8192) ** 2 * T3
37 t_fine = v1 + v2
38 t = t_fine / 5120
39
40 # Basınç, Pa / pressure, Pa
41 v1 = t_fine / 2 - 64000
42 v2 = v1 * v1 * P6 / 32768 + v1 * P5 * 2
43 v2 = v2 / 4 + P4 * 65536
44 v1 = (P3 * v1 * v1 / 524288 + P2 * v1) / 524288
45 v1 = (1 + v1 / 32768) * P1
46 p = 1048576 - adc_p
47 p = (p - v2 / 4096) * 6250 / v1
48 p = p + (P9 * p * p / 2147483648 + p * P8 / 32768 + P7) / 16
49
50 h = None
51 if BME: # nem, % / humidity, %
52 adc_h = (d[6] << 8) | d[7]
53 x = t_fine - 76800
54 x = (adc_h - (H4 * 64 + H5 / 16384 * x)) * (H2 / 65536 * (1 + H6 / 67108864 * x * (1 + H3 / 67108864 * x)))
55 x = x * (1 - H1 * x / 524288)
56 h = min(max(x, 0), 100)
57 return t, p / 100, h # °C, hPa, %
58
59while True:
60 t, p, h = oku()
61 irtifa = 44330 * (1 - (p / P0) ** 0.1903) # metre / meters
62 print("Sicaklik: %.1f C Basinc: %.1f hPa Irtifa: %.0f m" % (t, p, irtifa))
63 if h is not None:
64 print("Nem: %.1f %%" % h)
65 time.sleep(2)Vale notar alguns detalhes do código. A configuração de umidade (registrador 0xF2) só passa a valer depois de uma escrita no 0xF4, então a configuração de umidade é enviada primeiro e o comando de medição depois. O valor 0x25 escrito no 0xF4 significa “temperatura x1, pressão x1, modo forced”; com essas configurações, uma medição leva no máximo cerca de 10 ms, então esperar 15 ms basta. Testado com os valores de calibração de exemplo do datasheet do BMP280 da Bosch, o código retorna 25,08 °C e 1006,5 hPa, ou seja, os cálculos dele batem exatamente com as fórmulas da Bosch.
O BMP280 vendido como BME280: qual sensor você tem de verdade?
Como os dois chips cabem no mesmo desenho de placa, alguns vendedores vendem módulos BMP280 como BME280; às vezes a placa só diz “BME/BMP280”. O sintoma é sempre o mesmo: a biblioteca Adafruit BME280 mostra “Could not find a valid BME280 sensor, check wiring, address, sensor ID!” e, logo abaixo, SensorID was: 0x58. Outras bibliotecas não mostram erro, mas sempre informam a umidade como 0 ou nan. Não há nada de errado com a sua ligação; o chip que você tem é um BMP280, que não mede umidade.


- Olhe o formato do chip: se a tampa metálica for quadrada (2,5 × 2,5 mm), é um BME280; se for claramente retangular (2,0 × 2,5 mm), é um BMP280. Dê zoom com a câmera do celular e a diferença fica fácil de ver.
- Leia o ID do chip: o método mais confiável é o sketch abaixo; ele lê o ID no registrador 0xD0 do chip e diz qual sensor é.
- Fique de olho no preço: um BME280 genuíno custa bem mais que um BMP280, então desconfie de módulos “BME280” vendidos muito abaixo do preço de mercado.
1#include <Wire.h>
2
3void setup() {
4 Serial.begin(9600);
5 Wire.begin();
6 bool bulundu = false;
7
8 for (uint8_t adres = 0x76; adres <= 0x77; adres++) {
9 Wire.beginTransmission(adres);
10 if (Wire.endTransmission() != 0) continue; // bu adreste cihaz yok / no device at this address
11
12 Wire.beginTransmission(adres);
13 Wire.write(0xD0); // chip ID register'ı / chip ID register
14 Wire.endTransmission();
15 Wire.requestFrom(adres, (uint8_t)1);
16 uint8_t id = Wire.read();
17 bulundu = true;
18
19 Serial.print(F("Adres 0x"));
20 Serial.print(adres, HEX);
21 Serial.print(F(" Chip ID 0x"));
22 Serial.print(id, HEX);
23 if (id == 0x60) Serial.println(F(" -> BME280 (sicaklik + nem + basinc)"));
24 else if (id >= 0x56 && id <= 0x58) Serial.println(F(" -> BMP280 (nem olcmez)"));
25 else if (id == 0x61) Serial.println(F(" -> BME680 / BME688"));
26 else if (id == 0x55) Serial.println(F(" -> BMP180"));
27 else Serial.println(F(" -> bilinmeyen yonga / unknown chip"));
28 }
29
30 if (!bulundu) Serial.println(F("0x76 ve 0x77'de sensor yok: kablolari kontrol et"));
31}
32
33void loop() {
34}Se o resultado for 0x58, não se preocupe: as leituras de temperatura e pressão do BMP280 são tão boas quanto as do BME280. Instale a biblioteca Adafruit BMP280 e use o sketch abaixo; se precisar de umidade, acrescente um DHT22 separado ao projeto ou devolva o produto. De vez em quando você também encontra amostras de BMP280 com ID 0x56 ou 0x57; para elas, escreva a linha begin como bmp.begin(0x76, 0x56).
1#include <Wire.h>
2#include <Adafruit_BMP280.h>
3
4Adafruit_BMP280 bmp;
5
6void setup() {
7 Serial.begin(9600);
8 if (!bmp.begin(0x76) && !bmp.begin(0x77)) {
9 Serial.println(F("BMP280 bulunamadi! Kablolari ve adresi kontrol et."));
10 while (true) delay(10);
11 }
12 // Datasheet'in önerdiği varsayılan ayarlar / default settings from the datasheet
13 bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,
14 Adafruit_BMP280::SAMPLING_X2, // sıcaklık / temperature
15 Adafruit_BMP280::SAMPLING_X16, // basınç / pressure
16 Adafruit_BMP280::FILTER_X16, // IIR filtre / IIR filter
17 Adafruit_BMP280::STANDBY_MS_500); // bekleme süresi / standby time
18}
19
20void loop() {
21 Serial.print(F("Sicaklik: ")); Serial.print(bmp.readTemperature(), 1); Serial.println(F(" C"));
22 Serial.print(F("Basinc: ")); Serial.print(bmp.readPressure() / 100.0F, 1); Serial.println(F(" hPa"));
23 Serial.print(F("Irtifa: ")); Serial.print(bmp.readAltitude(1013.25), 0); Serial.println(F(" m"));
24 Serial.println();
25 delay(2000);
26}Ideias de projetos com BME280
- Estação meteorológica de mesa: mostre temperatura, umidade e pressão em um display OLED de 0,96 polegada ou em um LCD I2C que divida o mesmo barramento I2C.
- Previsão do tempo barométrica: registre a pressão a cada hora; uma queda de mais de 2 hPa em 3 horas costuma indicar piora do tempo, enquanto uma subida constante aponta para céu limpo.
- Ponto de orvalho e aviso de mofo: calcule o ponto de orvalho com a fórmula de Magnus (a = 17,62, b = 243,12 °C) e dispare um alerta quando a temperatura da parede chegar perto dele.
- Estufa inteligente: acione uma ventoinha ou uma bomba de nebulização conforme a umidade e a temperatura; detalhes no projeto de estufa inteligente com Arduino.
- Registrador de dados: grave as leituras em um módulo de cartão SD ou, com um ESP32, no Google Sheets e trace um gráfico semanal.
- Sensor para casa inteligente: envie os valores de um ESP32 para o Home Assistant via MQTT.
- Estação externa a bateria: acorde o ESP32 do deep sleep a cada 10 minutos; o BME280 consome só 0,1 µA dormindo.
- Contador de andares: use o sketch de altitude relativa para mostrar em que andar você chegou no elevador ou pela escada.
Erros comuns e como resolvê-los
| Sintoma | Causa provável | Solução |
|---|---|---|
| “Could not find a valid BME280 sensor”, SensorID 0x0 ou 0xFF | Endereço errado ou defeito na ligação | Use begin(0x76), confira se SDA e SCL não estão trocados e se o GND está ligado, rode um scanner I2C |
| Mesmo erro, SensorID 0x58 | O chip na verdade é um BMP280 | Use a biblioteca Adafruit BMP280 e acrescente um sensor separado para a umidade |
| fatal error: Adafruit_Sensor.h: No such file or directory (arquivo não encontrado) | Uma biblioteca de dependência não está instalada | Instale a biblioteca Adafruit Unified Sensor |
| As leituras são nan | Nenhuma medição nova pedida no modo forced, ou o begin() falhou | Chame takeForcedMeasurement() antes de cada leitura e confira o resultado do begin() |
| Temperatura 1–3 °C alta demais | Autoaquecimento pela medição contínua, calor de um ESP32 ou de um regulador próximo | Passe para o modo forced, afaste o sensor da placa, use setTemperatureCompensation() se precisar |
| Pressão baixa, de até 900 hPa | É a pressão da estação; ela cai conforme a altitude sobe | Reduza-a ao nível do mar com seaLevelForAltitude() para comparar com as previsões |
| Altitude errada em dezenas de metros | A pressão ao nível do mar ficou em 1013,25 | Coloque o P0 atual (QNH) ou calibre com uma altitude conhecida |
| Travamentos aleatórios com fios longos | O barramento I2C está longo e com ruído | Mantenha o cabo abaixo de 50 cm, reduza a velocidade do I2C ou use SPI |
O BME280 cuida de todas as medições básicas de uma estação meteorológica em uma pequena placa: primeiro confirme o endereço e o ID do chip, depois escolha o modo de medição conforme o seu objetivo e mantenha a pressão ao nível do mar atualizada para a altitude. No app BlueGrays você encontra projetos que dá para combinar com este guia, como medição de temperatura e umidade com DHT11 e DHT22, displays meteorológicos com ESP32, um registrador de temperatura e um servidor web no ESP32, cada um com esquemas do circuito e código passo a passo.
Perguntas frequentes
Qual é a diferença entre o BME280 e o BMP280?
O BME280 mede temperatura, umidade relativa e pressão; o BMP280 só mede temperatura e pressão e não tem sensor de umidade. A precisão de pressão e de temperatura dos dois é a mesma. Os chips também são diferentes: o BME280 é quadrado (2,5 × 2,5 mm), o BMP280 retangular (2,0 × 2,5 mm), e os IDs de chip são 0x60 e 0x58.
O endereço I2C do BME280 é 0x76 ou 0x77?
É 0x76 quando o pino SDO está ligado ao GND e 0x77 quando está ligado a 3,3 V. A maioria dos módulos baratos usa 0x76, enquanto as placas da Adafruit usam 0x77. A biblioteca da Adafruit tenta 0x77 por padrão, então talvez você precise escrever bme.begin(0x76) no código; se estiver em dúvida, rode um sketch scanner I2C.
O BME280 funciona com 5V?
O chip em si funciona com no máximo 3,6 V. A maioria dos módulos de 4 pinos marcados VIN tem regulador, então pode ser ligada no 5V. Alimente os módulos de 6 pinos de 3,3 V sem regulador só com 3,3 V; 5 V pode danificar o sensor.
Como resolvo “Could not find a valid BME280 sensor”?
Primeiro confira o valor de SensorID mostrado abaixo do erro. Se for 0x58, o seu sensor é um BMP280 e você deve usar a biblioteca Adafruit BMP280. Se for 0x0 ou 0xFF, é um problema de endereço ou de ligação: tente begin(0x76), garanta que SDA e SCL não estão trocados e que o pino CSB está em 3,3 V.
Qual é a precisão da medição de altitude do BME280?
Ele mede variações de altura relativa com cerca de ±1 m, o que basta para detectar uma mudança de andar. A altitude absoluta depende da pressão ao nível do mar que você informar; um erro de 1 hPa desloca o resultado em cerca de 8 m. Se você colocar o valor atual de QNH ou calibrar com uma altitude conhecida, consegue chegar a poucos metros.
Por que meu BME280 lê a temperatura alta demais?
As causas mais comuns são o autoaquecimento pela medição contínua e o calor de peças próximas, como o ESP32 ou um regulador. Passe para o modo forced, faça algumas leituras por minuto e afaste o sensor da placa com um cabo. Se sobrar uma diferença constante, compare com um termômetro confiável e corrija com setTemperatureCompensation().
Projetos para montar depois desta leitura
Ver todos os projetos
Temperatura e umidade com DHT11
Qual é a temperatura do seu quarto? O ar está úmido ou seco? O sensor DHT11 mede a temperatura e a umidade, e o Arduino mostra os valores em um display LCD de duas linhas, atualizando a cada poucos se

Temperatura e umidade com ESP32 e DHT22 (com display LCD)
Este projeto mede a temperatura e a umidade do ambiente com um sensor DHT22 e exibe os dados em tempo real em um LCD I2C 16x2. Os dados são lidos do sensor pelo protocolo de um fio (one-wire) com a biblioteca Adafruit DHT. Este projeto serve de base para estações meteorológicas IoT, automação residencial ou sistemas de monitoramento ambiental em estufas. A comunicação com o DHT22 é feita pelo pino GPIO 4 do ESP32.

Relógio, calendário e estação meteorológica de matriz de pontos (MAX7219, DS1307)
Um painel com texto em rolagem para sua mesa ou parede que mostra, em sequência, a hora, a data e as condições do ambiente. No display LED 8x32, você vê primeiro a temperatura em Celsius e Fahrenheit,

Registrador de temperatura com ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
Monte um registrador de temperatura com data e hora usando ESP32! Leia a temperatura e a umidade do DHT22 a cada minuto, obtenha a hora real do DS1307 RTC e grave os dados em CSV no cartão microSD. O OLED exibe a temperatura atual em letras grandes, a porcentagem de umidade, a data e a hora e o contador de registros. O arquivo /temp_log.csv no cartão SD pode ser aberto no Excel, Google Sheets ou pandas do Python para análise — ideal para monitorar estufas, acompanhar a temperatura de casa ou…

ESP32 HTTPClient + API de clima (com display OLED SSD1306)
Neste projeto, usamos o ESP32 para fazer uma chamada REST à API de clima wttr.in pela internet com HTTPClient.h. Diferentemente da versão anterior com LCD I2C, aqui usamos um display OLED SSD1306 (128×64), que permite usar fontes grandes, ícones vetoriais e uma apresentação visual rica em uma única tela. Sete ícones vetoriais de condições do tempo (ensolarado, parcialmente nublado, nublado, chuvoso, com neve, com tempestade e com neblina) são desenhados durante a execução, sem arquivos bitmap.

Servidor web assíncrono com ESP32 (IP no LCD)
Neste projeto, transformamos o ESP32 em um servidor web assíncrono que você pode controlar pelo celular ou computador na mesma rede Wi-Fi. Com a biblioteca ESPAsyncWebServer, o servidor processa várias requisições ao mesmo tempo (ao contrário do WebServer.h tradicional, que bloqueia a execução ao processar uma requisição). Você poderá abrir o endereço IP do ESP32 no navegador e clicar nos botões ON/OFF (as rotas /on e /off) para ligar e desligar o LED conectado ao GPIO 5.

ESP32 HTTPClient + API de clima (com display LCD)
Neste projeto, usamos o ESP32 para fazer uma chamada REST à API de clima wttr.in pela internet com HTTPClient.h. Interpretamos a resposta JSON com ArduinoJson v7 e mostramos cidade, temperatura, umidade, condições do tempo e vento em um display LCD I2C, em turco e inglês. O wttr.in é grátis e não exige chave de API — basta informar o nome de uma cidade para consultar o clima atual. Os dados se atualizam sozinhos a cada 30 minutos, e o LED dá um retorno visual diferente para cada tela.

Display LCD I2C com ESP32 (16x2)
Neste projeto, exibimos texto conectando um display LCD de 16x2 caracteres ao ESP32 pelo protocolo I2C. Com o I2C, controlamos o display usando apenas dois pinos de dados (SDA e SCL), dispensando o uso de seis ou mais pinos da conexão paralela tradicional. O código mostra uma mensagem fixa na primeira linha e um contador que aumenta a cada segundo na segunda linha. Na inicialização, também executamos um scanner I2C para mostrar o endereço do display no Monitor Serial (geralmente 0x27 ou 0x3F).
Mais artigos
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

