From 310ed1e2e946eae7d5d7396078bedaec360ac6c9 Mon Sep 17 00:00:00 2001 From: Murtaza Alexandru Date: Tue, 10 May 2016 15:30:06 +0300 Subject: [PATCH] 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 --- drivers/sensor/Kconfig | 4 +- drivers/sensor/Kconfig.bme280 | 180 ++++++++++++ drivers/sensor/Kconfig.bmp280 | 146 ---------- drivers/sensor/Makefile | 2 +- drivers/sensor/sensor_bme280.c | 269 ++++++++++++++++++ drivers/sensor/sensor_bme280.h | 156 ++++++++++ drivers/sensor/sensor_bmp280.c | 204 ------------- drivers/sensor/sensor_bmp280.h | 123 -------- samples/sensor/{bmp280 => bme280}/Makefile | 0 samples/sensor/{bmp280 => bme280}/prj.conf | 2 +- .../sensor/{bmp280 => bme280}/src/Makefile | 0 samples/sensor/{bmp280 => bme280}/src/main.c | 13 +- 12 files changed, 616 insertions(+), 483 deletions(-) create mode 100644 drivers/sensor/Kconfig.bme280 delete mode 100644 drivers/sensor/Kconfig.bmp280 create mode 100644 drivers/sensor/sensor_bme280.c create mode 100644 drivers/sensor/sensor_bme280.h delete mode 100644 drivers/sensor/sensor_bmp280.c delete mode 100644 drivers/sensor/sensor_bmp280.h rename samples/sensor/{bmp280 => bme280}/Makefile (100%) rename samples/sensor/{bmp280 => bme280}/prj.conf (86%) rename samples/sensor/{bmp280 => bme280}/src/Makefile (100%) rename samples/sensor/{bmp280 => bme280}/src/main.c (75%) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 50bedf307c2..6ca73d8ac9d 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -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" diff --git a/drivers/sensor/Kconfig.bme280 b/drivers/sensor/Kconfig.bme280 new file mode 100644 index 00000000000..3154d892b01 --- /dev/null +++ b/drivers/sensor/Kconfig.bme280 @@ -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 diff --git a/drivers/sensor/Kconfig.bmp280 b/drivers/sensor/Kconfig.bmp280 deleted file mode 100644 index 0b7034a0e1b..00000000000 --- a/drivers/sensor/Kconfig.bmp280 +++ /dev/null @@ -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 diff --git a/drivers/sensor/Makefile b/drivers/sensor/Makefile index 894a7ccc110..1665279e51a 100644 --- a/drivers/sensor/Makefile +++ b/drivers/sensor/Makefile @@ -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 diff --git a/drivers/sensor/sensor_bme280.c b/drivers/sensor/sensor_bme280.c new file mode 100644 index 00000000000..8c9414376cb --- /dev/null +++ b/drivers/sensor/sensor_bme280.c @@ -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 +#include +#include +#include +#include +#include +#include + +#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); diff --git a/drivers/sensor/sensor_bme280.h b/drivers/sensor/sensor_bme280.h new file mode 100644 index 00000000000..0aa56af99b0 --- /dev/null +++ b/drivers/sensor/sensor_bme280.h @@ -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 +#include + +#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 +#endif /* __SENSOR_BME280_H__ */ diff --git a/drivers/sensor/sensor_bmp280.c b/drivers/sensor/sensor_bmp280.c deleted file mode 100644 index 2fbbb8a5128..00000000000 --- a/drivers/sensor/sensor_bmp280.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include - -#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); diff --git a/drivers/sensor/sensor_bmp280.h b/drivers/sensor/sensor_bmp280.h deleted file mode 100644 index bb5e09f2d39..00000000000 --- a/drivers/sensor/sensor_bmp280.h +++ /dev/null @@ -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 -#include - -#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 -#endif /* __SENSOR_BMP280_H__ */ diff --git a/samples/sensor/bmp280/Makefile b/samples/sensor/bme280/Makefile similarity index 100% rename from samples/sensor/bmp280/Makefile rename to samples/sensor/bme280/Makefile diff --git a/samples/sensor/bmp280/prj.conf b/samples/sensor/bme280/prj.conf similarity index 86% rename from samples/sensor/bmp280/prj.conf rename to samples/sensor/bme280/prj.conf index c19c68b461c..784792afada 100644 --- a/samples/sensor/bmp280/prj.conf +++ b/samples/sensor/bme280/prj.conf @@ -5,4 +5,4 @@ CONFIG_NANO_TIMEOUTS=y CONFIG_SENSOR=y CONFIG_SENSOR_DEBUG=y -CONFIG_BMP280=y +CONFIG_BME280=y diff --git a/samples/sensor/bmp280/src/Makefile b/samples/sensor/bme280/src/Makefile similarity index 100% rename from samples/sensor/bmp280/src/Makefile rename to samples/sensor/bme280/src/Makefile diff --git a/samples/sensor/bmp280/src/main.c b/samples/sensor/bme280/src/main.c similarity index 75% rename from samples/sensor/bmp280/src/main.c rename to samples/sensor/bme280/src/main.c index 48d6cad0c9a..adb96e1c998 100644 --- a/samples/sensor/bmp280/src/main.c +++ b/samples/sensor/bme280/src/main.c @@ -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); } } -