Adafruit_BMP085.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*!
  2. * @file Adafruit_BMP085.cpp
  3. *
  4. * @mainpage Adafruit BMP085 Library
  5. *
  6. * @section intro_sec Introduction
  7. *
  8. * This is a library for the Adafruit BMP085/BMP180 Barometric Pressure + Temp
  9. * sensor
  10. *
  11. * Designed specifically to work with the Adafruit BMP085 or BMP180 Breakout
  12. * ----> http://www.adafruit.com/products/391
  13. * ----> http://www.adafruit.com/products/1603
  14. *
  15. * These displays use I2C to communicate, 2 pins are required to
  16. * interface
  17. * Adafruit invests time and resources providing this open source code,
  18. * please support Adafruit and open-source hardware by purchasing
  19. * products from Adafruit!
  20. *
  21. * @section author Author
  22. *
  23. * Written by Limor Fried/Ladyada for Adafruit Industries.
  24. * Updated by Samy Kamkar for cross-platform support.
  25. *
  26. * @section license License
  27. *
  28. * BSD license, all text above must be included in any redistribution
  29. */
  30. #include "Adafruit_BMP085.h"
  31. #include <Adafruit_I2CDevice.h>
  32. Adafruit_BMP085::Adafruit_BMP085() { i2c_dev = nullptr; }
  33. bool Adafruit_BMP085::begin(uint8_t mode, TwoWire *wire) {
  34. if (mode > BMP085_ULTRAHIGHRES)
  35. mode = BMP085_ULTRAHIGHRES;
  36. oversampling = mode;
  37. if (i2c_dev) {
  38. delete i2c_dev; // remove old interface
  39. }
  40. i2c_dev = new Adafruit_I2CDevice(BMP085_I2CADDR, wire);
  41. if (!i2c_dev->begin()) {
  42. return false;
  43. }
  44. if (read8(0xD0) != 0x55)
  45. return false;
  46. /* read calibration data */
  47. ac1 = read16(BMP085_CAL_AC1);
  48. ac2 = read16(BMP085_CAL_AC2);
  49. ac3 = read16(BMP085_CAL_AC3);
  50. ac4 = read16(BMP085_CAL_AC4);
  51. ac5 = read16(BMP085_CAL_AC5);
  52. ac6 = read16(BMP085_CAL_AC6);
  53. b1 = read16(BMP085_CAL_B1);
  54. b2 = read16(BMP085_CAL_B2);
  55. mb = read16(BMP085_CAL_MB);
  56. mc = read16(BMP085_CAL_MC);
  57. md = read16(BMP085_CAL_MD);
  58. #if (BMP085_DEBUG == 1)
  59. Serial.print("ac1 = ");
  60. Serial.println(ac1, DEC);
  61. Serial.print("ac2 = ");
  62. Serial.println(ac2, DEC);
  63. Serial.print("ac3 = ");
  64. Serial.println(ac3, DEC);
  65. Serial.print("ac4 = ");
  66. Serial.println(ac4, DEC);
  67. Serial.print("ac5 = ");
  68. Serial.println(ac5, DEC);
  69. Serial.print("ac6 = ");
  70. Serial.println(ac6, DEC);
  71. Serial.print("b1 = ");
  72. Serial.println(b1, DEC);
  73. Serial.print("b2 = ");
  74. Serial.println(b2, DEC);
  75. Serial.print("mb = ");
  76. Serial.println(mb, DEC);
  77. Serial.print("mc = ");
  78. Serial.println(mc, DEC);
  79. Serial.print("md = ");
  80. Serial.println(md, DEC);
  81. #endif
  82. return true;
  83. }
  84. int32_t Adafruit_BMP085::computeB5(int32_t UT) {
  85. int32_t X1 = (UT - (int32_t)ac6) * ((int32_t)ac5) >> 15;
  86. int32_t X2 = ((int32_t)mc << 11) / (X1 + (int32_t)md);
  87. return X1 + X2;
  88. }
  89. uint16_t Adafruit_BMP085::readRawTemperature(void) {
  90. write8(BMP085_CONTROL, BMP085_READTEMPCMD);
  91. delay(5);
  92. #if BMP085_DEBUG == 1
  93. Serial.print("Raw temp: ");
  94. Serial.println(read16(BMP085_TEMPDATA));
  95. #endif
  96. return read16(BMP085_TEMPDATA);
  97. }
  98. uint32_t Adafruit_BMP085::readRawPressure(void) {
  99. uint32_t raw;
  100. write8(BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6));
  101. if (oversampling == BMP085_ULTRALOWPOWER)
  102. delay(5);
  103. else if (oversampling == BMP085_STANDARD)
  104. delay(8);
  105. else if (oversampling == BMP085_HIGHRES)
  106. delay(14);
  107. else
  108. delay(26);
  109. raw = read16(BMP085_PRESSUREDATA);
  110. raw <<= 8;
  111. raw |= read8(BMP085_PRESSUREDATA + 2);
  112. raw >>= (8 - oversampling);
  113. /* this pull broke stuff, look at it later?
  114. if (oversampling==0) {
  115. raw <<= 8;
  116. raw |= read8(BMP085_PRESSUREDATA+2);
  117. raw >>= (8 - oversampling);
  118. }
  119. */
  120. #if BMP085_DEBUG == 1
  121. Serial.print("Raw pressure: ");
  122. Serial.println(raw);
  123. #endif
  124. return raw;
  125. }
  126. int32_t Adafruit_BMP085::readPressure(void) {
  127. int32_t UT, UP, B3, B5, B6, X1, X2, X3, p;
  128. uint32_t B4, B7;
  129. UT = readRawTemperature();
  130. UP = readRawPressure();
  131. #if BMP085_DEBUG == 1
  132. // use datasheet numbers!
  133. UT = 27898;
  134. UP = 23843;
  135. ac6 = 23153;
  136. ac5 = 32757;
  137. mc = -8711;
  138. md = 2868;
  139. b1 = 6190;
  140. b2 = 4;
  141. ac3 = -14383;
  142. ac2 = -72;
  143. ac1 = 408;
  144. ac4 = 32741;
  145. oversampling = 0;
  146. #endif
  147. B5 = computeB5(UT);
  148. #if BMP085_DEBUG == 1
  149. Serial.print("X1 = ");
  150. Serial.println(X1);
  151. Serial.print("X2 = ");
  152. Serial.println(X2);
  153. Serial.print("B5 = ");
  154. Serial.println(B5);
  155. #endif
  156. // do pressure calcs
  157. B6 = B5 - 4000;
  158. X1 = ((int32_t)b2 * ((B6 * B6) >> 12)) >> 11;
  159. X2 = ((int32_t)ac2 * B6) >> 11;
  160. X3 = X1 + X2;
  161. B3 = ((((int32_t)ac1 * 4 + X3) << oversampling) + 2) / 4;
  162. #if BMP085_DEBUG == 1
  163. Serial.print("B6 = ");
  164. Serial.println(B6);
  165. Serial.print("X1 = ");
  166. Serial.println(X1);
  167. Serial.print("X2 = ");
  168. Serial.println(X2);
  169. Serial.print("B3 = ");
  170. Serial.println(B3);
  171. #endif
  172. X1 = ((int32_t)ac3 * B6) >> 13;
  173. X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16;
  174. X3 = ((X1 + X2) + 2) >> 2;
  175. B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15;
  176. B7 = ((uint32_t)UP - B3) * (uint32_t)(50000UL >> oversampling);
  177. #if BMP085_DEBUG == 1
  178. Serial.print("X1 = ");
  179. Serial.println(X1);
  180. Serial.print("X2 = ");
  181. Serial.println(X2);
  182. Serial.print("B4 = ");
  183. Serial.println(B4);
  184. Serial.print("B7 = ");
  185. Serial.println(B7);
  186. #endif
  187. if (B7 < 0x80000000) {
  188. p = (B7 * 2) / B4;
  189. } else {
  190. p = (B7 / B4) * 2;
  191. }
  192. X1 = (p >> 8) * (p >> 8);
  193. X1 = (X1 * 3038) >> 16;
  194. X2 = (-7357 * p) >> 16;
  195. #if BMP085_DEBUG == 1
  196. Serial.print("p = ");
  197. Serial.println(p);
  198. Serial.print("X1 = ");
  199. Serial.println(X1);
  200. Serial.print("X2 = ");
  201. Serial.println(X2);
  202. #endif
  203. p = p + ((X1 + X2 + (int32_t)3791) >> 4);
  204. #if BMP085_DEBUG == 1
  205. Serial.print("p = ");
  206. Serial.println(p);
  207. #endif
  208. return p;
  209. }
  210. int32_t Adafruit_BMP085::readSealevelPressure(float altitude_meters) {
  211. float pressure = readPressure();
  212. return (int32_t)(pressure / pow(1.0 - altitude_meters / 44330, 5.255));
  213. }
  214. float Adafruit_BMP085::readTemperature(void) {
  215. int32_t UT, B5; // following ds convention
  216. float temp;
  217. UT = readRawTemperature();
  218. #if BMP085_DEBUG == 1
  219. // use datasheet numbers!
  220. UT = 27898;
  221. ac6 = 23153;
  222. ac5 = 32757;
  223. mc = -8711;
  224. md = 2868;
  225. #endif
  226. B5 = computeB5(UT);
  227. temp = (B5 + 8) >> 4;
  228. temp /= 10;
  229. return temp;
  230. }
  231. float Adafruit_BMP085::readAltitude(float sealevelPressure) {
  232. float altitude;
  233. float pressure = readPressure();
  234. altitude = 44330 * (1.0 - pow(pressure / sealevelPressure, 0.1903));
  235. return altitude;
  236. }
  237. /*********************************************************************/
  238. uint8_t Adafruit_BMP085::read8(uint8_t a) {
  239. uint8_t ret;
  240. // send 1 byte, reset i2c, read 1 byte
  241. i2c_dev->write_then_read(&a, 1, &ret, 1, true);
  242. return ret;
  243. }
  244. uint16_t Adafruit_BMP085::read16(uint8_t a) {
  245. uint8_t retbuf[2];
  246. uint16_t ret;
  247. // send 1 byte, reset i2c, read 2 bytes
  248. // we could typecast uint16_t as uint8_t array but would need to ensure proper
  249. // endianness
  250. i2c_dev->write_then_read(&a, 1, retbuf, 2, true);
  251. // write_then_read uses uint8_t array
  252. ret = retbuf[1] | (retbuf[0] << 8);
  253. return ret;
  254. }
  255. void Adafruit_BMP085::write8(uint8_t a, uint8_t d) {
  256. // send d prefixed with a (a d [stop])
  257. i2c_dev->write(&d, 1, true, &a, 1);
  258. }