Statistics
| Revision:

root / Ports / PortsSHT11.cpp

History | View | Annotate | Download (5.1 KB)

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