Skip to content

Commit 332f2e3

Browse files
committed
Improved calculation accuracy
1 parent 6ce0f14 commit 332f2e3

File tree

1 file changed

+84
-51
lines changed

1 file changed

+84
-51
lines changed

mrblib/i2c_bme280.rb

+84-51
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# This libraries are adapted from :bme280.rb => lukasjapan/i2c-bme280.
55
# https://github.com/lukasjapan/i2c-bme280
66
#
7-
# refer to BST-BME280_DS001-12.pdf
8-
# https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME280_DS001-12.pdf
7+
# refer to BST-BME280-DS001-24(bst-bme280-ds002.pdf)
8+
# https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme280-ds002.pdf
99
#
1010

1111
module SENSOR
@@ -22,7 +22,7 @@ def init
2222
# BME280 register setting
2323
set_register
2424

25-
# read trimming parameter
25+
# read trimming parameter
2626
read_trim_params
2727
self
2828
end
@@ -53,27 +53,59 @@ def humidity
5353

5454
private
5555

56-
# Suggested settings for indoor navigation, BST-BME280_DS001-12.pdf (page: 18)
56+
57+
5758
def set_register
59+
# IIR filter coefficient
60+
# filter off => 0b000
61+
# filter x2 => 0b001
62+
# filter X4 => 0b010
63+
# filter x8 => 0b011
64+
# filter x16 => 0b100
65+
#
66+
# oversampling (Temperature, Humidity, Pressure)
67+
# sampling none => 0b000
68+
# sampling x1 => 0b001
69+
# sampling X2 => 0b010
70+
# sampling x4 => 0b011
71+
# sampling x8 => 0b100
72+
# sampling x16 => 0b101
73+
#
74+
# sensor mode
75+
# sleep => 0b00
76+
# forced => 0b01
77+
# normal => 0b11
78+
#
79+
# standby time [ms]
80+
# 0.5 => 0b000
81+
# 62.5 => 0b001
82+
# 125 => 0b010
83+
# 250 => 0b011
84+
# 500 => 0b100
85+
# 1000 => 0b101
86+
# 10 => 0b110
87+
# 20 => 0b111
88+
#
89+
5890
# set config registers
5991
config_reg = 0xF5 # Register address for config settings
6092
t_sb = 0b000 # Standby time = 0.5ms (0b000)
61-
filter = 0b100 # filter coefficient = 16
93+
filter = 0b000 # filter coefficient = OFF
6294
spi3w_en = 0 # Disable SPI
6395
config_val = (t_sb << 5) | (filter << 2) | spi3w_en
6496
write(config_reg, config_val)
6597

6698
# set ctrl_meas registers
6799
tp_reg = 0xF4 # Register address for temperature/pressure settings
68-
osrs_t = 0b010 # Temperature oversampling = x2 (0b010)
100+
osrs_t = 0b101 # Temperature oversampling = x16 (0b101)
69101
osrs_p = 0b101 # Pressure oversampling = x16 (0b101)
70102
mode = 0b11 # Normal mode (0b11)
71103
tp_val = (osrs_t << 5) | (osrs_p << 2) | mode
72104
write(tp_reg, tp_val)
73105

74-
# set ctrl_hum registers
75-
hum_reg = 0xF2 # Register address for humidity settings
76-
osrs_h = 0b001 # Humidity oversampling = x1 (0b001)
106+
# set ctrl_hum registers
107+
hum_reg = 0xF2 # Register address for humidity settings
108+
osrs_h = 0b101 # Humidity oversampling = x16 (0b101)
77109
hum_val = osrs_h
78110
write(hum_reg, hum_val)
79111
end
@@ -92,7 +124,7 @@ def int8(n)
92124
end
93125

94126
# Read compensation parameters of the BME280
95-
# refer to BST-BME280_DS001-12.pdf (Page 22)
127+
# refer to bst-bme280-ds002.pdf (Page 24)
96128
def read_trim_params
97129
# compensation parameter register mapping
98130
Calibration = Struct.new(
@@ -117,16 +149,16 @@ def read_trim_params
117149
:dig_H6, # 0xE7 dig_H6 signed char
118150
:t_fine
119151
)
120-
calib = []
152+
calib = []
121153

