From 7d7345a620f26d96e95749b76b1eb48ec14e5049 Mon Sep 17 00:00:00 2001 From: likun17 Date: Wed, 6 Sep 2023 11:02:33 +0800 Subject: [PATCH] sensor/bmp180.c:provides work in character device mode and UORB communication mode. Use the macro CONFIG_SENSORS_BMP180_UORB to enable the uorb feature. Signed-off-by: likun17 --- drivers/sensors/Kconfig | 11 + drivers/sensors/Make.defs | 5 + drivers/sensors/bmp180.c | 433 +-------------------------------- drivers/sensors/bmp180_base.c | 391 +++++++++++++++++++++++++++++ drivers/sensors/bmp180_base.h | 135 ++++++++++ drivers/sensors/bmp180_uorb.c | 276 +++++++++++++++++++++ include/nuttx/sensors/bmp180.h | 8 +- 7 files changed, 827 insertions(+), 432 deletions(-) create mode 100644 drivers/sensors/bmp180_base.c create mode 100644 drivers/sensors/bmp180_base.h create mode 100644 drivers/sensors/bmp180_uorb.c diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 800c9a2401..d31a500d7c 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -241,6 +241,17 @@ config SENSORS_BMP180 ---help--- Enable driver support for the Bosch BMP180 barometer sensor. +if SENSORS_BMP180 + +config SENSORS_BMP180_UORB + bool "BMP180 UORB Interface" + select UORB + ---help--- + Enables work with the UORB or Character Device interface. + If not set, the Character Device is used by default. + +endif #SENSORS_BMP180 + config SENSORS_BMP280 bool "Bosch BMP280 Barometric Pressure Sensor" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 7a36870ed5..cee3cdf15f 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -150,8 +150,13 @@ ifeq ($(CONFIG_SENSORS_BMI270),y) endif ifeq ($(CONFIG_SENSORS_BMP180),y) + CSRCS += bmp180_base.c +ifeq ($(CONFIG_SENSORS_BMP180_UORB),y) + CSRCS += bmp180_uorb.c +else CSRCS += bmp180.c endif +endif ifeq ($(CONFIG_SENSORS_BMP280),y) CSRCS += bmp280.c diff --git a/drivers/sensors/bmp180.c b/drivers/sensors/bmp180.c index c5132abff9..2fd168f4b2 100644 --- a/drivers/sensors/bmp180.c +++ b/drivers/sensors/bmp180.c @@ -24,20 +24,7 @@ * Included Files ****************************************************************************/ -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include "bmp180_base.h" #if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_BMP180) @@ -45,90 +32,14 @@ * Pre-processor Definitions ****************************************************************************/ -#define BMP180_ADDR 0x77 -#define BMP180_FREQ 100000 -#define DEVID 0x55 - -#define BMP180_AC1_MSB 0xaa -#define BMP180_AC1_LSB 0xab -#define BMP180_AC2_MSB 0xac -#define BMP180_AC2_LSB 0xad -#define BMP180_AC3_MSB 0xae -#define BMP180_AC3_LSB 0xaf -#define BMP180_AC4_MSB 0xb0 -#define BMP180_AC4_LSB 0xb1 -#define BMP180_AC5_MSB 0xb2 -#define BMP180_AC5_LSB 0xb3 -#define BMP180_AC6_MSB 0xb4 -#define BMP180_AC6_LSB 0xb5 -#define BMP180_B1_MSB 0xb6 -#define BMP180_B1_LSB 0xb7 -#define BMP180_B2_MSB 0xb8 -#define BMP180_B2_LSB 0xb9 -#define BMP180_MB_MSB 0xba -#define BMP180_MB_LSB 0xbb -#define BMP180_MC_MSB 0xbc -#define BMP180_MC_LSB 0xbd -#define BMP180_MD_MSB 0xbe -#define BMP180_MD_LSB 0xbf - -#define BMP180_DEVID 0xd0 -#define BMP180_SOFT_RESET 0xe0 -#define BMP180_CTRL_MEAS 0xf4 -#define BMP180_ADC_OUT_MSB 0xf6 -#define BMP180_ADC_OUT_LSB 0xf7 -#define BMP180_ADC_OUT_XLSB 0xf8 - -#define BMP180_READ_TEMP 0x2e -#define BMP180_READ_PRESS 0x34 - -#define BMP180_NOOVERSAMPLE 0x00 -#define BMP180_OVERSAMPLE2X 0x70 -#define BMP180_OVERSAMPLE4X 0xb0 -#define BMP180_OVERSAMPLE8X 0xc0 - -/* Current Oversampling */ - -#define CURRENT_OSS (BMP180_OVERSAMPLE8X) - /**************************************************************************** * Private Type Definitions ****************************************************************************/ -struct bmp180_dev_s -{ - FAR struct i2c_master_s *i2c; /* I2C interface */ - uint8_t addr; /* BMP180 I2C address */ - int freq; /* BMP180 Frequency <= 3.4MHz */ - int16_t bmp180_cal_ac1; /* Calibration coefficients */ - int16_t bmp180_cal_ac2; - int16_t bmp180_cal_ac3; - uint16_t bmp180_cal_ac4; - uint16_t bmp180_cal_ac5; - uint16_t bmp180_cal_ac6; - int16_t bmp180_cal_b1; - int16_t bmp180_cal_b2; - int16_t bmp180_cal_mb; - int16_t bmp180_cal_mc; - int16_t bmp180_cal_md; - int32_t bmp180_utemp; /* Uncompensated temperature read from BMP180 */ - int32_t bmp180_upress; /* Uncompensated pressure read from BMP180 */ -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static uint8_t bmp180_getreg8(FAR struct bmp180_dev_s *priv, - uint8_t regaddr); -static uint16_t bmp180_getreg16(FAR struct bmp180_dev_s *priv, - uint8_t regaddr); -static void bmp180_putreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr, - uint8_t regval); -static void bmp180_updatecaldata(FAR struct bmp180_dev_s *priv); -static void bmp180_read_press_temp(FAR struct bmp180_dev_s *priv); -static int bmp180_getpressure(FAR struct bmp180_dev_s *priv); - /* Character driver methods */ static ssize_t bmp180_read(FAR struct file *filep, FAR char *buffer, @@ -152,344 +63,6 @@ static const struct file_operations g_bmp180fops = * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: bmp180_getreg8 - * - * Description: - * Read from an 8-bit BMP180 register - * - ****************************************************************************/ - -static uint8_t bmp180_getreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr) -{ - struct i2c_config_s config; - uint8_t regval = 0; - int ret; - - /* Set up the I2C configuration */ - - config.frequency = priv->freq; - config.address = priv->addr; - config.addrlen = 7; - - /* Write the register address */ - - ret = i2c_write(priv->i2c, &config, ®addr, 1); - if (ret < 0) - { - snerr("ERROR: i2c_write failed: %d\n", ret); - return ret; - } - - /* Read the register value */ - - ret = i2c_read(priv->i2c, &config, ®val, 1); - if (ret < 0) - { - snerr("ERROR: i2c_read failed: %d\n", ret); - return ret; - } - - return regval; -} - -/**************************************************************************** - * Name: bmp180_getreg16 - * - * Description: - * Read two 8-bit from a BMP180 register - * - ****************************************************************************/ - -static uint16_t bmp180_getreg16(FAR struct bmp180_dev_s *priv, - uint8_t regaddr) -{ - struct i2c_config_s config; - uint16_t msb; - uint16_t lsb; - uint16_t regval = 0; - int ret; - - /* Set up the I2C configuration */ - - config.frequency = priv->freq; - config.address = priv->addr; - config.addrlen = 7; - - /* Register to read */ - - ret = i2c_write(priv->i2c, &config, ®addr, 1); - if (ret < 0) - { - snerr("ERROR: i2c_write failed: %d\n", ret); - return ret; - } - - /* Read register */ - - ret = i2c_read(priv->i2c, &config, (uint8_t *)®val, 2); - if (ret < 0) - { - snerr("ERROR: i2c_read failed: %d\n", ret); - return ret; - } - - /* MSB and LSB are inverted */ - - msb = (regval & 0xff); - lsb = (regval & 0xff00) >> 8; - - regval = (msb << 8) | lsb; - - return regval; -} - -/**************************************************************************** - * Name: bmp180_putreg8 - * - * Description: - * Write to an 8-bit BMP180 register - * - ****************************************************************************/ - -static void bmp180_putreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr, - uint8_t regval) -{ - struct i2c_config_s config; - uint8_t data[2]; - int ret; - - /* Set up the I2C configuration */ - - config.frequency = priv->freq; - config.address = priv->addr; - config.addrlen = 7; - - data[0] = regaddr; - data[1] = regval; - - /* Write the register address and value */ - - ret = i2c_write(priv->i2c, &config, (uint8_t *) &data, 2); - if (ret < 0) - { - snerr("ERROR: i2c_write failed: %d\n", ret); - return; - } -} - -/**************************************************************************** - * Name: bmp180_checkid - * - * Description: - * Read and verify the BMP180 chip ID - * - ****************************************************************************/ - -static int bmp180_checkid(FAR struct bmp180_dev_s *priv) -{ - uint8_t devid = 0; - - /* Read device ID */ - - devid = bmp180_getreg8(priv, BMP180_DEVID); - sninfo("devid: 0x%02x\n", devid); - - if (devid != (uint16_t)DEVID) - { - /* ID is not Correct */ - - snerr("ERROR: Wrong Device ID!\n"); - return -ENODEV; - } - - return OK; -} - -/**************************************************************************** - * Name: bmp180_updatecaldata - * - * Description: - * Update Calibration Coefficient Data - * - ****************************************************************************/ - -static void bmp180_updatecaldata(FAR struct bmp180_dev_s *priv) -{ - /* AC1 */ - - priv->bmp180_cal_ac1 = (int16_t) bmp180_getreg16(priv, BMP180_AC1_MSB); - - /* AC2 */ - - priv->bmp180_cal_ac2 = (int16_t) bmp180_getreg16(priv, BMP180_AC2_MSB); - - /* AC3 */ - - priv->bmp180_cal_ac3 = (int16_t) bmp180_getreg16(priv, BMP180_AC3_MSB); - - /* AC4 */ - - priv->bmp180_cal_ac4 = bmp180_getreg16(priv, BMP180_AC4_MSB); - - /* AC5 */ - - priv->bmp180_cal_ac5 = bmp180_getreg16(priv, BMP180_AC5_MSB); - - /* AC6 */ - - priv->bmp180_cal_ac6 = bmp180_getreg16(priv, BMP180_AC6_MSB); - - /* B1 */ - - priv->bmp180_cal_b1 = (int16_t) bmp180_getreg16(priv, BMP180_B1_MSB); - - /* B2 */ - - priv->bmp180_cal_b2 = (int16_t) bmp180_getreg16(priv, BMP180_B2_MSB); - - /* MB */ - - priv->bmp180_cal_mb = (int16_t) bmp180_getreg16(priv, BMP180_MB_MSB); - - /* MC */ - - priv->bmp180_cal_mc = (int16_t) bmp180_getreg16(priv, BMP180_MC_MSB); - - /* MD */ - - priv->bmp180_cal_md = (int16_t) bmp180_getreg16(priv, BMP180_MD_MSB); -} - -/**************************************************************************** - * Name: bmp180_read_press_temp - * - * Description: - * Read raw pressure and temperature from BMP180 and store it in the - * bmp180_dev_s structure. - * - ****************************************************************************/ - -static void bmp180_read_press_temp(FAR struct bmp180_dev_s *priv) -{ - uint8_t oss = CURRENT_OSS; - - /* Issue a read temperature command */ - - bmp180_putreg8(priv, BMP180_CTRL_MEAS, BMP180_READ_TEMP); - - /* Wait 5ms */ - - nxsig_usleep(5000); - - /* Read temperature */ - - priv->bmp180_utemp = bmp180_getreg16(priv, BMP180_ADC_OUT_MSB); - - /* Issue a read pressure command */ - - bmp180_putreg8(priv, BMP180_CTRL_MEAS, (BMP180_READ_PRESS | oss)); - - /* Delay 25.5ms (to OverSampling 8X) */ - - nxsig_usleep(25500); - - /* Read pressure */ - - priv->bmp180_upress = bmp180_getreg16(priv, BMP180_ADC_OUT_MSB) << 8; - priv->bmp180_upress |= bmp180_getreg8(priv, BMP180_ADC_OUT_XLSB); - priv->bmp180_upress = priv->bmp180_upress >> (8 - (oss >> 6)); - - sninfo("Uncompensated temperature = %" PRId32 "\n", priv->bmp180_utemp); - sninfo("Uncompensated pressure = %" PRId32 "\n", priv->bmp180_upress); -} - -/**************************************************************************** - * Name: bmp180_getpressure - * - * Description: - * Calculate the Barometric Pressure using the temperature compensated - * See Freescale AN3785 and BMP1801 data sheet for details - * - ****************************************************************************/ - -static int bmp180_getpressure(FAR struct bmp180_dev_s *priv) -{ - int32_t x1; - int32_t x2; - int32_t x3; - int32_t b3; - int32_t b5; - int32_t b6; - int32_t press; - int32_t temp; - uint32_t b4; - uint32_t b7; - uint8_t oss = (CURRENT_OSS >> 6); - - /* Check if coefficient data were read correctly */ - - if ((priv->bmp180_cal_ac1 == 0) || (priv->bmp180_cal_ac2 == 0) || - (priv->bmp180_cal_ac3 == 0) || (priv->bmp180_cal_ac4 == 0) || - (priv->bmp180_cal_ac5 == 0) || (priv->bmp180_cal_ac6 == 0) || - (priv->bmp180_cal_b1 == 0) || (priv->bmp180_cal_b2 == 0) || - (priv->bmp180_cal_mb == 0) || (priv->bmp180_cal_mc == 0) || - (priv->bmp180_cal_md == 0)) - { - bmp180_updatecaldata(priv); - } - - /* Read temperature and pressure */ - - bmp180_read_press_temp(priv); - - /* Feed raw sensor data to entropy pool */ - - add_sensor_randomness((priv->bmp180_utemp << 16) ^ priv->bmp180_upress); - - /* Calculate true temperature */ - - x1 = ((priv->bmp180_utemp - priv->bmp180_cal_ac6) * - priv->bmp180_cal_ac5) >> 15; - x2 = (priv->bmp180_cal_mc << 11) / (x1 + priv->bmp180_cal_md); - b5 = x1 + x2; - - temp = (b5 + 8) >> 4; - sninfo("Compensated temperature = %" PRId32 "\n", temp); - UNUSED(temp); - - /* Calculate true pressure */ - - b6 = b5 - 4000; - x1 = (priv->bmp180_cal_b2 * ((b6 * b6) >> 12)) >> 11; - x2 = (priv->bmp180_cal_ac2 * b6) >> 11; - x3 = x1 + x2; - b3 = (((((int32_t) priv->bmp180_cal_ac1) * 4 + x3) << oss) + 2) >> 2; - x1 = (priv->bmp180_cal_ac3 * b6) >> 13; - x2 = (priv->bmp180_cal_b1 * ((b6 * b6) >> 12)) >> 16; - x3 = ((x1 + x2) + 2) >> 2; - b4 = (priv->bmp180_cal_ac4 * (uint32_t) (x3 + 32768)) >> 15; - b7 = ((uint32_t) (priv->bmp180_upress - b3) * (50000 >> oss)); - - if (b7 < 0x80000000) - { - press = (b7 << 1) / b4; - } - else - { - press = (b7 / b4) << 1; - } - - x1 = (press >> 8) * (press >> 8); - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * press) >> 16; - - press = press + ((x1 + x2 + 3791) >> 4); - - sninfo("Compressed pressure = %" PRId32 "\n", press); - return press; -} - /**************************************************************************** * Name: bmp180_read ****************************************************************************/ @@ -516,7 +89,7 @@ static ssize_t bmp180_read(FAR struct file *filep, FAR char *buffer, /* Get the pressure compensated */ - *press = (int32_t) bmp180_getpressure(priv); + *press = (int32_t) bmp180_getpressure(priv, NULL); /* Return size of uint32_t (4 bytes) */ @@ -560,7 +133,7 @@ int bmp180_register(FAR const char *devpath, FAR struct i2c_master_s *i2c) /* Initialize the BMP180 device structure */ - priv = kmm_malloc(sizeof(struct bmp180_dev_s)); + priv = (FAR struct bmp180_dev_s *)kmm_malloc(sizeof(struct bmp180_dev_s)); if (!priv) { snerr("ERROR: Failed to allocate instance\n"); diff --git a/drivers/sensors/bmp180_base.c b/drivers/sensors/bmp180_base.c new file mode 100644 index 0000000000..834faa3b63 --- /dev/null +++ b/drivers/sensors/bmp180_base.c @@ -0,0 +1,391 @@ +/**************************************************************************** + * drivers/sensors/bmp180_base.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* Character driver for the Freescale BMP1801 Barometer Sensor */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "bmp180_base.h" + +#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_BMP180) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bmp180_getreg8 + * + * Description: + * Read from an 8-bit BMP180 register + * + ****************************************************************************/ + +uint8_t bmp180_getreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr) +{ + struct i2c_config_s config; + uint8_t regval = 0; + int ret; + + /* Set up the I2C configuration */ + + config.frequency = priv->freq; + config.address = priv->addr; + config.addrlen = 7; + + /* Write the register address */ + + ret = i2c_write(priv->i2c, &config, ®addr, 1); + if (ret < 0) + { + snerr("ERROR: i2c_write failed: %d\n", ret); + return ret; + } + + /* Read the register value */ + + ret = i2c_read(priv->i2c, &config, ®val, 1); + if (ret < 0) + { + snerr("ERROR: i2c_read failed: %d\n", ret); + return ret; + } + + return regval; +} + +/**************************************************************************** + * Name: bmp180_getreg16 + * + * Description: + * Read two 8-bit from a BMP180 register + * + ****************************************************************************/ + +uint16_t bmp180_getreg16(FAR struct bmp180_dev_s *priv, uint8_t regaddr) +{ + struct i2c_config_s config; + uint16_t msb; + uint16_t lsb; + uint16_t regval = 0; + int ret; + + /* Set up the I2C configuration */ + + config.frequency = priv->freq; + config.address = priv->addr; + config.addrlen = 7; + + /* Register to read */ + + ret = i2c_write(priv->i2c, &config, ®addr, 1); + if (ret < 0) + { + snerr("ERROR: i2c_write failed: %d\n", ret); + return ret; + } + + /* Read register */ + + ret = i2c_read(priv->i2c, &config, (uint8_t *)®val, 2); + if (ret < 0) + { + snerr("ERROR: i2c_read failed: %d\n", ret); + return ret; + } + + /* MSB and LSB are inverted */ + + msb = (regval & 0xff); + lsb = (regval & 0xff00) >> 8; + + regval = (msb << 8) | lsb; + + return regval; +} + +/**************************************************************************** + * Name: bmp180_putreg8 + * + * Description: + * Write to an 8-bit BMP180 register + * + ****************************************************************************/ + +void bmp180_putreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr, + uint8_t regval) +{ + struct i2c_config_s config; + uint8_t data[2]; + int ret; + + /* Set up the I2C configuration */ + + config.frequency = priv->freq; + config.address = priv->addr; + config.addrlen = 7; + + data[0] = regaddr; + data[1] = regval; + + /* Write the register address and value */ + + ret = i2c_write(priv->i2c, &config, (uint8_t *) &data, 2); + if (ret < 0) + { + snerr("ERROR: i2c_write failed: %d\n", ret); + return; + } +} + +/**************************************************************************** + * Name: bmp180_checkid + * + * Description: + * Read and verify the BMP180 chip ID + * + ****************************************************************************/ + +int bmp180_checkid(FAR struct bmp180_dev_s *priv) +{ + uint8_t devid = 0; + + /* Read device ID */ + + devid = bmp180_getreg8(priv, BMP180_DEVID); + sninfo("devid: 0x%02x\n", devid); + + if (devid != (uint16_t)DEVID) + { + /* ID is not Correct */ + + snerr("ERROR: Wrong Device ID!\n"); + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: bmp180_updatecaldata + * + * Description: + * Update Calibration Coefficient Data + * + ****************************************************************************/ + +void bmp180_updatecaldata(FAR struct bmp180_dev_s *priv) +{ + /* AC1 */ + + priv->bmp180_cal_ac1 = (int16_t) bmp180_getreg16(priv, BMP180_AC1_MSB); + + /* AC2 */ + + priv->bmp180_cal_ac2 = (int16_t) bmp180_getreg16(priv, BMP180_AC2_MSB); + + /* AC3 */ + + priv->bmp180_cal_ac3 = (int16_t) bmp180_getreg16(priv, BMP180_AC3_MSB); + + /* AC4 */ + + priv->bmp180_cal_ac4 = bmp180_getreg16(priv, BMP180_AC4_MSB); + + /* AC5 */ + + priv->bmp180_cal_ac5 = bmp180_getreg16(priv, BMP180_AC5_MSB); + + /* AC6 */ + + priv->bmp180_cal_ac6 = bmp180_getreg16(priv, BMP180_AC6_MSB); + + /* B1 */ + + priv->bmp180_cal_b1 = (int16_t) bmp180_getreg16(priv, BMP180_B1_MSB); + + /* B2 */ + + priv->bmp180_cal_b2 = (int16_t) bmp180_getreg16(priv, BMP180_B2_MSB); + + /* MB */ + + priv->bmp180_cal_mb = (int16_t) bmp180_getreg16(priv, BMP180_MB_MSB); + + /* MC */ + + priv->bmp180_cal_mc = (int16_t) bmp180_getreg16(priv, BMP180_MC_MSB); + + /* MD */ + + priv->bmp180_cal_md = (int16_t) bmp180_getreg16(priv, BMP180_MD_MSB); +} + +/**************************************************************************** + * Name: bmp180_read_press_temp + * + * Description: + * Read raw pressure and temperature from BMP180 and store it in the + * bmp180_dev_s structure. + * + ****************************************************************************/ + +void bmp180_read_press_temp(FAR struct bmp180_dev_s *priv) +{ + uint8_t oss = CURRENT_OSS; + + /* Issue a read temperature command */ + + bmp180_putreg8(priv, BMP180_CTRL_MEAS, BMP180_READ_TEMP); + + /* Wait 5ms */ + + nxsig_usleep(5000); + + /* Read temperature */ + + priv->bmp180_utemp = bmp180_getreg16(priv, BMP180_ADC_OUT_MSB); + + /* Issue a read pressure command */ + + bmp180_putreg8(priv, BMP180_CTRL_MEAS, (BMP180_READ_PRESS | oss)); + + /* Delay 25.5ms (to OverSampling 8X) */ + + nxsig_usleep(25500); + + /* Read pressure */ + + priv->bmp180_upress = bmp180_getreg16(priv, BMP180_ADC_OUT_MSB) << 8; + priv->bmp180_upress |= bmp180_getreg8(priv, BMP180_ADC_OUT_XLSB); + priv->bmp180_upress = priv->bmp180_upress >> (8 - (oss >> 6)); + + sninfo("Uncompensated temperature = %" PRId32 "\n", priv->bmp180_utemp); + sninfo("Uncompensated pressure = %" PRId32 "\n", priv->bmp180_upress); +} + +/**************************************************************************** + * Name: bmp180_getpressure + * + * Description: + * Calculate the Barometric Pressure using the temperature compensated + * See Freescale AN3785 and BMP1801 data sheet for details + * + ****************************************************************************/ + +int bmp180_getpressure(FAR struct bmp180_dev_s *priv, + FAR float *temperature) +{ + int32_t x1; + int32_t x2; + int32_t x3; + int32_t b3; + int32_t b5; + int32_t b6; + int32_t press; + int32_t temp; + uint32_t b4; + uint32_t b7; + uint8_t oss = (CURRENT_OSS >> 6); + + /* Check if coefficient data were read correctly */ + + if ((priv->bmp180_cal_ac1 == 0) || (priv->bmp180_cal_ac2 == 0) || + (priv->bmp180_cal_ac3 == 0) || (priv->bmp180_cal_ac4 == 0) || + (priv->bmp180_cal_ac5 == 0) || (priv->bmp180_cal_ac6 == 0) || + (priv->bmp180_cal_b1 == 0) || (priv->bmp180_cal_b2 == 0) || + (priv->bmp180_cal_mb == 0) || (priv->bmp180_cal_mc == 0) || + (priv->bmp180_cal_md == 0)) + { + bmp180_updatecaldata(priv); + } + + /* Read temperature and pressure */ + + bmp180_read_press_temp(priv); + + /* Feed raw sensor data to entropy pool */ + + add_sensor_randomness((priv->bmp180_utemp << 16) ^ priv->bmp180_upress); + + /* Calculate true temperature */ + + x1 = ((priv->bmp180_utemp - priv->bmp180_cal_ac6) * + priv->bmp180_cal_ac5) >> 15; + x2 = (priv->bmp180_cal_mc << 11) / (x1 + priv->bmp180_cal_md); + b5 = x1 + x2; + + temp = (b5 + 8) >> 4; + sninfo("Compensated temperature = %" PRId32 "\n", temp); + + if (temperature != NULL) + *temperature = temp; + + /* Calculate true pressure */ + + b6 = b5 - 4000; + x1 = (priv->bmp180_cal_b2 * ((b6 * b6) >> 12)) >> 11; + x2 = (priv->bmp180_cal_ac2 * b6) >> 11; + x3 = x1 + x2; + b3 = (((((int32_t) priv->bmp180_cal_ac1) * 4 + x3) << oss) + 2) >> 2; + x1 = (priv->bmp180_cal_ac3 * b6) >> 13; + x2 = (priv->bmp180_cal_b1 * ((b6 * b6) >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + b4 = (priv->bmp180_cal_ac4 * (uint32_t) (x3 + 32768)) >> 15; + b7 = ((uint32_t) (priv->bmp180_upress - b3) * (50000 >> oss)); + + if (b7 < 0x80000000) + { + press = (b7 << 1) / b4; + } + else + { + press = (b7 / b4) << 1; + } + + x1 = (press >> 8) * (press >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * press) >> 16; + + press = press + ((x1 + x2 + 3791) >> 4); + + sninfo("Compressed pressure = %" PRId32 "\n", press); + return press; +} + +#endif /* CONFIG_I2C && CONFIG_SENSORS_BMP180 */ diff --git a/drivers/sensors/bmp180_base.h b/drivers/sensors/bmp180_base.h new file mode 100644 index 0000000000..92507ec8a9 --- /dev/null +++ b/drivers/sensors/bmp180_base.h @@ -0,0 +1,135 @@ +/**************************************************************************** + * drivers/sensors/bmp180_base.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* Character driver for the Freescale BMP1801 Barometer Sensor */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_BMP180) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BMP180_ADDR 0x77 +#define BMP180_FREQ 100000 +#define DEVID 0x55 + +#define BMP180_AC1_MSB 0xaa +#define BMP180_AC1_LSB 0xab +#define BMP180_AC2_MSB 0xac +#define BMP180_AC2_LSB 0xad +#define BMP180_AC3_MSB 0xae +#define BMP180_AC3_LSB 0xaf +#define BMP180_AC4_MSB 0xb0 +#define BMP180_AC4_LSB 0xb1 +#define BMP180_AC5_MSB 0xb2 +#define BMP180_AC5_LSB 0xb3 +#define BMP180_AC6_MSB 0xb4 +#define BMP180_AC6_LSB 0xb5 +#define BMP180_B1_MSB 0xb6 +#define BMP180_B1_LSB 0xb7 +#define BMP180_B2_MSB 0xb8 +#define BMP180_B2_LSB 0xb9 +#define BMP180_MB_MSB 0xba +#define BMP180_MB_LSB 0xbb +#define BMP180_MC_MSB 0xbc +#define BMP180_MC_LSB 0xbd +#define BMP180_MD_MSB 0xbe +#define BMP180_MD_LSB 0xbf + +#define BMP180_DEVID 0xd0 +#define BMP180_SOFT_RESET 0xe0 +#define BMP180_CTRL_MEAS 0xf4 +#define BMP180_ADC_OUT_MSB 0xf6 +#define BMP180_ADC_OUT_LSB 0xf7 +#define BMP180_ADC_OUT_XLSB 0xf8 + +#define BMP180_READ_TEMP 0x2e +#define BMP180_READ_PRESS 0x34 + +#define BMP180_NOOVERSAMPLE 0x00 +#define BMP180_OVERSAMPLE2X 0x70 +#define BMP180_OVERSAMPLE4X 0xb0 +#define BMP180_OVERSAMPLE8X 0xc0 + +/* Current Oversampling */ + +#define CURRENT_OSS (BMP180_OVERSAMPLE8X) + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +struct bmp180_dev_s +{ + FAR struct i2c_master_s *i2c; /* I2C interface */ + uint8_t addr; /* BMP180 I2C address */ + int freq; /* BMP180 Frequency <= 3.4MHz */ + int16_t bmp180_cal_ac1; /* Calibration coefficients */ + int16_t bmp180_cal_ac2; + int16_t bmp180_cal_ac3; + uint16_t bmp180_cal_ac4; + uint16_t bmp180_cal_ac5; + uint16_t bmp180_cal_ac6; + int16_t bmp180_cal_b1; + int16_t bmp180_cal_b2; + int16_t bmp180_cal_mb; + int16_t bmp180_cal_mc; + int16_t bmp180_cal_md; + int32_t bmp180_utemp; /* Uncompensated temperature read from BMP180 */ + int32_t bmp180_upress; /* Uncompensated pressure read from BMP180 */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +uint8_t bmp180_getreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr); + +uint16_t bmp180_getreg16(FAR struct bmp180_dev_s *priv, uint8_t regaddr); +void bmp180_putreg8(FAR struct bmp180_dev_s *priv, uint8_t regaddr, + uint8_t regval); + +int bmp180_checkid(FAR struct bmp180_dev_s *priv); + +void bmp180_updatecaldata(FAR struct bmp180_dev_s *priv); +void bmp180_read_press_temp(FAR struct bmp180_dev_s *priv); +int bmp180_getpressure(FAR struct bmp180_dev_s *priv, + FAR float *temperature); + +#endif /* CONFIG_I2C && CONFIG_SENSORS_BMP180 */ diff --git a/drivers/sensors/bmp180_uorb.c b/drivers/sensors/bmp180_uorb.c new file mode 100644 index 0000000000..35592e01c2 --- /dev/null +++ b/drivers/sensors/bmp180_uorb.c @@ -0,0 +1,276 @@ +/**************************************************************************** + * drivers/sensors/bmp180_uorb.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/* Character driver for the Freescale BMP1801 Barometer Sensor */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "bmp180_base.h" + +#include +#include + +#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_BMP180) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BMP180_MIN_INTERVAL 30000 + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +struct bmp180_dev_uorb_s +{ + /* sensor_lowerhalf_s must be in the first line. */ + + struct sensor_lowerhalf_s lower; /* Lower half sensor driver. */ + struct work_s work; /* Interrupt handler worker. */ + unsigned long interval; /* Sensor acquisition interval. */ + struct bmp180_dev_s dev; +}; +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void bmp180_worker(FAR void *arg); +static int bmp180_set_interval(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR unsigned long *period_us); +static int bmp180_activate(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + bool enable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct sensor_ops_s g_bmp180_ops = +{ + .activate = bmp180_activate, /* Enable/disable sensor. */ + .set_interval = bmp180_set_interval, /* Set output data period. */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bmp180_set_interval + * + * Description: + * Set the sensor output data period in microseconds for a given sensor. + * If *period_us > max_delay it will be truncated to max_delay and if + * *period_us < min_delay it will be replaced by min_delay. + * + * Input Parameters: + * lower - The instance of lower half sensor driver. + * filep - The pointer of file, represents each user using the sensor. + * period_us - The time between report data, in us. It may by overwrite + * by lower half driver. + * + * Returned Value: + * Return OK(0) if the driver was success; A negated errno + * value is returned on any failure. + * + * Assumptions/Limitations: + * None. + * + ****************************************************************************/ + +static int bmp180_set_interval(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR unsigned long *period_us) +{ + FAR struct bmp180_dev_uorb_s *priv = (FAR struct bmp180_dev_uorb_s *)lower; + + /* minimum interval 4.5ms + 25.5ms */ + + if (*period_us < BMP180_MIN_INTERVAL) + { + priv->interval = BMP180_MIN_INTERVAL; + *period_us = priv->interval; + } + else + { + priv->interval = *period_us; + } + + return OK; +} + +/**************************************************************************** + * Name: bmp180_activate + * + * Description: + * Enable or disable sensor device. when enable sensor, sensor will + * work in current mode(if not set, use default mode). when disable + * sensor, it will disable sense path and stop convert. + * + * Input Parameters: + * lower - The instance of lower half sensor driver. + * filep - The pointer of file, represents each user using the sensor. + * enable - true(enable) and false(disable). + * + * Returned Value: + * Return OK(0) if the driver was success; A negated errno + * value is returned on any failure. + * + * Assumptions/Limitations: + * None. + * + ****************************************************************************/ + +static int bmp180_activate(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, bool enable) +{ + FAR struct bmp180_dev_uorb_s *priv = (FAR struct bmp180_dev_uorb_s *)lower; + + /* Set accel output data rate. */ + + if (enable) + { + work_queue(HPWORK, &priv->work, + bmp180_worker, priv, + priv->interval / USEC_PER_TICK); + } + else + { + /* Set suspend mode to sensors. */ + + work_cancel(HPWORK, &priv->work); + } + + return OK; +} + +/**************************************************************************** + * Name: bmp180_worker + * + * Description: + * Task the worker with retrieving the latest sensor data. We should not do + * this in a interrupt since it might take too long. Also we cannot lock + * the I2C bus from within an interrupt. + * + * Input Parameters: + * arg - Device struct. + * + * Returned Value: + * none. + * + * Assumptions/Limitations: + * none. + * + ****************************************************************************/ + +static void bmp180_worker(FAR void *arg) +{ + FAR struct bmp180_dev_uorb_s *priv = arg; + struct sensor_baro baro; + + DEBUGASSERT(priv != NULL); + + work_queue(HPWORK, &priv->work, + bmp180_worker, priv, + priv->interval / USEC_PER_TICK); + + baro.pressure = bmp180_getpressure(&priv->dev, &baro.temperature) / 100.0f; + baro.timestamp = sensor_get_timestamp(); + + priv->lower.push_event(priv->lower.priv, &baro, sizeof(baro)); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bmp180_register + * + * Description: + * Register the BMP180 character device as 'devpath' + * + * Input Parameters: + * devno - Sensor device number. + * i2c - An instance of the I2C interface to use to communicate with + * BMP180 + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int bmp180_register_uorb(int devno, FAR struct i2c_master_s *i2c) +{ + FAR struct bmp180_dev_uorb_s *priv; + int ret; + + /* Initialize the BMP180 device structure */ + + priv = (FAR struct bmp180_dev_uorb_s *) + kmm_zalloc(sizeof(struct bmp180_dev_uorb_s)); + + if (!priv) + { + snerr("ERROR: Failed to allocate instance\n"); + return -ENOMEM; + } + + priv->dev.i2c = i2c; + priv->dev.addr = BMP180_ADDR; + priv->dev.freq = BMP180_FREQ; + priv->lower.ops = &g_bmp180_ops; + priv->lower.type = SENSOR_TYPE_BAROMETER; + priv->lower.nbuffer = 1; + priv->interval = BMP180_MIN_INTERVAL; + + /* Check Device ID */ + + ret = bmp180_checkid(&priv->dev); + if (ret < 0) + { + snerr("ERROR: Failed to register driver: %d\n", ret); + kmm_free(priv); + return ret; + } + + /* Read the coefficient value */ + + bmp180_updatecaldata(&priv->dev); + + /* Register the character driver */ + + ret = sensor_register(&priv->lower, devno); + + if (ret < 0) + { + snerr("ERROR: Failed to register driver: %d\n", ret); + kmm_free(priv); + } + + sninfo("BMP180 driver loaded successfully!\n"); + return ret; +} + +#endif /* CONFIG_I2C && CONFIG_SENSORS_BMP180 */ diff --git a/include/nuttx/sensors/bmp180.h b/include/nuttx/sensors/bmp180.h index a28d1d552d..f588d83a15 100644 --- a/include/nuttx/sensors/bmp180.h +++ b/include/nuttx/sensors/bmp180.h @@ -68,7 +68,8 @@ extern "C" * Register the BMP180 character device as 'devpath' * * Input Parameters: - * devpath - The full path to the driver to register. E.g., "/dev/press0" + * path/no - The full path (or number) to the driver to register. + * E.g.:("/dev/press0", i2c) or (0, i2c) * i2c - An instance of the I2C interface to use to communicate with * BMP180 * @@ -76,8 +77,11 @@ extern "C" * Zero (OK) on success; a negated errno value on failure. * ****************************************************************************/ - +#ifndef CONFIG_SENSORS_BMP180_UORB int bmp180_register(FAR const char *devpath, FAR struct i2c_master_s *i2c); +#else +int bmp180_register_uorb(int devno, FAR struct i2c_master_s *i2c); +#endif /* CONFIG_SENSORS_BMP180_UORB */ #undef EXTERN #ifdef __cplusplus