1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
public class BMP085 : I2CDevice, Barometer {
public uint8 oversampling_setting = 0x03;
private Calibration cal = Calibration();
private int64 next_temp_measurement;
private int raw_temp;
private int raw_pressure;
private int64 temp_correction_coefficient;
struct Calibration {
int16 AC1;
int16 AC2;
int16 AC3;
uint16 AC4;
uint16 AC5;
uint16 AC6;
int16 B1;
int16 B2;
int16 MB;
int16 MC;
int16 MD;
}
public BMP085(uint8 dev, uint8 addr = 0x77) throws I2CError {
base(dev, addr);
read_calibration_values();
}
private void read_calibration_values() throws I2CError {
var data = get_block(0xaa, 22);
cal.AC1 = data[0] << 8 | data[1];
cal.AC2 = data[2] << 8 | data[3];
cal.AC3 = data[4] << 8 | data[5];
cal.AC4 = data[6] << 8 | data[7];
cal.AC5 = data[8] << 8 | data[9];
cal.AC6 = data[10] << 8 | data[11];
cal.B1 = data[12] << 8 | data[13];
cal.B2 = data[14] << 8 | data[15];
cal.MB = data[16] << 8 | data[17];
cal.MC = data[18] << 8 | data[19];
cal.MD = data[20] << 8 | data[21];
}
private void msleep(uint msecs) {
Posix.usleep(msecs*1000);
}
private void update_raw_temperature() throws I2CError {
set_byte(0xf4, 0x2e);
msleep(5);
var data = get_block(0xf6, 2);
raw_temp = data[0] << 8 | data[1];
next_temp_measurement = time_t() + 1;
}
private void update_raw_pressure() throws I2CError {
set_byte(0xf4, 0x34 + (oversampling_setting<<6));
msleep(2+(3 << oversampling_setting<<1));
var data = get_block(0xf6, 3);
raw_pressure = data[0] << 16 | data[1] << 8 | data[2];
raw_pressure >>= 8-oversampling_setting;
}
public int32 get_temperature() throws I2CError {
if(next_temp_measurement+1 < time_t())
update_raw_temperature();
int64 x1 = ((raw_temp - cal.AC6) * cal.AC5) >> 15;
int64 x2 = (cal.MC << 11) / (x1 + cal.MD);
temp_correction_coefficient = x1 + x2 - 4000;
return (int32) (x1+x2+8) >> 4;
}
public int32 get_pressure() throws I2CError {
int64 x1, x2, x3, b3, p;
uint64 b4, b7;
if(next_temp_measurement+1 < time_t())
get_temperature();
update_raw_pressure();
x1 = (temp_correction_coefficient * temp_correction_coefficient) >> 12;
x1 *= cal.B2;
x1 >>= 11;
x2 = cal.AC2 * temp_correction_coefficient;
x2 >>= 11;
x3 = x1 + x2;
b3 = (((((int64)cal.AC1) * 4 + x3) << oversampling_setting) + 2) >> 2;
x1 = (cal.AC3 * temp_correction_coefficient) >> 13;
x2 = (cal.B1 * ((temp_correction_coefficient * temp_correction_coefficient) >> 12)) >> 16;
x3 = (x1 + x2 + 2) >> 2;
b4 = (cal.AC4 * (uint64)(x3 + 32768)) >> 15;
b7 = ((uint64)raw_pressure - b3) * (50000 >> oversampling_setting);
p = (int64) ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
x1 = p >> 8;
x1 *= x1;
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
p += (x1 + x2 + 3791) >> 4;
return (int32) p;
}
}
|