-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSI_7021.cpp
More file actions
144 lines (115 loc) · 4.07 KB
/
SI_7021.cpp
File metadata and controls
144 lines (115 loc) · 4.07 KB
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
/*
* File: SI_7021.cpp
* Author: Gary Stofer
*
* Created on December 18, 2013, 8:25 PM
*/
/* Functions to initialzie and read the SI 7021 Relative humidity sensor device */
#include "SI_7021.h"
//////////////////////////////////////////// Humidity sensor SI 7021 //////////////////////
#define SI7021_ADDR (0x40<<1)
#define SI7021_RESET_CMD 0xFE
#define SI7021_Convert_CMD 0xF5 // Starts a temperature and RH conversion cycle, but does not hold CLK line until complete
#define SI7021_ReadPrevTemp_CMD 0xE0 // Read out the temperature reading from the previous conversion
#define SI7021_WriteUserRegister 0xE6 // used to turn the heater on and set ADC resolution
#define SI7021_ReadUserRegister 0xE7
// Structure to read the on chip calibration values
enum _SI7021_READ_SM {
SM_START = 0,
SM_Wait_Results,
SM_Read_Results,
SM_ERROR,
SM_STOP,
SM_IDLE,
SM_NOTFOUND
};
static int ThisState = SM_NOTFOUND;
struct tag_HygReadings HygReading;
// See if the Device can be addressed -- Listen for the ACK on address
unsigned short
SI7021_init(void)
{
unsigned short BusErr = 0;
i2c_init();
if ((BusErr = i2c_start( SI7021_ADDR +I2C_WRITE )) !=0 )
{
ThisState = SM_NOTFOUND;
}
else
ThisState = SM_IDLE;
i2c_stop(); // and finish by transition into stop state
return ( BusErr ); // i2c bus could not be opened, or device not attached
}
void
SI7021_startMeasure(void)
{
if(ThisState == SM_IDLE)
ThisState = SM_START;
}
void
SI7021_Read_Process(void )
{
static unsigned long t;
union {
unsigned char bytes[2];
unsigned short val;
} ADC_RH;
union {
unsigned char bytes[2];
unsigned short val;
} ADC_TEMP;
switch (ThisState)
{
case SM_START: // initiate the Temp and RH conversion
if ( i2c_start( SI7021_ADDR +I2C_WRITE ) != 0) // if the device fails to ack the address
{
ThisState = SM_ERROR;
break;
}
i2c_write( SI7021_Convert_CMD); // internal register address
i2c_stop();
t = millis();
ThisState++;
break;
case SM_Wait_Results: // The conversion should take a maximum of 20.4 ms
if ((millis() - t) > 30) // wait for the result to arrive
ThisState++;
break;
case SM_Read_Results:
if ( i2c_start( SI7021_ADDR +I2C_READ ) != 0) // Check for ACK-- If conversion is not ready yet device repsonds with NACK
{
ThisState = SM_ERROR;
break;
}
ADC_RH.bytes[1] = i2c_readAck();// read rh data msb
ADC_RH.bytes[0] = i2c_readNak(); // read rh data lsb
i2c_stop();
// Collect the temperature data from the last conversion
if ( i2c_start( SI7021_ADDR + I2C_WRITE ) != 0) // if the device fails to ack the address
{
ThisState = SM_ERROR;
break;
}
i2c_write( SI7021_ReadPrevTemp_CMD); // internal register address
i2c_rep_start( SI7021_ADDR +I2C_READ ); // restart in Read mode now
ADC_TEMP.bytes[1] = i2c_readAck(); // read Temp data msb
ADC_TEMP.bytes[0] = i2c_readNak(); // read Temp data lsb
i2c_stop();
HygReading.TempC = (ADC_TEMP.val*175.72/65536) -46.85; // Magic numbers from SI datasheet
HygReading.RelHum = (ADC_RH.val*125.0/65536)-6.0; // Magic numbers from SI datasheet
ThisState = SM_IDLE;
break;
case SM_ERROR:
HygReading.TempC = -302.0; // impossible numbers
HygReading.RelHum = 1.0;
i2c_stop();
ThisState++;
break;
case SM_IDLE: // park here until someone starts the process again.
break;
case SM_NOTFOUND: // initially not found -- never escapes from here.
HygReading.TempC = -302.0; // Equally impossible numbers
HygReading.RelHum = 2.0;
break;
}
}