122154
# data addresses
123155
dig_t_reg = 0x88
124156
dig_p_reg = 0x8E
125157
dig_h_reg1 = 0xA1
126158
dig_h_reg2 = 0xE1
127-
159+
128160
data = read(dig_t_reg, 6)
129-
calib << ((data[1] << 8) | data[0]) # uint16_t dig_T1 [1][0]
161+
calib << ((data[1] << 8) | data[0]) # uint16_t dig_T1 [1][0]
130162
calib << int16(data[3], data[2]) # int16_t dig_T2 [3][2]
131163
calib << int16(data[5], data[4]) # int16_t dig_T3 [5][4]
132164

@@ -143,75 +175,76 @@ def read_trim_params
143175

144176
data = read(dig_h_reg1, 1)
145177
calib << data[0] # uint8_t dig_H1 [0]
146-
178+
147179
data = read(dig_h_reg2, 7)
148180
calib << int16(data[1], data[0]) # int16_t dig_H2 [1],[0]
149-
calib << data[2] # uint8_t dig_H3 [2]
181+
calib << data[2] # uint8_t dig_H3 [2]
150182

151183
# 109876543210 bit[11:0]
152184
# xxxxxxxx.... dig_H4_msb [11:4] [3]
153185
# ....xxxx dig_H4_lsb [3:0] [4]
154-
# xxxxxxxxxxxx dig_H4 [11:0]
186+
# xxxxxxxxxxxx dig_H4 [11:0]
155187
dig_H4_msb = (data[3] >> 4) & 0x0F
156-
dig_H4_lsb = ((data[3] << 4) & 0xF0) | (data[4] & 0x0F)
188+
dig_H4_lsb = ((data[3] << 4) & 0xF0) | (data[4] & 0x0F)
157189
calib << int16(dig_H4_msb, dig_H4_lsb) # int16_t dig_H4 [3][4]
158-
190+
159191
# 109876543210 bit[11:0]
160192
# xxxxxxxx.... dig_H5_msb [11:4] [5]
161193
# xxxx.... dig_H5_lsb [7:4] [4]
162194
# xxxxxxxxxxxx dig_H5 [11:0]
163195
dig_H5_msb = (data[5] >> 4) & 0x0F
164-
dig_H5_lsb = ((data[5] << 4) & 0xF0) | (data[4] >> 4)
196+
dig_H5_lsb = ((data[5] << 4) & 0xF0) | (data[4] >> 4)
165197
calib << int16(dig_H5_msb, dig_H5_lsb) # int16_t dig_H5 [4][5]
166-
198+
167199
calib << int8(data[6]) # int8_t dig_H6 [6]
168200

169201
@calib = Calibration.new(*calib)
170202
end
171203

172-
# compensate temperature
173-
# refer to BST-BME280_DS001-12.pdf (page: 23)
204+
# compensate temperature
205+
# refer to bst-bme280-ds002.pdf (page: 49)
174206
def trim_t(adc_T)
175-
var1 = ((((adc_T >> 3) - (@calib[:dig_T1] << 1))) * @calib[:dig_T2]) >> 11
176-
var2 = (((((adc_T >> 4) - @calib[:dig_T1]) * ((adc_T >> 4) - @calib[:dig_T1])) >> 12) * @calib[:dig_T3]) >> 14
207+
var1 = (adc_T / 16384.0 - @calib[:dig_T1] / 1024.0) * @calib[:dig_T2]
208+
var2 = ((adc_T / 131072.0 - @calib[:dig_T1] / 8192.0) * (adc_T / 131072.0 - @calib[:dig_T1] / 8192.0)) * @calib[:dig_T3]
177209
@calib[:t_fine] = var1 + var2
178-
t = ((@calib[:t_fine] * 5 + 128) >> 8) / 100
210+
t = @calib[:t_fine] / 5120.0
179211
end
180212

