Skip to content

Commit 5c9ddd6

Browse files
committed
Moved dht11.py into __init__.py
1 parent cf9f4f5 commit 5c9ddd6

File tree

2 files changed

+202
-203
lines changed

2 files changed

+202
-203
lines changed

dht11/__init__.py

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,203 @@
1+
import time
2+
import RPi
13

4+
5+
class DHT11Result:
6+
'DHT11 sensor result returned by DHT11.read() method'
7+
8+
ERR_NO_ERROR = 0
9+
ERR_MISSING_DATA = 1
10+
ERR_CRC = 2
11+
12+
error_code = ERR_NO_ERROR
13+
temperature = -1
14+
humidity = -1
15+
16+
def __init__(self, error_code, temperature, humidity):
17+
self.error_code = error_code
18+
self.temperature = temperature
19+
self.humidity = humidity
20+
21+
def is_valid(self):
22+
return self.error_code == DHT11Result.ERR_NO_ERROR
23+
24+
25+
class DHT11:
26+
'DHT11 sensor reader class for Raspberry'
27+
28+
__pin = 0
29+
30+
def __init__(self, pin):
31+
self.__pin = pin
32+
33+
def read(self):
34+
RPi.GPIO.setup(self.__pin, RPi.GPIO.OUT)
35+
36+
# send initial high
37+
self.__send_and_sleep(RPi.GPIO.HIGH, 0.05)
38+
39+
# pull down to low
40+
self.__send_and_sleep(RPi.GPIO.LOW, 0.02)
41+
42+
# change to input using pull up
43+
RPi.GPIO.setup(self.__pin, RPi.GPIO.IN, RPi.GPIO.PUD_UP)
44+
45+
# collect data into an array
46+
data = self.__collect_input()
47+
48+
# parse lengths of all data pull up periods
49+
pull_up_lengths = self.__parse_data_pull_up_lengths(data)
50+
51+
# if bit count mismatch, return error (4 byte data + 1 byte checksum)
52+
if len(pull_up_lengths) != 40:
53+
return DHT11Result(DHT11Result.ERR_MISSING_DATA, 0, 0)
54+
55+
# calculate bits from lengths of the pull up periods
56+
bits = self.__calculate_bits(pull_up_lengths)
57+
58+
# we have the bits, calculate bytes
59+
the_bytes = self.__bits_to_bytes(bits)
60+
61+
# calculate checksum and check
62+
checksum = self.__calculate_checksum(the_bytes)
63+
if the_bytes[4] != checksum:
64+
return DHT11Result(DHT11Result.ERR_CRC, 0, 0)
65+
66+
# ok, we have valid data
67+
68+
# The meaning of the return sensor values
69+
# the_bytes[0]: humidity int
70+
# the_bytes[1]: humidity decimal
71+
# the_bytes[2]: temperature int
72+
# the_bytes[3]: temperature decimal
73+
74+
temperature = the_bytes[2] + float(the_bytes[3]) / 10
75+
humidity = the_bytes[0] + float(the_bytes[1]) / 10
76+
77+
return DHT11Result(DHT11Result.ERR_NO_ERROR, temperature, humidity)
78+
79+
def __send_and_sleep(self, output, sleep):
80+
RPi.GPIO.output(self.__pin, output)
81+
time.sleep(sleep)
82+
83+
def __collect_input(self):
84+
# collect the data while unchanged found
85+
unchanged_count = 0
86+
87+
# this is used to determine where is the end of the data
88+
max_unchanged_count = 100
89+
90+
last = -1
91+
data = []
92+
while True:
93+
current = RPi.GPIO.input(self.__pin)
94+
data.append(current)
95+
if last != current:
96+
unchanged_count = 0
97+
last = current
98+
else:
99+
unchanged_count += 1
100+
if unchanged_count > max_unchanged_count:
101+
break
102+
103+
return data
104+
105+
def __parse_data_pull_up_lengths(self, data):
106+
STATE_INIT_PULL_DOWN = 1
107+
STATE_INIT_PULL_UP = 2
108+
STATE_DATA_FIRST_PULL_DOWN = 3
109+
STATE_DATA_PULL_UP = 4
110+
STATE_DATA_PULL_DOWN = 5
111+
112+
state = STATE_INIT_PULL_DOWN
113+
114+
lengths = [] # will contain the lengths of data pull up periods
115+
current_length = 0 # will contain the length of the previous period
116+
117+
for i in range(len(data)):
118+
119+
current = data[i]
120+
current_length += 1
121+
122+
if state == STATE_INIT_PULL_DOWN:
123+
if current == RPi.GPIO.LOW:
124+
# ok, we got the initial pull down
125+
state = STATE_INIT_PULL_UP
126+
continue
127+
else:
128+
continue
129+
if state == STATE_INIT_PULL_UP:
130+
if current == RPi.GPIO.HIGH:
131+
# ok, we got the initial pull up
132+
state = STATE_DATA_FIRST_PULL_DOWN
133+
continue
134+
else:
135+
continue
136+
if state == STATE_DATA_FIRST_PULL_DOWN:
137+
if current == RPi.GPIO.LOW:
138+
# we have the initial pull down, the next will be the data pull up
139+
state = STATE_DATA_PULL_UP
140+
continue
141+
else:
142+
continue
143+
if state == STATE_DATA_PULL_UP:
144+
if current == RPi.GPIO.HIGH:
145+
# data pulled up, the length of this pull up will determine whether it is 0 or 1
146+
current_length = 0
147+
state = STATE_DATA_PULL_DOWN
148+
continue
149+
else:
150+
continue
151+
if state == STATE_DATA_PULL_DOWN:
152+
if current == RPi.GPIO.LOW:
153+
# pulled down, we store the length of the previous pull up period
154+
lengths.append(current_length)
155+
state = STATE_DATA_PULL_UP
156+
continue
157+
else:
158+
continue
159+
160+
return lengths
161+
162+
def __calculate_bits(self, pull_up_lengths):
163+
# find shortest and longest period
164+
shortest_pull_up = 1000
165+
longest_pull_up = 0
166+
167+
for i in range(0, len(pull_up_lengths)):
168+
length = pull_up_lengths[i]
169+
if length < shortest_pull_up:
170+
shortest_pull_up = length
171+
if length > longest_pull_up:
172+
longest_pull_up = length
173+
174+
# use the halfway to determine whether the period it is long or short
175+
halfway = shortest_pull_up + (longest_pull_up - shortest_pull_up) / 2
176+
bits = []
177+
178+
for i in range(0, len(pull_up_lengths)):
179+
bit = False
180+
if pull_up_lengths[i] > halfway:
181+
bit = True
182+
bits.append(bit)
183+
184+
return bits
185+
186+
def __bits_to_bytes(self, bits):
187+
the_bytes = []
188+
byte = 0
189+
190+
for i in range(0, len(bits)):
191+
byte = byte << 1
192+
if (bits[i]):
193+
byte = byte | 1
194+
else:
195+
byte = byte | 0
196+
if ((i + 1) % 8 == 0):
197+
the_bytes.append(byte)
198+
byte = 0
199+
200+
return the_bytes
201+
202+
def __calculate_checksum(self, the_bytes):
203+
return the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3] & 255

0 commit comments

Comments
 (0)