mirror of
				https://github.com/alexandrebobkov/ESP-Nodes.git
				synced 2025-10-30 23:48:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			373 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			373 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include "freertos/FreeRTOS.h"
 | |
| #include "i2c_bus.h"
 | |
| #include "bme280.h"
 | |
| #include "math.h"
 | |
| #include "esp_log.h"
 | |
| 
 | |
| bme280_handle_t bme280_create(i2c_bus_handle_t bus, uint8_t dev_addr)
 | |
| {
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) calloc(1, sizeof(bme280_dev_t));
 | |
|     sens->i2c_dev = i2c_bus_device_create(bus, dev_addr, i2c_bus_get_current_clk_speed(bus));
 | |
|     if (sens->i2c_dev == NULL) {
 | |
|         free(sens);
 | |
|         return NULL;
 | |
|     }
 | |
|     sens->dev_addr = dev_addr;
 | |
|     return (bme280_handle_t)sens;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_delete(bme280_handle_t *sensor)
 | |
| {
 | |
|     if (*sensor == NULL) {
 | |
|         return ESP_OK;
 | |
|     }
 | |
|     bme280_dev_t *sens = (bme280_dev_t *)(*sensor);
 | |
|     i2c_bus_device_delete(&sens->i2c_dev);
 | |
|     free(sens);
 | |
|     *sensor = NULL;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| static esp_err_t bme280_read_uint16(bme280_handle_t sensor, uint8_t addr, uint16_t *data)
 | |
| {
 | |
|     esp_err_t ret = ESP_FAIL;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     uint8_t data0, data1;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, addr, &data0) != ESP_OK) {
 | |
|         return ret;
 | |
|     }
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, addr + 1, &data1) != ESP_OK) {
 | |
|         return ret;
 | |
|     }
 | |
|     *data = (data0 << 8) | data1;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| static esp_err_t bme280_read_uint16_le(bme280_handle_t sensor, uint8_t addr, uint16_t *data)
 | |
| {
 | |
|     esp_err_t ret = ESP_FAIL;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     uint8_t data0, data1;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, addr, &data0) != ESP_OK) {
 | |
|         return ret;
 | |
|     }
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, addr + 1, &data1) != ESP_OK) {
 | |
|         return ret;
 | |
|     }
 | |
|     *data = (data1 << 8) | data0;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| unsigned int bme280_getconfig(bme280_handle_t sensor)
 | |
| {
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     return (sens->config_t.t_sb << 5) | (sens->config_t.filter << 3) | sens->config_t.spi3w_en;
 | |
| }
 | |
| 
 | |
| unsigned int bme280_getctrl_meas(bme280_handle_t sensor)
 | |
| {
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     return (sens->ctrl_meas_t.osrs_t << 5) | (sens->ctrl_meas_t.osrs_p << 3) | sens->ctrl_meas_t.mode;
 | |
| }
 | |
| 
 | |
| unsigned int bme280_getctrl_hum(bme280_handle_t sensor)
 | |
| {
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     return (sens->ctrl_hum_t.osrs_h);
 | |
| }
 | |
| 
 | |
| bool bme280_is_reading_calibration(bme280_handle_t sensor)
 | |
| {
 | |
|     uint8_t rstatus = 0;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_STATUS, &rstatus) != ESP_OK) {
 | |
|         return false;
 | |
|     }
 | |
|     return (rstatus & (1 << 0)) != 0;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_read_coefficients(bme280_handle_t sensor)
 | |
