Adafruit_MPRLS.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*!
  2. * @file Adafruit_MPRLS.cpp
  3. *
  4. * @mainpage Adafruit MPRLS Pressure sensor
  5. *
  6. * @section intro_sec Introduction
  7. *
  8. * Designed specifically to work with the MPRLS sensor from Adafruit
  9. * ----> https://www.adafruit.com/products/3965
  10. *
  11. * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
  12. * to interface with the breakout.
  13. *
  14. * Adafruit invests time and resources providing this open source code,
  15. * please support Adafruit and open-source hardware by purchasing
  16. * products from Adafruit!
  17. *
  18. * @section dependencies Dependencies
  19. *
  20. *
  21. * @section author Author
  22. *
  23. * Written by Limor Fried/Ladyada for Adafruit Industries.
  24. *
  25. * @section license License
  26. *
  27. * MIT license, all text here must be included in any redistribution.
  28. *
  29. * @section changes Changes
  30. *
  31. * Changes by arkhipenko (https://github.com/arkhipenko) (December 2020)
  32. * Overall, with all the defaults this should be 99% backwards compatible and
  33. * could be a drop-in replacement. The 1% difference is that the library can now
  34. * return NAN due to a timeout
  35. * - added parameters to constructor to support different transfer function
  36. * curves and a factor for conversion to desired units
  37. * - PSI_min and PSI_max are 16 bit unsigned to support values > 255
  38. * - readPressure(void) method calculates based on the provided curve values,
  39. * and converts to desired units
  40. * - readData(void) method may return NAN in case of timeout (20 millis
  41. * currently - could be changed)
  42. * - public variable lastStatus could be accessed to check the error bits in
  43. * case of a NAN value
  44. * - begin() method updates lastStatus, so in case of a failure, the reason
  45. * could be checked explicitly success is "true" if status ==
  46. * MPRLS_STATUS_POWERED and no other bits are set
  47. */
  48. #if (ARDUINO >= 100)
  49. #include "Arduino.h"
  50. #else
  51. #include "WProgram.h"
  52. #endif
  53. #include "Adafruit_MPRLS.h"
  54. /**************************************************************************/
  55. /*!
  56. @brief constructor initializes default configuration value
  57. @param reset_pin Optional hardware reset pin, default set to -1 to skip
  58. @param EOC_pin Optional End-of-Convert indication pin, default set to -1 to
  59. skip
  60. @param PSI_min The minimum PSI measurement range of the sensor, default 0
  61. @param PSI_max The maximum PSI measurement range of the sensor, default 25
  62. @param OUTPUT_min The minimum transfer function curve value in %, default
  63. 10%
  64. @param OUTPUT_max The maximum transfer function curve value in %, default
  65. 90%
  66. @param K Conversion Factor to desired units, default is PSI to HPA
  67. */
  68. /**************************************************************************/
  69. Adafruit_MPRLS::Adafruit_MPRLS(int8_t reset_pin, int8_t EOC_pin,
  70. uint16_t PSI_min, uint16_t PSI_max,
  71. float OUTPUT_min, float OUTPUT_max, float K) {
  72. _reset = reset_pin;
  73. _eoc = EOC_pin;
  74. _PSI_min = PSI_min;
  75. _PSI_max = PSI_max;
  76. _OUTPUT_min = (uint32_t)((float)COUNTS_224 * (OUTPUT_min / 100.0) + 0.5);
  77. _OUTPUT_max = (uint32_t)((float)COUNTS_224 * (OUTPUT_max / 100.0) + 0.5);
  78. _K = K;
  79. }
  80. /**************************************************************************/
  81. /*!
  82. @brief setup and initialize communication with the hardware
  83. @param i2c_addr The I2C address for the sensor (default is 0x18)
  84. @param twoWire Optional pointer to the desired TwoWire I2C object. Defaults
  85. to &Wire
  86. @returns True on success, False if sensor not found
  87. */
  88. /**************************************************************************/
  89. boolean Adafruit_MPRLS::begin(uint8_t i2c_addr, TwoWire *twoWire) {
  90. if (i2c_dev)
  91. delete i2c_dev;
  92. i2c_dev = new Adafruit_I2CDevice(i2c_addr, twoWire);
  93. if (!i2c_dev->begin())
  94. return false;
  95. if (_reset != -1) {
  96. pinMode(_reset, OUTPUT);
  97. digitalWrite(_reset, HIGH);
  98. digitalWrite(_reset, LOW);
  99. delay(10);
  100. digitalWrite(_reset, HIGH);
  101. }
  102. if (_eoc != -1) {
  103. pinMode(_eoc, INPUT);
  104. }
  105. delay(10); // startup timing
  106. // Serial.print("Status: ");
  107. // Serial.println(stat);
  108. return ((readStatus() & MPRLS_STATUS_MASK) == MPRLS_STATUS_POWERED);
  109. }
  110. /**************************************************************************/
  111. /*!
  112. @brief Read and calculate the pressure
  113. @returns The measured pressure, in hPa on success, NAN on failure
  114. */
  115. /**************************************************************************/
  116. float Adafruit_MPRLS::readPressure(void) {
  117. uint32_t raw_psi = readData();
  118. if (raw_psi == 0xFFFFFFFF || _OUTPUT_min == _OUTPUT_max) {
  119. return NAN;
  120. }
  121. // All is good, calculate and convert to desired units using provided factor
  122. // use the 10-90 calibration curve by default or whatever provided by the user
  123. float psi = (raw_psi - _OUTPUT_min) * (_PSI_max - _PSI_min);
  124. psi /= (float)(_OUTPUT_max - _OUTPUT_min);
  125. psi += _PSI_min;
  126. // convert to desired units
  127. return psi * _K;
  128. }
  129. /**************************************************************************/
  130. /*!
  131. @brief Read 24 bits of measurement data from the device
  132. @returns -1 on failure (check status) or 24 bits of raw ADC reading
  133. */
  134. /**************************************************************************/
  135. uint32_t Adafruit_MPRLS::readData(void) {
  136. uint8_t buffer[4] = {0xAA, 0, 0, 0};
  137. // Request data
  138. i2c_dev->write(buffer, 3);
  139. // Use the gpio to tell end of conversion
  140. uint32_t t = millis();
  141. if (_eoc != -1) {
  142. while (!digitalRead(_eoc)) {
  143. if (millis() - t > MPRLS_READ_TIMEOUT)
  144. return 0xFFFFFFFF; // timeout
  145. }
  146. } else {
  147. // check the status byte
  148. // uint8_t stat;
  149. while ((lastStatus = readStatus()) & MPRLS_STATUS_BUSY) {
  150. // Serial.print("Status: "); Serial.println(stat, HEX);
  151. if (millis() - t > MPRLS_READ_TIMEOUT)
  152. return 0xFFFFFFFF; // timeout
  153. }
  154. }
  155. // Read status byte and data
  156. i2c_dev->read(buffer, 4);
  157. // check status byte
  158. if (buffer[0] & MPRLS_STATUS_MATHSAT) {
  159. return 0xFFFFFFFF;
  160. }
  161. if (buffer[0] & MPRLS_STATUS_FAILED) {
  162. return 0xFFFFFFFF;
  163. }
  164. // all good, return data
  165. return (uint32_t(buffer[1]) << 16) | (uint32_t(buffer[2]) << 8) |
  166. (uint32_t(buffer[3]));
  167. }
  168. /**************************************************************************/
  169. /*!
  170. @brief Read just the status byte, see datasheet for bit definitions
  171. @returns 8 bits of status data
  172. */
  173. /**************************************************************************/
  174. uint8_t Adafruit_MPRLS::readStatus(void) {
  175. uint8_t buffer[1];
  176. i2c_dev->read(buffer, 1);
  177. return buffer[0];
  178. }