AVRly - AVR Development Resources
#include <util/delay.h>
#include "bme280.h"
#include "atmega_i2c.h"
#include "log_system.h"

Go to the source code of this file.

Macros

#define BME280_ADDRESS_W   0xEC
 
#define BME280_ADDRESS_R   0xED
 
#define CONFIG_REG   0xF5
 
#define CTRL_MEAS_REG   0xF4
 
#define STATUS_REG   0xF3
 
#define CTRL_HUM_REG   0xF2
 
#define SOFT_RESET_REG   0xE0
 
#define CHIP_ID_REG   0xD0
 
#define SKIPPED   0
 
#define OVERSAMPLE_x1   1
 
#define OVERSAMPLE_x2   2
 
#define OVERSAMPLE_x4   3
 
#define OVERSAMPLE_x8   4
 
#define OVERSAMPLE_x16   5
 
#define SLEEP_MODE   0
 
#define FORCED_MODE   1
 
#define NORMAL_MODE   3
 
#define BUS_SPEED_100KHZ   100000U
 

Functions

void bme280_write_byte (uint8_t reg, uint8_t byte)
 Writes a single byte to a specified reguster. More...
 
void bme280_write_word (uint8_t reg1, uint8_t reg2, uint8_t msb, uint8_t lsb)
 
uint16_t bme280_read_word (uint8_t start_address)
 Reads a 16bit unsigned integer from a specified register. More...
 
uint8_t bme280_read_byte (uint8_t reg)
 
void bme280_read_comp_data (void)
 Reads in all compensation data from the device and stores it in a buffer. More...
 
uint32_t bme280_get_raw_temp_val (void)
 
uint32_t bme280_get_raw_hum_val (void)
 
void bme280_burst_read (uint8_t start_addr, uint8_t start_position, uint8_t length)
 
int32_t bme280_compensate_temp (int32_t adc_T)
 Returns temperature in DegC, resolution is 0.01 DegC. More...
 
int32_t bme280_compensate_pressure (int32_t adc_P)
 Returns pressure in Pa as unsigned 32 bit integer. More...
 
uint32_t bme280_compensate_humidity (int32_t adc_H)
 Returns humidity in RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits). More...
 
void init_bme280 (void)
 Initialise the device ready for measurements to be taken. More...
 
int16_t bme280_get_temperature (void)
 Fetches the latest temperature data from the sensor, compensates and formats the data in degrees Celcius * 100. More...
 
uint16_t bme280_get_humidity (void)
 Fetches the latest humidity data from the sensor, compensates and formats the data as RH * 100. More...
 
uint16_t bme280_get_pressure (void)
 Fetches the latest pressure data from the sensor, compensates and formats the data as Pa * 100. More...
 

Variables

log_system_config_t bme280_log
 
int32_t t_fine
 

Detailed Description

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Author
Jason Duffy
Date
22nd June 2022

Definition in file bme280.c.

Macro Definition Documentation

◆ BME280_ADDRESS_W

#define BME280_ADDRESS_W   0xEC

Definition at line 40 of file bme280.c.

◆ BME280_ADDRESS_R

#define BME280_ADDRESS_R   0xED

Definition at line 41 of file bme280.c.

◆ CONFIG_REG

#define CONFIG_REG   0xF5

Definition at line 44 of file bme280.c.

◆ CTRL_MEAS_REG

#define CTRL_MEAS_REG   0xF4

Definition at line 45 of file bme280.c.

◆ STATUS_REG

#define STATUS_REG   0xF3

Definition at line 46 of file bme280.c.

◆ CTRL_HUM_REG

#define CTRL_HUM_REG   0xF2

Definition at line 47 of file bme280.c.

◆ SOFT_RESET_REG

#define SOFT_RESET_REG   0xE0

Definition at line 49 of file bme280.c.

◆ CHIP_ID_REG

#define CHIP_ID_REG   0xD0

Definition at line 50 of file bme280.c.

◆ SKIPPED

#define SKIPPED   0

Definition at line 53 of file bme280.c.

◆ OVERSAMPLE_x1

#define OVERSAMPLE_x1   1

Definition at line 54 of file bme280.c.

◆ OVERSAMPLE_x2

#define OVERSAMPLE_x2   2

Definition at line 55 of file bme280.c.

◆ OVERSAMPLE_x4

#define OVERSAMPLE_x4   3

Definition at line 56 of file bme280.c.

◆ OVERSAMPLE_x8

#define OVERSAMPLE_x8   4

Definition at line 57 of file bme280.c.

◆ OVERSAMPLE_x16

#define OVERSAMPLE_x16   5

Definition at line 58 of file bme280.c.

