sensor: add support for BME280

* Rename BMP280 to BME280 which is a superset for the former.
* Autodetect device based on chip ID.
* Implement humidity fetching and reading for BME280
* Rename sample BMP280 to BME280

Change-Id: I565c769a7011e7496c9f1cad861d5ee311839b4f
Signed-off-by: Murtaza Alexandru <alexandru.murtaza@intel.com>
This commit is contained in:
Murtaza Alexandru 2016-05-10 15:30:06 +03:00 committed by Anas Nashif
commit 310ed1e2e9
12 changed files with 616 additions and 483 deletions

View file

@ -34,12 +34,12 @@ source "drivers/sensor/Kconfig.bma280"
source "drivers/sensor/Kconfig.bmc150_magn"
source "drivers/sensor/Kconfig.bme280"
source "drivers/sensor/Kconfig.bmg160"
source "drivers/sensor/Kconfig.bmi160"
source "drivers/sensor/Kconfig.bmp280"
source "drivers/sensor/Kconfig.dht"
source "drivers/sensor/Kconfig.hdc1008"

View file

@ -0,0 +1,180 @@
# Kconfig.bmp280 - BMP280 temperature and pressure sensor configuration options
#
# Copyright (c) 2016 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
menuconfig BME280
bool "BME280/BMP280 sensor"
depends on SENSOR && I2C
default n
help
Enable driver for BME280 I2C-based temperature and pressure sensor.
config BME280_SYS_LOG_LEVEL
int "BME280 Log level"
depends on SYS_LOG && BME280
default 0
range 0 4
help
Sets log level for BMP280 driver.
Levels are:
0 OFF, do not write
1 ERROR, only write SYS_LOG_ERR
2 WARNING, write SYS_LOG_WRN in addition to previous level
3 INFO, write SYS_LOG_INF in addition to previous levels
4 DEBUG, write SYS_LOG_DBG in addition to previous levels
config BME280_DEV_NAME
string "BME280 device name"
depends on BME280
default "BME280"
config BME280_INIT_PRIORITY
int
depends on BME280
default 70
prompt "Init priority"
help
Device driver initialization priority.
choice
prompt "BME280 I2C slave address"
default BME280_I2C_ADDR_76
depends on BME280
help
Specify the I2C slave address for the BME280.
config BME280_I2C_ADDR_76
bool
prompt "0x76 (GND)"
config BME280_I2C_ADDR_77
bool
prompt "0x77 (VCC)"
endchoice
config BME280_I2C_MASTER_DEV_NAME
string "I2C master where BME280 is connected"
depends on BME280
default "I2C_0"
help
Specify the device name of the I2C master device to which BME280 is
connected.
menu "Attributes"
depends on BME280
choice
prompt "BME280 temperature oversampling"
depends on BME280
default BME280_TEMP_OVER_2X
help
Select temperature oversampling for the BME280 sensor. Higher values
lead to more accurate readings, but higher power consumption.
config BME280_TEMP_OVER_1X
bool "x1"
config BME280_TEMP_OVER_2X
bool "x2"
config BME280_TEMP_OVER_4X
bool "x4"
config BME280_TEMP_OVER_8X
bool "x8"
config BME280_TEMP_OVER_16X
bool "x16"
endchoice
choice
prompt "BME280 pressure oversampling"
depends on BME280
default BME280_PRESS_OVER_16X
help
Select pressure oversampling for the BME280 sensor. Higher values
lead to more accurate readings, but higher power consumption.
config BME280_PRESS_OVER_1X
bool "x1"
config BME280_PRESS_OVER_2X
bool "x2"
config BME280_PRESS_OVER_4X
bool "x4"
config BME280_PRESS_OVER_8X
bool "x8"
config BME280_PRESS_OVER_16X
bool "x16"
endchoice
choice
prompt "BME280 humidity oversampling"
depends on BME280
default BME280_HUMIDITY_OVER_16X
help
Select humidity oversampling for the BME280 sensor. Higher values
lead to more accurate readings, but higher power consumption.
config BME280_HUMIDITY_OVER_1X
bool "x1"
config BME280_HUMIDITY_OVER_2X
bool "x2"
config BME280_HUMIDITY_OVER_4X
bool "x4"
config BME280_HUMIDITY_OVER_8X
bool "x8"
config BME280_HUMIDITY_OVER_16X
bool "x16"
endchoice
choice
prompt "BME280 standby time"
depends on BME280
default BME280_STANDBY_1000MS
help
Select standby time between measeurements for the BME280 sensor.
Higher values lead to lower power consumption.
config BME280_STANDBY_05MS
bool "0.5ms"
config BME280_STANDBY_62MS
bool "62.5ms"
config BME280_STANDBY_125MS
bool "125ms"
config BME280_STANDBY_250MS
bool "250ms"
config BME280_STANDBY_500MS
bool "500ms"
config BME280_STANDBY_1000MS
bool "1000ms"
config BME280_STANDBY_2000MS
bool "2000ms BMP280 / 10ms BME280"
config BME280_STANDBY_4000MS
bool "4000ms BMP280 / 20ms BME280"
endchoice
choice
prompt "BME280 filter coefficient"
depends on BME280
default BME280_FILTER_4
help
Select the filter coefficient for the BME280 sensor.
config BME280_FILTER_OFF
bool "filter off"
config BME280_FILTER_2
bool "2"
config BME280_FILTER_4
bool "4"
config BME280_FILTER_8
bool "8"
config BME280_FILTER_16
bool "16"
endchoice
endmenu

