-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSensirion_SGP40.py
172 lines (146 loc) · 6.24 KB
/
Sensirion_SGP40.py
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import smbus
import time
from Sensirion_SGP40_VOCAlgorithm import Sensirion_VOCAlgorithm
class Sensirion_SGP40:
SGP40_ICC_ADDR = 0x59
TEST_OK_H = 0xD4
TEST_OK_L = 0x00
CMD_HEATER_OFF_H = 0x36
CMD_HEATER_OFF_L = 0x15
CMD_MEASURE_TEST_H = 0x28
CMD_MEASURE_TEST_L = 0x0E
CMD_SOFT__reset_H = 0x00
CMD_SOFT__reset_L = 0x06
CMD_MEASURE_RAW_H = 0x26
CMD_MEASURE_RAW_L = 0x0F
DURATION_READ_RAW_VOC = 0.03
DURATION_WAIT_MEASURE_TEST = 0.25
OFFSET = 0x00
def __init__(self,bus = 1,relative_humidity = 50,temperature_c = 25):
""" Module init
:param bus:int Set to IICBus
:param relative_humidity:float Set to relative_humidity
:param temperature_c:float Set to temperature
"""
self.__i2cbus = smbus.SMBus(bus)
self.__my_vocalgorithm = Sensirion_VOCAlgorithm()
self.__i2c_addr = self.SGP40_ICC_ADDR
self.c = temperature_c
self.__temperature_c = self.c
self.__relative_humidity = relative_humidity
self.__rh = 0
self.__temc = 0
self.__rh_h = 0
self.__rh_l = 0
self.__temc_h = 0
self.__temc_l = 0
self.__temc__crc = 0
self.__rh__crc = 0
def set_envparams(self, relative_humidity,temperature_c):
""" Set temperature and humidity
:param relative_humidity:float Set to relative_humidity
:param temperature_c:float Set to temperature
"""
self.__temperature_c = temperature_c
self.__relative_humidity = relative_humidity
def begin(self,duration = 10):
""" start equipment
:param duration:int Set to Warm-up time
:return int equipment condition
: 0 succeed
: 1 failed
"""
self.__my_vocalgorithm.vocalgorithm_init()
timeOne = int(time.time())
while(int(time.time())-timeOne<duration):
self.get_voc_index()
return self.__measure_test()
def measure_raw(self):
""" Get raw data
: return int collect result
:-1 collect failed
:>0 the collection value
"""
self.__data_transform()
self.__i2cbus.write_i2c_block_data(self.__i2c_addr,self.CMD_MEASURE_RAW_H, [self.CMD_MEASURE_RAW_L,self.__rh_h,self.__rh_l,self.__rh__crc,self.__temc_h,self.__temc_l,self.__temc__crc])
time.sleep(self.DURATION_READ_RAW_VOC)
raw = self.__i2cbus.read_i2c_block_data(self.__i2c_addr,self.OFFSET,3)
if self.__check__crc(raw) == 0:
return raw[0]<<8 | raw[1]
else:
return -1
def get_voc_index(self):
""" Measure VOC index after humidity compensation
:note VOC index can indicate the quality of the air directly. The larger the value, the worse the air quality.
:note 0-100,no need to ventilate, purify
:note 100-200,no need to ventilate, purify
:note 200-400,ventilate, purify
:note 00-500,ventilate, purify intensely
:return int The VOC index measured, ranged from 0 to 500
"""
raw = self.measure_raw()
if raw<0:
return -1
else:
vocIndex = self.__my_vocalgorithm.vocalgorithm_process(raw)
return vocIndex
def __data_transform(self):
""" Convert environment parameters
"""
self.__rh = int(((self.__relative_humidity*65535)/100+0.5))
self.__temc = int(((self.__temperature_c+45)*(65535/175)+0.5))
self.__rh_h = int(self.__rh)>>8
self.__rh_l = int(self.__rh)&0xFF
self.__rh__crc = self.__crc(self.__rh_h,self.__rh_l)
self.__temc_h = int(self.__temc)>>8
self.__temc_l = int(self.__temc)&0xFF
self.__temc__crc = self.__crc(self.__temc_h,self.__temc_l)
def __measure_test(self):
""" Sensor self-test
:return int self-test condition
: 0 succeed
: 1 failed
"""
self.__i2cbus.write_i2c_block_data(self.__i2c_addr,self.CMD_MEASURE_TEST_H, [self.CMD_MEASURE_TEST_L])
time.sleep(self.DURATION_WAIT_MEASURE_TEST)
raw = self.__i2cbus.read_i2c_block_data(self.__i2c_addr,self.OFFSET,2)
if raw[0] == self.TEST_OK_H and raw[1] == self.TEST_OK_L :
return 0
else:
return 1
def __reset(self):
""" Sensor reset
"""
self.__i2cbus.write_i2c_block_data(self.__i2c_addr,self.CMD_SOFT__reset_H, [self.CMD_SOFT__reset_L])
def __heater_off(self):
""" spg40 Heater Off. Turn the hotplate off and stop the measurement. Subsequently, the sensor enters the idle mode.
"""
self.__i2cbus.write_i2c_block_data(self.__i2c_addr,self.CMD_HEATER_OFF_H, [self.CMD_HEATER_OFF_L])
def __check__crc(self, raw):
""" Verify the calibration value of the sensor
:param raw : list Parameter to check
:return int Check result
:-1 Check failed
: 0 Check succeed
"""
assert (len(raw) == 3)
if self.__crc(raw[0], raw[1]) != raw[2]:
return -1
return 0
def __crc(self,data_1,data_2):
""" CRC
:param data1 High 8 bits data
:param data2 LOW 8 bits data
:return int Calibration value
"""
crc = 0xff
list = [data_1,data_2]
for i in range(0,2):
crc = crc^list[i]
for bit in range(0,8):
if(crc&0x80):
crc = ((crc <<1)^0x31)
else:
crc = (crc<<1)
crc = crc&0xFF
return crc