diff --git a/README.md b/README.md index 0a0e398..e9feefb 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ The sensor driver package includes bme280.c, bme280.h and bme280_defs.h files. SPI 3-wire is currently not supported in the API. ## Usage guide ### Initializing the sensor -To initialize the sensor, user need to create a device structure. User can do this by -creating an instance of the structure bme280_dev. After creating the device strcuture, user -need to fill in the various parameters as shown below. +To initialize the sensor, user needs to create a device structure. User can do this by +creating an instance of the structure bme280_dev. After creating the device structure, user +needs to fill in the various parameters as shown below. #### Example for SPI 4-Wire ``` c @@ -40,7 +40,7 @@ dev.intf_ptr = &dev_addr; dev.intf = BME280_SPI_INTF; dev.read = user_spi_read; dev.write = user_spi_write; -dev.delay_ms = user_delay_ms; +dev.delay_us = user_delay_us; rslt = bme280_init(&dev); ``` @@ -54,43 +54,44 @@ dev.intf_ptr = &dev_addr; dev.intf = BME280_I2C_INTF; dev.read = user_i2c_read; dev.write = user_i2c_write; -dev.delay_ms = user_delay_ms; +dev.delay_us = user_delay_us; rslt = bme280_init(&dev); ``` -Regarding compensation functions for temperature,pressure and humidity we have two implementations. +Regarding compensation functions for temperature, pressure and humidity we have two implementations. 1) Double precision floating point version -2) Integer version +2) Integer versions -By default, integer version is used in the API. If the user needs the floating point version, the user has to uncomment BME280_FLOAT_ENABLE macro in bme280_defs.h file or add that to the compiler flags. +By default, BME280_FLOAT_ENABLE i.e. double precision floating point version is used in the API. +If the user needs an integer version, the user has to define BME280_64BIT_ENABLE or BME280_32BIT_ENABLE macro in bme280_defs.h file or add that to the compiler flags. In integer compensation functions, we also have below two implementations for pressure. 1) For 32 bit machine. 2) For 64 bit machine. -By default, 64 bit variant is used in the API. If the user wants 32 bit variant, the user can disable the -macro BME280_64BIT_ENABLE in bme280_defs.h file. +When using integer versions the 64 bit variant is recommended to use in the API. If the user wants 32 bit variant, the user can define the +macro BME280_32BIT_ENABLE in bme280_defs.h file. ### Sensor data units -> The sensor data units depends on the following macros being enabled or not, +> The sensor data units depends on the following macros being enabled or not, > (in bme280_defs.h file or as compiler macros) > * BME280_FLOAT_ENABLE > * BME280_64BIT_ENABLE -In case of the macro "BME280_FLOAT_ENABLE" enabled, +In case of the macro "BME280_FLOAT_ENABLE" enabled (default), The outputs are in double and the units are - °C for temperature - % relative humidity - Pascal for pressure -In case if "BME280_FLOAT_ENABLE" is not enabled, then it is +In case if "BME280_FLOAT_ENABLE" is _not_ enabled, then it is - int32_t for temperature with the units 100 * °C - uint32_t for humidity with the units 1024 * % relative humidity - uint32_t for pressure - If macro "BME280_64BIT_ENABLE" is enabled, which it is by default, the unit is 100 * Pascal - If this macro is disabled, Then the unit is in Pascal + If macro "BME280_64BIT_ENABLE" is enabled, the unit is 100 * Pascal + If macro "BME280_32BIT_ENABLE" is enabled, then the unit is in Pascal ### Stream sensor data #### Stream sensor data in forced mode @@ -100,7 +101,7 @@ int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) { int8_t rslt; uint8_t settings_sel; - uint32_t req_delay; + uint32_t req_delay; struct bme280_data comp_data; /* Recommended mode of operation: Indoor navigation */ @@ -112,9 +113,9 @@ int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL; rslt = bme280_set_sensor_settings(settings_sel, dev); - - /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled - * and the oversampling configuration. */ + + /* Calculate the minimum delay in microseconds required between consecutive measurements + * based upon the sensor enabled and oversampling configuration. */ req_delay = bme280_cal_meas_delay(&dev->settings); printf("Temperature, Pressure, Humidity\r\n"); @@ -122,7 +123,7 @@ int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) while (1) { rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, dev); /* Wait for the measurement to complete and print data @25Hz */ - dev->delay_ms(req_delay, dev->intf_ptr); + dev->delay_us(req_delay, dev->intf_ptr); rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); print_sensor_data(&comp_data); } @@ -164,7 +165,7 @@ int8_t stream_sensor_data_normal_mode(struct bme280_dev *dev) printf("Temperature, Pressure, Humidity\r\n"); while (1) { /* Delay while the sensor completes a measurement */ - dev->delay_ms(70, dev->intf_ptr); + dev->delay_us(70000, dev->intf_ptr); rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, dev); print_sensor_data(&comp_data); } @@ -185,11 +186,11 @@ void print_sensor_data(struct bme280_data *comp_data) ### Templates for function pointers ``` c -void user_delay_ms(uint32_t period, void *intf_ptr) +void user_delay_us(uint32_t period, void *intf_ptr) { /* * Return control or wait, - * for a period amount of milliseconds + * for a period amount of microseconds */ } @@ -219,7 +220,7 @@ int8_t user_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *in return rslt; } -int8_t user_spi_write(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +int8_t user_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) { int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ @@ -272,7 +273,7 @@ int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *in return rslt; } -int8_t user_i2c_write(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) { int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ @@ -296,5 +297,3 @@ int8_t user_i2c_write(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *i return rslt; } - -``` \ No newline at end of file diff --git a/bme280.c b/bme280.c index cabefc2..43a341f 100644 --- a/bme280.c +++ b/bme280.c @@ -850,8 +850,8 @@ int8_t bme280_compensate_data(uint8_t sensor_comp, } /*! - * @brief This API is used to calculate the maximum delay in milliseconds required for the - * temperature/pressure/humidity(which ever at enabled) measurement to complete. + * @brief This API is used to calculate the maximum delay in microseconds required for the + * temperature/pressure/humidity (whichever are enabled) measurement to complete. */ uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings) { @@ -892,9 +892,9 @@ uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings) } max_delay = - (uint32_t)((BME280_MEAS_OFFSET + (BME280_MEAS_DUR * temp_osr) + + (uint32_t)(BME280_MEAS_OFFSET + (BME280_MEAS_DUR * temp_osr) + ((BME280_MEAS_DUR * pres_osr) + BME280_PRES_HUM_MEAS_OFFSET) + - ((BME280_MEAS_DUR * hum_osr) + BME280_PRES_HUM_MEAS_OFFSET)) / BME280_MEAS_SCALING_FACTOR); + ((BME280_MEAS_DUR * hum_osr) + BME280_PRES_HUM_MEAS_OFFSET)); return max_delay; } diff --git a/bme280.h b/bme280.h index fd95990..43125d9 100644 --- a/bme280.h +++ b/bme280.h @@ -377,13 +377,13 @@ int8_t bme280_compensate_data(uint8_t sensor_comp, * \code * uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings); * \endcode - * @brief This API is used to calculate the maximum delay in milliseconds required for the - * temperature/pressure/humidity(which ever are enabled) measurement to complete. + * @brief This API is used to calculate the maximum delay in microseconds required for the + * temperature/pressure/humidity (whichever are enabled) measurement to complete. * The delay depends upon the number of sensors enabled and their oversampling configuration. * * @param[in] settings : contains the oversampling configurations. * - * @return delay required in milliseconds. + * @return delay required in microseconds. * */ uint32_t bme280_cal_meas_delay(const struct bme280_settings *settings); diff --git a/bme280_defs.h b/bme280_defs.h index 686ba6a..20b5fd8 100644 --- a/bme280_defs.h +++ b/bme280_defs.h @@ -218,7 +218,6 @@ #define BME280_MEAS_OFFSET UINT16_C(1250) #define BME280_MEAS_DUR UINT16_C(2300) #define BME280_PRES_HUM_MEAS_OFFSET UINT16_C(575) -#define BME280_MEAS_SCALING_FACTOR UINT16_C(1000) /**\name Standby duration selection macros */ #define BME280_STANDBY_TIME_0_5_MS (0x00) diff --git a/examples/linux_userspace.c b/examples/linux_userspace.c index 0b8fc9a..d58975a 100644 --- a/examples/linux_userspace.c +++ b/examples/linux_userspace.c @@ -13,14 +13,17 @@ /*! * @ingroup bme280Examples * @defgroup bme280GroupExampleLU linux_userspace - * @brief Linux userspace test code, simple and mose code directly from the doco. + * @brief Linux userspace test code, simple and fast code directly from the docs. * compile like this: gcc linux_userspace.c ../bme280.c -I ../ -o bme280 - * tested: Raspberry Pi. + * tested: Beagle Bone Black, Raspberry Pi. * Use like: ./bme280 /dev/i2c-0 * \include linux_userspace.c */ -#ifdef __KERNEL__ +/* For compiling not with Beagle Bone Black (tested) uncomment following line: */ +#define USE_IOCTL + +#if defined __KERNEL__ || defined USE_IOCTL #include #include #endif @@ -139,6 +142,9 @@ int main(int argc, char* argv[]) struct identifier id; + /* Make sure to select BME280_I2C_ADDR_PRIM or BME280_I2C_ADDR_SEC as needed */ + id.dev_addr = BME280_I2C_ADDR_PRIM; + /* Variable to define the result */ int8_t rslt = BME280_OK; @@ -154,7 +160,7 @@ int main(int argc, char* argv[]) exit(1); } -#ifdef __KERNEL__ +#if defined __KERNEL__ || defined USE_IOCTL if (ioctl(id.fd, I2C_SLAVE, id.dev_addr) < 0) { fprintf(stderr, "Failed to acquire bus access and/or talk to slave.\n"); @@ -163,9 +169,6 @@ int main(int argc, char* argv[]) #endif - /* Make sure to select BME280_I2C_ADDR_PRIM or BME280_I2C_ADDR_SEC as needed */ - id.dev_addr = BME280_I2C_ADDR_PRIM; - dev.intf = BME280_I2C_INTF; dev.read = user_i2c_read; dev.write = user_i2c_write; @@ -201,10 +204,15 @@ int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_p id = *((struct identifier *)intf_ptr); - write(id.fd, ®_addr, 1); - read(id.fd, data, len); - - return 0; + if (write(id.fd, ®_addr, 1) != 1) + { + return BME280_E_COMM_FAIL; + } + if (read(id.fd, data, len) != (ssize_t)len) + { + return BME280_E_COMM_FAIL; + } + return BME280_OK; } /*! @@ -213,6 +221,7 @@ int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len, void *intf_p */ void user_delay_us(uint32_t period, void *intf_ptr) { + (void)intf_ptr; /* unused parameter, suppress warnings */ usleep(period); } @@ -223,20 +232,28 @@ int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len, void { uint8_t *buf; struct identifier id; + int8_t ret = BME280_OK; id = *((struct identifier *)intf_ptr); buf = malloc(len + 1); - buf[0] = reg_addr; - memcpy(buf + 1, data, len); - if (write(id.fd, buf, len + 1) < (uint16_t)len) + if (buf == NULL) /* could not allocate enough memory */ { - return BME280_E_COMM_FAIL; + return BME280_E_NULL_PTR; } - + do + { + buf[0] = reg_addr; + memcpy(buf + 1, data, len); + if (write(id.fd, buf, len + 1) != (ssize_t)(len+1)) + { + ret = BME280_E_COMM_FAIL; + break; + } + } while(0); free(buf); - return BME280_OK; + return ret; } /*! @@ -300,8 +317,8 @@ int8_t stream_sensor_data_forced_mode(struct bme280_dev *dev) printf("Temperature, Pressure, Humidity\n"); - /*Calculate the minimum delay required between consecutive measurement based upon the sensor enabled - * and the oversampling configuration. */ + /* Calculate the minimum delay in microseconds required between consecutive measurements + * based upon the sensor enabled and oversampling configuration. */ req_delay = bme280_cal_meas_delay(&dev->settings); /* Continuously stream sensor data */