View file

@ -1,146 +0,0 @@
# Kconfig.bmp280 - BMP280 temperature and pressure sensor configuration options
#
# Copyright (c) 2016 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
menuconfig BMP280
bool "BMP280 temperature and pressure sensor"
depends on SENSOR && I2C
default n
help
Enable driver for BMP280 I2C-based temperature and pressure sensor.
config BMP280_SYS_LOG_LEVEL
int "BMP280 Log level"
depends on SYS_LOG && BMP280
default 0
range 0 4
help
Sets log level for BMP280 driver.
Levels are:
0 OFF, do not write
1 ERROR, only write SYS_LOG_ERR
2 WARNING, write SYS_LOG_WRN in addition to previous level
3 INFO, write SYS_LOG_INF in addition to previous levels
4 DEBUG, write SYS_LOG_DBG in addition to previous levels
config BMP280_DEV_NAME
string "BMP280 device name"
depends on BMP280
default "BMP280"
config BMP280_INIT_PRIORITY
int
depends on BMP280
default 70
prompt "Init priority"
help
Device driver initialization priority.
config BMP280_I2C_ADDR
hex "BMP280 I2C slave address"
depends on BMP280
default 0x76
help
Specify the I2C slave address for the BMP280.
config BMP280_I2C_MASTER_DEV_NAME
string "I2C master where BMP280 is connected"
depends on BMP280
default "I2C_0"
help
Specify the device name of the I2C master device to which BMP280 is
connected.
choice
prompt "BMP280 pressure oversampling"
depends on BMP280
default BMP280_PRESS_OVER_16X
help
Select pressure oversampling for the BMP280 sensor. Higher values
lead to more accurate readings, but higher power consumption.
config BMP280_PRESS_OVER_1X
bool "x1"
config BMP280_PRESS_OVER_2X
bool "x2"
config BMP280_PRESS_OVER_4X
bool "x4"
config BMP280_PRESS_OVER_8X
bool "x8"
config BMP280_PRESS_OVER_16X
bool "x16"
endchoice
choice
prompt "BMP280 temperature oversampling"
depends on BMP280
default BMP280_TEMP_OVER_2X
help
Select temperature oversampling for the BMP280 sensor. Higher values
lead to more accurate readings, but higher power consumption.
config BMP280_TEMP_OVER_1X
bool "x1"
config BMP280_TEMP_OVER_2X
bool "x2"
config BMP280_TEMP_OVER_4X
bool "x4"
config BMP280_TEMP_OVER_8X
bool "x8"
config BMP280_TEMP_OVER_16X
bool "x16"
endchoice
choice
prompt "BMP280 standby time"
depends on BMP280
default BMP280_STANDBY_1000MS
help
Select standby time between measeurements for the BMP280 sensor.
Higher values lead to lower power consumption.
config BMP280_STANDBY_05MS
bool "0.5ms"
config BMP280_STANDBY_62MS
bool "62.5ms"
config BMP280_STANDBY_125MS
bool "125ms"
config BMP280_STANDBY_250MS
bool "250ms"
config BMP280_STANDBY_500MS
bool "500ms"
config BMP280_STANDBY_1000MS
bool "1000ms"
config BMP280_STANDBY_2000MS
bool "2000ms"
config BMP280_STANDBY_4000MS
bool "4000ms"
endchoice
choice
prompt "BMP280 filter coefficient"
depends on BMP280
default BMP280_FILTER_4
help
Select the filter coefficient for the BMP280 sensor.
config BMP280_FILTER_OFF
bool "filter off"
config BMP280_FILTER_2
bool "2"
config BMP280_FILTER_4
bool "4"
config BMP280_FILTER_8
bool "8"
config BMP280_FILTER_16
bool "16"
endchoice

View file

