행복한 하루
라즈베리파이 제로 프로젝트(15) – Pioneer600 모듈 (BMP280) 본문
안녕하세요.
이번에는 부착된 기압을 측정하는 센서를 이용해보도록 하겠습니다.
Pioneer600 소스상에는 BMP180도 있고 BMP280도 있습니다. 그러나 실제 장착된 것은 BMP280이므로 이 모듈로 확인해보겠습니다.
(소스코드가 Pioneer600 제품에서만 동작되는 것이 아니라, I2C로 BMP280 모듈을 연결하면 사용할 수 있으니 소스코드를 참고하시면 조금이나마 도움되지 않을까 합니다.)
1. 기압 센서 란
- BMP180 센서 테스트하면서 찾은 자료가 있어 링크로 대신하겠습니다.
https://remnant24c.tistory.com/175
2. BMP280 스펙
- Pressure range 300 … 1100 hPa (equiv. to +9000…-500 m above/below sea level)
- Package 8-pin LGA metal-lid Footprint : 2.0 × 2.5 mm², height: 0.95 mm
- Relative accuracy ±0.12 hPa, equiv. to ±1 m (950 … 1050 hPa @25°C)
- Absolute accuracy typ. ±1 hPa (950... 1050 hPa, 0...+40 °C)
- Temperature coefficient offset 1.5 Pa/K, equiv. to 12.6 cm/K (25... 40°C @900hPa)
- Digital interfaces I²C (up to 3.4 MHz) SPI (3 and 4 wire, up to 10 MHz)
- Current consumption 2.7 µA @ 1 Hz sampling rate
- Temperature range -40 … +85 °C
3. BMP180과 BMP280 차이
- 아래의 표에서도 알 수 있듯이 BMP280이 사이즈도 작아지고, 정확도와 통신 지원하는 것도 향상되었다는 것을 알 수 있습니다.
4. 회로도
- I2C로 통신하도록 되어 있고 기본 주소는 0x76으로 되어 있습니다.
- 핀 설명 (Pin Description)
5. 연결하기
- I2C 통신 장점 중 하나가 통신선만 연결하면 여러 모듈을 주소로 접근할 수 있다는 것입니다. 그래서 이전 내용과 같이 I2C로 핀으로 연결하면 됩니다.
- 핀 배열이 동일하기 때문에 쉽게 연결할 수 있습니다. (1, 3, 5, 9)
6. 소스 확인
- 소스가 약간 복잡할 수 있는데, wiringPi 기준으로 크게 보면 bmp280.h 파일에 레지스터 주소를 선언해두었고, bmp280에 구현이 되어 있습니다.
- bmp280.c 에는 I2C_readByte(), I2C_readU16(), I2C_readS16() 함수가 있는데 바이트 형태 8bit로 받을지 16bit(LSB, MSB) 구분해서 처리할지, 부호 있는 값인지에 따라서 구현이 되어 있습니다.
- load_calibration() 해더 파일에 정의된 주소로 보정 값들을 읽어 출력해줍니다.
- BSP_BMP280_Init() bmp280 모드 등 초기 설정 값을 칩에다가 전달해줍니다. (모드 상세한 내용은 데이터 시트를 참조해야 합니다. 아래 첨부파일 참고)
- compensate_temperature(), compensate_pressure() 읽어 드린 ADC 온도와 기압 값에 보정 값을 넣어 계산 후 출력할 온도와 기압 값을 리턴해줍니다.
- 메인 함수에서 get_temperature_and_pressure() 함수에 포인터로 전달해서 값을 읽어와서 출력해줍니다.
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <math.h>
#include "bmp280.h"
short dig_T2,dig_T3,dig_P2,dig_P3,dig_P4,dig_P5,dig_P6,dig_P7,dig_P8,dig_P9;
unsigned short dig_T1,dig_P1;
int t_fine;
int fd;
/******************* BMP280 Driver Interface *****************************/
char I2C_readByte(int reg)
{
return (char)wiringPiI2CReadReg8(fd,reg);
}
unsigned short I2C_readU16(int reg)
{
int MSB,LSB;
LSB = I2C_readByte(reg);
MSB = I2C_readByte(reg + 1);
int value = (MSB << 8) +LSB;
return (unsigned short)value;
}
short I2C_readS16(int reg)
{
int result;
result = I2C_readU16(reg);
if (result > 32767)result -= 65536;
return (short)result;
}
void I2C_writeByte(int reg,int val)
{
wiringPiI2CWriteReg8(fd,reg,val);
}
/******************* BMP280 operation functions *****************************/
void load_calibration()
{
/* read the temperature calibration parameters */
dig_T1 = I2C_readU16(BMP280_DIG_T1_LSB_REG);
dig_T2 = I2C_readS16(BMP280_DIG_T2_LSB_REG);
dig_T3 = I2C_readS16(BMP280_DIG_T3_LSB_REG);
/* read the pressure calibration parameters */
dig_P1 = I2C_readU16(BMP280_DIG_P1_LSB_REG);
dig_P2 = I2C_readS16(BMP280_DIG_P2_LSB_REG);
dig_P3 = I2C_readS16(BMP280_DIG_P3_LSB_REG);
dig_P4 = I2C_readS16(BMP280_DIG_P4_LSB_REG);
dig_P4 = I2C_readS16(BMP280_DIG_P4_LSB_REG);
dig_P5 = I2C_readS16(BMP280_DIG_P5_LSB_REG);
dig_P6 = I2C_readS16(BMP280_DIG_P6_LSB_REG);
dig_P7 = I2C_readS16(BMP280_DIG_P7_LSB_REG);
dig_P8 = I2C_readS16(BMP280_DIG_P8_LSB_REG);
dig_P9 = I2C_readS16(BMP280_DIG_P9_LSB_REG);
printf("dig_T1 = %d\r\n",dig_T1);
printf("dig_T2 = %d\r\n",dig_T2);
printf("dig_T3 = %d\r\n",dig_T3);
printf("dig_P1 = %d\r\n",dig_P1);
printf("dig_P2 = %d\r\n",dig_P2);
printf("dig_P3 = %d\r\n",dig_P3);
printf("dig_P4 = %d\r\n",dig_P4);
printf("dig_P5 = %d\r\n",dig_P5);
printf("dig_P6 = %d\r\n",dig_P6);
printf("dig_P7 = %d\r\n",dig_P7);
printf("dig_P8 = %d\r\n",dig_P8);
printf("dig_P9 = %d\r\n",dig_P9);
}
unsigned char BSP_BMP280_Init(void)
{
unsigned char id,ctrlmeas, config;
id = I2C_readByte(BMP280_ID_REG);
if(id == BMP280_ID_Value)
{
load_calibration();
ctrlmeas = 0xFF; //BMP280_T_MODE_1 << 5 | BMP280_P_MODE_1 << 2 | BMP280_SLEEP_MODE;
config = 0x14; //BMP280_T_SB1 << 5 | BMP280_FILTER_MODE_1 << 2;
I2C_writeByte(BMP280_CTRL_MEAS_REG, ctrlmeas);
I2C_writeByte(BMP280_CONFIG_REG, config);
return 0;
}
else
{
printf("Read BMP280 id error!\r\n");
return 1;
}
}
/* Returns pressure in Pa as double. Output value of "6386.2"equals 96386.2 Pa = 963.862 hPa */
void get_temperature_and_pressure(double *temperature, double *pressure)
{
unsigned char lsb, msb, xlsb;
int adc_P,adc_T;
xlsb = I2C_readByte(BMP280_TEMP_XLSB_REG);
lsb = I2C_readByte(BMP280_TEMP_LSB_REG);
msb = I2C_readByte(BMP280_TEMP_MSB_REG);
adc_T = (msb << 12) | (lsb << 4) | (xlsb >> 4);
//adc_T = 415148;
* temperature = compensate_temperature(adc_T);
xlsb = I2C_readByte(BMP280_PRESS_XLSB_REG);
lsb = I2C_readByte(BMP280_PRESS_LSB_REG);
msb = I2C_readByte(BMP280_PRESS_MSB_REG);
adc_P = (msb << 12) | (lsb << 4) | (xlsb >> 4);
//adc_P = 51988;
* pressure = compensate_pressure(adc_P);
}
int main(int argc,char **argv)
{
double temp,press;
printf("BMP180 Test Program ...\n");
if(wiringPiSetup() < 0) return 1;
fd = wiringPiI2CSetup(BMP280_I2C_ADDRESS);
load_calibration();
while(1)
{
get_temperature_and_pressure(&temp,&press);
printf("Temperature = %.2f C Pressure = %.3f kPa \r\n",temp,press/1000);
delay(1000);
}
return 0;
}
- BMP280.h
#ifndef _BMP280_
#define _BMP280_
//i2c address
#define BMP280_I2C_ADDRESS 0x76 //SDO = 0
//Registers value
#define BMP280_ID_Value 0x58
#define BMP280_RESET_VALUE 0xB6
/* BMP280 Registers definition */
#define BMP280_TEMP_XLSB_REG 0xFC /*Temperature XLSB Register */
#define BMP280_TEMP_LSB_REG 0xFB /*Temperature LSB Register */
#define BMP280_TEMP_MSB_REG 0xFA /*Temperature LSB Register */
#define BMP280_PRESS_XLSB_REG 0xF9 /*Pressure XLSB Register */
#define BMP280_PRESS_LSB_REG 0xF8 /*Pressure LSB Register */
#define BMP280_PRESS_MSB_REG 0xF7 /*Pressure MSB Register */
#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
#define BMP280_CTRL_MEAS_REG 0xF4 /*Ctrl Measure Register */
#define BMP280_STATUS_REG 0xF3 /*Status Register */
#define BMP280_RESET_REG 0xE0 /*Softreset Register */
#define BMP280_ID_REG 0xD0 /*Chip ID Register */
/*calibration parameters */
#define BMP280_DIG_T1_LSB_REG 0x88
#define BMP280_DIG_T1_MSB_REG 0x89
#define BMP280_DIG_T2_LSB_REG 0x8A
#define BMP280_DIG_T2_MSB_REG 0x8B
#define BMP280_DIG_T3_LSB_REG 0x8C
#define BMP280_DIG_T3_MSB_REG 0x8D
#define BMP280_DIG_P1_LSB_REG 0x8E
#define BMP280_DIG_P1_MSB_REG 0x8F
#define BMP280_DIG_P2_LSB_REG 0x90
#define BMP280_DIG_P2_MSB_REG 0x91
#define BMP280_DIG_P3_LSB_REG 0x92
#define BMP280_DIG_P3_MSB_REG 0x93
#define BMP280_DIG_P4_LSB_REG 0x94
#define BMP280_DIG_P4_MSB_REG 0x95
#define BMP280_DIG_P5_LSB_REG 0x96
#define BMP280_DIG_P5_MSB_REG 0x97
#define BMP280_DIG_P6_LSB_REG 0x98
#define BMP280_DIG_P6_MSB_REG 0x99
#define BMP280_DIG_P7_LSB_REG 0x9A
#define BMP280_DIG_P7_MSB_REG 0x9B
#define BMP280_DIG_P8_LSB_REG 0x9C
#define BMP280_DIG_P8_MSB_REG 0x9D
#define BMP280_DIG_P9_LSB_REG 0x9E
#define BMP280_DIG_P9_MSB_REG 0x9F
#endif
-Makefile
bmp280:bmp280.c bmp280.h
gcc -Wall bmp280.c -o bmp280 -lwiringPi -lm
clean:
rm bmp280
7. 실행결과
- 컴파일해서 실행파일을 만듭니다.
pi@raspberrypi:~/Pioneer600/BMP280/wiringPi $ make clean && make
- 프로그램을 실행합니다. 그러면 각종 보정값과 기압, 온도가 나옵니다.
pi@raspberrypi:~/Pioneer600/BMP280/wiringPi $ ./bmp280
- 그런데 가지고 있는 모듈이 고장인지 값이 변하지 않았습니다. (당황);;; 그래서 지난번에 테스트한 BMP180 모듈을 가지고 확인해보았습니다.
- BMP180 소스로 이동해서 소스 컴파일 후 실행해보았습니다.
pi@raspberrypi:~/Pioneer600/BMP180/wiringPi $ make clean && make
pi@raspberrypi:~/Pioneer600/BMP180/wiringPi $ ./bmp180
- BMP180, BMP280 모듈을 좀 더 정확한 값으로 사용하려면 현재 측정하는 곳의 해발고도 혹은 해면기압 등을 넣어 추가 보정을 해주어야 합니다.
감사합니다.
<참조 사이트>
1. How to use the BMP280 Barometric Pressure Chip
https://www.best-microcontroller-projects.com/bmp280.html
2. Pioneer600
https://www.waveshare.com/wiki/Pioneer600
"쿠팡 파트너스 활동을 통해 일정액의 수수료를 받을 수 있음"
'RaspberryPi > Raspberry Pi Zero' 카테고리의 다른 글
라즈베리파이 제로 프로젝트(17) – Pioneer600 모듈 1-wire 온도센서 (DS18B20) (0) | 2021.03.27 |
---|---|
라즈베리파이 제로 프로젝트(16) – Pioneer600 모듈 Real Time Clock (DS3231) (0) | 2021.03.13 |
라즈베리파이 제로 프로젝트(14) – Pioneer600 모듈 (PCF8574 I/O expansion) (0) | 2021.02.19 |
라즈베리파이 제로 프로젝트(13) – Pioneer600 모듈 (키 버튼 입력받기) (0) | 2021.02.14 |
라즈베리파이 제로 프로젝트(12) – Pioneer600 모듈 (LED 제어 - PWM) (0) | 2021.02.13 |