◆ SLEEP_MODE

#define SLEEP_MODE   0

Definition at line 60 of file bme280.c.

◆ FORCED_MODE

#define FORCED_MODE   1

Definition at line 61 of file bme280.c.

◆ NORMAL_MODE

#define NORMAL_MODE   3

Definition at line 62 of file bme280.c.

◆ BUS_SPEED_100KHZ

#define BUS_SPEED_100KHZ   100000U

Definition at line 64 of file bme280.c.

Function Documentation

◆ bme280_write_byte()

void bme280_write_byte ( uint8_t  reg,
uint8_t  byte 
)

Writes a single byte to a specified reguster.

Parameters
regis the reguster to be written to.
byteis the data to be sent.

Definition at line 244 of file bme280.c.

245{
246 i2c_start();
247 i2c_send(BME280_ADDRESS_W);
248 i2c_send(reg);
249 i2c_send(byte);
250 i2c_stop();
251}
void i2c_stop(void)
Sends a stop condition (sets TWSTO).
Definition: atmega_i2c.c:80
void i2c_send(uint8_t data)
Loads data, sends it out, waiting for completion.
Definition: atmega_i2c.c:90
void i2c_start(void)
Sends a start condition (sets TWSTA).
Definition: atmega_i2c.c:70

◆ bme280_read_word()

uint16_t bme280_read_word ( uint8_t  start_address)

Reads a 16bit unsigned integer from a specified register.

Parameters
start_addressis the first memory location to be read from.
Returns
The data read from the device is returned.

Definition at line 295 of file bme280.c.

296{
297 unsigned short msb;
298 unsigned short lsb;
299 unsigned short word;
300
301 i2c_start();
302 i2c_send(BME280_ADDRESS_W);
303 i2c_send(start_address);
304 i2c_start();
305 i2c_send(BME280_ADDRESS_R);
306
307 lsb = i2c_read_ack();
308 msb = i2c_read_no_ack();
309 i2c_stop();
310
311 word = (msb << 8);
312 word |= lsb;
313 return word;
314}
uint8_t i2c_read_no_ack(void)
Read in from slave, sending NOACK when done (no TWEA).
Definition: atmega_i2c.c:115
uint8_t i2c_read_ack(void)
Read in from slave, sending ACK when done (sets TWEA).
Definition: atmega_i2c.c:102

◆ bme280_read_byte()

uint8_t bme280_read_byte ( uint8_t  reg)

Definition at line 254 of file bme280.c.

255{
256 uint8_t byte;
257
258 i2c_start();
259 i2c_send(BME280_ADDRESS_W);
260 i2c_send(reg);
261 i2c_start();
262 i2c_send(BME280_ADDRESS_R);
263 byte = i2c_read_no_ack();
264 i2c_stop();
265 return byte;
266}

◆ bme280_read_comp_data()

void bme280_read_comp_data ( void  )

Reads in all compensation data from the device and stores it in a buffer.

Definition at line 322 of file bme280.c.

323{
324 signed short h_lsb;
325 signed short h_msb;
326
327 // Read and store temperature compensation data.
328 dig_T1 = bme280_read_word(0x88);
329 dig_T2 = bme280_read_word(0x8A);
330 dig_T3 = bme280_read_word(0x8C);
331
332 // Read and store pressure compensation data.
333 dig_P1 = bme280_read_word(0x8E);
334 dig_P2 = bme280_read_word(0x90);
335 dig_P3 = bme280_read_word(0x92);
336 dig_P4 = bme280_read_word(0x94);
337 dig_P5 = bme280_read_word(0x96);
338 dig_P6 = bme280_read_word(0x98);
339 dig_P7 = bme280_read_word(0x9A);
340 dig_P8 = bme280_read_word(0x9C);
341 dig_P9 = bme280_read_word(0x9E);
342
343 // Read and store humidity compensation data.
344 dig_H1 = bme280_read_byte(0xA1);
345 dig_H2 = bme280_read_word(0xE1);
346 dig_H3 = bme280_read_byte(0xE3);
347
348 h_msb = bme280_read_byte(0xE4);
349 h_lsb = bme280_read_byte(0xE5);
350 h_lsb &= 0b00001111;
351 dig_H4 = h_lsb;
352 dig_H4 |= (h_msb << 4);
353
354 h_msb = bme280_read_byte(0xE6);
355 h_lsb = bme280_read_byte(0xE5);
356 h_lsb &= 0b11110000;
357 dig_H5 = (h_lsb >> 4);
358 dig_H5 |= (h_msb << 4);
359
360 dig_H6 = bme280_read_byte(0xE7);
361}
uint16_t bme280_read_word(uint8_t start_address)
Reads a 16bit unsigned integer from a specified register.
Definition: bme280.c:295