@ -4,11 +4,11 @@ obj-$(CONFIG_BMA280) += sensor_bma280.o
obj-$(CONFIG_BMA280_TRIGGER) += sensor_bma280_trigger.o
obj-$(CONFIG_BMC150_MAGN) += sensor_bmc150_magn.o
obj-$(CONFIG_BMC150_MAGN_TRIGGER_DRDY) += sensor_bmc150_magn_trigger.o
obj-$(CONFIG_BME280) += sensor_bme280.o
obj-$(CONFIG_BMG160) += sensor_bmg160.o
obj-$(CONFIG_BMG160_TRIGGER) += sensor_bmg160_trigger.o
obj-$(CONFIG_BMI160) += sensor_bmi160.o
obj-$(CONFIG_BMI160_TRIGGER) += sensor_bmi160_trigger.o
obj-$(CONFIG_BMP280) += sensor_bmp280.o
obj-$(CONFIG_DHT) += sensor_dht.o
obj-$(CONFIG_HDC1008) += sensor_hdc1008.o
obj-$(CONFIG_ISL29035) += sensor_isl29035.o

View file

@ -0,0 +1,269 @@
/* sensor_bmp280.c - Driver for Bosch BMP280 temperature and pressure sensor */
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <nanokernel.h>
#include <i2c.h>
#include <sensor.h>
#include <init.h>
#include <gpio.h>
#include <misc/byteorder.h>
#include <misc/__assert.h>
#include "sensor_bme280.h"
/*
* Compensation code taken from BME280 datasheet, Section 4.2.3
* "Compensation formula".
*/
static void bme280_compensate_temp(struct bme280_data *data, int32_t adc_temp)
{
int32_t var1, var2;
var1 = (((adc_temp >> 3) - ((int32_t)data->dig_t1 << 1)) *
((int32_t)data->dig_t2)) >> 11;
var2 = (((((adc_temp >> 4) - ((int32_t)data->dig_t1)) *
((adc_temp >> 4) - ((int32_t)data->dig_t1))) >> 12) *
((int32_t)data->dig_t3)) >> 14;
data->t_fine = var1 + var2;
data->comp_temp = (data->t_fine * 5 + 128) >> 8;
}
static void bme280_compensate_press(struct bme280_data *data, int32_t adc_press)
{
int64_t var1, var2, p;
var1 = ((int64_t)data->t_fine) - 128000;
var2 = var1 * var1 * (int64_t)data->dig_p6;
var2 = var2 + ((var1 * (int64_t)data->dig_p5) << 17);
var2 = var2 + (((int64_t)data->dig_p4) << 35);
var1 = ((var1 * var1 * (int64_t)data->dig_p3) >> 8) +
((var1 * (int64_t)data->dig_p2) << 12);
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)data->dig_p1) >> 33;
/* Avoid exception caused by division by zero. */
if (var1 == 0) {
data->comp_press = 0;
return;
}
p = 1048576 - adc_press;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((int64_t)data->dig_p9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((int64_t)data->dig_p8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)data->dig_p7) << 4);
data->comp_press = (uint32_t)p;
}
static void bme280_compensate_humidity(struct bme280_data *data,
int32_t adc_humidity)
{
int32_t h;
h = (data->t_fine - ((int32_t)76800));
h = ((((adc_humidity << 14) - (((int32_t)data->dig_h4) << 20) -
(((int32_t)data->dig_h5) * h)) + ((int32_t)16384)) >> 15) *
(((((((h * ((int32_t)data->dig_h6)) >> 10) * (((h *
((int32_t)data->dig_h3)) >> 11) + ((int32_t)32768))) >> 10) +
((int32_t)2097152)) * ((int32_t)data->dig_h2) + 8192) >> 14);
h = (h - (((((h >> 15) * (h >> 15)) >> 7) *
((int32_t)data->dig_h1)) >> 4));
h = (h > 419430400 ? 419430400 : h);
data->comp_humidity = (uint32_t)(h >> 12);
}
static int bme280_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct bme280_data *data = dev->driver_data;
uint8_t buf[8];
int32_t adc_press, adc_temp, adc_humidity;
int size = 6;
__ASSERT(chan == SENSOR_CHAN_ALL);
if (data->chip_id == BME280_CHIP_ID) {
size = 8;
}
if (i2c_burst_read(data->i2c_master, data->i2c_slave_addr,
BME280_REG_PRESS_MSB, buf, size) < 0) {
return -EIO;
}
adc_press = (buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4);
adc_temp = (buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4);
bme280_compensate_temp(data, adc_temp);
bme280_compensate_press(data, adc_press);
if (data->chip_id == BME280_CHIP_ID) {
adc_humidity = (buf[6] << 8) | buf[7];
bme280_compensate_humidity(data, adc_humidity);
}
return 0;
}
static int bme280_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct bme280_data *data = dev->driver_data;
switch (chan) {
case SENSOR_CHAN_TEMP:
/*
* data->comp_temp has a resolution of 0.01 degC. So
* 5123 equals 51.23 degC.
*/
val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;
val->val1 = data->comp_temp / 100;
val->val2 = data->comp_temp % 100 * 10000;
break;
case SENSOR_CHAN_PRESS:
/*
* data->comp_press has 24 integer bits and 8
* fractional. Output value of 24674867 represents
* 24674867/256 = 96386.2 Pa = 963.862 hPa
*/
val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;
val->val1 = (data->comp_press >> 8) / 1000;
val->val2 = (data->comp_press >> 8) % 1000 * 1000 +
(((data->comp_press & 0xff) * 1000) >> 8);
break;
case SENSOR_CHAN_HUMIDITY:
/*
* data->comp_humidity has 22 integer bits and 10
* fractional. Output value of 47445 represents
* 47445/1024 = 46.333 %RH
*/
val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;
val->val1 = (data->comp_humidity >> 10);
val->val2 = (((data->comp_humidity & 0x3ff) * 1000 * 1000) >> 10);
val->val1 = val->val1 * 1000 + (val->val2 * 1000) / 1000000;
val->val2 = (val->val2 * 1000) % 1000000;
break;
default:
return -EINVAL;
}
return 0;
}
static struct sensor_driver_api bme280_api_funcs = {
.sample_fetch = bme280_sample_fetch,
.channel_get = bme280_channel_get,
};
static void bme280_read_compensation(struct bme280_data *data)
{
uint16_t buf[12];
uint8_t hbuf[7];
i2c_burst_read(data->i2c_master, data->i2c_slave_addr,
BME280_REG_COMP_START, (uint8_t *)buf, sizeof(buf));
data->dig_t1 = sys_le16_to_cpu(buf[0]);
data->dig_t2 = sys_le16_to_cpu(buf[1]);
data->dig_t3 = sys_le16_to_cpu(buf[2]);
data->dig_p1 = sys_le16_to_cpu(buf[3]);
data->dig_p2 = sys_le16_to_cpu(buf[4]);
data->dig_p4 = sys_le16_to_cpu(buf[5]);
data->dig_p3 = sys_le16_to_cpu(buf[6]);
data->dig_p5 = sys_le16_to_cpu(buf[7]);
data->dig_p6 = sys_le16_to_cpu(buf[8]);
data->dig_p7 = sys_le16_to_cpu(buf[9]);
data->dig_p8 = sys_le16_to_cpu(buf[10]);
data->dig_p9 = sys_le16_to_cpu(buf[11]);
if (data->chip_id == BME280_CHIP_ID) {
i2c_reg_read_byte(data->i2c_master, data->i2c_slave_addr,
BME280_REG_HUM_COMP_PART1, &data->dig_h1);
i2c_burst_read(data->i2c_master, data->i2c_slave_addr,
BME280_REG_HUM_COMP_PART2, hbuf, 7);
data->dig_h2 = (hbuf[1] << 8) | hbuf[0];
data->dig_h3 = hbuf[2];
data->dig_h4 = (hbuf[3] << 4) | (hbuf[4] & 0x0F);
data->dig_h5 = ((hbuf[4] >> 4) & 0x0F) | (hbuf[5] << 4);
data->dig_h6 = hbuf[6];
}
}
static int bme280_chip_init(struct device *dev)
{
struct bme280_data *data = (struct bme280_data *) dev->driver_data;
i2c_reg_read_byte(data->i2c_master, data->i2c_slave_addr,
BME280_REG_ID, &data->chip_id);
if (data->chip_id == BME280_CHIP_ID) {
SYS_LOG_DBG("BME280 chip detected");
} else if (data->chip_id == BMP280_CHIP_ID_MP ||
data->chip_id == BMP280_CHIP_ID_SAMPLE_1) {
SYS_LOG_DBG("BMP280 chip detected");
} else {
SYS_LOG_DBG("bad chip id 0x%x", data->chip_id);
return -ENOTSUP;
}
bme280_read_compensation(data);
if (data->chip_id == BME280_CHIP_ID) {
i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr,
BME280_REG_CTRL_HUM, BME280_HUMIDITY_OVER);
}
i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr,
BME280_REG_CTRL_MEAS, BME280_CTRL_MEAS_VAL);
i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr,
BME280_REG_CONFIG, BME280_CONFIG_VAL);
return 0;
}
int bme280_init(struct device *dev)
{
struct bme280_data *data = dev->driver_data;
data->i2c_master = device_get_binding(CONFIG_BME280_I2C_MASTER_DEV_NAME);
if (!data->i2c_master) {
SYS_LOG_DBG("i2c master not found: %s",
CONFIG_BME280_I2C_MASTER_DEV_NAME);
return -EINVAL;
}
data->i2c_slave_addr = BME280_I2C_ADDR;
if (bme280_chip_init(dev) < 0) {
return -EINVAL;
}
dev->driver_api = &bme280_api_funcs;
return 0;
}
static struct bme280_data bme280_data;
DEVICE_INIT(bme280, CONFIG_BME280_DEV_NAME, bme280_init, &bme280_data,
NULL, SECONDARY, CONFIG_BME280_INIT_PRIORITY);

