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