RocketLogger  1.1.6
bme280.c
Go to the documentation of this file.
1 
32 #include "sensor.h"
33 
34 #include "bme280.h"
35 
37 
38 int32_t BME280_temperature[sizeof(BME280_sensors)] = {0};
39 int32_t BME280_humidity[sizeof(BME280_sensors)] = {0};
40 int32_t BME280_preasure[sizeof(BME280_sensors)] = {0};
41 
43 
49 int BME280_init(int sensor_identifier) {
51  if (sensor_bus < 0) {
52  rl_log(ERROR, "BME280 I2C bus not initialized properly");
53  return FAILURE;
54  }
55 
56  int result;
57 
58  uint8_t device_address = (uint8_t)sensor_identifier;
59  result = Sensors_initSharedComm(device_address);
60  if (result < 0) {
61  rl_log(ERROR, "BME280 I2C initialization failed");
62  return FAILURE;
63  }
64 
65  uint8_t sensor_id = BME280_getID();
66  if (sensor_id != BME280_ID) {
67  rl_log(ERROR, "BME280 with wrong sensor ID: %d", sensor_id);
68  return FAILURE;
69  }
70 
71  result = BME280_readCalibration(sensor_identifier);
72  if (result < 0) {
73  rl_log(ERROR, "BME280 reading calibration failed");
74  return FAILURE;
75  }
76 
77  result = BME280_setParameters(sensor_identifier);
78  if (result < 0) {
79  rl_log(ERROR, "BME280 setting configuraiton failed");
80  return FAILURE;
81  }
82 
83  return SUCCESS;
84 }
85 
90 void BME280_close(int sensor_identifier) {
91  (void)sensor_identifier; // suppress unsued variable warning
92 }
93 
99 int BME280_read(int sensor_identifier) {
101  int sensor_index = BME280_getIndex(sensor_identifier);
102  uint8_t data[BME280_DATA_BLOCK_SIZE];
103 
104  // select sensor
105  uint8_t device_address = (uint8_t)sensor_identifier;
106  int result = Sensors_initSharedComm(device_address);
107  if (result < 0) {
108  rl_log(ERROR, "BME280 I2C communication failed");
109  return FAILURE;
110  }
111 
112  // burst read required for data consistency
113  // i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length, __u8
114  // *values)
115  int data_size = i2c_smbus_read_i2c_block_data(
117  if (data_size != BME280_DATA_BLOCK_SIZE) {
118  rl_log(ERROR, "BME280 reading data block failed");
119  return FAILURE;
120  }
121 
122  // reconstruct and compensate data
123  int32_t preasure_raw = (((int32_t)data[0]) << 12) |
124  (((int32_t)data[1]) << 4) |
125  (((int32_t)data[2]) & 0x0f);
126  int32_t temperature_raw = (((int32_t)data[3]) << 12) |
127  (((int32_t)data[4]) << 4) |
128  (((int32_t)data[5]) & 0x0f);
129  int32_t humidity_raw = (((int32_t)data[6]) << 8) | ((int32_t)data[7]);
130 
131  BME280_temperature[sensor_index] =
132  BME280_compensate_temperature(sensor_identifier, temperature_raw);
133  BME280_humidity[sensor_index] = (int32_t)BME280_compensate_humidity(
134  sensor_identifier, humidity_raw, temperature_raw);
135  BME280_preasure[sensor_index] = (int32_t)BME280_compensate_preasure(
136  sensor_identifier, preasure_raw, temperature_raw);
137 
138  return SUCCESS;
139 }
140 
147 int32_t BME280_getValue(int sensor_identifier, int channel) {
148  int sensor_index = BME280_getIndex(sensor_identifier);
149 
150  switch (channel) {
152  return BME280_temperature[sensor_index];
153 
155  return BME280_humidity[sensor_index];
156 
158  return BME280_preasure[sensor_index];
159 
160  default:
161  return 0;
162  }
163 }
164 
170 int BME280_getID(void) {
172 
173  int read_result = i2c_smbus_read_byte_data(sensor_bus, BME280_REG_ID);
174 
175  if (read_result < 0) {
176  rl_log(ERROR, "BME280 I2C error reading ID of sensor");
177  }
178  return read_result;
179 }
180 
186 int BME280_readCalibration(int sensor_identifier) {
188  int sensor_index = BME280_getIndex(sensor_identifier);
189  uint8_t data[26];
190 
191  // first calibration data block (0x88...0xA1, 26 values)
192  int data_size1 =
193  i2c_smbus_read_i2c_block_data(sensor_bus, BME280_REG_CALIBRATION_BLOCK1,
195  if (data_size1 != BME280_CALIBRATION_BLOCK1_SIZE) {
196  rl_log(ERROR, "BME280 reading calibration block 1 failed");
197  return FAILURE;
198  }
199 
200  BME280_calibration[sensor_index].T1 =
201  ((uint16_t)data[1] << 8) | ((uint16_t)data[0]);
202  BME280_calibration[sensor_index].T2 =
203  ((int16_t)data[3] << 8) | ((int16_t)data[2]);
204  BME280_calibration[sensor_index].T3 =
205  ((int16_t)data[5] << 8) | ((int16_t)data[4]);
206 
207  BME280_calibration[sensor_index].P1 =
208  ((uint16_t)data[7] << 8) | ((uint16_t)data[6]);
209  BME280_calibration[sensor_index].P2 =
210  ((int16_t)data[9] << 8) | ((int16_t)data[8]);
211  BME280_calibration[sensor_index].P3 =
212  ((int16_t)data[11] << 8) | ((int16_t)data[10]);
213  BME280_calibration[sensor_index].P4 =
214  ((int16_t)data[13] << 8) | ((int16_t)data[12]);
215  BME280_calibration[sensor_index].P5 =
216  ((int16_t)data[15] << 8) | ((int16_t)data[14]);
217  BME280_calibration[sensor_index].P6 =
218  ((int16_t)data[17] << 8) | ((int16_t)data[16]);
219  BME280_calibration[sensor_index].P7 =
220  ((int16_t)data[19] << 8) | ((int16_t)data[18]);
221  BME280_calibration[sensor_index].P8 =
222  ((int16_t)data[21] << 8) | ((int16_t)data[20]);
223  BME280_calibration[sensor_index].P9 =
224  ((int16_t)data[23] << 8) | ((int16_t)data[22]);
225 
226  BME280_calibration[sensor_index].H1 = (uint8_t)data[25];
227 
228  // second calibration data block (0xE1...0xE7 [0xF0], 7 [16] values)
229  int data_size2 =
230  i2c_smbus_read_i2c_block_data(sensor_bus, BME280_REG_CALIBRATION_BLOCK2,
232  if (data_size2 != BME280_CALIBRATION_BLOCK2_SIZE) {
233  rl_log(ERROR, "BME280 reading calibration block 2 failed");
234  return FAILURE;
235  }
236 
237  BME280_calibration[sensor_index].H2 =
238  ((int16_t)data[1] << 8) | ((int16_t)data[0]);
239  BME280_calibration[sensor_index].H3 = (uint8_t)data[2];
240  BME280_calibration[sensor_index].H4 =
241  ((int16_t)data[3] << 4) | ((int16_t)data[4] & 0x0f);
242  BME280_calibration[sensor_index].H5 =
243  ((int16_t)data[5] << 4) | ((int16_t)data[4] >> 4);
244  BME280_calibration[sensor_index].H6 = (int8_t)data[6];
245 
246  return SUCCESS;
247 }
248 
253 int BME280_setParameters(int sensor_identifier) {
254  (void)sensor_identifier; // suppress unsued variable warning
256 
257  int result;
258 
259  // config: standby 250ms, filter off, no SPI, continuous measurement
260  result = i2c_smbus_write_byte_data(sensor_bus, BME280_REG_CONFIG,
263  if (result < 0) {
264  rl_log(ERROR, "BME280 setting config register failed");
265  return FAILURE;
266  }
267 
268  // humidity control: oversampling x1
269  result = i2c_smbus_write_byte_data(sensor_bus, BME280_REG_CONTROL_HUMIDITY,
271  if (result < 0) {
272  rl_log(ERROR, "BME280 setting humidiy control register failed");
273  return FAILURE;
274  }
275 
276  // measure control: oversampling x1, continuous measurement
277  result = i2c_smbus_write_byte_data(sensor_bus, BME280_REG_CONTROL_MEASURE,
281  if (result < 0) {
282  rl_log(ERROR, "BME280 setting measure control register failed");
283  return FAILURE;
284  }
285 
286  return SUCCESS;
287 }
288 
294 int BME280_getIndex(int sensor_identifier) {
295  unsigned int index = 0;
296  while (index < sizeof(BME280_sensors)) {
297  if (sensor_identifier == BME280_sensors[index]) {
298  return (int)index;
299  }
300  index++;
301  }
302  return -1;
303 }
304 
311 int32_t BME280_compensate_temperature_fine(int sensor_identifier,
312  int32_t temperature_raw) {
313  int sensor_index = BME280_getIndex(sensor_identifier);
314 
315  int32_t var1, var2, temperature_fine;
316  var1 = ((((temperature_raw >> 3) -
317  ((int32_t)BME280_calibration[sensor_index].T1 << 1))) *
318  ((int32_t)((int16_t)BME280_calibration[sensor_index].T2))) >>
319  11;
320  var2 = (((((temperature_raw >> 4) -
321  ((int32_t)BME280_calibration[sensor_index].T1)) *
322  ((temperature_raw >> 4) -
323  ((int32_t)BME280_calibration[sensor_index].T1))) >>
324  12) *
325  ((int32_t)((int16_t)BME280_calibration[sensor_index].T3))) >>
326  14;
327  temperature_fine = var1 + var2;
328 
329  return temperature_fine;
330 }
331 
338 int32_t BME280_compensate_temperature(int sensor_identifier,
339  int32_t temperature_raw) {
340  int32_t temperature_fine =
341  BME280_compensate_temperature_fine(sensor_identifier, temperature_raw);
342  int32_t temperature = (temperature_fine * 50 + 1280) >> 8;
343  return temperature;
344 }
345 
353 uint32_t BME280_compensate_preasure(int sensor_identifier, int32_t preasure_raw,
354  int32_t temperature_raw) {
355  int sensor_index = BME280_getIndex(sensor_identifier);
356  int64_t var1, var2, preasure;
357 
358  int64_t temperature_fine =
359  BME280_compensate_temperature_fine(sensor_identifier, temperature_raw);
360  var1 = temperature_fine - 128000;
361  var2 = var1 * var1 * (int64_t)BME280_calibration[sensor_index].P6 +
362  ((var1 * (int64_t)BME280_calibration[sensor_index].P5) << 17) +
363  (((int64_t)BME280_calibration[sensor_index].P4) << 35);
364  var1 = ((var1 * var1 * (int64_t)BME280_calibration[sensor_index].P3) >> 8) +
365  ((var1 * (int64_t)BME280_calibration[sensor_index].P2) << 12);
366  var1 = (((((int64_t)1) << 47) + var1) *
367  ((int64_t)BME280_calibration[sensor_index].P1)) >>
368  33;
369  if (var1 == 0) {
370  return 0; // avoid exception caused by division by zero
371  }
372  preasure = 1048576 - preasure_raw;
373  preasure = (((preasure << 31) - var2) * 3125) / var1;
374  var1 = (((int64_t)BME280_calibration[sensor_index].P9) * (preasure >> 13) *
375  (preasure >> 13)) >>
376  25;
377  var2 = (((int64_t)BME280_calibration[sensor_index].P8) * preasure) >> 19;
378  preasure = ((preasure + var1 + var2) >> 8) +
379  (((int64_t)BME280_calibration[sensor_index].P7) << 4);
380 
381  // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24
382  // integer bits and 8 fractional bits).
383  // Output value of '24674867' represents 24674867/256 = 96386.2 Pa = 963.862
384  // hPa
385  // return (uint32_t)preasure;
386 
387  int64_t preasure_rebased = (1000 * preasure) >> 8;
388  return (uint32_t)preasure_rebased;
389 }
390 
398 uint32_t BME280_compensate_humidity(int sensor_identifier, int32_t humidity_raw,
399  int32_t temperature_raw) {
400  int sensor_index = BME280_getIndex(sensor_identifier);
401 
402  int32_t temperature_fine =
403  BME280_compensate_temperature_fine(sensor_identifier, temperature_raw);
404 
405  int32_t humidity = (temperature_fine - ((int32_t)76800));
406  humidity =
407  ((((humidity_raw << 14) -
408  (((int32_t)BME280_calibration[sensor_index].H4) << 20) -
409  (((int32_t)BME280_calibration[sensor_index].H5) * humidity)) +
410  ((int32_t)16384)) >>
411  15) *
412  (((((((humidity * ((int32_t)BME280_calibration[sensor_index].H6)) >>
413  10) *
414  (((humidity * ((int32_t)BME280_calibration[sensor_index].H3)) >>
415  11) +
416  ((int32_t)32768))) >>
417  10) +
418  ((int32_t)2097152)) *
419  ((int32_t)BME280_calibration[sensor_index].H2) +
420  8192) >>
421  14);
422  humidity = (humidity - (((((humidity >> 15) * (humidity >> 15)) >> 7) *
423  ((int32_t)BME280_calibration[sensor_index].H1)) >>
424  4));
425  if (humidity < 0) {
426  humidity = 0;
427  } else if (humidity > 419430400) {
428  humidity = 419430400;
429  }
430 
431  // Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22
432  // integer and 10 fractional bits).
433  // Output value of '47445' represents 47445/1024 = 46.333 %RH
434  // return (uint32_t)(humidity >> 12);
435 
436  uint32_t humidity_rebased = (((uint64_t)10000 * humidity) >> 22);
437  return humidity_rebased;
438 }
int32_t BME280_preasure[sizeof(BME280_sensors)]
Definition: bme280.c:40
#define BME280_FILTER_OFF
Definition: bme280.h:120
int BME280_read(int sensor_identifier)
Definition: bme280.c:99
int BME280_getIndex(int sensor_identifier)
Definition: bme280.c:294
#define FAILURE
Definition: types.h:78
#define SUCCESS
Definition: types.h:75
#define BME280_OVERSAMPLE_PREASURE_1
Definition: bme280.h:103
int BME280_init(int sensor_identifier)
Definition: bme280.c:49
#define BME280_CHANNEL_PRESSURE
Definition: bme280.h:57
int32_t BME280_compensate_temperature(int sensor_identifier, int32_t temperature_raw)
Definition: bme280.c:338
int32_t BME280_compensate_temperature_fine(int sensor_identifier, int32_t temperature_raw)
Definition: bme280.c:311
int sensor_bus
Definition: sensor.c:43
uint32_t BME280_compensate_humidity(int sensor_identifier, int32_t humidity_raw, int32_t temperature_raw)
Definition: bme280.c:398
#define BME280_OVERSAMPLE_TEMPERATURE_1
Definition: bme280.h:97
void rl_log(rl_log_type type, const char *format,...)
Definition: log.c:39
int32_t BME280_temperature[sizeof(BME280_sensors)]
Definition: bme280.c:38
int Sensors_initSharedComm(uint8_t device_address)
Definition: sensor.c:126
#define BME280_ID
Definition: bme280.h:60
#define BME280_OVERSAMPLE_HUMIDITY_1
Definition: bme280.h:87
#define BME280_REG_CALIBRATION_BLOCK1
Definition: bme280.h:62
#define BME280_DATA_BLOCK_SIZE
Definition: bme280.h:82
int Sensors_getSharedBus(void)
Definition: sensor.c:119
#define BME280_STANDBY_DURATION_250
Definition: bme280.h:115
#define BME280_CHANNEL_TEMPERATURE
Definition: bme280.h:55
#define BME280_REG_CONFIG
Definition: bme280.h:69
#define BME280_REG_CONTROL_MEASURE
Definition: bme280.h:68
#define BME280_I2C_ADDRESSES
Definition: bme280.h:52
#define BME280_REG_ID
Definition: bme280.h:63
#define BME280_REG_CALIBRATION_BLOCK2
Definition: bme280.h:65
#define BME280_REG_PREASURE_MSB
Definition: bme280.h:70
#define BME280_CALIBRATION_BLOCK2_SIZE
Definition: bme280.h:80
Error.
Definition: types.h:200
#define BME280_CALIBRATION_BLOCK1_SIZE
Definition: bme280.h:79
struct BME280_calibration_t BME280_calibration[sizeof(BME280_sensors)]
Definition: bme280.c:42
int BME280_setParameters(int sensor_identifier)
Definition: bme280.c:253
#define BME280_CHANNEL_HUMIDITY
Definition: bme280.h:56
void BME280_close(int sensor_identifier)
Definition: bme280.c:90
int32_t BME280_humidity[sizeof(BME280_sensors)]
Definition: bme280.c:39
#define BME280_MODE_NORMAL
Definition: bme280.h:110
int BME280_readCalibration(int sensor_identifier)
Definition: bme280.c:186
#define BME280_REG_CONTROL_HUMIDITY
Definition: bme280.h:66
int32_t BME280_getValue(int sensor_identifier, int channel)
Definition: bme280.c:147
const int BME280_sensors[]
Definition: bme280.c:36
uint32_t BME280_compensate_preasure(int sensor_identifier, int32_t preasure_raw, int32_t temperature_raw)
Definition: bme280.c:353
int BME280_getID(void)
Definition: bme280.c:170