BME280 – это интегрированный датчик окружающей среды давления, влажности и температуры, сочетающий высокую линейность, высокую точность и низкое энергопотребление. Датчик влажности имеет чрезвычайно быстрое время отклика. Датчик давления является абсолютным барометрическим датчиком давления с функциями исключительно высокой точности и разрешения при очень низком уровне шума. Встроенный датчик температуры оптимизирован для очень низкого уровня шума и высокого разрешения. Он в основном используется для температурной компенсации датчиков давления и влажности, а также может использоваться для оценки температуры окружающей среды.
Подключение датчика
BME280 поддерживает цифровые интерфейсы I²C и SPI;
Интерфейс I²C поддерживает стандартные, быстрые и высокоскоростные режимы. Интерфейс SPI поддерживает режим SPI ’00’ (CPOL = CPHA = ‘0’) и режим ’11’ (CPOL = CPHA = ‘1’) в 4-проводной и 3-проводной конфигурации.
Интерфейс I²C использует следующие контакты:
- SCK: serial clock (SCL)
- SDI: data (SDA)
- SDO: Slave address LSB (GND = ‘0’, VDDIO = ‘1’)
Подключение SDO к GND приводит к ведомому адресу 1110110 (0x76); подключение его к VDDIO приводит к ведомому адресу 1110111 (0x77), который совпадает с адресом I²C BMP280. Штырь SDO не может оставаться плавающим; если он оставлен плавающим, адрес I²C будет не определен.
Исходник bme280_p.c
// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// BME280
// This code is designed to work with the BME280 sensor with I2C Interface
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
//void main()
//{
void print_usage() {
printf("Usage: bme280_p -[ahCFH] -P[factor]\n");
printf("Usage: bme280_p -a all parms verbose\n");
printf("Usage: bme280_p -C Temp value in Celsius\n");
printf("Usage: bme280_p -F Temp value in Fahrenheit\n");
printf("Usage: bme280_p -H Humidity value in %%RH\n");
printf("Usage: bme280_p -P[factor] Pressure value in hPa * factor\n");
}
int main(int argc, char *argv[]) {
int option = 0;
float fact = 1.0;
float fpressure;
// Create I2C bus
int file;
char *bus = "/dev/i2c-1";
if((file = open(bus, O_RDWR)) < 0)
{
printf("Failed to open the bus. \n");
exit(1);
}
// Get I2C device, BME280 I2C address is 0x76(136)
ioctl(file, I2C_SLAVE, 0x76);
// Read 24 bytes of data from register(0x88)
char reg[1] = {0x88};
write(file, reg, 1);
char b1[24] = {0};
if(read(file, b1, 24) != 24)
{
printf("Error : Input/Output error \n");
exit(1);
}
// Convert the data
// temp coefficents
int dig_T1 = (b1[0] + b1[1] * 256);
int dig_T2 = (b1[2] + b1[3] * 256);
if(dig_T2 > 32767)
{
dig_T2 -= 65536;
}
int dig_T3 = (b1[4] + b1[5] * 256);
if(dig_T3 > 32767)
{
dig_T3 -= 65536;
}
// pressure coefficents
int dig_P1 = (b1[6] + b1[7] * 256);
int dig_P2 = (b1[8] + b1[9] * 256);
if(dig_P2 > 32767)
{
dig_P2 -= 65536;
}
int dig_P3 = (b1[10] + b1[11] * 256);
if(dig_P3 > 32767)
{
dig_P3 -= 65536;
}
int dig_P4 = (b1[12] + b1[13] * 256);
if(dig_P4 > 32767)
{
dig_P4 -= 65536;
}
int dig_P5 = (b1[14] + b1[15] * 256);
if(dig_P5 > 32767)
{
dig_P5 -= 65536;
}
int dig_P6 = (b1[16] + b1[17] * 256);
if(dig_P6 > 32767)
{
dig_P6 -= 65536;
}
int dig_P7 = (b1[18] + b1[19] * 256);
if(dig_P7 > 32767)
{
dig_P7 -= 65536;
}
int dig_P8 = (b1[20] + b1[21] * 256);
if(dig_P8 > 32767)
{
dig_P8 -= 65536;
}
int dig_P9 = (b1[22] + b1[23] * 256);
if(dig_P9 > 32767)
{
dig_P9 -= 65536;
}
// Read 1 byte of data from register(0xA1)
reg[0] = 0xA1;
write(file, reg, 1);
char data[8] = {0};
read(file, data, 1);
int dig_H1 = data[0];
// Read 7 bytes of data from register(0xE1)
reg[0] = 0xE1;
write(file, reg, 1);
read(file, b1, 7);
// Convert the data
// humidity coefficents
int dig_H2 = (b1[0] + b1[1] * 256);
if(dig_H2 > 32767)
{
dig_H2 -= 65536;
}
int dig_H3 = b1[2] & 0xFF ;
int dig_H4 = (b1[3] * 16 + (b1[4] & 0xF));
if(dig_H4 > 32767)
{
dig_H4 -= 65536;
}
int dig_H5 = (b1[4] / 16) + (b1[5] * 16);
if(dig_H5 > 32767)
{
dig_H5 -= 65536;
}
int dig_H6 = b1[6];
if(dig_H6 > 127)
{
dig_H6 -= 256;
}
// Select control humidity register(0xF2)
// Humidity over sampling rate = 1(0x01)
char config[2] = {0};
config[0] = 0xF2;
config[1] = 0x01;
write(file, config, 2);
// Select control measurement register(0xF4)
// Normal mode, temp and pressure over sampling rate = 1(0x27)
config[0] = 0xF4;
config[1] = 0x27;
write(file, config, 2);
// Select config register(0xF5)
// Stand_by time = 1000 ms(0xA0)
config[0] = 0xF5;
config[1] = 0xA0;
write(file, config, 2);
// Read 8 bytes of data from register(0xF7)
// pressure msb1, pressure msb, pressure lsb, temp msb1, temp msb, temp lsb, humidity lsb, humidity msb
reg[0] = 0xF7;
write(file, reg, 1);
read(file, data, 8);
// Convert pressure and temperature data to 19-bits
long adc_p = ((long)(data[0] * 65536 + ((long)(data[1] * 256) + (long)(data[2] & 0xF0)))) / 16;
long adc_t = ((long)(data[3] * 65536 + ((long)(data[4] * 256) + (long)(data[5] & 0xF0)))) / 16;
// Convert the humidity data
long adc_h = (data[6] * 256 + data[7]);
// Temperature offset calculations
float var1 = (((float)adc_t) / 16384.0 - ((float)dig_T1) / 1024.0) * ((float)dig_T2);
float var2 = ((((float)adc_t) / 131072.0 - ((float)dig_T1) / 8192.0) *
(((float)adc_t)/131072.0 - ((float)dig_T1)/8192.0)) * ((float)dig_T3);
float t_fine = (long)(var1 + var2);
float cTemp = (var1 + var2) / 5120.0;
float fTemp = cTemp * 1.8 + 32;
// Pressure offset calculations
var1 = ((float)t_fine / 2.0) - 64000.0;
var2 = var1 * var1 * ((float)dig_P6) / 32768.0;
var2 = var2 + var1 * ((float)dig_P5) * 2.0;
var2 = (var2 / 4.0) + (((float)dig_P4) * 65536.0);
var1 = (((float) dig_P3) * var1 * var1 / 524288.0 + ((float) dig_P2) * var1) / 524288.0;
var1 = (1.0 + var1 / 32768.0) * ((float)dig_P1);
float p = 1048576.0 - (float)adc_p;
p = (p - (var2 / 4096.0)) * 6250.0 / var1;
var1 = ((float) dig_P9) * p * p / 2147483648.0;
var2 = p * ((float) dig_P8) / 32768.0;
float pressure = (p + (var1 + var2 + ((float)dig_P7)) / 16.0) / 100;
// Humidity offset calculations
float var_H = (((float)t_fine) - 76800.0);
var_H = (adc_h - (dig_H4 * 64.0 + dig_H5 / 16384.0 * var_H)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * var_H * (1.0 + dig_H3 / 67108864.0 * var_H)));
float humidity = var_H * (1.0 - dig_H1 * var_H / 524288.0);
if(humidity > 100.0)
{
humidity = 100.0;
}else
if(humidity < 0.0)
{
humidity = 0.0;
}
while ((option = getopt(argc, argv,"ahCFHP::")) != -1) {
switch (option) {
case 'a' :
printf("Temperature in Celsius : %.2f C \n", cTemp);
printf("Temperature in Fahrenheit : %.2f F \n", fTemp);
printf("Pressure : %.2f hPa \n", pressure);
printf("Relative Humidity : %.2f %%RH \n", humidity);
close(file);
exit(0);
case 'C' :
printf("%.2f \n", cTemp);
close(file);
exit(0);
case 'P' :
if (optarg != NULL )
fact = atof(optarg);
else
fact = 1;
fpressure = fact * pressure;
if (fact < 1)
printf("%.4f \n", fpressure);
else
printf("%.2f \n", fpressure);
close(file);
exit(0);
case 'H' :
printf("%.2f \n", humidity);
close(file);
exit(0);
case 'F' :
printf("%.2f \n", fTemp);
close(file);
exit(0);
case 'h' :
print_usage();
close(file);
exit(0);
case '?' :
case ':' :
default: print_usage();
exit(EXIT_FAILURE);
}
}
print_usage();
close(file);
}
Компиляция
gcc -g -Wall -Wextra -pedantic -std=c11 -o bme280_p bme280_p.c
Запуск программы
./bme280_p
Usage: bme280_p -[ahCFH] -P[factor]
Usage: bme280_p -a all parms verbose
Usage: bme280_p -C Temp value in Celsius
Usage: bme280_p -F Temp value in Fahrenheit
Usage: bme280_p -H Humidity value in %RH
Usage: bme280_p -P[factor] Pressure value in hPa * factor
./bme280_p -a
Temperature in Celsius : 22.29 C
Temperature in Fahrenheit : 72.13 F
Pressure : 1009.53 hPa
Relative Humidity : 43.52 %RH
./bme280_p -C
22.30
./bme280_p -F
72.14
./bme280_p -H
43.53
./bme280_p -P
1009.52
./bme280_p -P1
1009.55
./bme280_p -P10
10095.85
./bme280_p -P0.01
10.0960
На этом всё !