View file

@ -0,0 +1,156 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SENSOR_BME280_H__
#define __SENSOR_BME280_H__
#include <stdint.h>
#include <device.h>
#define BME280_REG_PRESS_MSB 0xF7
#define BME280_REG_COMP_START 0x88
#define BME280_REG_HUM_COMP_PART1 0xA1
#define BME280_REG_HUM_COMP_PART2 0xE1
#define BME280_REG_ID 0xD0
#define BME280_REG_CONFIG 0xF5
#define BME280_REG_CTRL_MEAS 0xF4
#define BME280_REG_CTRL_HUM 0xF2
#define BMP280_CHIP_ID_SAMPLE_1 0x56
#define BMP280_CHIP_ID_SAMPLE_2 0x57
#define BMP280_CHIP_ID_MP 0x58
#define BME280_CHIP_ID 0x60
#define BME280_MODE_NORMAL 0x03
#define BME280_SPI_3W_DISABLE 0x00
#if defined CONFIG_BME280_TEMP_OVER_1X
#define BME280_TEMP_OVER (1 << 5)
#elif defined CONFIG_BME280_TEMP_OVER_2X
#define BME280_TEMP_OVER (2 << 5)
#elif defined CONFIG_BME280_TEMP_OVER_4X
#define BME280_TEMP_OVER (3 << 5)
#elif defined CONFIG_BME280_TEMP_OVER_8X
#define BME280_TEMP_OVER (4 << 5)
#elif defined CONFIG_BME280_TEMP_OVER_16X
#define BME280_TEMP_OVER (5 << 5)
#endif
#if defined CONFIG_BME280_PRESS_OVER_1X
#define BME280_PRESS_OVER (1 << 2)
#elif defined CONFIG_BME280_PRESS_OVER_2X
#define BME280_PRESS_OVER (2 << 2)
#elif defined CONFIG_BME280_PRESS_OVER_4X
#define BME280_PRESS_OVER (3 << 2)
#elif defined CONFIG_BME280_PRESS_OVER_8X
#define BME280_PRESS_OVER (4 << 2)
#elif defined CONFIG_BME280_PRESS_OVER_16X
#define BME280_PRESS_OVER (5 << 2)
#endif
#if defined CONFIG_BME280_HUMIDITY_OVER_1X
#define BME280_HUMIDITY_OVER 1
#elif defined CONFIG_BME280_HUMIDITY_OVER_2X
#define BME280_HUMIDITY_OVER 2
#elif defined CONFIG_BME280_HUMIDITY_OVER_4X
#define BME280_HUMIDITY_OVER 3
#elif defined CONFIG_BME280_HUMIDITY_OVER_8X
#define BME280_HUMIDITY_OVER 4
#elif defined CONFIG_BME280_HUMIDITY_OVER_16X
#define BME280_HUMIDITY_OVER 5
#endif
#if defined CONFIG_BME280_STANDBY_05MS
#define BME280_STANDBY 0
#elif defined CONFIG_BME280_STANDBY_62MS
#define BME280_STANDBY (1 << 5)
#elif defined CONFIG_BME280_STANDBY_125MS
#define BME280_STANDBY (2 << 5)
#elif defined CONFIG_BME280_STANDBY_250MS
#define BME280_STANDBY (3 << 5)
#elif defined CONFIG_BME280_STANDBY_500MS
#define BME280_STANDBY (4 << 5)
#elif defined CONFIG_BME280_STANDBY_1000MS
#define BME280_STANDBY (5 << 5)
#elif defined CONFIG_BME280_STANDBY_2000MS
#define BME280_STANDBY (6 << 5)
#elif defined CONFIG_BME280_STANDBY_4000MS
#define BME280_STANDBY (7 << 5)
#endif
#if defined CONFIG_BME280_FILTER_OFF
#define BME280_FILTER 0
#elif defined CONFIG_BME280_FILTER_2
#define BME280_FILTER (1 << 2)
#elif defined CONFIG_BME280_FILTER_4
#define BME280_FILTER (2 << 2)
#elif defined CONFIG_BME280_FILTER_8
#define BME280_FILTER (3 << 2)
#elif defined CONFIG_BME280_FILTER_16
#define BME280_FILTER (4 << 2)
#endif
#define BME280_CTRL_MEAS_VAL (BME280_PRESS_OVER | \
BME280_TEMP_OVER | \
BME280_MODE_NORMAL)
#define BME280_CONFIG_VAL (BME280_STANDBY | \
BME280_FILTER | \
BME280_SPI_3W_DISABLE)
#if defined CONFIG_BME280_I2C_ADDR_76
#define BME280_I2C_ADDR 0x76
#elif defined CONFIG_BME280_I2C_ADDR_77
#define BME280_I2C_ADDR 0x77
#endif
struct bme280_data {
struct device *i2c_master;
uint16_t i2c_slave_addr;
/* Compensation parameters. */
uint16_t dig_t1;
int16_t dig_t2;
int16_t dig_t3;
uint16_t dig_p1;
int16_t dig_p2;
int16_t dig_p3;
int16_t dig_p4;
int16_t dig_p5;
int16_t dig_p6;
int16_t dig_p7;
int16_t dig_p8;
int16_t dig_p9;
uint8_t dig_h1;
int16_t dig_h2;
uint8_t dig_h3;
int16_t dig_h4;
int16_t dig_h5;
int8_t dig_h6;
/* Compensated values. */
int32_t comp_temp;
uint32_t comp_press;
uint32_t comp_humidity;
/* Carryover between temperature and pressure/humidity compensation. */
int32_t t_fine;
uint8_t chip_id;
};
#define SYS_LOG_DOMAIN "BME280"
#define SYS_LOG_LEVEL CONFIG_BME280_SYS_LOG_LEVEL
#include <misc/sys_log.h>
#endif /* __SENSOR_BME280_H__ */

