bzr branch
http://bzr.ed.am/elec/quadcopter
3
by Tim Marston
added test programs for all 4 IMU sensors |
1 |
/*************************************************** |
2 |
This is a library for the BMP085 Barometric Pressure & Temp Sensor |
|
3 |
||
4 |
Designed specifically to work with the Adafruit BMP085 Breakout |
|
5 |
----> https://www.adafruit.com/products/391 |
|
6 |
||
7 |
These displays use I2C to communicate, 2 pins are required to |
|
8 |
interface |
|
9 |
Adafruit invests time and resources providing this open source code, |
|
10 |
please support Adafruit and open-source hardware by purchasing |
|
11 |
products from Adafruit! |
|
12 |
||
13 |
Written by Limor Fried/Ladyada for Adafruit Industries. |
|
14 |
BSD license, all text above must be included in any redistribution |
|
15 |
****************************************************/ |
|
16 |
||
17 |
#include "BMP085.h" |
|
18 |
#include <util/delay.h> |
|
19 |
||
20 |
BMP085::BMP085() { |
|
21 |
} |
|
22 |
||
23 |
||
24 |
boolean BMP085::begin(uint8_t mode) { |
|
25 |
if (mode > BMP085_ULTRAHIGHRES) |
|
26 |
mode = BMP085_ULTRAHIGHRES; |
|
27 |
oversampling = mode; |
|
28 |
||
29 |
Wire.begin(); |
|
30 |
||
31 |
if (read8(0xD0) != 0x55) return false; |
|
32 |
||
33 |
/* read calibration data */ |
|
34 |
ac1 = read16(BMP085_CAL_AC1); |
|
35 |
ac2 = read16(BMP085_CAL_AC2); |
|
36 |
ac3 = read16(BMP085_CAL_AC3); |
|
37 |
ac4 = read16(BMP085_CAL_AC4); |
|
38 |
ac5 = read16(BMP085_CAL_AC5); |
|
39 |
ac6 = read16(BMP085_CAL_AC6); |
|
40 |
||
41 |
b1 = read16(BMP085_CAL_B1); |
|
42 |
b2 = read16(BMP085_CAL_B2); |
|
43 |
||
44 |
mb = read16(BMP085_CAL_MB); |
|
45 |
mc = read16(BMP085_CAL_MC); |
|
46 |
md = read16(BMP085_CAL_MD); |
|
47 |
#if (BMP085_DEBUG == 1) |
|
48 |
Serial.print("ac1 = "); Serial.println(ac1, DEC); |
|
49 |
Serial.print("ac2 = "); Serial.println(ac2, DEC); |
|
50 |
Serial.print("ac3 = "); Serial.println(ac3, DEC); |
|
51 |
Serial.print("ac4 = "); Serial.println(ac4, DEC); |
|
52 |
Serial.print("ac5 = "); Serial.println(ac5, DEC); |
|
53 |
Serial.print("ac6 = "); Serial.println(ac6, DEC); |
|
54 |
||
55 |
Serial.print("b1 = "); Serial.println(b1, DEC); |
|
56 |
Serial.print("b2 = "); Serial.println(b2, DEC); |
|
57 |
||
58 |
Serial.print("mb = "); Serial.println(mb, DEC); |
|
59 |
Serial.print("mc = "); Serial.println(mc, DEC); |
|
60 |
Serial.print("md = "); Serial.println(md, DEC); |
|
61 |
#endif |
|
62 |
} |
|
63 |
||
64 |
uint16_t BMP085::readRawTemperature(void) { |
|
65 |
write8(BMP085_CONTROL, BMP085_READTEMPCMD); |
|
66 |
_delay_ms(5); |
|
67 |
#if BMP085_DEBUG == 1 |
|
68 |
Serial.print("Raw temp: "); Serial.println(read16(BMP085_TEMPDATA)); |
|
69 |
#endif |
|
70 |
return read16(BMP085_TEMPDATA); |
|
71 |
} |
|
72 |
||
73 |
uint32_t BMP085::readRawPressure(void) { |
|
74 |
uint32_t raw; |
|
75 |
||
76 |
write8(BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6)); |
|
77 |
||
78 |
if (oversampling == BMP085_ULTRALOWPOWER) |
|
79 |
_delay_ms(5); |
|
80 |
else if (oversampling == BMP085_STANDARD) |
|
81 |
_delay_ms(8); |
|
82 |
else if (oversampling == BMP085_HIGHRES) |
|
83 |
_delay_ms(14); |
|
84 |
else |
|
85 |
_delay_ms(26); |
|
86 |
||
87 |
raw = read16(BMP085_PRESSUREDATA); |
|
88 |
||
89 |
raw <<= 8; |
|
90 |
raw |= read8(BMP085_PRESSUREDATA+2); |
|
91 |
raw >>= (8 - oversampling); |
|
92 |
||
93 |
/* this pull broke stuff, look at it later? |
|
94 |
if (oversampling==0) { |
|
95 |
raw <<= 8; |
|
96 |
raw |= read8(BMP085_PRESSUREDATA+2); |
|
97 |
raw >>= (8 - oversampling); |
|
98 |
} |
|
99 |
*/ |
|
100 |
||
101 |
#if BMP085_DEBUG == 1 |
|
102 |
Serial.print("Raw pressure: "); Serial.println(raw); |
|
103 |
#endif |
|
104 |
return raw; |
|
105 |
} |
|
106 |
||
107 |
||
108 |
int32_t BMP085::readPressure(void) { |
|
109 |
int32_t UT, UP, B3, B5, B6, X1, X2, X3, p; |
|
110 |
uint32_t B4, B7; |
|
111 |
||
112 |
UT = readRawTemperature(); |
|
113 |
UP = readRawPressure(); |
|
114 |
||
115 |
#if BMP085_DEBUG == 1 |
|
116 |
// use datasheet numbers! |
|
117 |
UT = 27898; |
|
118 |
UP = 23843; |
|
119 |
ac6 = 23153; |
|
120 |
ac5 = 32757; |
|
121 |
mc = -8711; |
|
122 |
md = 2868; |
|
123 |
b1 = 6190; |
|
124 |
b2 = 4; |
|
125 |
ac3 = -14383; |
|
126 |
ac2 = -72; |
|
127 |
ac1 = 408; |
|
128 |
ac4 = 32741; |
|
129 |
oversampling = 0; |
|
130 |
#endif |
|
131 |
||
132 |
// do temperature calculations |
|
133 |
X1=(UT-(int32_t)(ac6))*((int32_t)(ac5))/pow(2,15); |
|
134 |
X2=((int32_t)mc*pow(2,11))/(X1+(int32_t)md); |
|
135 |
B5=X1 + X2; |
|
136 |
||
137 |
#if BMP085_DEBUG == 1 |
|
138 |
Serial.print("X1 = "); Serial.println(X1); |
|
139 |
Serial.print("X2 = "); Serial.println(X2); |
|
140 |
Serial.print("B5 = "); Serial.println(B5); |
|
141 |
#endif |
|
142 |
||
143 |
// do pressure calcs |
|
144 |
B6 = B5 - 4000; |
|
145 |
X1 = ((int32_t)b2 * ( (B6 * B6)>>12 )) >> 11; |
|
146 |
X2 = ((int32_t)ac2 * B6) >> 11; |
|
147 |
X3 = X1 + X2; |
|
148 |
B3 = ((((int32_t)ac1*4 + X3) << oversampling) + 2) / 4; |
|
149 |
||
150 |
#if BMP085_DEBUG == 1 |
|
151 |
Serial.print("B6 = "); Serial.println(B6); |
|
152 |
Serial.print("X1 = "); Serial.println(X1); |
|
153 |
Serial.print("X2 = "); Serial.println(X2); |
|
154 |
Serial.print("B3 = "); Serial.println(B3); |
|
155 |
#endif |
|
156 |
||
157 |
X1 = ((int32_t)ac3 * B6) >> 13; |
|
158 |
X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16; |
|
159 |
X3 = ((X1 + X2) + 2) >> 2; |
|
160 |
B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15; |
|
161 |
B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> oversampling ); |
|
162 |
||
163 |
#if BMP085_DEBUG == 1 |
|
164 |
Serial.print("X1 = "); Serial.println(X1); |
|
165 |
Serial.print("X2 = "); Serial.println(X2); |
|
166 |
Serial.print("B4 = "); Serial.println(B4); |
|
167 |
Serial.print("B7 = "); Serial.println(B7); |
|
168 |
#endif |
|
169 |
||
170 |
if (B7 < 0x80000000) { |
|
171 |
p = (B7 * 2) / B4; |
|
172 |
} else { |
|
173 |
p = (B7 / B4) * 2; |
|
174 |
} |
|
175 |
X1 = (p >> 8) * (p >> 8); |
|
176 |
X1 = (X1 * 3038) >> 16; |
|
177 |
X2 = (-7357 * p) >> 16; |
|
178 |
||
179 |
#if BMP085_DEBUG == 1 |
|
180 |
Serial.print("p = "); Serial.println(p); |
|
181 |
Serial.print("X1 = "); Serial.println(X1); |
|
182 |
Serial.print("X2 = "); Serial.println(X2); |
|
183 |
#endif |
|
184 |
||
185 |
p = p + ((X1 + X2 + (int32_t)3791)>>4); |
|
186 |
#if BMP085_DEBUG == 1 |
|
187 |
Serial.print("p = "); Serial.println(p); |
|
188 |
#endif |
|
189 |
return p; |
|
190 |
} |
|
191 |
||
192 |
||
193 |
float BMP085::readTemperature(void) { |
|
194 |
int32_t UT, X1, X2, B5; // following ds convention |
|
195 |
float temp; |
|
196 |
||
197 |
UT = readRawTemperature(); |
|
198 |
||
199 |
#if BMP085_DEBUG == 1 |
|
200 |
// use datasheet numbers! |
|
201 |
UT = 27898; |
|
202 |
ac6 = 23153; |
|
203 |
ac5 = 32757; |
|
204 |
mc = -8711; |
|
205 |
md = 2868; |
|
206 |
#endif |
|
207 |
||
208 |
// step 1 |
|
209 |
X1 = (UT - (int32_t)ac6) * ((int32_t)ac5) / pow(2,15); |
|
210 |
X2 = ((int32_t)mc * pow(2,11)) / (X1+(int32_t)md); |
|
211 |
B5 = X1 + X2; |
|
212 |
temp = (B5+8)/pow(2,4); |
|
213 |
temp /= 10; |
|
214 |
||
215 |
return temp; |
|
216 |
} |
|
217 |
||
218 |
float BMP085::readAltitude(float sealevelPressure) { |
|
219 |
float altitude; |
|
220 |
||
221 |
float pressure = readPressure(); |
|
222 |
||
223 |
altitude = 44330 * (1.0 - pow(pressure /sealevelPressure,0.1903)); |
|
224 |
||
225 |
return altitude; |
|
226 |
} |
|
227 |
||
228 |
||
229 |
/*********************************************************************/ |
|
230 |
||
231 |
uint8_t BMP085::read8(uint8_t a) { |
|
232 |
uint8_t ret; |
|
233 |
||
234 |
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device |
|
235 |
#if (ARDUINO >= 100) |
|
236 |
Wire.write(a); // sends register address to read from |
|
237 |
#else |
|
238 |
Wire.send(a); // sends register address to read from |
|
239 |
#endif |
|
240 |
Wire.endTransmission(); // end transmission |
|
241 |
||
242 |
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device |
|
243 |
Wire.requestFrom(BMP085_I2CADDR, 1);// send data n-bytes read |
|
244 |
#if (ARDUINO >= 100) |
|
245 |
ret = Wire.read(); // receive DATA |
|
246 |
#else |
|
247 |
ret = Wire.receive(); // receive DATA |
|
248 |
#endif |
|
249 |
Wire.endTransmission(); // end transmission |
|
250 |
||
251 |
return ret; |
|
252 |
} |
|
253 |
||
254 |
uint16_t BMP085::read16(uint8_t a) { |
|
255 |
uint16_t ret; |
|
256 |
||
257 |
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device |
|
258 |
#if (ARDUINO >= 100) |
|
259 |
Wire.write(a); // sends register address to read from |
|
260 |
#else |
|
261 |
Wire.send(a); // sends register address to read from |
|
262 |
#endif |
|
263 |
Wire.endTransmission(); // end transmission |
|
264 |
||
265 |
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device |
|
266 |
Wire.requestFrom(BMP085_I2CADDR, 2);// send data n-bytes read |
|
267 |
#if (ARDUINO >= 100) |
|
268 |
ret = Wire.read(); // receive DATA |
|
269 |
ret <<= 8; |
|
270 |
ret |= Wire.read(); // receive DATA |
|
271 |
#else |
|
272 |
ret = Wire.receive(); // receive DATA |
|
273 |
ret <<= 8; |
|
274 |
ret |= Wire.receive(); // receive DATA |
|
275 |
#endif |
|
276 |
Wire.endTransmission(); // end transmission |
|
277 |
||
278 |
return ret; |
|
279 |
} |
|
280 |
||
281 |
void BMP085::write8(uint8_t a, uint8_t d) { |
|
282 |
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device |
|
283 |
#if (ARDUINO >= 100) |
|
284 |
Wire.write(a); // sends register address to read from |
|
285 |
Wire.write(d); // write data |
|
286 |
#else |
|
287 |
Wire.send(a); // sends register address to read from |
|
288 |
Wire.send(d); // write data |
|
289 |
#endif |
|
290 |
Wire.endTransmission(); // end transmission |
|
291 |
} |