26 abril 2017

Use o BMP280 para medir temperatura, pressão e altitude

O sensor de pressão e temperatura BMP280 é o sucessor dos sensores BMP085 e BMP180, com excelentes ganhos em termos de precisão e reduzido consumo de energia, mantendo o baixo custo.

Sensor de temperatura e pressão BMP280

O BMP280 realiza medições de pressão com precisão de ±1 hPa e temperatura com precisão de ±1 °C. Com essa precisão, é possível realizar medições de altitude com margem de erro de ±1 metro, e vamos fazer isso neste post, usando o sensor para mostrar os valores de temperatura, pressão e altitude em um display OLED.

O hardware do módulo BMP280


O antigo sensor BMP180 foi redesenhado pela Bosch, resultando no BMP280 (datasheet) com um tamanho significativamente menor, trazendo excelentes ganhos em termos de consumo de energia tornando-o ideal para projetos operados por baterias por longos períodos, como por exemplo drones e estações meteorológicas.

Com relação à medição de pressão, o BMP280 efetua a leitura entre 300 e 1100hPa, o que corresponde à faixa de altitude de +9000 à -500 m.

Na imagem abaixo mostramos a pinagem do módulo BMP280, que funciona com interfaces SPI e I2C.

Pinagem BMP280

Temos os pinos de alimentação (Vcc (3.3V) e GND), e os pinos de interface SPI: SCL (Clock) e SDA (Data), CSB (Chip Select) e SDO (Serial Data OUT). 

Para conectar o módulo usando a interface I2C, usamos os mesmos pinos SCL e SDA que já estamos acostumados a ver em outros projetos, mais o pino SDO para seleção do endereço I2C, que é 0x76 com o pino em estado baixo (LOW), e 0x77 para o pino em estado alto (HIGH).

Usando o BMP280 com Arduino Uno


No nosso circuito de testes vamos usar um Arduino Uno com o BMP280 e um display OLED compartilhando o barramento I2C. Isso libera os demais pinos do Arduino Uno para outros sensores, o que é muito útil por exemplo se quisermos montar uma estação meteorológica com sensor de umidade, sensor UV, anemômetro, etc.

Circuito Arduino Uno BMP280 e Display OLED


Neste exemplo vamos usar o endereço 0x77 da interface I2C, mantendo o pino SDO em nível alto (HIGH), conectado ao pino 3.3V, que é o mesmo usado para alimentação do módulo. Os pinos SCL e SDA estão conectados aos pinos analógicos A4 e A5 do Arduino.

Instalação das bibliotecas


Para o programa de teste vamos usar as bibliotecas Adafruit Unified SensorAdafruit BMP280 e U8GLIB, fazendo a instalação por meio do Gerenciador de Bibliotecas da IDE do Arduino (estamos usando a IDE versão 1.8.1).

Primeiramente, acesse o menu Sketch, depois Incluir Biblioteca e finalmente Gerenciar Bibliotecas:

IDE Arduino - Gerenciar Bibliotecas


Dentro do Gerenciador de Biblioteca, digite na caixa do lado direito "Adafruit BMP280". A biblioteca da Adafruit será exibida logo abaixo, bastando que você clique em Instalar para que a mesma seja incluída na IDE:

Biblioteca Adafruit BMP280


Faça o mesmo procedimento para a próxima biblioteca, digitando "Unified Sensor based libraries" na caixa de seleção:

Biblioteca Adafruit Sensor

E por último, repita o procedimento para a biblioteca U8GLIB. Finalizada a instalação, podemos carregar o nosso programa de teste.

Programa BMP280 e Arduino


O programa usa as três bibliotecas adicionadas anteriormente, sendo que a U8Glib é a responsável pelos comandos do display gráficos, e as duas bibliotecas da Adafruit ficam encarregadas da comunicação com o sensor BMP280:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//Programa: Temperatura, Pressao e Altitude com BMP280
//Autor: Arduino e Cia

#include <Wire.h>
#include <U8glib.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 sensor_bmp;

//Definicoes do display Oled
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_FAST);

void draw()
{
  //Comandos graficos para o display devem ser colocados aqui
  u8g.setFont(u8g_font_8x13B);
  u8g.drawRFrame(0, 16, 128, 48, 4);
  u8g.drawRFrame(0, 0, 128, 16, 4);
  u8g.drawStr(40, 13, "BMP280");
  //Mostra a temperatura
  u8g.drawStr(10, 31, "Temp:      C");
  u8g.drawCircle(93, 22, 2); //Grau
  u8g.setPrintPos(55, 31);
  u8g.print(sensor_bmp.readTemperature(), 1);
  //Mostra a pressao (em hPa)
  u8g.drawStr(10, 45, "Pres:");
  u8g.setPrintPos(55, 45);
  u8g.print(sensor_bmp.readPressure(), 1);
  //Mostra a altitude
  u8g.drawStr(10, 59, "Alt :       m");
  u8g.setPrintPos(55, 59);
  u8g.print(sensor_bmp.readAltitude(1013.25));
}