View file

@ -1,204 +0,0 @@
/* sensor_bmp280.c - Driver for Bosch BMP280 temperature and pressure sensor */
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <nanokernel.h>
#include <i2c.h>
#include <sensor.h>
#include <init.h>
#include <gpio.h>
#include <misc/byteorder.h>
#include <misc/__assert.h>
#include "sensor_bmp280.h"
/*
* Compensation code taken from BMP280 datasheet, Section 3.11.3
* "Compensation formula".
*/
static void bmp280_compensate_temp(struct bmp280_data *data, int32_t adc_temp)
{
int32_t var1, var2;
var1 = (((adc_temp >> 3) - ((int32_t)data->dig_t1 << 1)) *
((int32_t)data->dig_t2)) >> 11;
var2 = (((((adc_temp >> 4) - ((int32_t)data->dig_t1)) *
((adc_temp >> 4) - ((int32_t)data->dig_t1))) >> 12) *
((int32_t)data->dig_t3)) >> 14;
data->t_fine = var1 + var2;
data->comp_temp = (data->t_fine * 5 + 128) >> 8;
}
static void bmp280_compensate_press(struct bmp280_data *data, int32_t adc_press)
{
int64_t var1, var2, p;
var1 = ((int64_t)data->t_fine) - 128000;
var2 = var1 * var1 * (int64_t)data->dig_p6;
var2 = var2 + ((var1 * (int64_t)data->dig_p5) << 17);
var2 = var2 + (((int64_t)data->dig_p4) << 35);
var1 = ((var1 * var1 * (int64_t)data->dig_p3) >> 8) +
((var1 * (int64_t)data->dig_p2) << 12);
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)data->dig_p1) >> 33;
/* Avoid exception caused by division by zero. */
if (var1 == 0) {
data->comp_press = 0;
return;
}
p = 1048576 - adc_press;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((int64_t)data->dig_p9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((int64_t)data->dig_p8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)data->dig_p7) << 4);
data->comp_press = (uint32_t)p;
}
static int bmp280_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct bmp280_data *data = dev->driver_data;
uint8_t buf[6];
int32_t adc_press, adc_temp;
__ASSERT(chan == SENSOR_CHAN_ALL);
if (i2c_burst_read(data->i2c_master, data->i2c_slave_addr,
BMP280_REG_PRESS_MSB, buf, sizeof(buf)) < 0) {
return -EIO;
}
adc_press = (buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4);
adc_temp = (buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4);
bmp280_compensate_temp(data, adc_temp);
bmp280_compensate_press(data, adc_press);
return 0;
}
static int bmp280_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct bmp280_data *data = dev->driver_data;
switch (chan) {
case SENSOR_CHAN_TEMP:
/*
* data->comp_temp has a resolution of 0.01 degC. So
* 5123 equals 51.23 degC.
*/
val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;
val->val1 = data->comp_temp / 100;
val->val2 = data->comp_temp % 100 * 10000;
break;
case SENSOR_CHAN_PRESS:
/*
* data->comp_press has 24 integer bits and 8
* fractional. Output value of 24674867 represents
* 24674867/256 = 96386.2 Pa = 963.862 hPa
*/
val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;
val->val1 = (data->comp_press >> 8) / 1000;
val->val2 = (data->comp_press >> 8) % 1000 * 1000 +
(((data->comp_press & 0xff) * 1000) >> 8);
break;
default:
return -EINVAL;
}
return 0;
}
static struct sensor_driver_api bmp280_api_funcs = {
.sample_fetch = bmp280_sample_fetch,
.channel_get = bmp280_channel_get,
};
static void bmp280_read_compensation(struct bmp280_data *data)
{
uint16_t buf[12];
i2c_burst_read(data->i2c_master, data->i2c_slave_addr,
BMP280_REG_COMP_START, (uint8_t *)buf,
sizeof(buf));
data->dig_t1 = sys_le16_to_cpu(buf[0]);
data->dig_t2 = sys_le16_to_cpu(buf[1]);
data->dig_t3 = sys_le16_to_cpu(buf[2]);
data->dig_p1 = sys_le16_to_cpu(buf[3]);
data->dig_p2 = sys_le16_to_cpu(buf[4]);
data->dig_p3 = sys_le16_to_cpu(buf[5]);
data->dig_p4 = sys_le16_to_cpu(buf[6]);
data->dig_p5 = sys_le16_to_cpu(buf[7]);
data->dig_p6 = sys_le16_to_cpu(buf[8]);
data->dig_p7 = sys_le16_to_cpu(buf[9]);
data->dig_p8 = sys_le16_to_cpu(buf[10]);
data->dig_p9 = sys_le16_to_cpu(buf[11]);
}
static int bmp280_chip_init(struct device *dev)
{
struct bmp280_data *data = (struct bmp280_data *) dev->driver_data;
uint8_t buf;
i2c_reg_read_byte(data->i2c_master, data->i2c_slave_addr,
BMP280_REG_ID, &buf);
if (buf != BMP280_CHIP_ID) {
SYS_LOG_DBG("bmp280: bad chip id %x", buf);
return -ENOTSUP;
}
bmp280_read_compensation(data);
i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr,
BMP280_REG_CTRL_MEAS, BMP280_CTRL_MEAS_VAL);
i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr,
BMP280_REG_CONFIG, BMP280_CONFIG_VAL);
return 0;
}
int bmp280_init(struct device *dev)
{
struct bmp280_data *data = dev->driver_data;
data->i2c_master = device_get_binding(CONFIG_BMP280_I2C_MASTER_DEV_NAME);
if (!data->i2c_master) {
SYS_LOG_DBG("bmp280: i2c master not found: %s",
CONFIG_BMP280_I2C_MASTER_DEV_NAME);
return -EINVAL;
}
data->i2c_slave_addr = CONFIG_BMP280_I2C_ADDR;
if (bmp280_chip_init(dev) < 0) {
return -EINVAL;
}
dev->driver_api = &bmp280_api_funcs;
return 0;
}
static struct bmp280_data bmp280_data;
DEVICE_INIT(bmp280, CONFIG_BMP280_DEV_NAME, bmp280_init, &bmp280_data,
NULL, SECONDARY, CONFIG_BMP280_INIT_PRIORITY);

