Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1993 - 1
/****************************************************************************
2
* BMP085.cpp - BMP085/I2C (Digital Pressure Sensor) library for Arduino     *
3
* Copyright 2010-2011 Filipe Vieira & various contributors                  *
4
*                                                                           *
5
* This file is part of BMP085 Arduino library.                              *
6
*                                                                           *
7
* This library is free software: you can redistribute it and/or modify      *
8
* it under the terms of the GNU Lesser General Public License as published  *
9
* by the Free Software Foundation, either version 3 of the License, or      *
10
* (at your option) any later version.                                       *
11
*                                                                           *
12
* This program is distributed in the hope that it will be useful,           *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of            *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
15
* GNU Lesser General Public License for more details.                       *
16
*                                                                           *
17
* You should have received a copy of the GNU Lesser General Public License  *
18
* along with this program.  If not, see <http://www.gnu.org/licenses/>.     *
19
****************************************************************************/
20
/****************************************************************************
21
* Tested on Arduino Mega with BMP085 Breakout                               *
22
* SDA   -> pin 20   (no pull up resistors)                                  *
23
* SCL   -> pin 21   (no pull up resistors)                                  *
24
* XCLR  -> not connected                                                    *
25
* EOC   -> not connected                                                    *
26
* GND   -> pin GND                                                          *
27
* VCC   -> pin 3.3V                                                         *
28
* NOTE: SCL and SDA needs pull-up resistors for each I2C bus.               *
29
*  2.2kOhm..10kOhm, typ. 4.7kOhm                                            *
30
*****************************************************************************/
31
#include <Wire.h>
32
#include <BMP085.h>
33
 
34
BMP085::BMP085() {
35
  _dev_address = BMP085_ADDR;
36
  _pressure_waittime[0] = 5; // These are maximum convertion times.
37
  _pressure_waittime[1] = 8; // It is possible to use pin EOC (End Of Conversion)
38
  _pressure_waittime[2] = 14;// to check if conversion is finished (logic 1) 
39
  _pressure_waittime[3] = 26;// or running (logic 0) insted of waiting for convertion times.
40
  _cm_Offset = 0;
41
  _Pa_Offset = 0;               // 1hPa = 100Pa = 1mbar
42
 
43
  oldEMA = 0;
44
}
45
 
46
void BMP085::init() {  
47
  init(MODE_STANDARD, 0, true);
48
}
49
 
50
void BMP085::init(byte _BMPMode, int32_t _initVal, bool _Unitmeters){    
51
  getCalData();               // initialize cal data
52
  calcTrueTemperature();      // initialize b5
53
  setMode(_BMPMode);
54
  _Unitmeters ? setLocalAbsAlt(_initVal) : setLocalPressure(_initVal);
55
}
56
 
57
byte BMP085::getDevAddr() {  
58
  return _dev_address;
59
}
60
 
61
byte BMP085::getMode(){
62
  return _oss;
63
}
64
 
65
void BMP085::setMode(byte _BMPMode){
66
  _oss = _BMPMode;
67
}
68
 
69
void BMP085::setLocalPressure(int32_t _Pa){  
70
  int32_t tmp_alt;
71
 
72
  _param_datum = _Pa;  
73
  getAltitude(&tmp_alt);    // calc altitude based on current pressure   
74
  _param_centimeters = tmp_alt;
75
}
76
 
77
void BMP085::setLocalAbsAlt(int32_t _centimeters){  
78
  int32_t tmp_Pa;
79
 
80
  _param_centimeters = _centimeters;  
81
  getPressure(&tmp_Pa);    // calc pressure based on current altitude
82
  _param_datum = tmp_Pa;
83
}
84
 
85
void BMP085::setAltOffset(int32_t _centimeters){
86
  _cm_Offset = _centimeters;
87
}
88
 
89
void BMP085::sethPaOffset(int32_t _Pa){
90
  _Pa_Offset = _Pa;
91
}
92
 