181213
# compensate pressure
182-
# refer to BST-BME280_DS001-12.pdf (page: 50)
214+
# refer to bst-bme280-ds002.pdf (page: 49)
183215
def trim_p(adc_P)
184-
var1 = (@calib[:t_fine] >> 1) - 64000
185-
var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * @calib[:dig_P6]
186-
var2 = var2 + ((var1 * @calib[:dig_P5]) << 1)
187-
var2 = (var2 >> 2) + (@calib[:dig_P4] << 16)
188-
var1 = (((@calib[:dig_P3] * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((@calib[:dig_P2] * var1) >> 1)) >> 18
189-
var1 = ((0x8000 + var1) * @calib[:dig_P1]) >> 15
216+
var1 = (@calib[:t_fine] / 2.0) - 64000.0
217+
var2 = var1 * var1 / 32768.0 * @calib[:dig_P6]
218+
var2 = var2 + ((var1 * @calib[:dig_P5]) * 2.0)
219+
var2 = (var2 / 4.0) + (@calib[:dig_P4] * 65536.0)
220+
var1 = (@calib[:dig_P3] * var1 * var1 / 524288.0 + @calib[:dig_P2] * var1) / 524288.0
221+
var1 = (1.0 + var1 / 32768.0) * @calib[:dig_P1]
190222

191223
if var1 == 0
192224
p = 0.0
193225
else
194-
p = (0x100000 - adc_P - (var2 >> 12)) * 3125
195-
p = (p << 1) / var1
196-
var1 = (@calib[:dig_P9] * ((p >> 3) * (p >> 3)) >> 13) >> 12
197-
var2 = ((p >> 2) * @calib[:dig_P8]) >> 13
198-
p = p + ((var1 + var2 + @calib[:dig_P7]) >> 4)
199-
p /= 100
226+
p = 1048576.0 - adc_P
227+
p = (p - (var2 / 4096.0)) * 6250.0 / var1
228+
var1 = @calib[:dig_P9] * p * p / 2147483648.0
229+
var2 = p * @calib[:dig_P8] / 32768.0
230+
p = p + (var1 + var2 + @calib[:dig_P7]) / 16.0
231+
p /= 100.0
200232
end
201233
end
202234

203235
# compensate humidity
204-
# refer to BST-BME280_DS001-12.pdf (page: 23)
236+
# refer to bst-bme280-ds002.pdf (page: 49)
205237
def trim_h(adc_H)
206-
h = @calib[:t_fine] - 76800
207-
h = ((((adc_H << 14) - (@calib[:dig_H4] << 20) - (@calib[:dig_H5] * h)) + 0x4000) >> 15) *
208-
(((((((h * (@calib[:dig_H6])) >> 10) * (((h * @calib[:dig_H3]) >> 11) + 0x8000)) >> 10) + 0x200000) * @calib[:dig_H2] + 0x2000) >> 14)
209-
h = h - (((((h >> 15) * (h >> 15)) >> 7) * @calib[:dig_H1]) >> 4)
210-
h = h < 0 ? 0 : h
211-
h = h > 419430400 ? 419430400 : h
212-
h = (h >> 12) / 1024
213-
end
214-
238+
h = @calib[:t_fine] - 76800.0
239+
h1 = adc_H - (@calib[:dig_H4] * 64.0 + @calib[:dig_H5] / 16384.0 * h)
240+
h2 = @calib[:dig_H2] / 65536.0 * (1.0 + @calib[:dig_H6] / 67108864.0 * h * (1.0 + @calib[:dig_H3] / 67108864.0 * h))
241+
h = h1 * h2
242+
h = h * (1.0 - @calib[:dig_H1] * h / 524288.0)
243+
h = 100.0 if h > 100.0
244+
h = 0.0 if h < 0.0
245+
h
246+
end
247+
215248
# Measurement of temperature, pressure and humidity
216249
# return all compensated values
217250
def data
@@ -225,8 +258,8 @@ def data
225258
# Apply compensation to received ADC data and return as hash
226259
{
227260
t: trim_t(adc_T),
228-
p: trim_p(adc_P).round(2),
229-
h: trim_h(adc_H).round(2)
261+
p: trim_p(adc_P),
262+
h: trim_h(adc_H)
230263
}
231264
end
232265

@@ -240,6 +273,6 @@ def write(reg_address, data)
240273
def read(reg_address, size = 1)
241274
receive(reg_address, size, @addr)
242275
end
243-
276+
244277
end
245278
end

0 commit comments

Comments
 (0)