Interface PIC MCU com sensor de temperatura e pressão BMP280

Tempo de leitura: 7 minutes

Este post mostra como fazer a interface do microcontrolador Microchip PIC16F877A com o sensor de temperatura e pressão barométrica BMP280. Os valores da temperatura e da pressão são exibidos na tela LCD 16×2 conectada ao microcontrolador.

Neste projeto é utilizado o sensor BMP280 em modo I2C e o compilador utilizado é o CCS PIC C.

O sensor BMP280 da Bosch Sensortec é um sensor de pressão e temperatura de baixo custo com boa precisão. Como a pressão muda com a altitude, podemos usá-lo como um altímetro com precisão de ±1 metro (precisão de pressão = ±1 hPa). Alguns parâmetros do sensor estão listados abaixo:

Faixa de pressão: 300…1100 hPa (equivalente a +9000…-500m acima/abaixo do nível do mar)
Resolução de pressão: 0,01 hPa ( < 10 cm)
Faixa de temperatura: -40…85 °C
Resolução de temperatura: 0,01 °C
Interface: I2C e SPI

O chip BMP280 funciona com tensão máxima de 3,6V (faixa de tensão de alimentação é de 1,71 a 3,6V), o que significa que temos que usar um regulador de tensão 3V3 para alimentá-lo de uma fonte de 5V.
Além disso, se estivermos trabalhando com um sistema de 5V (placa de desenvolvimento, microcontrolador…) como o microcontrolador PIC16F877A, temos que usar um deslocador de nível de tensão (conversor de nível) que converte os 3,3V (vem do chip BMP280) em 5V (vai para o MCU PIC16F877A) e vice-versa. Este deslocador de nível é para as linhas de barramento I2C (relógio e dados).

Alguns módulos BMP280 vêm com regulador de tensão 3V3 e seletor de nível como o fornecido pela Adafruit Industries, mostrado abaixo.

Um módulo como este pode ser usado com sistema de 3,3V ou 5V sem nenhum problema.

Neste exemplo vou usar um módulo BMP280 chinês que veio com regulador de 3,3V e nivelador, essa conexão do homem será mais fácil!

 

Driver BMP280 para compilador CCS C:

Para simplificar o código C, escrevi um driver simples (biblioteca) para o sensor BMP280. Com este driver a interface é mais fácil.

Funções do Driver:

BMP280_begin(mode, T_sampling, P_sampling, filter, standby): esta função inicializa o sensor BMP280 com as 5 configurações (mode, T_sampling, P_sampling, filtro e standby), retorna 1 se OK e 0 se erro:
modo é o modo sensor que pode ser: MODE_SLEEP, MODE_FORCED ou MODE_NORMAL

T_sampling é oversampling de temperatura e P_sampling é oversampling de pressão, cada um deles pode ser uma das seguintes listas (o padrão da biblioteca é SAMPLING_X1):
SAMPLING_SKIPPED —> ignorado, saída definida como 0x80000
SAMPLING_X1 —> sobreamostragem x1
SAMPLING_X2 —> sobreamostragem x2
SAMPLING_X4 —> sobreamostragem x4
SAMPLING_X8 —> sobreamostragem x8
SAMPLING_X16 —> sobreamostragem x16

Filtro define a configuração do filtro IIR do sensor BMP280, pode ser (o padrão da biblioteca é FILTER_OFF):
FILTER_OFF —> filtrar
FILTER_2 —> coeficiente de filtro = 2
FILTER_4 —> coeficiente de filtro = 4
FILTER_8 —> coeficiente de filtro = 8
FILTER_16 —> coeficiente de filtro = 16

standby é o tempo de espera do sensor BMP280 (o padrão da biblioteca é STANDBY_0_5):
STANDBY_0_5 —> tempo de espera = 0,5 ms
STANDBY_62_5 —> tempo de espera = 62,5 ms
STANDBY_125 —> tempo de espera = 125 ms
STANDBY_250 —> tempo de espera = 250 ms
STANDBY_500 —> tempo de espera = 500 ms
STANDBY_1000 —> tempo de espera = 1000 ms
STANDBY_2000 —> tempo de espera = 2000 ms
STANDBY_4000 —> tempo de espera = 4000 ms

Exemplos:
A linha a seguir inicializa o sensor BMP280 no modo normal, sobreamostragem de temperatura = X2, sobreamostragem de pressão = X16, coeficiente de filtro IIR = 4 e tempo de espera = 125 ms:
BMP280_begin(MODE_NORMAL, SAMPLING_X2, SAMPLING_X16, FILTER_4, STANDBY_125);

