Adafruit_MPL3115A2.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*!
  2. * @file Adafruit_MPL3115A2.cpp
  3. *
  4. * @mainpage Adafruit MPL3115A2 alitmeter
  5. *
  6. * @section intro_sec Introduction
  7. *
  8. * This is the documentation for Adafruit's MPL3115A2 driver for the
  9. * Arduino platform. It is designed specifically to work with the
  10. * Adafruit MPL3115A2 breakout: https://www.adafruit.com/products/1893
  11. *
  12. * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
  13. * to interface with the breakout.
  14. *
  15. * Adafruit invests time and resources providing this open source code,
  16. * please support Adafruit and open-source hardware by purchasing
  17. * products from Adafruit!
  18. *
  19. * @section dependencies Dependencies
  20. *
  21. * @section author Author
  22. *
  23. * Written by Kevin "KTOWN" Townsend for Adafruit Industries.
  24. *
  25. * @section license License
  26. *
  27. * BSD license, all text here must be included in any redistribution.
  28. *
  29. */
  30. #include "Adafruit_MPL3115A2.h"
  31. /*!
  32. @brief Instantiates a new MPL3115A2 class
  33. */
  34. Adafruit_MPL3115A2::Adafruit_MPL3115A2() {}
  35. /*!
  36. * @brief Setups the HW (reads coefficients values, etc.)
  37. * @param twoWire
  38. * Optional TwoWire I2C object
  39. * @return true on successful startup, false otherwise
  40. */
  41. boolean Adafruit_MPL3115A2::begin(TwoWire *twoWire) {
  42. if (i2c_dev)
  43. delete i2c_dev;
  44. i2c_dev = new Adafruit_I2CDevice(MPL3115A2_ADDRESS, twoWire);
  45. if (!i2c_dev->begin())
  46. return false;
  47. // sanity check
  48. uint8_t whoami = read8(MPL3115A2_WHOAMI);
  49. if (whoami != 0xC4) {
  50. return false;
  51. }
  52. // software reset
  53. write8(MPL3115A2_CTRL_REG1, MPL3115A2_CTRL_REG1_RST);
  54. while (read8(MPL3115A2_CTRL_REG1) & MPL3115A2_CTRL_REG1_RST)
  55. delay(10);
  56. // set oversampling and altitude mode
  57. currentMode = MPL3115A2_ALTIMETER;
  58. _ctrl_reg1.reg = MPL3115A2_CTRL_REG1_OS128 | MPL3115A2_CTRL_REG1_ALT;
  59. write8(MPL3115A2_CTRL_REG1, _ctrl_reg1.reg);
  60. // enable data ready events for pressure/altitude and temperature
  61. write8(MPL3115A2_PT_DATA_CFG, MPL3115A2_PT_DATA_CFG_TDEFE |
  62. MPL3115A2_PT_DATA_CFG_PDEFE |
  63. MPL3115A2_PT_DATA_CFG_DREM);
  64. return true;
  65. }
  66. /*!
  67. * @brief Get barometric pressure
  68. * @return pressure reading as a floating point value in hPa
  69. */
  70. float Adafruit_MPL3115A2::getPressure() {
  71. if (currentMode != MPL3115A2_BAROMETER)
  72. setMode(MPL3115A2_BAROMETER);
  73. startOneShot();
  74. while (!conversionComplete())
  75. delay(10);
  76. return getLastConversionResults(MPL3115A2_PRESSURE);
  77. }
  78. /*!
  79. * @brief Get altitude
  80. * @return altitude reading as a floating-point value in meters
  81. */
  82. float Adafruit_MPL3115A2::getAltitude() {
  83. if (currentMode != MPL3115A2_ALTIMETER)
  84. setMode(MPL3115A2_ALTIMETER);
  85. startOneShot();
  86. while (!conversionComplete())
  87. delay(10);
  88. return getLastConversionResults(MPL3115A2_ALTITUDE);
  89. }
  90. /*!
  91. * @brief Get the altitude offset
  92. * @return Offset value in meters
  93. */
  94. int8_t Adafruit_MPL3115A2::getAltitudeOffset(void) {
  95. return int8_t(read8(MPL3115A2_OFF_H));
  96. }
  97. /*!
  98. * @brief Set the altitude offset
  99. * @param offset Offset value in meters, from -127 to 128
  100. */
  101. void Adafruit_MPL3115A2::setAltitudeOffset(int8_t offset) {
  102. write8(MPL3115A2_OFF_H, uint8_t(offset));
  103. }
  104. /*!
  105. * @brief Set the local sea level pressure
  106. * @param SLP sea level pressure in hPa
  107. */
  108. void Adafruit_MPL3115A2::setSeaPressure(float SLP) {
  109. // multiply by 100 to convert hPa to Pa
  110. // divide by 2 to convert to 2 Pa per LSB
  111. // convert to integer
  112. uint16_t bar = SLP * 50;
  113. // write result to register
  114. uint8_t buffer[3];
  115. buffer[0] = MPL3115A2_BAR_IN_MSB;
  116. buffer[1] = bar >> 8;
  117. buffer[2] = bar & 0xFF;
  118. i2c_dev->write(buffer, 3);
  119. }
  120. /*!
  121. * @brief Get temperature
  122. * @return temperature reading as a floating-point value in degC
  123. */
  124. float Adafruit_MPL3115A2::getTemperature() {
  125. startOneShot();
  126. while (!conversionComplete())
  127. delay(10);
  128. return getLastConversionResults(MPL3115A2_TEMPERATURE);
  129. }
  130. /*!
  131. * @brief Set measurement mode.
  132. * @param mode The measurement mode. Can be MPL3115A2_BAROMETER or
  133. * MPL3115A2_ALTIMETER.
  134. */
  135. void Adafruit_MPL3115A2::setMode(mpl3115a2_mode_t mode) {
  136. // assumes STANDBY mode
  137. _ctrl_reg1.reg = read8(MPL3115A2_CTRL_REG1);
  138. _ctrl_reg1.bit.ALT = mode;
  139. write8(MPL3115A2_CTRL_REG1, _ctrl_reg1.reg);
  140. currentMode = mode;
  141. }
  142. /*!
  143. * @brief Initiate a one-shot measurement.
  144. */
  145. void Adafruit_MPL3115A2::startOneShot(void) {
  146. // wait for one-shot to clear before proceeding
  147. _ctrl_reg1.reg = read8(MPL3115A2_CTRL_REG1);
  148. while (_ctrl_reg1.bit.OST) {
  149. delay(10);
  150. _ctrl_reg1.reg = read8(MPL3115A2_CTRL_REG1);
  151. }
  152. // initiate one-shot measurement
  153. _ctrl_reg1.bit.OST = 1;
  154. write8(MPL3115A2_CTRL_REG1, _ctrl_reg1.reg);
  155. }
  156. /*!
  157. * @brief Check for measurement conversion completion.
  158. * @return true if conversion is complete, otherwise false.
  159. */
  160. bool Adafruit_MPL3115A2::conversionComplete(void) {
  161. // PTDR bit works for either pressure or temperature
  162. // 0: No new set of data ready
  163. // 1: A new set of data is ready
  164. return ((read8(MPL3115A2_REGISTER_STATUS) & MPL3115A2_REGISTER_STATUS_PTDR) !=
  165. 0);
  166. }
  167. /*!
  168. * @brief Get results from last measurement.
  169. * @param value Measurement value, can be MPL3115A2_PRESSURE,
  170. * MPL3115A2_ALTITUDE, or MPL3115A2_TEMPERATURE
  171. * @return The measurement value.
  172. */
  173. float Adafruit_MPL3115A2::getLastConversionResults(mpl3115a2_meas_t value) {
  174. uint8_t buffer[5] = {MPL3115A2_REGISTER_PRESSURE_MSB, 0, 0, 0, 0};
  175. i2c_dev->write_then_read(buffer, 1, buffer, 5);
  176. switch (value) {
  177. case MPL3115A2_PRESSURE:
  178. uint32_t pressure;
  179. pressure = uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8 |
  180. uint32_t(buffer[2]);
  181. return float(pressure) / 6400.0;
  182. case MPL3115A2_ALTITUDE:
  183. int32_t alt;
  184. alt = uint32_t(buffer[0]) << 24 | uint32_t(buffer[1]) << 16 |
  185. uint32_t(buffer[2]) << 8;
  186. return float(alt) / 65536.0;
  187. case MPL3115A2_TEMPERATURE:
  188. default:
  189. int16_t t;
  190. t = uint16_t(buffer[3]) << 8 | uint16_t(buffer[4]);
  191. return float(t) / 256.0;
  192. }
  193. }
  194. /*!
  195. * @brief read 1 byte of data at the specified address
  196. * @param a
  197. * the address to read
  198. * @return the read data byte
  199. */
  200. uint8_t Adafruit_MPL3115A2::read8(uint8_t a) {
  201. uint8_t buffer[1] = {a};
  202. i2c_dev->write_then_read(buffer, 1, buffer, 1);
  203. return buffer[0];
  204. }
  205. /*!
  206. * @brief write a byte of data to the specified address
  207. * @param a
  208. * the address to write to
  209. * @param d
  210. * the byte to write
  211. */
  212. void Adafruit_MPL3115A2::write8(uint8_t a, uint8_t d) {
  213. uint8_t buffer[2] = {a, d};
  214. i2c_dev->write(buffer, 2);
  215. }