| {
 | |
|     uint8_t data = 0;
 | |
|     uint8_t data1 = 0;
 | |
|     uint16_t data16 = 0;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_T1, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_t1 = data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_T2, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_t2 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_T3, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_t3 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P1, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p1 = data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P2, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p2 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P3, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p3 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P4, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p4 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P5, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p5 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P6, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p6 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P7, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p7 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P8, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p8 = (int16_t) data16;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_P9, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_p9 = (int16_t) data16;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H1, &data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_h1 = data;
 | |
|     if (bme280_read_uint16_le(sensor, BME280_REGISTER_DIG_H2, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_h2 = (int16_t) data16;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H3, &data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_h3 = data;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H4, &data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H4 + 1, &data1) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_h4 = (data << 4) | (data1 & 0xF);
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H5 + 1, &data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H5, &data1) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_h5 = (data << 4) | (data1 >> 4);
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_DIG_H6, &data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     sens->data_t.dig_h6 = (int8_t) data;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_set_sampling(bme280_handle_t sensor, bme280_sensor_mode mode, bme280_sensor_sampling tempSampling, bme280_sensor_sampling pressSampling, bme280_sensor_sampling humSampling, bme280_sensor_filter filter, bme280_standby_duration duration)
 | |
| {
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     sens->ctrl_meas_t.mode = mode;
 | |
|     sens->ctrl_meas_t.osrs_t = tempSampling;
 | |
|     sens->ctrl_meas_t.osrs_p = pressSampling;
 | |
|     sens->ctrl_hum_t.osrs_h = humSampling;
 | |
|     sens->config_t.filter = filter;
 | |
|     sens->config_t.t_sb = duration;
 | |
|     // you must make sure to also set REGISTER_CONTROL after setting the
 | |
|     // CONTROLHUMID register, otherwise the values won't be applied (see DS 5.4.3)
 | |
|     if (i2c_bus_write_byte(sens->i2c_dev, BME280_REGISTER_CONTROLHUMID, bme280_getctrl_hum(sensor)) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (i2c_bus_write_byte(sens->i2c_dev, BME280_REGISTER_CONFIG, bme280_getconfig(sensor)) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (i2c_bus_write_byte(sens->i2c_dev, BME280_REGISTER_CONTROL, bme280_getctrl_meas(sensor)) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_default_init(bme280_handle_t sensor)
 | |
| {
 | |
|     // check if sensor, i.e. the chip ID is correct
 | |
|     uint8_t chipid = 0;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_CHIPID, &chipid) != ESP_OK) {
 | |
|         ESP_LOGI("BME280:", "bme280_default_init->bme280_read_byte ->BME280_REGISTER_CHIPID failed!!!!:%x", chipid);
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (chipid != BME280_DEFAULT_CHIPID) {
 | |
|         ESP_LOGI("BME280:", "bme280_default_init->BME280_DEFAULT_CHIPID:%x", chipid);
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     // reset the sens using soft-reset, this makes sure the IIR is off, etc.
 | |
|     if (i2c_bus_write_byte(sens->i2c_dev, BME280_REGISTER_SOFTRESET, 0xB6) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     // wait for chip to wake up.
 | |
|     vTaskDelay(300 / portTICK_RATE_MS);
 | |
|     // if chip is still reading calibration, delay
 | |
|     while (bme280_is_reading_calibration(sensor)) {
 | |
|         vTaskDelay(100 / portTICK_RATE_MS);
 | |
|     }
 | |
|     if (bme280_read_coefficients(sensor) != ESP_OK) { // read trimming parameters, see DS 4.2.2
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (bme280_set_sampling(sensor, BME280_MODE_NORMAL, BME280_SAMPLING_X16, BME280_SAMPLING_X16, BME280_SAMPLING_X16, BME280_FILTER_OFF, BME280_STANDBY_MS_0_5) != ESP_OK) {    // use defaults
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_take_forced_measurement(bme280_handle_t sensor)
 | |
| {
 | |
|     uint8_t data = 0;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     if (sens->ctrl_meas_t.mode == BME280_MODE_FORCED) {
 | |
|         // set to forced mode, i.e. "take next measurement"
 | |
|         if (i2c_bus_write_byte(sens->i2c_dev, BME280_REGISTER_CONTROL,      bme280_getctrl_meas(sensor)) != ESP_OK) {
 | |
|             return ESP_FAIL;
 | |
|         }
 | |
|         // wait until measurement has been completed, otherwise we would read, the values from the last measurement
 | |
|         if (i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_STATUS, &data) != ESP_OK) {
 | |
|             return ESP_FAIL;
 | |
|         }
 | |
|         while (data & 0x08) {
 | |
|             i2c_bus_read_byte(sens->i2c_dev, BME280_REGISTER_STATUS, &data);
 | |
|             vTaskDelay(10 / portTICK_RATE_MS);
 | |
|         }
 | |
|     }
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_read_temperature(bme280_handle_t sensor, float *temperature)
 | |
| {
 | |
|     int32_t var1, var2;
 | |
|     uint8_t data[3] = { 0 };
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     if (i2c_bus_read_bytes(sens->i2c_dev, BME280_REGISTER_TEMPDATA, 3, data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     int32_t adc_T = (data[0] << 16) | (data[1] << 8) | data[2];
 | |
|     if (adc_T == 0x800000) {      // value in case temp measurement was disabled
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     adc_T >>= 4;
 | |
| 
 | |
|     var1 = ((((adc_T >> 3) - ((int32_t) sens->data_t.dig_t1 << 1)))
 | |
|             * ((int32_t) sens->data_t.dig_t2)) >> 11;
 | |
| 
 | |
|     var2 = (((((adc_T >> 4) - ((int32_t) sens->data_t.dig_t1))
 | |
|               * ((adc_T >> 4) - ((int32_t) sens->data_t.dig_t1))) >> 12)
 | |
|             * ((int32_t) sens->data_t.dig_t3)) >> 14;
 | |
| 
 | |
|     sens->t_fine = var1 + var2;
 | |
|     *temperature = ((sens->t_fine * 5 + 128) >> 8) / 100.0;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_read_pressure(bme280_handle_t sensor, float *pressure)
 | |
| {
 | |
|     int64_t var1, var2, p;
 | |
|     uint8_t data[3] = { 0 };
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     float temp = 0.0;
 | |
|     if (bme280_read_temperature(sensor, &temp) != ESP_OK) {
 | |
|         // must be done first to get t_fine
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (i2c_bus_read_bytes(sens->i2c_dev, BME280_REGISTER_PRESSUREDATA, 3, data) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     int32_t adc_P = (data[0] << 16) | (data[1] << 8) | data[2];
 | |
|     if (adc_P == 0x800000) {  // value in case pressure measurement was disabled
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     adc_P >>= 4;
 | |
|     var1 = ((int64_t) sens->t_fine) - 128000;
 | |
|     var2 = var1 * var1 * (int64_t) sens->data_t.dig_p6;
 | |
|     var2 = var2 + ((var1 * (int64_t) sens->data_t.dig_p5) << 17);
 | |
|     var2 = var2 + (((int64_t) sens->data_t.dig_p4) << 35);
 | |
|     var1 = ((var1 * var1 * (int64_t) sens->data_t.dig_p3) >> 8) + ((var1 * (int64_t) sens->data_t.dig_p2) << 12);
 | |
|     var1 = (((((int64_t) 1) << 47) + var1)) * ((int64_t) sens->data_t.dig_p1) >> 33;
 | |
|     if (var1 == 0) {
 | |
|         return ESP_FAIL; // avoid exception caused by division by zero
 | |
|     }
 | |
|     p = 1048576 - adc_P;
 | |
|     p = (((p << 31) - var2) * 3125) / var1;
 | |
|     var1 = (((int64_t) sens->data_t.dig_p9) * (p >> 13) * (p >> 13)) >> 25;
 | |
|     var2 = (((int64_t) sens->data_t.dig_p8) * p) >> 19;
 | |
|     p = ((p + var1 + var2) >> 8) + (((int64_t) sens->data_t.dig_p7) << 4);
 | |
|     p = p >> 8; // /256
 | |
|     *pressure = (float) p / 100;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_read_humidity(bme280_handle_t sensor, float *humidity)
 | |
| {
 | |
|     uint16_t data16;
 | |
|     bme280_dev_t *sens = (bme280_dev_t *) sensor;
 | |
|     float temp = 0.0;
 | |
|     if (bme280_read_temperature(sensor, &temp) != ESP_OK) {
 | |
|         // must be done first to get t_fine
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     if (bme280_read_uint16(sensor, BME280_REGISTER_HUMIDDATA, &data16) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     int32_t adc_H = data16;
 | |
|     if (adc_H == 0x8000) { // value in case humidity measurement was disabled
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     int32_t v_x1_u32r;
 | |
|     v_x1_u32r = (sens->t_fine - ((int32_t) 76800));
 | |
|     v_x1_u32r = (((((adc_H << 14) - (((int32_t) sens->data_t.dig_h4) << 20)
 | |
|                     - (((int32_t) sens->data_t.dig_h5) * v_x1_u32r))
 | |
|                    + ((int32_t) 16384)) >> 15)
 | |
|                  * (((((((v_x1_u32r * ((int32_t) sens->data_t.dig_h6)) >> 10)
 | |
|                         * (((v_x1_u32r * ((int32_t) sens->data_t.dig_h3)) >> 11)  + ((int32_t) 32768))) >> 10) + ((int32_t) 2097152))
 | |
|                      * ((int32_t) sens->data_t.dig_h2) + 8192) >> 14));
 | |
|     v_x1_u32r = (v_x1_u32r
 | |
|                  - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7)
 | |
|                      * ((int32_t) sens->data_t.dig_h1)) >> 4));
 | |
|     v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
 | |
|     v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
 | |
|     *humidity = (v_x1_u32r >> 12) / 1024.0;
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_read_altitude(bme280_handle_t sensor, float seaLevel, float *altitude)
 | |
| {
 | |
|     float pressure = 0.0;
 | |
|     float temp = 0.0;
 | |
|     if (bme280_read_pressure(sensor, &temp) != ESP_OK) {
 | |
|         return ESP_FAIL;
 | |
|     }
 | |
|     float atmospheric = pressure / 100.0F;
 | |
|     *altitude = 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
 | |
|     return ESP_OK;
 | |
| }
 | |
| 
 | |
| esp_err_t bme280_calculates_pressure(bme280_handle_t sensor, float altitude,
 | |
|                                      float atmospheric, float *pressure)
 | |
| {
 | |
|     *pressure = atmospheric / pow(1.0 - (altitude / 44330.0), 5.255);
 | |
|     return ESP_OK;
 | |
| }
 |