93
void BMP085::zeroCal(int32_t _Pa, int32_t _centimeters){
94
  setAltOffset(_centimeters - _param_centimeters);    
95
  sethPaOffset(_Pa - _param_datum);    
96
}
97
 
98
void BMP085::getPressure(int32_t *_Pa){  
99
  long TruePressure;
100
 
101
  calcTruePressure(&TruePressure);
102
  *_Pa = TruePressure / pow((1 - (float)_param_centimeters / 4433000), 5.255) + _Pa_Offset;
103
  // converting from float to int32_t truncates toward zero, 1010.999985 becomes 1010 resulting in 1 Pa error (max).  
104
  // Note that BMP085 abs accuracy from 700...1100hPa and 0..+65ºC is +-100Pa (typ.)
105
}
106
 
107
void BMP085::getAltitude(int32_t *_centimeters){
108
  long TruePressure;
109
 
110
  calcTruePressure(&TruePressure);
111
  *_centimeters =  4433000 * (1 - pow((TruePressure / (float)_param_datum), 0.1903)) + _cm_Offset;  
112
  // converting from float to int32_t truncates toward zero, 100.999985 becomes 100 resulting in 1 cm error (max).
113
}
114
 
115
void BMP085::getTemperature(int32_t *_Temperature) {
116
  calcTrueTemperature();                            // force b5 update
117
  *_Temperature = ((b5 + 8) >> 4);
118
}
119
 
120
void BMP085::calcTrueTemperature(){
121
  long ut,x1,x2;
122
 
123
  //read Raw Temperature
124
  writemem(CONTROL, READ_TEMPERATURE);
125
  delayMicroseconds(4500);                          // min. 4.5ms read Temp delay
126
  readmem(CONTROL_OUTPUT, 2, _buff);
127
  ut = ((long)_buff[0] << 8 | ((long)_buff[1]));    // uncompensated temperature value
128
 
129
  // calculate temperature
130
  x1 = ((long)ut - ac6) * ac5 >> 15;
131
  x2 = ((long)mc << 11) / (x1 + md);
132
  b5 = x1 + x2;
133
}
134
 
135
void BMP085::calcTruePressure(long *_TruePressure) {
136
  long up,x1,x2,x3,b3,b6,p;
137
  unsigned long b4,b7;
138
  int32_t tmp;
139
 
140
  #if AUTO_UPDATE_TEMPERATURE
141
  calcTrueTemperature();        // b5 update 
142
  #endif 
143
 
144
 //read Raw Pressure
145
  writemem(CONTROL, READ_PRESSURE+(_oss << 6));
146
  delay(_pressure_waittime[_oss]);    
147
  readmem(CONTROL_OUTPUT, 3, _buff);  
148
  up = ((((long)_buff[0] <<16) | ((long)_buff[1] <<8) | ((long)_buff[2])) >> (8-_oss)); // uncompensated pressure value
149
 
150
  // calculate true pressure
151
  b6 = b5 - 4000;             // b5 is updated by calcTrueTemperature().
152
  x1 = (b2* (b6 * b6 >> 12)) >> 11;
153
  x2 = ac2 * b6 >> 11;
154
  x3 = x1 + x2;
155
  tmp = ac1;
156
  tmp = (tmp * 4 + x3) << _oss;
157
  b3 = (tmp + 2) >> 2;
158
  x1 = ac3 * b6 >> 13;
159
  x2 = (b1 * (b6 * b6 >> 12)) >> 16;
160
  x3 = ((x1 + x2) + 2) >> 2;
161
  b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
162
  b7 = ((uint32_t)up - b3) * (50000 >> _oss);
163
  p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1;
164
  x1 = (p >> 8) * (p >> 8);
165
  x1 = (x1 * 3038) >> 16;
166
  x2 = (-7357 * p) >> 16;
167
  *_TruePressure = p + ((x1 + x2 + 3791) >> 4);
168
}
169
 