◆ bme280_get_raw_temp_val()

uint32_t bme280_get_raw_temp_val ( void  )

Definition at line 364 of file bme280.c.

365{
366 uint32_t retval;
367 uint32_t temp_msb;
368 uint32_t temp_lsb;
369 uint32_t temp_xlsb;
370
371 i2c_start();
372 i2c_send(BME280_ADDRESS_W);
373 i2c_send(0xFA);
374 i2c_start();
375 i2c_send(BME280_ADDRESS_R);
376 temp_msb = i2c_read_ack();
377 temp_lsb = i2c_read_ack();
378 temp_xlsb = i2c_read_no_ack();
379 i2c_stop();
380
381 retval = temp_msb << 12;
382 retval |= temp_lsb << 4;
383 retval |= temp_xlsb >> 4;
384
385 return retval;
386}

◆ bme280_get_raw_hum_val()

uint32_t bme280_get_raw_hum_val ( void  )

Definition at line 388 of file bme280.c.

389{
390 uint32_t retval;
391 uint16_t hum_msb;
392 uint16_t hum_lsb;
393
394 i2c_start();
395 i2c_send(BME280_ADDRESS_W);
396 i2c_send(0xFD);
397 i2c_start();
398 i2c_send(BME280_ADDRESS_R);
399 hum_msb = i2c_read_ack();
400 hum_lsb = i2c_read_no_ack();
401 i2c_stop();
402
403 retval = hum_msb << 8;
404 retval |= hum_lsb;
405
406 return retval;
407}

◆ bme280_burst_read()

void bme280_burst_read ( uint8_t  start_addr,
uint8_t  start_position,
uint8_t  length 
)

Definition at line 269 of file bme280.c.

272{
273 i2c_start();
274 i2c_send(BME280_ADDRESS_W);
275 i2c_send(start_address);
276 i2c_start();
277 i2c_send(BME280_ADDRESS_R);
278
279 int i;
280 for (i = 0; i < (length - 1); ++i)
281 {
282 BME280_read_buffer[i] = i2c_read_ack();
283 }
284 BME280_read_buffer[i] = i2c_read_no_ack();
285
286 i2c_stop();
287}

◆ bme280_compensate_temp()

int32_t bme280_compensate_temp ( int32_t  adc_T)

Returns temperature in DegC, resolution is 0.01 DegC.

Output value of "5123" equals 51.23 DegC.

Definition at line 420 of file bme280.c.

421{
422 int32_t var1, var2, T;
423 var1 = (((adc_T >> 3) - ((int32_t)dig_T1 << 1)) * ((int32_t)dig_T2)) >> 11;
424 var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T >> 4)
425 - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
426 t_fine = var1 + var2;
427 T = (t_fine * 5 + 128) >> 8;
428 return T;
429}

◆ bme280_compensate_pressure()

int32_t bme280_compensate_pressure ( int32_t  adc_P)

Returns pressure in Pa as unsigned 32 bit integer.

Output value of "96386" equals 96386 Pa = 963.86 hPa.

Definition at line 436 of file bme280.c.

437{
438 int32_t var1, var2;
439 uint32_t p;
440 var1 = (t_fine >> 1) - 64000;
441 var2 = (((var1 >> 2) * (var1 >> 2)) >> 11 ) * ((int32_t)dig_P6);
442 var2 = var2 + ((var1 * ((int32_t)dig_P5)) << 1);
443 var2 = (var2 >> 2) + (((int32_t)dig_P4) << 16);
444 var1 = ((((int32_t)dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13 )) >> 3)
445 + (((((int32_t)dig_P2) * var1) >> 1 ))) >> 18;
446 var1 = ((((32768 + var1)) * ((int32_t)dig_P1)) >> 15);
447
448 if (var1 == 0)
449 {
450 return 0; // avoid exception caused by division by zero
451 }
452
453 p = ((((1048576) - adc_P) - (var2 >> 12))) * 3125;
454
455 if (p < 0x80000000)
456 {
457 p = (p << 1) / (var1);
458 }
459
460 else
461 {
462 p = (p / var1) * 2;
463 }
464
465 var1 = ((dig_P9) * ((((p>>3) * (p >> 3)) >> 13))) >> 12;
466 var2 = (((p >> 2)) * (dig_P8)) >> 13;
467 p = (p + ((var1 + var2 + dig_P7) >> 4));
468 return p;
469}

◆ bme280_compensate_humidity()

uint32_t bme280_compensate_humidity ( int32_t  adc_H)

Returns humidity in RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).

Output value of "47445" represents 47445/1024 = 46.333 RH.

