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.

6 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