Statistics
| Revision:

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