/elec/quadcopter

To get this branch, use:
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
}