e a linha a seguir inicializa o sensor BMP280 no modo normal, sobreamostragem de temperatura = X1, sobreamostragem de pressão = X1, filtro IIR desligado e tempo de espera = 0,5 ms onde as configurações padrão são usadas:
BMP280_begin(MODE_NORMAL);

BMP280_ForcedMeasurement(): esta função é utilizada para iniciar uma nova conversão de medição, utilizada somente no modo forçado. Retorna 1 se estiver ok e 0 se houver erro (o sensor não está em modo de suspensão).

BMP280_readTemperature(int32_t *temp): lê a temperatura do sensor BMP280. A temperatura é armazenada em centésimos °C (o valor de saída de “5123” é igual a 51,23 °C). O valor da temperatura é salvo em *temp, retorna 1 se estiver OK e 0 se houver erro.

BMP280_readPressure(uint32_t *pres): lê a pressão do sensor BMP280. A pressão é armazenada em Pa (o valor de saída de “96386” é igual a 96386 Pa = 963,86 hPa). O valor da pressão é salvo em *pres, retorna 1 se estiver OK e 0 se houver erro.

Driver BMP280 para download do compilador CCS C:
O link de download do arquivo de origem do driver está abaixo, a instalação deste driver é fácil, basta adicioná-lo à pasta do projeto ou pasta de drivers CCS C (por exemplo C:\Program Files (x86)\CCS\Drivers). O nome do driver é: BMP280_Lib.c.

BMP280_Lib_c

Interface do microcontrolador PIC16F877A com o sensor BMP280:

Este é um exemplo que mostra como fazer a interface do sensor BMP280 com o PIC MCU e mostra como usar o driver do dispositivo.

Hardware Necessário:

  • Microcontrolador PIC16F877A
  • Módulo sensor BMP280 com regulador de 3,3V e alavanca de nível —-> folha de dados BMP280
  • 1602 tela LCD
  • oscilador de cristal de 8 MHz
  • 2 x capacitor cerâmico de 22pF
  • Resistor variável de 10k ohm (ou potenciômetro)
  • resistor de 330 ohms
  • resistor de 10k ohms
  • Fonte de 5V
  • Protoboard
  • Fios de ligação

O diagrama esquemático do circuito de exemplo é mostrado abaixo.
Observe que o módulo BMP280 mostrado no diagrama de circuito possui um regulador de 3,3 V e um seletor de nível.

