-
Notifications
You must be signed in to change notification settings - Fork 11
/
SI7021.cpp
158 lines (133 loc) · 3.96 KB
/
SI7021.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
Copyright 2014 Marcus Sorensen <marcus@electron14.com>
This program is licensed under the GNU LGPL v2.1
*/
#include "Arduino.h"
#include "SI7021.h"
#include <Wire.h>
#define I2C_ADDR 0x40
// I2C commands
byte RH_READ[] = { 0xE5 };
byte TEMP_READ[] = { 0xE3 };
byte POST_RH_TEMP_READ[] = { 0xE0 };
byte RESET[] = { 0xFE };
byte USER1_READ[] = { 0xE7 };
byte USER1_WRITE[] = { 0xE6 };
byte SERIAL1_READ[] = { 0xFA, 0x0F };
byte SERIAL2_READ[] = { 0xFC, 0xC9 };
bool _si_exists = false;
SI7021::SI7021() {
}
bool SI7021::begin() {
Wire.begin();
Wire.beginTransmission(I2C_ADDR);
if (Wire.endTransmission() == 0) {
_si_exists = true;
}
return _si_exists;
}
bool SI7021::sensorExists() {
return _si_exists;
}
int SI7021::getFahrenheitHundredths() {
unsigned int c = getCelsiusHundredths();
return (1.8 * c) + 3200;
}
int SI7021::getCelsiusHundredths() {
byte tempbytes[2];
_command(TEMP_READ, tempbytes);
long tempraw = (long)tempbytes[0] << 8 | tempbytes[1];
return ((17572 * tempraw) >> 16) - 4685;
}
int SI7021::_getCelsiusPostHumidity() {
byte tempbytes[2];
_command(POST_RH_TEMP_READ, tempbytes);
long tempraw = (long)tempbytes[0] << 8 | tempbytes[1];
return ((17572 * tempraw) >> 16) - 4685;
}
unsigned int SI7021::getHumidityPercent() {
byte humbytes[2];
_command(RH_READ, humbytes);
long humraw = (long)humbytes[0] << 8 | humbytes[1];
return ((125 * humraw) >> 16) - 6;
}
unsigned int SI7021::getHumidityBasisPoints() {
byte humbytes[2];
_command(RH_READ, humbytes);
long humraw = (long)humbytes[0] << 8 | humbytes[1];
return ((12500 * humraw) >> 16) - 600;
}
void SI7021::_command(byte * cmd, byte * buf ) {
_writeReg(cmd, sizeof cmd);
_readReg(buf, sizeof buf);
}
void SI7021::_writeReg(byte * reg, int reglen) {
Wire.beginTransmission(I2C_ADDR);
for(int i = 0; i < reglen; i++) {
reg += i;
Wire.write(*reg);
}
Wire.endTransmission();
}
int SI7021::_readReg(byte * reg, int reglen) {
Wire.requestFrom(I2C_ADDR, reglen);
while(Wire.available() < reglen) {
}
for(int i = 0; i < reglen; i++) {
reg[i] = Wire.read();
}
return 1;
}
//note this has crc bytes embedded, per datasheet, so provide 12 byte buf
// DEPRECATED, keeping to avoid breaking linked code
int SI7021::getSerialBytes(byte * buf) {
_writeReg(SERIAL1_READ, sizeof SERIAL1_READ);
_readReg(buf, 6);
_writeReg(SERIAL2_READ, sizeof SERIAL2_READ);
_readReg(buf + 6, 6);
// could verify crc here and return only the 8 bytes that matter
return 1;
}
// we ignore CRC here, provide 8 byte buffer
// use this instead of getSerialBytes
int SI7021::getEightByteSerial(byte * buf) {
// note we are ignoring CRC bytes
byte serial[8];
_writeReg(SERIAL1_READ, sizeof SERIAL1_READ);
_readReg(serial, 8);
buf[0] = serial[0]; //SNA_3
buf[1] = serial[2]; //SNA_2
buf[2] = serial[4]; //SNA_1
buf[3] = serial[6]; //SNA_0
_writeReg(SERIAL2_READ, sizeof SERIAL2_READ);
_readReg(serial, 6);
buf[4] = serial[0]; //SNB_3, AKA SI device type ID
buf[5] = serial[1]; //SNB_2
buf[6] = serial[3]; //SNB_1
buf[7] = serial[4]; //SNB_0
return 1;
}
int SI7021::getDeviceId() {
byte serial[8];
getEightByteSerial(serial);
int id = serial[4];
return id;
}
void SI7021::setHeater(bool on) {
byte userbyte;
if (on) {
userbyte = 0x3E;
} else {
userbyte = 0x3A;
}
byte userwrite[] = {USER1_WRITE[0], userbyte};
_writeReg(userwrite, sizeof userwrite);
}
// get humidity, then get temperature reading from humidity measurement
struct si7021_env SI7021::getHumidityAndTemperature() {
si7021_env ret = {0, 0, 0};
ret.humidityBasisPoints = getHumidityBasisPoints();
ret.celsiusHundredths = _getCelsiusPostHumidity();
ret.fahrenheitHundredths = (1.8 * ret.celsiusHundredths) + 3200;
return ret;
}