DHT22.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # 2014-07-11 DHT22.py
4 
5 import time
6 import atexit
7 
8 import pigpio
9 
10 class sensor:
11  """
12  A class to read relative humidity and temperature from the
13  DHT22 sensor. The sensor is also known as the AM2302.
14 
15  The sensor can be powered from the Pi 3V3 or the Pi 5V rail.
16 
17  Powering from the 3V3 rail is simpler and safer. You may need
18  to power from 5V if the sensor is connected via a long cable.
19 
20  For 3V3 operation connect pin 1 to 3V3 and pin 4 to ground.
21 
22  Connect pin 2 to a gpio.
23 
24  For 5V operation connect pin 1 to 5V and pin 4 to ground.
25 
26  The following pin 2 connection works for me. Use at YOUR OWN RISK.
27 
28  5V--5K_resistor--+--10K_resistor--Ground
29  |
30  DHT22 pin 2 -----+
31  |
32  gpio ------------+
33  """
34 
35  def __init__(self, pi, gpio, LED=None, power=None):
36  """
37  Instantiate with the Pi and gpio to which the DHT22 output
38  pin is connected.
39 
40  Optionally a LED may be specified. This will be blinked for
41  each successful reading.
42 
43  Optionally a gpio used to power the sensor may be specified.
44  This gpio will be set high to power the sensor. If the sensor
45  locks it will be power cycled to restart the readings.
46 
47  Taking readings more often than about once every two seconds will
48  eventually cause the DHT22 to hang. A 3 second interval seems OK.
49  """
50 
51  self.pi = pi
52  self.gpio = gpio
53  self.LED = LED
54  self.power = power
55 
56  if power is not None:
57  pi.write(power, 1) # Switch sensor on.
58  time.sleep(2)
59 
60  self.powered = True
61 
62  self.cb = None
63 
64  atexit.register(self.cancel)
65 
66  self.bad_CS = 0 # Bad checksum count.
67  self.bad_SM = 0 # Short message count.
68  self.bad_MM = 0 # Missing message count.
69  self.bad_SR = 0 # Sensor reset count.
70 
71  # Power cycle if timeout > MAX_TIMEOUTS.
72  self.no_response = 0
73  self.MAX_NO_RESPONSE = 2
74 
75  self.rhum = -999
76  self.temp = -999
77 
78  self.tov = None
79 
80  self.high_tick = 0
81  self.bit = 40
82 
83  pi.set_pull_up_down(gpio, pigpio.PUD_OFF)
84 
85  pi.set_watchdog(gpio, 0) # Kill any watchdogs.
86 
87  self.cb = pi.callback(gpio, pigpio.EITHER_EDGE, self._cb)
88 
89  def _cb(self, gpio, level, tick):
90  """
91  Accumulate the 40 data bits. Format into 5 bytes, humidity high,
92  humidity low, temperature high, temperature low, checksum.
93  """
94  diff = pigpio.tickDiff(self.high_tick, tick)
95 
96  if level == 0:
97 
98  # Edge length determines if bit is 1 or 0.
99 
100  if diff >= 50:
101  val = 1
102  if diff >= 200: # Bad bit?
103  self.CS = 256 # Force bad checksum.
104  else:
105  val = 0
106 
107  if self.bit >= 40: # Message complete.
108  self.bit = 40
109 
110  elif self.bit >= 32: # In checksum byte.
111  self.CS = (self.CS << 1) + val
112 
113  if self.bit == 39:
114 
115  # 40th bit received.
116 
117  self.pi.set_watchdog(self.gpio, 0)
118 
119  self.no_response = 0
120 
121  total = self.hH + self.hL + self.tH + self.tL
122 
123  if (total & 255) == self.CS: # Is checksum ok?
124 
125  self.rhum = ((self.hH << 8) + self.hL) * 0.1
126 
127  if self.tH & 128: # Negative temperature.
128  mult = -0.1
129  self.tH = self.tH & 127
130  else:
131  mult = 0.1
132 
133  self.temp = ((self.tH << 8) + self.tL) * mult
134 
135  self.tov = time.time()
136 
137  if self.LED is not None:
138  self.pi.write(self.LED, 0)
139 
140  else:
141 
142  self.bad_CS += 1
143 
144  elif self.bit >= 24: # in temp low byte
145  self.tL = (self.tL << 1) + val
146 
147  elif self.bit >= 16: # in temp high byte
148  self.tH = (self.tH << 1) + val
149 
150  elif self.bit >= 8: # in humidity low byte
151  self.hL = (self.hL << 1) + val
152 
153  elif self.bit >= 0: # in humidity high byte
154  self.hH = (self.hH << 1) + val
155 
156  else: # header bits
157  pass
158 
159  self.bit += 1
160 
161  elif level == 1:
162  self.high_tick = tick
163  if diff > 250000:
164  self.bit = -2
165  self.hH = 0
166  self.hL = 0
167  self.tH = 0
168  self.tL = 0
169  self.CS = 0
170 
171  else: # level == pigpio.TIMEOUT:
172  self.pi.set_watchdog(self.gpio, 0)
173  if self.bit < 8: # Too few data bits received.
174  self.bad_MM += 1 # Bump missing message count.
175  self.no_response += 1
176  if self.no_response > self.MAX_NO_RESPONSE:
177  self.no_response = 0
178  self.bad_SR += 1 # Bump sensor reset count.
179  if self.power is not None:
180  self.powered = False
181  self.pi.write(self.power, 0)
182  time.sleep(2)
183  self.pi.write(self.power, 1)
184  time.sleep(2)
185  self.powered = True
186  elif self.bit < 39: # Short message receieved.
187  self.bad_SM += 1 # Bump short message count.
188  self.no_response = 0
189 
190  else: # Full message received.
191  self.no_response = 0
192 
193  def temperature(self):
194  """Return current temperature."""
195  return self.temp
196 
197  def humidity(self):
198  """Return current relative humidity."""
199  return self.rhum
200 
201  def staleness(self):
202  """Return time since measurement made."""
203  if self.tov is not None:
204  return time.time() - self.tov
205  else:
206  return -999
207 
208  def bad_checksum(self):
209  """Return count of messages received with bad checksums."""
210  return self.bad_CS
211 
212  def short_message(self):
213  """Return count of short messages."""
214  return self.bad_SM
215 
216  def missing_message(self):
217  """Return count of missing messages."""
218  return self.bad_MM
219 
220  def sensor_resets(self):
221  """Return count of power cycles because of sensor hangs."""
222  return self.bad_SR
223 
224  def trigger(self):
225  """Trigger a new relative humidity and temperature reading."""
226  if self.powered:
227  if self.LED is not None:
228  self.pi.write(self.LED, 1)
229 
230  self.pi.write(self.gpio, pigpio.LOW)
231  time.sleep(0.017) # 17 ms
232  self.pi.set_mode(self.gpio, pigpio.INPUT)
233  self.pi.set_watchdog(self.gpio, 200)
234 
235  def cancel(self):
236  """Cancel the DHT22 sensor."""
237 
238  self.pi.set_watchdog(self.gpio, 0)
239 
240  if self.cb is not None:
241  self.cb.cancel()
242  self.cb = None
243 
244 if __name__ == "__main__":
245 
246  import time
247 
248  import pigpio
249 
250  import DHT22
251 
252  # Intervals of about 2 seconds or less will eventually hang the DHT22.
253  INTERVAL = 3
254 
255  pi = pigpio.pi()
256 
257  s = DHT22.sensor(pi, 22, LED=16, power=8)
258 
259  r = 0
260 
261  next_reading = time.time()
262 
263  while True:
264 
265  r += 1
266 
267  s.trigger()
268 
269  time.sleep(0.2)
270 
271  print("{} {} {} {:3.2f} {} {} {} {}".format(
272  r, s.humidity(), s.temperature(), s.staleness(),
273  s.bad_checksum(), s.short_message(), s.missing_message(),
274  s.sensor_resets()))
275 
276  next_reading += INTERVAL
277 
278  time.sleep(next_reading-time.time()) # Overall INTERVAL second polling.
279 
280  s.cancel()
281 
282  pi.stop()
283 
def humidity(self)
Definition: DHT22.py:197
def cancel(self)
Definition: DHT22.py:235
def missing_message(self)
Definition: DHT22.py:216
def temperature(self)
Definition: DHT22.py:193
MAX_NO_RESPONSE
Definition: DHT22.py:73
def __init__(self, pi, gpio, LED=None, power=None)
Definition: DHT22.py:35
def trigger(self)
Definition: DHT22.py:224
def short_message(self)
Definition: DHT22.py:212
def _cb(self, gpio, level, tick)
Definition: DHT22.py:89
def tickDiff(t1, t2)
Definition: pigpio.py:911
def sensor_resets(self)
Definition: DHT22.py:220
def bad_checksum(self)
Definition: DHT22.py:208
def staleness(self)
Definition: DHT22.py:201


cob_hand_bridge
Author(s): Mathias Lüdtke
autogenerated on Tue Oct 20 2020 03:35:57