Silicon Labs Si7021-A20 device driver: I2C Humidity and Temperature Sensor

Committer:
ninensei
Date:
Thu Sep 14 00:16:02 2017 +0000
Revision:
1:344923bddd4f
Converted to template so that I2C driver derivations can be used (I2C, SoftI2C, etc...); Changed filename to match class name.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ninensei 1:344923bddd4f 1 /* mbed Microcontroller Library
ninensei 1:344923bddd4f 2 * Copyright (c) 2017 AT&T, IIoT Foundry, Plano, TX, USA
ninensei 1:344923bddd4f 3 *
ninensei 1:344923bddd4f 4 * Licensed under the Apache License, Version 2.0 (the "License");
ninensei 1:344923bddd4f 5 * you may not use this file except in compliance with the License.
ninensei 1:344923bddd4f 6 * You may obtain a copy of the License at
ninensei 1:344923bddd4f 7 *
ninensei 1:344923bddd4f 8 * http://www.apache.org/licenses/LICENSE-2.0
ninensei 1:344923bddd4f 9 *
ninensei 1:344923bddd4f 10 * Unless required by applicable law or agreed to in writing, software
ninensei 1:344923bddd4f 11 * distributed under the License is distributed on an "AS IS" BASIS,
ninensei 1:344923bddd4f 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ninensei 1:344923bddd4f 13 * See the License for the specific language governing permissions and
ninensei 1:344923bddd4f 14 * limitations under the License.
ninensei 1:344923bddd4f 15 */
ninensei 1:344923bddd4f 16
ninensei 1:344923bddd4f 17 /** \addtogroup drivers */
ninensei 1:344923bddd4f 18
ninensei 1:344923bddd4f 19 /** Support for Silicon Labs SI7021 temperature and humidity sensor
ninensei 1:344923bddd4f 20 *
ninensei 1:344923bddd4f 21 * Example:
ninensei 1:344923bddd4f 22 * @code
ninensei 1:344923bddd4f 23 *
ninensei 1:344923bddd4f 24 * #include "mbed.h"
ninensei 1:344923bddd4f 25 * #include "SI7021.h"
ninensei 1:344923bddd4f 26 *
ninensei 1:344923bddd4f 27 * I2C i2c(I2C_SDA, I2C_SCL);
ninensei 1:344923bddd4f 28 * SI7021<I2C> si7021(&i2c);
ninensei 1:344923bddd4f 29 *
ninensei 1:344923bddd4f 30 * int main() {
ninensei 1:344923bddd4f 31 * si7021_measurements_t data;
ninensei 1:344923bddd4f 32 * bool ok;
ninensei 1:344923bddd4f 33 *
ninensei 1:344923bddd4f 34 * ok = si7021->read(&data);
ninensei 1:344923bddd4f 35 *
ninensei 1:344923bddd4f 36 * if (ok) {
ninensei 1:344923bddd4f 37 * printf("%%RelHum: %f\r\n", data.humidity_PR);
ninensei 1:344923bddd4f 38 * printf("temp C/F: %f/%f\r\n", data.temp_C, data.temp_C * 9 / 5 + 32);
ninensei 1:344923bddd4f 39 * } else {
ninensei 1:344923bddd4f 40 * printf("si7021 error!\r\n");
ninensei 1:344923bddd4f 41 * }
ninensei 1:344923bddd4f 42 * }
ninensei 1:344923bddd4f 43 * @endcode
ninensei 1:344923bddd4f 44 * @ingroup drivers
ninensei 1:344923bddd4f 45 */
ninensei 1:344923bddd4f 46
ninensei 1:344923bddd4f 47 #pragma once
ninensei 1:344923bddd4f 48
ninensei 1:344923bddd4f 49 #define SI7021A20_I2C_ADDR 0x80
ninensei 1:344923bddd4f 50
ninensei 1:344923bddd4f 51 #define SI7021A20_CMD_MEAS_RH_HMM 0xE5
ninensei 1:344923bddd4f 52 #define SI7021A20_CMD_MEAS_RH_NHMM 0xF5
ninensei 1:344923bddd4f 53 #define SI7021A20_CMD_MEAS_TEMP_HMM 0xE3
ninensei 1:344923bddd4f 54 #define SI7021A20_CMD_MEAS_TEMP_NHMM 0xF3
ninensei 1:344923bddd4f 55 #define SI7021A20_CMD_READ_TEMP 0xE0
ninensei 1:344923bddd4f 56 #define SI7021A20_CMD_RESET 0xFE
ninensei 1:344923bddd4f 57 #define SI7021A20_CMD_WRITE_USER1 0xE6
ninensei 1:344923bddd4f 58 #define SI7021A20_CMD_WRITE_USER2 0xE7
ninensei 1:344923bddd4f 59 #define SI7021A20_CMD_WRITE_HEAT_CTRL 0x51
ninensei 1:344923bddd4f 60 #define SI7021A20_CMD_READ_HEAT_CTRL 0x11
ninensei 1:344923bddd4f 61 #define SI7021A20_CMD_READ_ID1 0xFA0F
ninensei 1:344923bddd4f 62 #define SI7021A20_CMD_READ_ID2 0xFCC9
ninensei 1:344923bddd4f 63 #define SI7021A20_REGF_ID2_DEV_ID 0x15
ninensei 1:344923bddd4f 64 #define SI7021A20_CMD_READ_FW_REV 0x84B8
ninensei 1:344923bddd4f 65
ninensei 1:344923bddd4f 66 typedef struct {
ninensei 1:344923bddd4f 67 float temp_C;
ninensei 1:344923bddd4f 68 float humidity_PR;
ninensei 1:344923bddd4f 69 } si7021_measurements_t;
ninensei 1:344923bddd4f 70
ninensei 1:344923bddd4f 71 template <class T>
ninensei 1:344923bddd4f 72 class SI7021 {
ninensei 1:344923bddd4f 73 public:
ninensei 1:344923bddd4f 74 /**
ninensei 1:344923bddd4f 75 * Constructor
ninensei 1:344923bddd4f 76 *
ninensei 1:344923bddd4f 77 * @param i2c I2C class servicing the strip
ninensei 1:344923bddd4f 78 */
ninensei 1:344923bddd4f 79 SI7021(T * i2c) : _i2c(i2c) {}
ninensei 1:344923bddd4f 80
ninensei 1:344923bddd4f 81 /**
ninensei 1:344923bddd4f 82 * Read temperature and humidity
ninensei 1:344923bddd4f 83 *
ninensei 1:344923bddd4f 84 * @param data points to struct to store measurements in. Stucture is
ninensei 1:344923bddd4f 85 * valid only when function returns success indication.
ninensei 1:344923bddd4f 86 *
ninensei 1:344923bddd4f 87 * @returns true (success) or false (failure)
ninensei 1:344923bddd4f 88 */
ninensei 1:344923bddd4f 89 bool read(si7021_measurements_t * data) {
ninensei 1:344923bddd4f 90 bool ok;
ninensei 1:344923bddd4f 91 union {
ninensei 1:344923bddd4f 92 char cmd;
ninensei 1:344923bddd4f 93 struct {
ninensei 1:344923bddd4f 94 uint8_t meas_msb;
ninensei 1:344923bddd4f 95 uint8_t meas_lsb;
ninensei 1:344923bddd4f 96 };
ninensei 1:344923bddd4f 97 } buff;
ninensei 1:344923bddd4f 98
ninensei 1:344923bddd4f 99 buff.cmd = SI7021A20_CMD_MEAS_RH_HMM;
ninensei 1:344923bddd4f 100 ok = (_i2c_transfer(SI7021A20_I2C_ADDR, &buff, 1, 2));
ninensei 1:344923bddd4f 101 if (ok) {
ninensei 1:344923bddd4f 102 // Humidity% = measurement * 125/65536 - 6
ninensei 1:344923bddd4f 103 int meas_raw = ((int)buff.meas_msb << 8) + buff.meas_lsb;
ninensei 1:344923bddd4f 104 data->humidity_PR = (float)meas_raw * (125.0F/65536.0F) - 6.0F;
ninensei 1:344923bddd4f 105
ninensei 1:344923bddd4f 106 buff.cmd = SI7021A20_CMD_READ_TEMP;
ninensei 1:344923bddd4f 107 ok = _i2c_transfer(SI7021A20_I2C_ADDR, &buff, 1, 2);
ninensei 1:344923bddd4f 108 }
ninensei 1:344923bddd4f 109 if (ok) {
ninensei 1:344923bddd4f 110 // TempC = measurement * 175.72/65536 - 46.85
ninensei 1:344923bddd4f 111 int meas_raw = ((int)buff.meas_msb << 8) + buff.meas_lsb;
ninensei 1:344923bddd4f 112 data->temp_C = meas_raw * (175.72/65536.0) - 46.85;
ninensei 1:344923bddd4f 113 }
ninensei 1:344923bddd4f 114 return ok;
ninensei 1:344923bddd4f 115 }
ninensei 1:344923bddd4f 116
ninensei 1:344923bddd4f 117 protected:
ninensei 1:344923bddd4f 118
ninensei 1:344923bddd4f 119 /**
ninensei 1:344923bddd4f 120 * I2C read/write helper function
ninensei 1:344923bddd4f 121 *
ninensei 1:344923bddd4f 122 * @param address is the register to read/write
ninensei 1:344923bddd4f 123 * @param buff holds the data to write and recieves the data to read
ninensei 1:344923bddd4f 124 * @param writeSize is the number of bytes to write to register
ninensei 1:344923bddd4f 125 * @param readSize is the number of bytes to retrieve from device
ninensei 1:344923bddd4f 126 *
ninensei 1:344923bddd4f 127 * @returns true (success) or false (failure)
ninensei 1:344923bddd4f 128 */
ninensei 1:344923bddd4f 129 bool _i2c_transfer(int address, void * buff, size_t writeSize, size_t readSize) {
ninensei 1:344923bddd4f 130 bool ok;
ninensei 1:344923bddd4f 131 bool expect_response = (readSize != 0);
ninensei 1:344923bddd4f 132
ninensei 1:344923bddd4f 133 ok = !_i2c->write(address, (char*)buff, writeSize, expect_response);
ninensei 1:344923bddd4f 134 if (ok && expect_response)
ninensei 1:344923bddd4f 135 ok = !_i2c->read(address, (char*)buff, readSize);
ninensei 1:344923bddd4f 136
ninensei 1:344923bddd4f 137 return ok;
ninensei 1:344923bddd4f 138 }
ninensei 1:344923bddd4f 139
ninensei 1:344923bddd4f 140
ninensei 1:344923bddd4f 141 T *_i2c;
ninensei 1:344923bddd4f 142 };
ninensei 1:344923bddd4f 143