YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
bme280_drv.cpp
1/*
2 * bme280_drv.cpp
3 *
4 * Created on: Mar 15, 2017
5 * Author: Dennis Hoffmann
6 */
7
8#include "bme280_drv.h"
9
10bme280_drv::bme280_drv(i2c_interface & i2c, uint8_t i2c_addr) : _i2c(i2c), _i2c_addr(i2c_addr){
11 get_calibration_data();
12}
13
14void bme280_drv::soft_reset(){
15 writeRegister(BME280::REG_RESET, BME280::RESET);
16}
17
18float bme280_drv::get_temperature(){
19 int32_t var1, var2;
20 int32_t adc_T = static_cast<int32_t>(read_u24(BME280::REG_TEMP_MSB));
21
22 if (adc_T == 0x800000){
23 return -273.15;
24 }
25
26 // expect 20bit value
27 adc_T >>= 4;
28 var1 = ((((adc_T>>3) - ((int32_t)_calibration_data.dig_T1 <<1))) * ((int32_t)_calibration_data.dig_T2)) >> 11;
29
30 var2 = (((((adc_T>>4) - ((int32_t)_calibration_data.dig_T1)) *
31 ((adc_T>>4) - ((int32_t)_calibration_data.dig_T1))) >> 12) *
32 ((int32_t)_calibration_data.dig_T3)) >> 14;
33
34 t_fine = var1 + var2;
35
36 float T = (t_fine * 5 + 128) >> 8;
37 return T/100;
38}
39
40/*
41float bme280_drv::get_pressure(){
42 int64_t var1, var2, p;
43
44 int32_t adc_P = read_u24(BME280::REG_PRESS_MSB);
45 if (adc_P == 0x800000){
46 return -1;
47 }
48
49 // expect 20bit value
50 adc_P >>= 4;
51
52 var1 = ((int64_t)t_fine) - 128000;
53 var2 = var1 * var1 * (int64_t)_calibration_data.dig_P6;
54 var2 = var2 + ((var1*(int64_t)_calibration_data.dig_P5)<<17);
55 var2 = var2 + (((int64_t)_calibration_data.dig_P4)<<35);
56 var1 = ((var1 * var1 * (int64_t)_calibration_data.dig_P3)>>8) +
57 ((var1 * (int64_t)_calibration_data.dig_P2)<<12);
58 var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_calibration_data.dig_P1)>>33;
59
60 if (var1 == 0) {
61 return 0; // avoid exception caused by division by zero
62 }
63 p = 1048576 - adc_P;
64 p = (((p<<31) - var2)*3125) / var1;
65 var1 = (((int64_t)_calibration_data.dig_P9) * (p>>13) * (p>>13)) >> 25;
66 var2 = (((int64_t)_calibration_data.dig_P8) * p) >> 19;
67
68 p = ((p + var1 + var2) >> 8) + (((int64_t)_calibration_data.dig_P7)<<4);
69 return (float)p/256;
70}
71*/
72
73
74float bme280_drv::get_pressure(){
75 int32_t var1, var2;
76 int32_t adc_P = read_u24(BME280::REG_PRESS_MSB);
77 uint32_t p;
78
79 // 20bit format
80 adc_P >>= 4;
81
82 var1 = (t_fine >> 1) - 64000;
83 var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * static_cast<int32_t>(_calibration_data.dig_P6);
84 var2 = var2 + ((var1 * static_cast<int32_t>(_calibration_data.dig_P5)) << 1);
85 var2 = (var2 >> 2) + (static_cast<int32_t>(_calibration_data.dig_P4) << 16);
86 var1 = (((_calibration_data.dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + (((static_cast<int32_t>(_calibration_data.dig_P2)) * var1) >> 1)) >> 18;
87 var1 = ((((32768 + var1)) * (static_cast<int32_t>(_calibration_data.dig_P1))) >> 15);
88 if(var1 == 0){
89 return 0;
90 }
91 p = ((static_cast<uint32_t>(((int32_t)1048576) - adc_P) - (var2 >> 12))) * 3125;
92 if(p < 0x80000000){
93 p = (p << 1) / static_cast<uint32_t>(var1);
94 }else{
95 p = (p / static_cast<uint32_t>(var1)) * 2;
96 }
97
98 var1 = (static_cast<int32_t>(_calibration_data.dig_P9) * static_cast<int32_t>(((p >> 3) * (p >> 3)) >> 13)) >> 12;
99 var2 = (static_cast<int32_t>(p >> 2) * static_cast<int32_t>(_calibration_data.dig_P8)) >> 13;
100 p = static_cast<uint32_t>(static_cast<int32_t>(p) + ((var1 + var2 + _calibration_data.dig_P7) >> 4));
101 return p/100.0;
102}
103
104
105//from offical driver bme280.c
106float bme280_drv::get_humidity(){
107 int32_t adc_H = read_u16(BME280::REG_HUM_MSB);
108 if (adc_H == 0x8000){
109 return -1;
110 }
111
112 int32_t v_x1_u32r;
113
114 v_x1_u32r = (t_fine - ((int32_t)76800));
115
116 v_x1_u32r = (((((adc_H << 14) - (((int32_t)_calibration_data.dig_H4) << 20) -
117 (((int32_t)_calibration_data.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
118 (((((((v_x1_u32r * ((int32_t)_calibration_data.dig_H6)) >> 10) *
119 (((v_x1_u32r * ((int32_t)_calibration_data.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
120 ((int32_t)2097152)) * ((int32_t)_calibration_data.dig_H2) + 8192) >> 14));
121
122 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
123 ((int32_t)_calibration_data.dig_H1)) >> 4));
124
125 v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
126 v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
127 float h = (v_x1_u32r>>12);
128 return h / 1024.0;
129}
130
131
132void bme280_drv::set_sampling(BME280::MODE m,
133 BME280::FILTER f,
134 BME280::STANDBY_TIME t,
135 BME280::SAMPLING s_temp,
136 BME280::SAMPLING s_press,
137 BME280::SAMPLING s_hum){
138 uint8_t reg_conf = static_cast<uint8_t>(t) << 5 | static_cast<uint8_t>(f) << 2;
139 uint8_t reg_ctrl_meas = static_cast<uint8_t>(s_temp) << 5 | static_cast<uint8_t>(s_press) << 2 | static_cast<uint8_t>(m);
140 uint8_t reg_ctrl_hum = static_cast<uint8_t>(s_hum);
141
142 writeRegister(BME280::REG_CTRL_HUM, reg_ctrl_hum);
143 writeRegister(BME280::REG_CTRL_MEAS, reg_ctrl_meas);
144 writeRegister(BME280::REG_CONFIG, reg_conf);
145}
146
147void bme280_drv::get_calibration_data(){
148 _calibration_data.dig_T1 = read_u16_le(BME280::REG_DIG_T1);
149 _calibration_data.dig_T2 = read_s16_le(BME280::REG_DIG_T2);
150 _calibration_data.dig_T3 = read_s16_le(BME280::REG_DIG_T3);
151
152 _calibration_data.dig_P1 = read_u16_le(BME280::REG_DIG_P1);
153 _calibration_data.dig_P2 = read_s16_le(BME280::REG_DIG_P2);
154 _calibration_data.dig_P3 = read_s16_le(BME280::REG_DIG_P3);
155 _calibration_data.dig_P4 = read_s16_le(BME280::REG_DIG_P4);
156 _calibration_data.dig_P5 = read_s16_le(BME280::REG_DIG_P5);
157 _calibration_data.dig_P6 = read_s16_le(BME280::REG_DIG_P6);
158 _calibration_data.dig_P7 = read_s16_le(BME280::REG_DIG_P7);
159 _calibration_data.dig_P8 = read_s16_le(BME280::REG_DIG_P8);
160 _calibration_data.dig_P9 = read_s16_le(BME280::REG_DIG_P9);
161
162 _calibration_data.dig_H1 = readRegister(BME280::REG_DIG_H1);
163 _calibration_data.dig_H2 = read_s16_le(BME280::REG_DIG_H2);
164 _calibration_data.dig_H3 = readRegister(BME280::REG_DIG_H3);
165 _calibration_data.dig_H4 = readRegister(BME280::REG_DIG_H4) << 4 | (readRegister(BME280::REG_DIG_H4+1) & 0b00001111);
166 _calibration_data.dig_H5 = readRegister(BME280::REG_DIG_H5+1) << 4 | readRegister(BME280::REG_DIG_H5) >> 4;
167 _calibration_data.dig_H6 = static_cast<int8_t>(readRegister(BME280::REG_DIG_H6));
168}
169
170bool bme280_drv::detect_sensor() {
171 return (readRegister(BME280::REG_ID) == 0x60);
172}
173
174void bme280_drv::writeRegister(uint8_t reg, uint8_t value){
175 uint8_t txbuf[2];
176 txbuf[0] = reg;
177 txbuf[1] = value;
178 _i2c.i2cWrite(_i2c_addr, txbuf, 2);
179}
180
181uint8_t bme280_drv::readRegister(uint8_t reg){
182 uint8_t txbuf[1];
183 uint8_t rxbuf[1];
184 txbuf[0] = reg;
185 _i2c.i2cWrite(_i2c_addr, txbuf, 1);
186 _i2c.i2cRead (_i2c_addr, rxbuf, 1);
187 return rxbuf[0];
188}
189
190uint32_t bme280_drv::read_u24(uint8_t reg){
191 uint8_t txbuf[1];
192 uint8_t rxbuf[3];
193 txbuf[0] = reg;
194 uint32_t val = 0;
195 _i2c.i2cWrite(_i2c_addr, txbuf, 1);
196 _i2c.i2cRead (_i2c_addr, rxbuf, 3);
197 val = rxbuf[0] << 16 | rxbuf[1] << 8 | rxbuf[2];
198 return val;
199}
200
201uint16_t bme280_drv::read_u16_le(uint8_t reg){
202 uint8_t txbuf[1];
203 uint8_t rxbuf[2];
204 txbuf[0] = reg;
205 uint16_t val;
206 _i2c.i2cWrite(_i2c_addr, txbuf, 1);
207 _i2c.i2cRead (_i2c_addr, rxbuf, 2);
208 val = (rxbuf[1] << 8) | rxbuf[0];
209 return val;
210}
211
212uint16_t bme280_drv::read_u16(uint8_t reg){
213 uint8_t txbuf[1];
214 uint8_t rxbuf[2];
215 txbuf[0] = reg;
216 uint16_t val;
217 _i2c.i2cWrite(_i2c_addr, txbuf, 1);
218 _i2c.i2cRead (_i2c_addr, rxbuf, 2);
219 val = (rxbuf[0] << 8) | rxbuf[1];
220 return val;
221}
222
223uint16_t bme280_drv::read_s16_le(uint8_t reg){
224 uint16_t val = read_u16_le(reg);
225 return static_cast<int16_t>(val);
226}
227