View file

@ -1,123 +0,0 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __SENSOR_BMP280_H__
#define __SENSOR_BMP280_H__
#include <stdint.h>
#include <device.h>
#define BMP280_REG_PRESS_MSB 0xF7
#define BMP280_REG_COMP_START 0x88
#define BMP280_REG_ID 0xD0
#define BMP280_REG_CONFIG 0xF5
#define BMP280_REG_CTRL_MEAS 0xF4
#define BMP280_CHIP_ID 0x58
#define BMP280_MODE_NORMAL 0x03
#define BMP280_SPI_3W_DISABLE 0x00
#if defined CONFIG_BMP280_TEMP_OVER_1X
#define BMP280_TEMP_OVER (1 << 5)
#elif defined CONFIG_BMP280_TEMP_OVER_2X
#define BMP280_TEMP_OVER (2 << 5)
#elif defined CONFIG_BMP280_TEMP_OVER_4X
#define BMP280_TEMP_OVER (3 << 5)
#elif defined CONFIG_BMP280_TEMP_OVER_8X
#define BMP280_TEMP_OVER (4 << 5)
#elif defined CONFIG_BMP280_TEMP_OVER_16X
#define BMP280_TEMP_OVER (5 << 5)
#endif
#if defined CONFIG_BMP280_PRESS_OVER_1X
#define BMP280_PRESS_OVER (1 << 2)
#elif defined CONFIG_BMP280_PRESS_OVER_2X
#define BMP280_PRESS_OVER (2 << 2)
#elif defined CONFIG_BMP280_PRESS_OVER_4X
#define BMP280_PRESS_OVER (3 << 2)
#elif defined CONFIG_BMP280_PRESS_OVER_8X
#define BMP280_PRESS_OVER (4 << 2)
#elif defined CONFIG_BMP280_PRESS_OVER_16X
#define BMP280_PRESS_OVER (5 << 2)
#endif
#if defined CONFIG_BMP280_STANDBY_05MS
#define BMP280_STANDBY 0
#elif defined CONFIG_BMP280_STANDBY_62MS
#define BMP280_STANDBY (1 << 5)
#elif defined CONFIG_BMP280_STANDBY_125MS
#define BMP280_STANDBY (2 << 5)
#elif defined CONFIG_BMP280_STANDBY_250MS
#define BMP280_STANDBY (3 << 5)
#elif defined CONFIG_BMP280_STANDBY_500MS
#define BMP280_STANDBY (4 << 5)
#elif defined CONFIG_BMP280_STANDBY_1000MS
#define BMP280_STANDBY (5 << 5)
#elif defined CONFIG_BMP280_STANDBY_2000MS
#define BMP280_STANDBY (6 << 5)
#elif defined CONFIG_BMP280_STANDBY_4000MS
#define BMP280_STANDBY (7 << 5)
#endif
#if defined CONFIG_BMP280_FILTER_OFF
#define BMP280_FILTER 0
#elif defined CONFIG_BMP280_FILTER_2
#define BMP280_FILTER (1 << 2)
#elif defined CONFIG_BMP280_FILTER_4
#define BMP280_FILTER (2 << 2)
#elif defined CONFIG_BMP280_FILTER_8
#define BMP280_FILTER (3 << 2)
#elif defined CONFIG_BMP280_FILTER_16
#define BMP280_FILTER (4 << 2)
#endif
#define BMP280_CTRL_MEAS_VAL (BMP280_PRESS_OVER | \
BMP280_TEMP_OVER | \
BMP280_MODE_NORMAL)
#define BMP280_CONFIG_VAL (BMP280_STANDBY | \
BMP280_FILTER | \
BMP280_SPI_3W_DISABLE)
struct bmp280_data {
struct device *i2c_master;
uint16_t i2c_slave_addr;
/* Compensation parameters. */
uint16_t dig_t1;
int16_t dig_t2;
int16_t dig_t3;
uint16_t dig_p1;
int16_t dig_p2;
int16_t dig_p3;
int16_t dig_p4;
int16_t dig_p5;
int16_t dig_p6;
int16_t dig_p7;
int16_t dig_p8;
int16_t dig_p9;
/* Compensated values. */
int32_t comp_temp;
uint32_t comp_press;
/* Carryover between temperature and pressure compensation. */
int32_t t_fine;
};
#define SYS_LOG_DOMAIN "BMP280"
#define SYS_LOG_LEVEL CONFIG_BMP280_SYS_LOG_LEVEL
#include <misc/sys_log.h>
#endif /* __SENSOR_BMP280_H__ */

View file

@ -5,4 +5,4 @@ CONFIG_NANO_TIMEOUTS=y
CONFIG_SENSOR=y
CONFIG_SENSOR_DEBUG=y
CONFIG_BMP280=y
CONFIG_BME280=y

View file

@ -30,21 +30,22 @@
void main(void)
{
struct device *dev = device_get_binding("BMP280");
struct device *dev = device_get_binding("BME280");
PRINT("dev %p name %s\n", dev, dev->config->name);
while (1) {
struct sensor_value temp, press;
struct sensor_value temp, press, humidity;
sensor_sample_fetch(dev);
sensor_channel_get(dev, SENSOR_CHAN_TEMP, &temp);
sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);
sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);
PRINT("temp: %d.%06d; press: %d.%06d\n",
temp.val1, temp.val2, press.val1, press.val2);
PRINT("temp: %d.%06d; press: %d.%06d; humidity: %d.%06d\n",
temp.val1, temp.val2, press.val1, press.val2,
humidity.val1, humidity.val2);
task_sleep(sys_clock_ticks_per_sec);
task_sleep(sys_clock_ticks_per_sec/5);
}
}