17
17
#include "mgos_barometer_bme280.h"
18
18
#include "mgos_i2c.h"
19
19
20
+ #define BME280_CONCAT_BYTES (msb , lsb ) (((uint16_t)msb << 8) | (uint16_t)lsb)
21
+
20
22
// Datasheet:
21
23
// https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
22
24
//
23
- // TODO(pim): Add humidity sensing
25
+
24
26
25
27
bool mgos_barometer_bme280_detect (struct mgos_barometer * dev ) {
26
28
int val ;
@@ -33,6 +35,9 @@ bool mgos_barometer_bme280_detect(struct mgos_barometer *dev) {
33
35
return false;
34
36
}
35
37
38
+ LOG (LL_DEBUG , ("Detecting BMx280 %d, reg b is: %d" , dev -> i2caddr , val ));
39
+
40
+
36
41
if (val == 0x56 || val == 0x57 ) {
37
42
LOG (LL_INFO , ("Preproduction version of BMP280 detected (0x%02x)" , val ));
38
43
return true;
@@ -74,19 +79,51 @@ bool mgos_barometer_bme280_create(struct mgos_barometer *dev) {
74
79
return false;
75
80
}
76
81
82
+ if ( dev -> capabilities && MGOS_BAROMETER_CAP_HYGROMETER ) {
83
+ uint8_t reg_data [ 7 ];
84
+ int16_t dig_h4_lsb ;
85
+ int16_t dig_h4_msb ;
86
+ int16_t dig_h5_lsb ;
87
+ int16_t dig_h5_msb ;
88
+
89
+ if (!mgos_i2c_read_reg_n (dev -> i2c , dev -> i2caddr , BME280_REG_HUMIDITY_CALIB_ADDR , 7 , reg_data )) {
90
+ free (dev -> user_data );
91
+ return false;
92
+ }
93
+
94
+ bme280_data -> calib .dig_H2 = (int16_t )BME280_CONCAT_BYTES (reg_data [1 ], reg_data [0 ]);
95
+ bme280_data -> calib .dig_H3 = reg_data [2 ];
96
+ dig_h4_msb = (int16_t )(int8_t )reg_data [3 ] * 16 ;
97
+ dig_h4_lsb = (int16_t )(reg_data [4 ] & 0x0F );
98
+ bme280_data -> calib .dig_H4 = dig_h4_msb | dig_h4_lsb ;
99
+ dig_h5_msb = (int16_t )(int8_t )reg_data [5 ] * 16 ;
100
+ dig_h5_lsb = (int16_t )(reg_data [4 ] >> 4 );
101
+ bme280_data -> calib .dig_H5 = dig_h5_msb | dig_h5_lsb ;
102
+ bme280_data -> calib .dig_H6 = (int8_t )reg_data [6 ];
103
+ }
104
+
77
105
// SPI | 0.5ms period | 16X IIR filter
78
106
if (!mgos_i2c_write_reg_b (dev -> i2c , dev -> i2caddr , BME280_REG_CONFIG , 0x00 | BME280_STANDBY_500us << 2 | BME280_FILTER_16X << 5 )) {
79
107
free (dev -> user_data );
80
108
return false;
81
109
}
82
110
mgos_usleep (10000 );
83
111
112
+
113
+ // Humidity OS
114
+ if (!mgos_i2c_write_reg_b (dev -> i2c , dev -> i2caddr , BME280_REG_CTRL_HUM , BME280_OVERSAMP_2X )) {
115
+ free (dev -> user_data );
116
+ return false;
117
+ }
118
+ mgos_usleep (5000 );
119
+
84
120
// Mode | Pressure OS | Temp OS
85
121
if (!mgos_i2c_write_reg_b (dev -> i2c , dev -> i2caddr , BME280_REG_CTRL_MEAS , BME280_MODE_NORMAL | BME280_OVERSAMP_16X << 2 | BME280_OVERSAMP_2X << 5 )) {
86
122
free (dev -> user_data );
87
123
return false;
88
124
}
89
125
126
+
90
127
dev -> capabilities |= MGOS_BAROMETER_CAP_BAROMETER ;
91
128
dev -> capabilities |= MGOS_BAROMETER_CAP_THERMOMETER ;
92
129
@@ -116,17 +153,19 @@ bool mgos_barometer_bme280_read(struct mgos_barometer *dev) {
116
153
}
117
154
118
155
// read data from sensor
119
- uint8_t data [6 ];
120
- if (!mgos_i2c_read_reg_n (dev -> i2c , dev -> i2caddr , BME280_REG_PRESSURE_MSB , 6 , data )) {
156
+ uint8_t data [8 ];
157
+ if (!mgos_i2c_read_reg_n (dev -> i2c , dev -> i2caddr , BME280_REG_PRESSURE_MSB , 8 , data )) {
121
158
return false;
122
159
}
123
- int32_t Padc , Tadc ;
124
- Padc = (int32_t )((((uint32_t )(data [0 ])) << 12 ) | (((uint32_t )(data [1 ])) << 4 ) | ((uint32_t )data [2 ] >> 4 ));
125
- Tadc = (int32_t )((((uint32_t )(data [3 ])) << 12 ) | (((uint32_t )(data [4 ])) << 4 ) | ((uint32_t )data [5 ] >> 4 ));
126
- // LOG(LL_DEBUG, ("Padc=%d Tadc=%d", Padc, Tadc)) ;
160
+ uint32_t Padc , Tadc , Hadc ;
161
+ Padc = (uint32_t )((((uint32_t )(data [0 ])) << 12 ) | (((uint32_t )(data [1 ])) << 4 ) | ((uint32_t )data [2 ] >> 4 ));
162
+ Tadc = (uint32_t )((((uint32_t )(data [3 ])) << 12 ) | (((uint32_t )(data [4 ])) << 4 ) | ((uint32_t )data [5 ] >> 4 ));
163
+ Hadc = ( data [ 6 ]) << 8 | data [ 7 ] ;
127
164
128
165
// Convert data (from datasheet, section 8.1)
129
- double var1 , var2 , T , P ;
166
+ double var1 , var2 , var3 , var4 , var5 , var6 , T , P , H ;
167
+ double H_min = 1.0 ;
168
+ double H_max = 100.0 ;
130
169
int32_t t_fine ;
131
170
132
171
// Compensation for temperature -- double precision
@@ -155,7 +194,27 @@ bool mgos_barometer_bme280_read(struct mgos_barometer *dev) {
155
194
}
156
195
dev -> pressure = (float )P ;
157
196
158
- // LOG(LL_DEBUG, ("P=%.2f T=%.2f", dev->pressure, dev->temperature));
197
+ H = 0.0 ;
198
+ if ( dev -> capabilities && MGOS_BAROMETER_CAP_HYGROMETER ) {
199
+ // Compensation for humidity
200
+ var1 = ((double )t_fine ) - 76800.0 ;
201
+ var2 = (((double )bme280_data -> calib .dig_H4 ) * 64.0 + (((double ) bme280_data -> calib .dig_H5 ) / 16384.0 ) * var1 );
202
+ var3 = Hadc - var2 ;
203
+ var4 = ((double )bme280_data -> calib .dig_H2 ) / 65536.0 ;
204
+ var5 = (1.0 + (((double ) bme280_data -> calib .dig_H3 ) / 67108864.0 ) * var1 );
205
+ var6 = 1.0 + (((double ) bme280_data -> calib .dig_H6 ) / 67108864.0 ) * var1 * var5 ;
206
+ var6 = var3 * var4 * (var5 * var6 );
207
+ H = var6 * (1.0 - ((double ) bme280_data -> calib .dig_H1 ) * var6 / 524288.0 );
208
+
209
+ if (H > H_max )
210
+ H = H_max ;
211
+ else if (H < H_min )
212
+ H = H_min ;
213
+ }
214
+
215
+ dev -> humidity = (float )H ;
216
+
217
+ LOG (LL_DEBUG , ("P=%.2f T=%.2f H=%.2f" , dev -> pressure , dev -> temperature , dev -> humidity ));
159
218
160
219
return true;
161
220
}
0 commit comments