root / Ports / PortsSHT11.cpp
History | View | Annotate | Download (5.1 KB)
| 1 | //>>> The latest version of this code can be found at https://github.com/jcw/ !!
|
|---|---|
| 2 | |
| 3 | // Port library interface to SHT11 sensors connected via "something like I2C"
|
| 4 | // 2009-02-16 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
|
| 5 | // $Id: PortsSHT11.cpp 7763 2011-12-11 01:28:16Z jcw $
|
| 6 | |
| 7 | // rewritten in C++ using the SENSIRION SHTxx Sample Code Application Note
|
| 8 | // the CRC calculation is from the SENSIRION SHTxx CRC Application Note
|
| 9 | |
| 10 | #include <Ports.h> |
| 11 | #include "PortsSHT11.h" |
| 12 | #include <avr/pgmspace.h> |
| 13 | #include <WProgram.h> |
| 14 | |
| 15 | enum {
|
| 16 | MEASURE_TEMP = 0x03,
|
| 17 | MEASURE_HUMI = 0x05,
|
| 18 | STATUS_REG_W = 0x06,
|
| 19 | STATUS_REG_R = 0x07,
|
| 20 | RESET = 0x1e,
|
| 21 | }; |
| 22 | |
| 23 | static uint8_t crcTab [] PROGMEM = {
|
| 24 | 0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46, 67, |
| 25 | 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109, 134, |
| 26 | 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168, 197, |
| 27 | 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235, 61, 12, |
| 28 | 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19, 126, 79, |
| 29 | 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80, 187, 138, |
| 30 | 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149, 248, 201, 154, |
| 31 | 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214, 122, 75, 24, 41, |
| 32 | 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84, 57, 8, 91, 106, 253, |
| 33 | 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23, 252, 205, 158, 175, 56, |
| 34 | 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210, 191, 142, 221, 236, 123, |
| 35 | 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145, 71, 118, 37, 20, 131, 178, |
| 36 | 225, 208, 254, 207, 156, 173, 58, 11, 88, 105, 4, 53, 102, 87, 192, 241, |
| 37 | 162, 147, 189, 140, 223, 238, 121, 72, 27, 42, 193, 240, 163, 146, 5, 52, |
| 38 | 103, 86, 120, 73, 26, 43, 188, 141, 222, 239, 130, 179, 224, 209, 70, 119, |
| 39 | 36, 21, 59, 10, 89, 104, 255, 206, 157, 172 |
| 40 | }; |
| 41 | |
| 42 | void SHT11::crcCalc(uint8_t x) {
|
| 43 | crc8 = pgm_read_byte(crcTab + (x ^ crc8)); |
| 44 | } |
| 45 | |
| 46 | static void dummyCRC(uint8_t) {} |
| 47 | |
| 48 | // static variables, i.e. CRC can only be enabled for all SHT11 devices at once
|
| 49 | // the code below avoids linking in any CRC code if enableCRC() is never called
|
| 50 | |
| 51 | uint8_t SHT11::crc8 = 0;
|
| 52 | void (*SHT11::crcFun)(uint8_t) = &dummyCRC;
|
| 53 | |
| 54 | void SHT11::enableCRC() {
|
| 55 | SHT11::crcFun = crcCalc; |
| 56 | } |
| 57 | |
| 58 | // idle line state is with data as input pulled high, and clock as output low
|
| 59 | |
| 60 | void SHT11::clock(uint8_t x) const { |
| 61 | delayMicroseconds(2);
|
| 62 | digiWrite2(x); |
| 63 | delayMicroseconds(5);
|
| 64 | } |
| 65 | |
| 66 | void SHT11::release() const { |
| 67 | mode(INPUT); |
| 68 | digiWrite(1);
|
| 69 | } |
| 70 | |
| 71 | uint8_t SHT11::writeByte(uint8_t value) const {
|
| 72 | mode(OUTPUT); |
| 73 | for (uint8_t i = 0x80; i != 0; i >>= 1) { |
| 74 | digiWrite(value & i); |
| 75 | clock(1);
|
| 76 | clock(0);
|
| 77 | } |
| 78 | release(); |
| 79 | clock(1);
|
| 80 | uint8_t error = digiRead(); |
| 81 | clock(0);
|
| 82 | |
| 83 | crcFun(value); |
| 84 | return error;
|
| 85 | } |
| 86 | |
| 87 | uint8_t SHT11::readByte(uint8_t ack) const {
|
| 88 | uint8_t value = 0;
|
| 89 | for (uint8_t i = 0x80; i != 0; i >>= 1) { |
| 90 | clock(1);
|
| 91 | if (digiRead())
|
| 92 | value |= i; |
| 93 | clock(0);
|
| 94 | } |
| 95 | mode(OUTPUT); |
| 96 | digiWrite(!ack); |
| 97 | clock(1);
|
| 98 | clock(0);
|
| 99 | release(); |
| 100 | |
| 101 | crcFun(value); |
| 102 | return value;
|
| 103 | } |
| 104 | |
| 105 | void SHT11::start() const { |
| 106 | clock(0);
|
| 107 | mode(OUTPUT); |
| 108 | digiWrite(1);
|
| 109 | |
| 110 | clock(1);
|
| 111 | digiWrite(0);
|
| 112 | clock(0);
|
| 113 | clock(1);
|
| 114 | digiWrite(1);
|
| 115 | clock(0);
|
| 116 | release(); |
| 117 | |
| 118 | crc8 = 0;
|
| 119 | } |
| 120 | |
| 121 | void SHT11::connReset() const { |
| 122 | mode2(OUTPUT); |
| 123 | clock(0);
|
| 124 | mode(OUTPUT); |
| 125 | digiWrite(1);
|
| 126 | for (uint8_t i = 0; i < 9; ++i) { |
| 127 | clock(1);
|
| 128 | clock(0);
|
| 129 | } |
| 130 | start(); |
| 131 | } |
| 132 | |
| 133 | void SHT11::softReset() const { |
| 134 | connReset(); |
| 135 | writeByte(RESET); |
| 136 | delay(11);
|
| 137 | } |
| 138 | |
| 139 | uint8_t SHT11::readStatus() const {
|
| 140 | start(); |
| 141 | writeByte(STATUS_REG_R); |
| 142 | uint8_t value = readByte(1);
|
| 143 | readByte(0);
|
| 144 | return value;
|
| 145 | } |
| 146 | |
| 147 | void SHT11::writeStatus(uint8_t value) const { |
| 148 | start(); |
| 149 | writeByte(STATUS_REG_W); |
| 150 | writeByte(value); |
| 151 | } |
| 152 | |
| 153 | uint8_t SHT11::measure(uint8_t type, void (*delayFun)()) {
|
| 154 | start(); |
| 155 | writeByte(type == TEMP? MEASURE_TEMP : MEASURE_HUMI); |
| 156 | for (uint8_t i = 0; i < 250; ++i) { |
| 157 | if (!digiRead()) {
|
| 158 | meas[type] = readByte(1) << 8; |
| 159 | meas[type] |= readByte(1);
|
| 160 | uint8_t flipped = 0;
|
| 161 | for (uint8_t j = 0x80; j != 0; j >>= 1) { |
| 162 | flipped >>= 1;
|
| 163 | if (crc8 & j)
|
| 164 | flipped |= 0x80;
|
| 165 | } |
| 166 | if (readByte(0) != flipped) |
| 167 | break;
|
| 168 | return 0; |
| 169 | } |
| 170 | if (delayFun)
|
| 171 | delayFun(); |
| 172 | else
|
| 173 | delay(1);
|
| 174 | } |
| 175 | connReset(); |
| 176 | return 1; |
| 177 | } |
| 178 | |
| 179 | #ifndef __AVR_ATtiny84__
|
| 180 | void SHT11::calculate(float& rh_true, float& t_C) const { |
| 181 | const float C1=-2.0468; |
| 182 | const float C2= 0.0367; |
| 183 | const float C3=-1.5955e-6; |
| 184 | const float T1=0.01; |
| 185 | const float T2=0.00008; |
| 186 | |
| 187 | t_C = meas[TEMP] * 0.01 - 39.66; // for 3.3 V |
| 188 | |
| 189 | float rh = meas[HUMI];
|
| 190 | rh_true = (t_C-25)*(T1+T2*rh) + C3*rh*rh + C2*rh + C1;
|
| 191 | if (rh_true > 99) rh_true = 100; |
| 192 | if (rh_true < 0.1) rh_true = 0.1; |
| 193 | } |
| 194 | |
| 195 | float SHT11::dewpoint(float h, float t) { |
| 196 | float k = (log10(h)-2)/0.4343 + (17.62*t)/(243.12+t); |
| 197 | return 243.12*k/(17.62-k); |
| 198 | } |
| 199 | #else
|
| 200 | //XXX TINY!
|
| 201 | #endif
|