Interface library for the Sensirion SHT7x series humidity and temperature sensors.

This was developed and tested on the LPC1768 board.

Currently, it doesn't work for LPC11U24. I'm investigating why.

Committer:
JacobBramley
Date:
Sun Aug 11 18:11:05 2013 +0000
Revision:
0:f1a93e55feb5
First Mbed release of the Sensirion SHT7x interface library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JacobBramley 0:f1a93e55feb5 1 // Copyright (c) 2012-2013 Jacob Bramley
JacobBramley 0:f1a93e55feb5 2 //
JacobBramley 0:f1a93e55feb5 3 // Permission is hereby granted, free of charge, to any person obtaining a copy
JacobBramley 0:f1a93e55feb5 4 // of this software and associated documentation files (the "Software"), to deal
JacobBramley 0:f1a93e55feb5 5 // in the Software without restriction, including without limitation the rights
JacobBramley 0:f1a93e55feb5 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
JacobBramley 0:f1a93e55feb5 7 // copies of the Software, and to permit persons to whom the Software is
JacobBramley 0:f1a93e55feb5 8 // furnished to do so, subject to the following conditions:
JacobBramley 0:f1a93e55feb5 9 //
JacobBramley 0:f1a93e55feb5 10 // The above copyright notice and this permission notice shall be included in
JacobBramley 0:f1a93e55feb5 11 // all copies or substantial portions of the Software.
JacobBramley 0:f1a93e55feb5 12 //
JacobBramley 0:f1a93e55feb5 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
JacobBramley 0:f1a93e55feb5 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
JacobBramley 0:f1a93e55feb5 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
JacobBramley 0:f1a93e55feb5 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
JacobBramley 0:f1a93e55feb5 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
JacobBramley 0:f1a93e55feb5 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
JacobBramley 0:f1a93e55feb5 19 // SOFTWARE.
JacobBramley 0:f1a93e55feb5 20
JacobBramley 0:f1a93e55feb5 21 #include <stdint.h>
JacobBramley 0:f1a93e55feb5 22 #include "mbed.h"
JacobBramley 0:f1a93e55feb5 23
JacobBramley 0:f1a93e55feb5 24 #ifndef SHT7X_SHT7X_H
JacobBramley 0:f1a93e55feb5 25 #define SHT7X_SHT7X_H
JacobBramley 0:f1a93e55feb5 26
JacobBramley 0:f1a93e55feb5 27 namespace sht7x {
JacobBramley 0:f1a93e55feb5 28
JacobBramley 0:f1a93e55feb5 29 //! The Reading class holds a generic reading.
JacobBramley 0:f1a93e55feb5 30 //!
JacobBramley 0:f1a93e55feb5 31 //! This class is used by the Temp and Hum classes, and cannot be instantiated
JacobBramley 0:f1a93e55feb5 32 //! by itself.
JacobBramley 0:f1a93e55feb5 33 class Reading {
JacobBramley 0:f1a93e55feb5 34 public:
JacobBramley 0:f1a93e55feb5 35 //! Return the raw reading value.
JacobBramley 0:f1a93e55feb5 36 //!
JacobBramley 0:f1a93e55feb5 37 //! Only the low-order bits are relevant. Use get_bits() to determine how many
JacobBramley 0:f1a93e55feb5 38 //! bits are part of the reading.
JacobBramley 0:f1a93e55feb5 39 inline uint32_t get_raw() const {
JacobBramley 0:f1a93e55feb5 40 return (is_valid()) ? reading : 0;
JacobBramley 0:f1a93e55feb5 41 }
JacobBramley 0:f1a93e55feb5 42
JacobBramley 0:f1a93e55feb5 43 //! Return the number of bits in the reading.
JacobBramley 0:f1a93e55feb5 44 inline uint32_t get_bits() const {
JacobBramley 0:f1a93e55feb5 45 return bits;
JacobBramley 0:f1a93e55feb5 46 }
JacobBramley 0:f1a93e55feb5 47
JacobBramley 0:f1a93e55feb5 48 //! Check the validity of the reading.
JacobBramley 0:f1a93e55feb5 49 //!
JacobBramley 0:f1a93e55feb5 50 //! Only the default constructor produces an invalid reading, so this can be
JacobBramley 0:f1a93e55feb5 51 //! used to determine whether or not a reading was taken.
JacobBramley 0:f1a93e55feb5 52 inline bool is_valid() const {
JacobBramley 0:f1a93e55feb5 53 return (bits > 0);
JacobBramley 0:f1a93e55feb5 54 }
JacobBramley 0:f1a93e55feb5 55
JacobBramley 0:f1a93e55feb5 56 protected:
JacobBramley 0:f1a93e55feb5 57 Reading(uint32_t bits, uint32_t reading)
JacobBramley 0:f1a93e55feb5 58 : bits(bits), reading(reading) {}
JacobBramley 0:f1a93e55feb5 59
JacobBramley 0:f1a93e55feb5 60 // The default constructor creates an invalid reading.
JacobBramley 0:f1a93e55feb5 61 Reading() : bits(0) {}
JacobBramley 0:f1a93e55feb5 62
JacobBramley 0:f1a93e55feb5 63 private:
JacobBramley 0:f1a93e55feb5 64 uint32_t bits;
JacobBramley 0:f1a93e55feb5 65 uint32_t reading;
JacobBramley 0:f1a93e55feb5 66 };
JacobBramley 0:f1a93e55feb5 67
JacobBramley 0:f1a93e55feb5 68 //! The Temp class holds a temperature reading.
JacobBramley 0:f1a93e55feb5 69 class Temp : public Reading {
JacobBramley 0:f1a93e55feb5 70 public:
JacobBramley 0:f1a93e55feb5 71 //! Initialize a Temp object with a raw reading.
JacobBramley 0:f1a93e55feb5 72 //!
JacobBramley 0:f1a93e55feb5 73 //! @param bits
JacobBramley 0:f1a93e55feb5 74 //! The number of significant bits in the reading.
JacobBramley 0:f1a93e55feb5 75 //!
JacobBramley 0:f1a93e55feb5 76 //! @param reading
JacobBramley 0:f1a93e55feb5 77 //! The raw reading taken from the SHT7x.
JacobBramley 0:f1a93e55feb5 78 //!
JacobBramley 0:f1a93e55feb5 79 //! @param mvdd
JacobBramley 0:f1a93e55feb5 80 //! The supply voltage.
JacobBramley 0:f1a93e55feb5 81 //!
JacobBramley 0:f1a93e55feb5 82 //! The coefficients used for the temperature calculation depend upon the
JacobBramley 0:f1a93e55feb5 83 //! supply voltage to the sensor. Specifying this voltage allows for the
JacobBramley 0:f1a93e55feb5 84 //! reading to be adjusted. The adjustment is applied to all of the get_*()
JacobBramley 0:f1a93e55feb5 85 //! methods except get_raw().
JacobBramley 0:f1a93e55feb5 86 Temp(uint32_t bits, uint32_t reading, uint32_t mvdd = mvdd_default)
JacobBramley 0:f1a93e55feb5 87 : Reading(bits, reading), mvdd(mvdd) {}
JacobBramley 0:f1a93e55feb5 88
JacobBramley 0:f1a93e55feb5 89 //! Initialize an empty object.
JacobBramley 0:f1a93e55feb5 90 //!
JacobBramley 0:f1a93e55feb5 91 //! The resulting object's is_valid() function will return false. It should
JacobBramley 0:f1a93e55feb5 92 //! be passed into SHT7x::measure() to get a valid reading.
JacobBramley 0:f1a93e55feb5 93 Temp() : Reading() {}
JacobBramley 0:f1a93e55feb5 94
JacobBramley 0:f1a93e55feb5 95 //! Return the reading (float).
JacobBramley 0:f1a93e55feb5 96 float get_f() const;
JacobBramley 0:f1a93e55feb5 97
JacobBramley 0:f1a93e55feb5 98 //! Return the reading as a 64-bit signed value with 32 fractional bits.
JacobBramley 0:f1a93e55feb5 99 //!
JacobBramley 0:f1a93e55feb5 100 //! The rounding mode is round-to-nearest, with ties away from zero.
JacobBramley 0:f1a93e55feb5 101 int64_t get_q32() const; // Fixed-point (q32)
JacobBramley 0:f1a93e55feb5 102
JacobBramley 0:f1a93e55feb5 103 //! Return the reading as a 32-bit signed value.
JacobBramley 0:f1a93e55feb5 104 //!
JacobBramley 0:f1a93e55feb5 105 //! @param fbits
JacobBramley 0:f1a93e55feb5 106 //! The number of fractional bits desired in the result.
JacobBramley 0:f1a93e55feb5 107 //!
JacobBramley 0:f1a93e55feb5 108 //! The rounding mode is round-to-nearest, with ties away from zero.
JacobBramley 0:f1a93e55feb5 109 int32_t get_fixed(int fbits) const; // Fixed-point (q0-q32)
JacobBramley 0:f1a93e55feb5 110
JacobBramley 0:f1a93e55feb5 111 //! Return the reading as an integer.
JacobBramley 0:f1a93e55feb5 112 //!
JacobBramley 0:f1a93e55feb5 113 //! The rounding mode is round-to-nearest, with ties away from zero.
JacobBramley 0:f1a93e55feb5 114 int32_t get_i() const { // Integer
JacobBramley 0:f1a93e55feb5 115 return get_fixed(0);
JacobBramley 0:f1a93e55feb5 116 }
JacobBramley 0:f1a93e55feb5 117
JacobBramley 0:f1a93e55feb5 118 //! Default supply voltage setting.
JacobBramley 0:f1a93e55feb5 119 //!
JacobBramley 0:f1a93e55feb5 120 //! This setting is the recommended supply voltage according to the
JacobBramley 0:f1a93e55feb5 121 //! datasheet.
JacobBramley 0:f1a93e55feb5 122 static uint32_t const mvdd_default = 3300;
JacobBramley 0:f1a93e55feb5 123
JacobBramley 0:f1a93e55feb5 124 private:
JacobBramley 0:f1a93e55feb5 125 uint32_t mvdd;
JacobBramley 0:f1a93e55feb5 126
JacobBramley 0:f1a93e55feb5 127 // The 'd1' coefficient used for the temperature calculation depend upon
JacobBramley 0:f1a93e55feb5 128 // the supply voltage to the sensor. These methods calculate and return the
JacobBramley 0:f1a93e55feb5 129 // proper coefficient, based on mvdd.
JacobBramley 0:f1a93e55feb5 130 float get_d1_f() const;
JacobBramley 0:f1a93e55feb5 131 int64_t get_d1_q32() const;
JacobBramley 0:f1a93e55feb5 132 };
JacobBramley 0:f1a93e55feb5 133
JacobBramley 0:f1a93e55feb5 134 //! The Hum class holds a humidity reading.
JacobBramley 0:f1a93e55feb5 135 class Hum : public Reading {
JacobBramley 0:f1a93e55feb5 136 public:
JacobBramley 0:f1a93e55feb5 137 //! Initialize a Hum object with a raw reading.
JacobBramley 0:f1a93e55feb5 138 //!
JacobBramley 0:f1a93e55feb5 139 //! @param bits
JacobBramley 0:f1a93e55feb5 140 //! The number of significant bits in the reading.
JacobBramley 0:f1a93e55feb5 141 //!
JacobBramley 0:f1a93e55feb5 142 //! @param reading
JacobBramley 0:f1a93e55feb5 143 //! The raw reading taken from the SHT7x.
JacobBramley 0:f1a93e55feb5 144 //!
JacobBramley 0:f1a93e55feb5 145 //! @param temp
JacobBramley 0:f1a93e55feb5 146 //! A recent temperature reading.
JacobBramley 0:f1a93e55feb5 147 //!
JacobBramley 0:f1a93e55feb5 148 //! The humidity reading is dependant on temperature. By providing a Temp, it
JacobBramley 0:f1a93e55feb5 149 //! will be used to adjust humidity readings accordingly.
JacobBramley 0:f1a93e55feb5 150 //!
JacobBramley 0:f1a93e55feb5 151 //! Note that the Temp object is not copied, so it must remain in scope at
JacobBramley 0:f1a93e55feb5 152 //! least until the last Hum::get_*() call (other than get_raw()).
JacobBramley 0:f1a93e55feb5 153 Hum(uint32_t bits, uint32_t reading, Temp const * temp = NULL)
JacobBramley 0:f1a93e55feb5 154 : Reading(bits, reading), temp(temp) {}
JacobBramley 0:f1a93e55feb5 155
JacobBramley 0:f1a93e55feb5 156 //! Initialize an empty object.
JacobBramley 0:f1a93e55feb5 157 //!
JacobBramley 0:f1a93e55feb5 158 //! The resulting object's is_valid() function will return false. It should be
JacobBramley 0:f1a93e55feb5 159 //! passed into SHT7x::measure() to get a valid reading.
JacobBramley 0:f1a93e55feb5 160 Hum() : Reading() {}
JacobBramley 0:f1a93e55feb5 161
JacobBramley 0:f1a93e55feb5 162 //! Return the reading (float).
JacobBramley 0:f1a93e55feb5 163 float get_f() const;
JacobBramley 0:f1a93e55feb5 164
JacobBramley 0:f1a93e55feb5 165 //! Return the reading as a 64-bit signed value with 32 fractional bits.
JacobBramley 0:f1a93e55feb5 166 //!
JacobBramley 0:f1a93e55feb5 167 //! The rounding mode is round-to-nearest, with ties away from zero.
JacobBramley 0:f1a93e55feb5 168 int64_t get_q32() const; // Fixed-point (q32)
JacobBramley 0:f1a93e55feb5 169
JacobBramley 0:f1a93e55feb5 170 //! Return the reading as a 32-bit signed value.
JacobBramley 0:f1a93e55feb5 171 //!
JacobBramley 0:f1a93e55feb5 172 //! @param fbits
JacobBramley 0:f1a93e55feb5 173 //! The number of fractional bits desired in the result.
JacobBramley 0:f1a93e55feb5 174 //!
JacobBramley 0:f1a93e55feb5 175 //! The rounding mode is round-to-nearest, with ties away from zero.
JacobBramley 0:f1a93e55feb5 176 int32_t get_fixed(int fbits) const; // Fixed-point (q0-q32)
JacobBramley 0:f1a93e55feb5 177
JacobBramley 0:f1a93e55feb5 178 //! Return the reading as an integer.
JacobBramley 0:f1a93e55feb5 179 //!
JacobBramley 0:f1a93e55feb5 180 //! The rounding mode is round-to-nearest, with ties away from zero.
JacobBramley 0:f1a93e55feb5 181 int32_t get_i() const { // Integer
JacobBramley 0:f1a93e55feb5 182 return get_fixed(0);
JacobBramley 0:f1a93e55feb5 183 }
JacobBramley 0:f1a93e55feb5 184
JacobBramley 0:f1a93e55feb5 185 private:
JacobBramley 0:f1a93e55feb5 186 Temp const * temp;
JacobBramley 0:f1a93e55feb5 187 };
JacobBramley 0:f1a93e55feb5 188
JacobBramley 0:f1a93e55feb5 189 enum Precision {
JacobBramley 0:f1a93e55feb5 190 PRECISION_HIGH = 0x0,
JacobBramley 0:f1a93e55feb5 191 PRECISION_LOW = 0x1,
JacobBramley 0:f1a93e55feb5 192 PRECISION_KEEP = -1
JacobBramley 0:f1a93e55feb5 193 };
JacobBramley 0:f1a93e55feb5 194
JacobBramley 0:f1a93e55feb5 195 enum OTP {
JacobBramley 0:f1a93e55feb5 196 OTP_ON = 0x0,
JacobBramley 0:f1a93e55feb5 197 OTP_OFF = 0x2,
JacobBramley 0:f1a93e55feb5 198 OTP_KEEP = -1
JacobBramley 0:f1a93e55feb5 199 };
JacobBramley 0:f1a93e55feb5 200
JacobBramley 0:f1a93e55feb5 201 enum Heater {
JacobBramley 0:f1a93e55feb5 202 HEATER_OFF = 0x0,
JacobBramley 0:f1a93e55feb5 203 HEATER_ON = 0x4,
JacobBramley 0:f1a93e55feb5 204 HEATER_KEEP = -1
JacobBramley 0:f1a93e55feb5 205 };
JacobBramley 0:f1a93e55feb5 206
JacobBramley 0:f1a93e55feb5 207 enum Battery {
JacobBramley 0:f1a93e55feb5 208 BATTERY_GT_2_47 = 0x00,
JacobBramley 0:f1a93e55feb5 209 BATTERY_LT_2_47 = 0x40
JacobBramley 0:f1a93e55feb5 210 };
JacobBramley 0:f1a93e55feb5 211
JacobBramley 0:f1a93e55feb5 212 struct Status {
JacobBramley 0:f1a93e55feb5 213 Precision precision;
JacobBramley 0:f1a93e55feb5 214 OTP otp;
JacobBramley 0:f1a93e55feb5 215 Heater heater;
JacobBramley 0:f1a93e55feb5 216 Battery battery;
JacobBramley 0:f1a93e55feb5 217 };
JacobBramley 0:f1a93e55feb5 218
JacobBramley 0:f1a93e55feb5 219 enum State {
JacobBramley 0:f1a93e55feb5 220 STATE_UNKNOWN,
JacobBramley 0:f1a93e55feb5 221 STATE_SLEEP,
JacobBramley 0:f1a93e55feb5 222 STATE_RESETTING,
JacobBramley 0:f1a93e55feb5 223 STATE_INITIALIZING,
JacobBramley 0:f1a93e55feb5 224 STATE_SETTING_CONFIGURATION,
JacobBramley 0:f1a93e55feb5 225 STATE_GETTING_CONFIGURATION,
JacobBramley 0:f1a93e55feb5 226 STATE_MEASURING_TEMPERATURE,
JacobBramley 0:f1a93e55feb5 227 STATE_MEASURING_HUMIDITY,
JacobBramley 0:f1a93e55feb5 228 STATE_COMMS_ERROR
JacobBramley 0:f1a93e55feb5 229 };
JacobBramley 0:f1a93e55feb5 230
JacobBramley 0:f1a93e55feb5 231 //! Sensirion SHT7x Interface Class
JacobBramley 0:f1a93e55feb5 232 //!
JacobBramley 0:f1a93e55feb5 233 //! This class interfaces with a Sensirion SHT7x series humidity and temperature
JacobBramley 0:f1a93e55feb5 234 //! sensor. The SHT7x series implement a protocol similar to I²C, but
JacobBramley 0:f1a93e55feb5 235 //! unfortunately not similar enough that the LPC I²C peripheral can communicate
JacobBramley 0:f1a93e55feb5 236 //! directly. This implementation uses GPIO.
JacobBramley 0:f1a93e55feb5 237 //!
JacobBramley 0:f1a93e55feb5 238 //! Other Sensirion sensors may also be compatible, but this code has only been
JacobBramley 0:f1a93e55feb5 239 //! tested with SHT71 and SHT75.
JacobBramley 0:f1a93e55feb5 240 //!
JacobBramley 0:f1a93e55feb5 241 //! The SHT7x interface functions in this class will return 'false' to indicate
JacobBramley 0:f1a93e55feb5 242 //! a fault. A fault can be caused by one of the following events:
JacobBramley 0:f1a93e55feb5 243 //!
JacobBramley 0:f1a93e55feb5 244 //! - The class is in the wrong state. After a reset, it is necessary to call
JacobBramley 0:f1a93e55feb5 245 //! initialize() before any communication with the sensor.
JacobBramley 0:f1a93e55feb5 246 //! - A communications error is detected, most likely in the CRC check.
JacobBramley 0:f1a93e55feb5 247 //! - The CRC byte sent from the sensor takes the status byte into account,
JacobBramley 0:f1a93e55feb5 248 //! so any CRC check will fail if the low-voltage detection bit has
JacobBramley 0:f1a93e55feb5 249 //! changed since it the status byte was last read.
JacobBramley 0:f1a93e55feb5 250 //!
JacobBramley 0:f1a93e55feb5 251 //! There is no way to determine the cause of a fault. The suggested
JacobBramley 0:f1a93e55feb5 252 //! error-handling routine is as follows:
JacobBramley 0:f1a93e55feb5 253 //!
JacobBramley 0:f1a93e55feb5 254 //! - Optionally, call status() to correct problems where the low-voltage
JacobBramley 0:f1a93e55feb5 255 //! detection bit in the status byte has changed. This should not be
JacobBramley 0:f1a93e55feb5 256 //! necessary if the power supply is known to be stable.
JacobBramley 0:f1a93e55feb5 257 //! - If that fails, call reset() and then initialize() to force a reset.
JacobBramley 0:f1a93e55feb5 258 //! - This operation is relatively slow since initialize() takes 11ms.
JacobBramley 0:f1a93e55feb5 259 //!
JacobBramley 0:f1a93e55feb5 260 //! The class is not thread-safe and interface functions are not re-entrant.
JacobBramley 0:f1a93e55feb5 261 //!
JacobBramley 0:f1a93e55feb5 262 //! The datasheet can (as of early 2012) be found here:
JacobBramley 0:f1a93e55feb5 263 //! http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT7x.pdf
JacobBramley 0:f1a93e55feb5 264 //!
JacobBramley 0:f1a93e55feb5 265 //! Example:
JacobBramley 0:f1a93e55feb5 266 //! @code
JacobBramley 0:f1a93e55feb5 267 //! #include "mbed.h"
JacobBramley 0:f1a93e55feb5 268 //! #include "sht7x.h"
JacobBramley 0:f1a93e55feb5 269 //!
JacobBramley 0:f1a93e55feb5 270 //! bool do_measure(sht7x::SHT7x & sensor) {
JacobBramley 0:f1a93e55feb5 271 //! sht7x::Temp temp;
JacobBramley 0:f1a93e55feb5 272 //! sht7x::Hum hum;
JacobBramley 0:f1a93e55feb5 273 //!
JacobBramley 0:f1a93e55feb5 274 //! if (!sensor.measure(temp, 5000)) {
JacobBramley 0:f1a93e55feb5 275 //! printf("Couldn't measure temperature.\n");
JacobBramley 0:f1a93e55feb5 276 //! return false;
JacobBramley 0:f1a93e55feb5 277 //! }
JacobBramley 0:f1a93e55feb5 278 //!
JacobBramley 0:f1a93e55feb5 279 //! if (!sensor.measure(hum, &temp)) {
JacobBramley 0:f1a93e55feb5 280 //! printf("Couldn't measure humidity.\n");
JacobBramley 0:f1a93e55feb5 281 //! return false;
JacobBramley 0:f1a93e55feb5 282 //! }
JacobBramley 0:f1a93e55feb5 283 //!
JacobBramley 0:f1a93e55feb5 284 //! printf("Temperature: %.3f degrees C.\n", temp.get_f());
JacobBramley 0:f1a93e55feb5 285 //! printf("Humidity: %.3f%% relative humidity.\n", hum.get_f());
JacobBramley 0:f1a93e55feb5 286 //!
JacobBramley 0:f1a93e55feb5 287 //! return true;
JacobBramley 0:f1a93e55feb5 288 //! }
JacobBramley 0:f1a93e55feb5 289 //!
JacobBramley 0:f1a93e55feb5 290 //! int main() {
JacobBramley 0:f1a93e55feb5 291 //! Serial serial(USBTX, USBRX);
JacobBramley 0:f1a93e55feb5 292 //! serial.baud(115200);
JacobBramley 0:f1a93e55feb5 293 //! serial.format(8, Serial::None, 1);
JacobBramley 0:f1a93e55feb5 294 //!
JacobBramley 0:f1a93e55feb5 295 //! sht7x::SHT7x sensor(p27, p28);
JacobBramley 0:f1a93e55feb5 296 //! // Set up communications with the sensor.
JacobBramley 0:f1a93e55feb5 297 //! sensor.initialize();
JacobBramley 0:f1a93e55feb5 298 //!
JacobBramley 0:f1a93e55feb5 299 //! printf("\n======== SHT7x Example ========\n\n");
JacobBramley 0:f1a93e55feb5 300 //! printf("==== Configuration: PRECISION_HIGH, OTP_ON ====\n");
JacobBramley 0:f1a93e55feb5 301 //! sensor.configure(sht7x::PRECISION_HIGH, sht7x::OTP_ON);
JacobBramley 0:f1a93e55feb5 302 //!
JacobBramley 0:f1a93e55feb5 303 //! while (1) {
JacobBramley 0:f1a93e55feb5 304 //! if (!do_measure(sensor)) {
JacobBramley 0:f1a93e55feb5 305 //! printf("==== Resetting sensor... ====\n");
JacobBramley 0:f1a93e55feb5 306 //! sensor.reset();
JacobBramley 0:f1a93e55feb5 307 //! sensor.initialize();
JacobBramley 0:f1a93e55feb5 308 //! continue;
JacobBramley 0:f1a93e55feb5 309 //! }
JacobBramley 0:f1a93e55feb5 310 //! wait(3);
JacobBramley 0:f1a93e55feb5 311 //! }
JacobBramley 0:f1a93e55feb5 312 //! }
JacobBramley 0:f1a93e55feb5 313 //! @endcode
JacobBramley 0:f1a93e55feb5 314 //!
JacobBramley 0:f1a93e55feb5 315 //! TODO: It might be possible to use I²C for the majority of communications,
JacobBramley 0:f1a93e55feb5 316 //! but switch the pin mapping to GPIO to wait for a reading. (This seems to be
JacobBramley 0:f1a93e55feb5 317 //! the only part that is not sufficiently I²C-compliant.) Is it worth
JacobBramley 0:f1a93e55feb5 318 //! investigating this?
JacobBramley 0:f1a93e55feb5 319 class SHT7x {
JacobBramley 0:f1a93e55feb5 320 public:
JacobBramley 0:f1a93e55feb5 321 //! Construct a new SHT7x interface object.
JacobBramley 0:f1a93e55feb5 322 //!
JacobBramley 0:f1a93e55feb5 323 //! The constructor does not communicate with the sensor in any way, but it
JacobBramley 0:f1a93e55feb5 324 //! assigns and configures the specified input and output pins.
JacobBramley 0:f1a93e55feb5 325 SHT7x(PinName sck, PinName sda);
JacobBramley 0:f1a93e55feb5 326
JacobBramley 0:f1a93e55feb5 327 //! Reset the sensor and restore its configuration to default values.
JacobBramley 0:f1a93e55feb5 328 //!
JacobBramley 0:f1a93e55feb5 329 //! Note that it should not normally be necessary to call this method manually
JacobBramley 0:f1a93e55feb5 330 //! because the sensor resets automatically when turned on.
JacobBramley 0:f1a93e55feb5 331 //!
JacobBramley 0:f1a93e55feb5 332 //! After calling reset, the sensor will be in the power-on state, so it is
JacobBramley 0:f1a93e55feb5 333 //! necessary to call initialize before issuing any other commands.
JacobBramley 0:f1a93e55feb5 334 bool reset();
JacobBramley 0:f1a93e55feb5 335
JacobBramley 0:f1a93e55feb5 336 //! Initialize the sensor and communications channel.
JacobBramley 0:f1a93e55feb5 337 //!
JacobBramley 0:f1a93e55feb5 338 //! This takes 11ms, and must be done manually before using the sensor for the
JacobBramley 0:f1a93e55feb5 339 //! first time after a hard or soft reset. For this reason, it is advisable to
JacobBramley 0:f1a93e55feb5 340 //! call initialize() in advance, rather than on-demand.
JacobBramley 0:f1a93e55feb5 341 bool initialize();
JacobBramley 0:f1a93e55feb5 342
JacobBramley 0:f1a93e55feb5 343 //! Configure the sensor's status byte.
JacobBramley 0:f1a93e55feb5 344 //!
JacobBramley 0:f1a93e55feb5 345 //! @param precision
JacobBramley 0:f1a93e55feb5 346 //! High-precision readings take longer to measure than low-precision
JacobBramley 0:f1a93e55feb5 347 //! readings. As a result, they will probably require more energy.
JacobBramley 0:f1a93e55feb5 348 //!
JacobBramley 0:f1a93e55feb5 349 //! @param otp
JacobBramley 0:f1a93e55feb5 350 //! By default, the sensor will reload OTP calibration data before each
JacobBramley 0:f1a93e55feb5 351 //! measurement. It is possible to disable this mechanism. However, the
JacobBramley 0:f1a93e55feb5 352 //! datasheet is not clear about the consequences of this, except that
JacobBramley 0:f1a93e55feb5 353 //! disabling it can take about 10ms off the measurement time.
JacobBramley 0:f1a93e55feb5 354 //!
JacobBramley 0:f1a93e55feb5 355 //! @param heater
JacobBramley 0:f1a93e55feb5 356 //! The heater can be used to verify the operation of the sensor. When the
JacobBramley 0:f1a93e55feb5 357 //! heater is activated, the temperature reading should increase and the
JacobBramley 0:f1a93e55feb5 358 //! humidity reading should decrease. Note that the heater should not be
JacobBramley 0:f1a93e55feb5 359 //! left on permanently because it could cause damage. The datasheet is not
JacobBramley 0:f1a93e55feb5 360 //! clear about how long it can be left on for, however.
JacobBramley 0:f1a93e55feb5 361 //!
JacobBramley 0:f1a93e55feb5 362 //! Setting any of the values to *_KEEP will cause the existing values to
JacobBramley 0:f1a93e55feb5 363 //! remain unchanged.
JacobBramley 0:f1a93e55feb5 364 bool configure(Precision precision,
JacobBramley 0:f1a93e55feb5 365 OTP otp = OTP_KEEP,
JacobBramley 0:f1a93e55feb5 366 Heater heater = HEATER_KEEP);
JacobBramley 0:f1a93e55feb5 367
JacobBramley 0:f1a93e55feb5 368 //! Retrieve the sensor's status byte.
JacobBramley 0:f1a93e55feb5 369 bool status(Status * & status);
JacobBramley 0:f1a93e55feb5 370
JacobBramley 0:f1a93e55feb5 371 //! Take a temperature measurement.
JacobBramley 0:f1a93e55feb5 372 //!
JacobBramley 0:f1a93e55feb5 373 //! @param temp
JacobBramley 0:f1a93e55feb5 374 //! The sht7x::Temp object to populate.
JacobBramley 0:f1a93e55feb5 375 //!
JacobBramley 0:f1a93e55feb5 376 //! @param mvdd
JacobBramley 0:f1a93e55feb5 377 //! The supply voltage to the sensor. This is used to adjust the sensor
JacobBramley 0:f1a93e55feb5 378 //! reading as specified by the datasheet. The datasheet recommends using a
JacobBramley 0:f1a93e55feb5 379 //! 3.3V supply voltage for maximum accuracy.
JacobBramley 0:f1a93e55feb5 380 //!
JacobBramley 0:f1a93e55feb5 381 //! The temperature reading can vary by approximately 0.8 degrees across the
JacobBramley 0:f1a93e55feb5 382 //! specified voltage range (2.4-5.5V). If this accuracty is sufficient, or
JacobBramley 0:f1a93e55feb5 383 //! if you only want to read the raw data, you may ignore mvdd.
JacobBramley 0:f1a93e55feb5 384 bool measure(Temp & temp, uint32_t mvdd = Temp::mvdd_default);
JacobBramley 0:f1a93e55feb5 385
JacobBramley 0:f1a93e55feb5 386
JacobBramley 0:f1a93e55feb5 387 //! Take a humidity measurement.
JacobBramley 0:f1a93e55feb5 388 //!
JacobBramley 0:f1a93e55feb5 389 //! @param hum
JacobBramley 0:f1a93e55feb5 390 //! The sht7x::Hum object to populate.
JacobBramley 0:f1a93e55feb5 391 //!
JacobBramley 0:f1a93e55feb5 392 //! @param temp
JacobBramley 0:f1a93e55feb5 393 //! A temperature reading. This is used to adjust the humidity reading as
JacobBramley 0:f1a93e55feb5 394 //! specified by the datasheet.
JacobBramley 0:f1a93e55feb5 395 //!
JacobBramley 0:f1a93e55feb5 396 //! The humidity reading can vary by approximately 2% relative humidity
JacobBramley 0:f1a93e55feb5 397 //! across the operating temperature and humidity ranges. If this accuracy is
JacobBramley 0:f1a93e55feb5 398 //! sufficient, or if you only want to read the raw data, you may ignore temp.
JacobBramley 0:f1a93e55feb5 399 bool measure(Hum & hum, Temp const * temp = NULL);
JacobBramley 0:f1a93e55feb5 400
JacobBramley 0:f1a93e55feb5 401 private:
JacobBramley 0:f1a93e55feb5 402 // Private types and fields.
JacobBramley 0:f1a93e55feb5 403
JacobBramley 0:f1a93e55feb5 404 enum Command {
JacobBramley 0:f1a93e55feb5 405 CMD_READ_TEMP = 0x03,
JacobBramley 0:f1a93e55feb5 406 CMD_READ_HUM = 0x05,
JacobBramley 0:f1a93e55feb5 407 CMD_READ_STATUS = 0x07,
JacobBramley 0:f1a93e55feb5 408 CMD_WRITE_STATUS = 0x06,
JacobBramley 0:f1a93e55feb5 409 CMD_RESET = 0x1e
JacobBramley 0:f1a93e55feb5 410 };
JacobBramley 0:f1a93e55feb5 411
JacobBramley 0:f1a93e55feb5 412 // Pin states, as driven by the microprocessor. Because sda is open-drain,
JacobBramley 0:f1a93e55feb5 413 // its real value may differ in the PIN_1 and PIN_FREE cases.
JacobBramley 0:f1a93e55feb5 414 enum pin_State {
JacobBramley 0:f1a93e55feb5 415 PIN_0 = 0x0,
JacobBramley 0:f1a93e55feb5 416 PIN_1 = 0x1,
JacobBramley 0:f1a93e55feb5 417 PIN_FREE = 0x2,
JacobBramley 0:f1a93e55feb5 418 PIN_INVALID = 0x3
JacobBramley 0:f1a93e55feb5 419 };
JacobBramley 0:f1a93e55feb5 420
JacobBramley 0:f1a93e55feb5 421 // Communications pins.
JacobBramley 0:f1a93e55feb5 422 DigitalOut sck_;
JacobBramley 0:f1a93e55feb5 423 DigitalInOut sda_;
JacobBramley 0:f1a93e55feb5 424 pin_State sck_state_;
JacobBramley 0:f1a93e55feb5 425 pin_State sda_state_;
JacobBramley 0:f1a93e55feb5 426
JacobBramley 0:f1a93e55feb5 427 // Sensor (local) state.
JacobBramley 0:f1a93e55feb5 428 State state_;
JacobBramley 0:f1a93e55feb5 429
JacobBramley 0:f1a93e55feb5 430 // Cached status register bits.
JacobBramley 0:f1a93e55feb5 431 Status status_;
JacobBramley 0:f1a93e55feb5 432
JacobBramley 0:f1a93e55feb5 433 // Utilities
JacobBramley 0:f1a93e55feb5 434 uint32_t encode_status_byte() const;
JacobBramley 0:f1a93e55feb5 435 void decode_status_byte(uint32_t value);
JacobBramley 0:f1a93e55feb5 436
JacobBramley 0:f1a93e55feb5 437 uint32_t bits_required_temperature() const;
JacobBramley 0:f1a93e55feb5 438 uint32_t bits_required_humidity() const;
JacobBramley 0:f1a93e55feb5 439
JacobBramley 0:f1a93e55feb5 440 uint32_t time_atom() const;
JacobBramley 0:f1a93e55feb5 441 uint32_t time_reset() const;
JacobBramley 0:f1a93e55feb5 442 uint32_t time_reading_temperature() const;
JacobBramley 0:f1a93e55feb5 443 uint32_t time_reading_humidity() const;
JacobBramley 0:f1a93e55feb5 444
JacobBramley 0:f1a93e55feb5 445 // Communications
JacobBramley 0:f1a93e55feb5 446 void start();
JacobBramley 0:f1a93e55feb5 447
JacobBramley 0:f1a93e55feb5 448 void put_bit(int b);
JacobBramley 0:f1a93e55feb5 449 int get_bit();
JacobBramley 0:f1a93e55feb5 450
JacobBramley 0:f1a93e55feb5 451 void put_ack(int b);
JacobBramley 0:f1a93e55feb5 452 void get_ack();
JacobBramley 0:f1a93e55feb5 453
JacobBramley 0:f1a93e55feb5 454 void put_byte(uint32_t value);
JacobBramley 0:f1a93e55feb5 455 uint32_t get_byte();
JacobBramley 0:f1a93e55feb5 456
JacobBramley 0:f1a93e55feb5 457 int get_sda();
JacobBramley 0:f1a93e55feb5 458 void set_sda(int pin);
JacobBramley 0:f1a93e55feb5 459 void set_sda(pin_State pin);
JacobBramley 0:f1a93e55feb5 460 void set_sck(int pin);
JacobBramley 0:f1a93e55feb5 461 void set_sck(pin_State pin);
JacobBramley 0:f1a93e55feb5 462
JacobBramley 0:f1a93e55feb5 463 // Utility methods.
JacobBramley 0:f1a93e55feb5 464 void reset_comms();
JacobBramley 0:f1a93e55feb5 465 void command(Command command);
JacobBramley 0:f1a93e55feb5 466 bool check_state(State s0);
JacobBramley 0:f1a93e55feb5 467 bool check_state(State s0, State s1);
JacobBramley 0:f1a93e55feb5 468 bool check_state(State s0, State s1, State s2);
JacobBramley 0:f1a93e55feb5 469 static int payload_size(Command command);
JacobBramley 0:f1a93e55feb5 470 bool status();
JacobBramley 0:f1a93e55feb5 471
JacobBramley 0:f1a93e55feb5 472 // Error handling.
JacobBramley 0:f1a93e55feb5 473 bool check_crc(Command command, uint32_t data, uint32_t crc);
JacobBramley 0:f1a93e55feb5 474 };
JacobBramley 0:f1a93e55feb5 475
JacobBramley 0:f1a93e55feb5 476 } // namespace sht7x
JacobBramley 0:f1a93e55feb5 477
JacobBramley 0:f1a93e55feb5 478 #endif // SHT7X_SHT7X_H