void setup()
{
  Serial.begin(9600);
  Serial.println("Teste modulo BMP280");

  //Verifica a conexão do sensor BMP280
  if (!sensor_bmp.begin())
  {
    Serial.println("Sensor não encontrado. Verifique as conexoes!");
    while (1);
  }

  //Display Oled
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255, 255, 255);
  }
}

void loop()
{
  //Chama a rotina de desenho na tela
  u8g.firstPage();
  do
  {
    draw();
  }
  while ( u8g.nextPage() );
  delay(10000);
}

Após o carregamento do programa, as informações de temperatura, pressão e altitude medidas pelo módulo serão exibidas no display Oled, conforme mostra a imagem do início deste post.

10 comentários:

  1. Muito Obrigado, ja estava ficando doido tentando fazer meu sensor funcionar... baixei os manuais e montei tudo numa placa, mandei fabricar na oshpark, passei hrs soldando mas no fim nao funcionava... mas esse tutorial me resolveu!!! muito obrigado!!!

    ResponderExcluir
  2. Olá, o tutorial de vocês é ótimo muito bem explicado, parabéns.
    Porém preciso de uma ajuda com relação a uma duvida, como eu faço para ligar mais de um sensor no mesmo barramento I2C?
    Eles possuem o mesmo endereço?

    Agradeço desde já

    ResponderExcluir
    Respostas
    1. Boa noite,

      Você pode mudar o endereço I2C aplicando tensão (3.3V) no pino SDO (o endereço I2C será então 0x77, se conectar o pino SDO ao GND, o endereço I2C será 0x76, ok?

      Abraço!

      Adilson

      Excluir
  3. Percebi que alguns caracteres estavam sendo desenhados errados... Então pesquisei e descobri a razão... Os valores devem ser obtidos fora da rotina de Draw()... A rotina para desenhar a imagem na tela foi feita para economizar memória... Então o autor da rotina (U8GLIB) fez um loop, que repete 8 vezes e a cada vez ele envia uma parte da tela de 128x8 bits... Assim ele economiza memoria, pois só precisa guardar 128x8 e não 128x64 bits... O problema é que a imagem não pode variar entre a primeira execução e a última execução do loop... Por isso a necessidade dos valores estarem estaticos durante esse loop.

    ResponderExcluir
  4. Boa tarde sou leigo no assunto precisava enviar os dados do bmp280 para o celular via Bluetooth podem me informar um progama para tal obrigado

    ResponderExcluir
  5. Boa tarde muito bom o tutorial sou leigo no assunto estou tendo uma dificuldade de um programa para enviar os dados do BMP280 para o cel via Bluetooth consigo realizar a conecção com o modulo mas não estou consequindo enviar os dados se puderem me dar uma luz obrigado.

    ResponderExcluir
  6. Olá amigos preciso de um projeto para um indicador de pressão de fluidos com display para leitura e um botão pra zerar a leitura , podem me ajudar ?

    ResponderExcluir
  7. Olá!
    Parabéns pelo conteúdo! Funcionou perfeitamente.
    No entanto, por se tratar de um instrumento, penso que as vezes necessite de calibração, pois eu fiz a aferição barométrica na praia, literalmente, deitado na minha esteira na areia, e obtive -73m (73 metros negativos).
    Minha pergunta é: Esta alteração é linear? ou seja, basta eu fazer a aferição em um local de altitude conhecida e utilizar um valor de correção (neste caso, poderia ser : f(h) = h + 73, com h = Altitude), para desta forma obtermos o valor 0, que é o esperado ao nível do mar e aplicarmos a mesma função na pressão atmosférica em regra de três, sabendo que a altitude (h) está associada com a pressão atmosférica (utilizando a grandeza ATM para facilitar os cálculos), considerando que ao nível do mar temos a pressão de 1 ATM (ATMreal) e obtemos h a partir de um coeficiente k (h = ATM*k, portanto: ATMreal = 1 - (h + 73)/k), ou seja, com h + 73, para h = (-)73, o valor da equação é zero, que subtraído de 1, é igual a 1 atmosfera, o valor esperado de pressão atmosféric para lo nível do mar.
    É assim simples ou esta questão é mais complexa e estas alterações não são lineares, ou seja, possuem proporcionalidade exponencial ao aumento e/ou diminuição da pressão atmosférica, sendo que teríamos que plotar um gráfico com várias altitudes conhecidas, digamos, 0, 100, 300, 500, 1000, 1500 e aplicar uma função não linear para descobrirmos a função f(h)?

    Abs

    Samuel Vaz

    ResponderExcluir