Geralmente, o módulo BMP280 possui pelo menos 4 pinos, pois pode funcionar no modo SPI ou no modo I2C. Para o modo I2C precisamos de 4 pinos: VCC, GND, SCL e SDA onde:
GND (terra) está conectado ao terra do circuito (0V)
VCC é o pino de alimentação, está conectado a +5V
SCL é a linha de clock serial do barramento I2C, conectada ao pino PIC16F877A RC3 (#18)
SDA é uma linha de dados serial de barramento I2C, conectada ao pino PIC16F877A RC4 (#23).

A tela LCD 1602 é usada para exibir valores de temperatura e pressão onde:
RS —> pino RD0
RW —> pino RD1
E —> pino RD2
D4 —> pino RD3
D5 —> pino RD4
D6 —> pino RD5
D7 —> pino RD7
VSS, RW, D0, D1, D2, D3 e K são conectados ao terra do circuito
VEE para a saída do resistor variável (ou potenciômetro)
VDD para +5V e A para +5V através de resistor de 330 ohm.

O pino VEE é usado para controlar o contraste do LCD. A (ânodo) e K (cátodo) são os pinos do LED da luz de fundo.

Neste projeto o microcontrolador PIC16F877A roda com oscilador de cristal de 8 MHz.

Interface PIC16F877A com código C do sensor BMP280:

O código C abaixo é para o compilador CCS C, foi testado com a versão 5.051.

Para poder compilar o código C do projeto, é necessário um driver para o sensor BMP280, o link para download está acima.

Depois de baixar o arquivo de driver chamado BMP280_Lib.c, adicione-o à pasta do seu projeto!

Como qualquer outro dispositivo I2C, o sensor BMP280 possui um endereço escravo I2C que é 0xEC ou 0xEE. Este endereço depende da conexão do pino SDO (usado para o modo SPI como saída de dados serial ou MISO), se o pino SDO estiver conectado (diretamente ou através de resistor) ao VCC (3.3V) o endereço será 0xEE, e se for conectado ao GND o endereço será 0xEC.

O endereço I2C padrão da biblioteca é definido como 0xEE e o endereço I2C do meu dispositivo é 0xEC.
No código a definição do endereço do escravo I2C é mostrada abaixo:

// define device I2C address: 0xEC or 0xEE (0xEE is library default address)
#define BMP280_I2C_ADDRESS  0xEC

A inicialização do sensor BMP280 é feita através da função BMP280_begin(MODE_NORMAL) que retorna 1 se OK e 0 se erro. No código a inicialização do sensor é mostrada abaixo:

// initialize the BMP280 sensor
if(BMP280_begin(MODE_NORMAL) == 0)
{  // connection error or device address wrong!
  lcd_gotoxy(1, 1);    // go to column 1 row 1
  lcd_putc("Connection");
  lcd_gotoxy(1, 2);    // go to column 1 row 2
  lcd_putc("error!");
  while(TRUE);  // stay here
}

O LCD exibe “erro de conexão!” se houve um erro com a inicialização do dispositivo.

A leitura dos valores de temperatura e pressão é feita conforme mostrado abaixo.
Observe que a biblioteca retorna a temperatura em centésimos °C o que significa que temos que dividir por 100 e ela retorna a pressão em Pa, para obter a pressão em hPa temos que dividir por 100.

// Read temperature (in hundredths C) and pressure (in Pa)
// values from BMP280 sensor
BMP280_readTemperature(&temperature);  // read temperature
BMP280_readPressure(&pressure);        // read pressure

Os valores de temperatura e pressão são exibidos na tela LCD 16×2.

1 bar = 10.000 Pa = 100 hPa. (1 hPa = 100 Pa)
Pa: Pascal
hPa: hectoPascal

Código CCS C Completo:

/*
 * Interfacing PIC16F877A microcontroller with BMP280 temperature and pressure sensor.
 * C Code for CCS C compiler.
 * Temperature and pressure values are displayed on 16x2 LCD.
 * This is a free software with NO WARRANTY.
 */

// define device I2C address: 0xEC or 0xEE (0xEE is library default address)
#define BMP280_I2C_ADDRESS  0xEC

// LCD module connections
#define LCD_RS_PIN      PIN_D0
#define LCD_RW_PIN      PIN_D1
#define LCD_ENABLE_PIN  PIN_D2
#define LCD_DATA4       PIN_D3
#define LCD_DATA5       PIN_D4
#define LCD_DATA6       PIN_D5
#define LCD_DATA7       PIN_D6
// end LCD module connections

#include <16F877A.h>
#fuses HS, NOWDT, NOPROTECT, NOLVP                       
#use delay(clock = 8MHz)
#use I2C(MASTER, I2C1, FAST = 400000, STREAM = BMP280_STREAM)
#include <BMP280_Lib.c>  // include BMP280 sensor driver source file
#include <lcd.c>         // include LCD driver source file

signed int32 temperature;
unsigned int32 pressure;

void main()
{
  delay_ms(1000);  // wait 1 second

  lcd_init();       // initialize LCD module
  lcd_putc('\f');   // clear the LCD

  // initialize the BMP280 sensor
  if(BMP280_begin(MODE_NORMAL) == 0)
  {  // connection error or device address wrong!
    lcd_gotoxy(1, 1);    // go to column 1 row 1
    lcd_putc("Connection");
    lcd_gotoxy(1, 2);    // go to column 1 row 2
    lcd_putc("error!");
    while(TRUE);  // stay here
  }

  lcd_gotoxy(1, 1);    // go to column 1 row 1
  lcd_putc("Temp:");
  lcd_gotoxy(1, 2);    // go to column 1 row 2
  lcd_putc("Pres:");
  
  while(TRUE)
  {
    // Read temperature (in hundredths C) and pressure (in Pa)
    // values from BMP280 sensor
    BMP280_readTemperature(&temperature);  // read temperature
    BMP280_readPressure(&pressure);        // read pressure

    // print data on the LCD screen
    // 1: print temperature
    lcd_gotoxy(6, 1);    // go to column 6 row 1
    if(temperature < 0)
    {
      lcd_putc('-');
      temperature = abs(temperature);
    }
    else
      lcd_putc(' ');

    printf(lcd_putc, "%02Lu.%02Lu%cC", temperature / 100, temperature % 100, 223);

    // 2: print pressure
    lcd_gotoxy(7, 2);    // go to column 7 row 1
    printf(lcd_putc, "%04Lu.%02LuhPa", pressure/100, pressure % 100);

    delay_ms(2000);  // wait 2 seconds

  }

}
// end of code.