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 |