Definition at line 477 of file bme280.c.

478{
479 int32_t v_x1_u32r;
480
481 v_x1_u32r = (t_fine - (76800));
482
483 v_x1_u32r = (((((adc_H << 14) - (((int32_t)dig_H4) << 20)
484 - (((int32_t)dig_H5) * v_x1_u32r)) + (16384)) >> 15) * (((((((v_x1_u32r
485 * ((int32_t)dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)dig_H3)) >> 11)
486 + (32768))) >> 10) + (2097152)) * ((int32_t)dig_H2) + 8192) >> 14));
487
488 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7)
489 * ((int32_t)dig_H1)) >> 4));
490 v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
491 v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
492 return (uint32_t)(v_x1_u32r>>12);
493}

◆ init_bme280()

void init_bme280 ( void  )

Initialise the device ready for measurements to be taken.

Definition at line 125 of file bme280.c.

126{
127 // Setup I2C hardware fpr use.
128 init_i2c(BUS_SPEED_100KHZ);
129
130 // Perform ID check.
131 uint8_t id = bme280_read_byte(CHIP_ID_REG);
132 if (id == 0x60)
133 {
134 log_message(&bme280_log,
135 DEBUG,
136 "In init_bme280(), Chip ID check passed.");
137 }
138 else
139 {
140 log_message(&bme280_log,
141 ERROR,
142 "In init_bme280(), Chip ID check failed.");
143 }
144
145 // Read compensation data from sensor and save it.
147
148 //
149 bme280_write_byte(CTRL_HUM_REG, OVERSAMPLE_x1);
150
151 //
152 bme280_write_byte(CONFIG_REG, 0b10100000);
153
154 // oversample x1 temp, pressure off, forced mode
155 bme280_write_byte(CTRL_MEAS_REG, 0b00100001);
156}
void init_i2c(uint32_t bus_speed)
Sets pullups and initializes i2c clock to desired bus speed.
Definition: atmega_i2c.c:49
void bme280_read_comp_data(void)
Reads in all compensation data from the device and stores it in a buffer.
Definition: bme280.c:322
void bme280_write_byte(uint8_t reg, uint8_t byte)
Writes a single byte to a specified reguster.
Definition: bme280.c:244

◆ bme280_get_temperature()

int16_t bme280_get_temperature ( void  )

Fetches the latest temperature data from the sensor, compensates and formats the data in degrees Celcius * 100.

Returns
eg. A return value of 5123 = 51.23˚C (Degrees Celcius).

Definition at line 164 of file bme280.c.

165{
166 int32_t retval;
167 uint32_t raw_temp_adc_val;
168
169 // oversample x1 temp, pressure off, forced mode.
170 bme280_write_byte(CTRL_MEAS_REG, 0b00100001);
171 raw_temp_adc_val = bme280_get_raw_temp_val();
172 retval = bme280_compensate_temp(raw_temp_adc_val);
173
174 return retval;
175}
int32_t bme280_compensate_temp(int32_t adc_T)
Returns temperature in DegC, resolution is 0.01 DegC.
Definition: bme280.c:420

◆ bme280_get_humidity()

uint16_t bme280_get_humidity ( void  )

Fetches the latest humidity data from the sensor, compensates and formats the data as RH * 100.

Returns
eg. A return value of 2852 = 28.50 RH (Relative Humidity).

Definition at line 207 of file bme280.c.

208{
209 uint32_t retval;
210 uint16_t raw_hum_adc_val;
211
212 // oversample x1 temp, pressure off, forced mode
213 bme280_write_byte(CTRL_MEAS_REG, 0b00100001);
214 raw_hum_adc_val = bme280_get_raw_hum_val();
215 retval = bme280_compensate_humidity(raw_hum_adc_val);
216 retval *= 100;
217 retval = (retval >> 10);
218
219 return retval;
220}
uint32_t bme280_compensate_humidity(int32_t adc_H)
Returns humidity in RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits...
Definition: bme280.c:477

◆ bme280_get_pressure()

uint16_t bme280_get_pressure ( void  )

Fetches the latest pressure data from the sensor, compensates and formats the data as Pa * 100.

Returns
eg. A return value of 96386 = 963.86 Pa (Pascals).

Definition at line 228 of file bme280.c.

229{
230 // Some pressure-getting code goes here.
231 return 0;
232}

Variable Documentation

◆ bme280_log

log_system_config_t bme280_log
Initial value:
=
{
.p_system_tag = "BME280",
.file_log_level = DEBUG,
}

Definition at line 66 of file bme280.c.

◆ t_fine

int32_t t_fine

Definition at line 414 of file bme280.c.