170
void BMP085::dumpCalData() {
171
  Serial.println("---cal data start---");
172
  Serial.print("ac1:");
173
  Serial.println(ac1,DEC);
174
  Serial.print("ac2:");
175
  Serial.println(ac2,DEC);
176
  Serial.print("ac3:");
177
  Serial.println(ac3,DEC);
178
  Serial.print("ac4:");
179
  Serial.println(ac4,DEC);
180
  Serial.print("ac5:");
181
  Serial.println(ac5,DEC);
182
  Serial.print("ac6:");
183
  Serial.println(ac6,DEC);
184
  Serial.print("b1:");
185
  Serial.println(b1,DEC);
186
  Serial.print("b2:");
187
  Serial.println(b2,DEC);
188
  Serial.print("mb:");
189
  Serial.println(mb,DEC);
190
  Serial.print("mc:");
191
  Serial.println(mc,DEC);
192
  Serial.print("md:");
193
  Serial.println(md,DEC);
194
  Serial.println("---cal data end---");
195
}
196
 
197
//PRIVATE methods
198
 
199
void BMP085::getCalData() {
200
  readmem(CAL_AC1, 2, _buff);
201
  ac1 = ((int)_buff[0] <<8 | ((int)_buff[1]));
202
  readmem(CAL_AC2, 2, _buff);
203
  ac2 = ((int)_buff[0] <<8 | ((int)_buff[1]));
204
  readmem(CAL_AC3, 2, _buff);
205
  ac3 = ((int)_buff[0] <<8 | ((int)_buff[1]));
206
  readmem(CAL_AC4, 2, _buff);
207
  ac4 = ((unsigned int)_buff[0] <<8 | ((unsigned int)_buff[1]));
208
  readmem(CAL_AC5, 2, _buff);
209
  ac5 = ((unsigned int)_buff[0] <<8 | ((unsigned int)_buff[1]));
210
  readmem(CAL_AC6, 2, _buff);
211
  ac6 = ((unsigned int)_buff[0] <<8 | ((unsigned int)_buff[1]));
212
  readmem(CAL_B1, 2, _buff);
213
  b1 = ((int)_buff[0] <<8 | ((int)_buff[1]));
214
  readmem(CAL_B2, 2, _buff);
215
  b2 = ((int)_buff[0] <<8 | ((int)_buff[1]));
216
  readmem(CAL_MB, 2, _buff);
217
  mb = ((int)_buff[0] <<8 | ((int)_buff[1]));
218
  readmem(CAL_MC, 2, _buff);
219
  mc = ((int)_buff[0] <<8 | ((int)_buff[1]));
220
  readmem(CAL_MD, 2, _buff);
221
  md = ((int)_buff[0] <<8 | ((int)_buff[1]));
222
}
223
 
224
 
225
void BMP085::writemem(uint8_t _addr, uint8_t _val) {
226
  Wire.beginTransmission(_dev_address);   // start transmission to device 
227
  Wire.send(_addr); // send register address
228
  Wire.send(_val); // send value to write
229
  Wire.endTransmission(); // end transmission
230
}
231
 
232
void BMP085::readmem(uint8_t _addr, uint8_t _nbytes, uint8_t __buff[]) {
233
  Wire.beginTransmission(_dev_address); // start transmission to device 
234
  Wire.send(_addr); // sends register address to read from
235
  Wire.endTransmission(); // end transmission
236
 
237
  Wire.beginTransmission(_dev_address); // start transmission to device 
238
  Wire.requestFrom(_dev_address, _nbytes);// send data n-bytes read
239
  uint8_t i = 0;
240
  while (Wire.available()) {
241
    __buff[i] = Wire.receive(); // receive DATA
242
    i++;
243
  }
244
  Wire.endTransmission(); // end transmission
245
}
246
 
247