Go to the documentation of this file.00001
00002
00003
00004
00005 import time
00006 import atexit
00007
00008 import pigpio
00009
00010 class sensor:
00011 """
00012 A class to read relative humidity and temperature from the
00013 DHT22 sensor. The sensor is also known as the AM2302.
00014
00015 The sensor can be powered from the Pi 3V3 or the Pi 5V rail.
00016
00017 Powering from the 3V3 rail is simpler and safer. You may need
00018 to power from 5V if the sensor is connected via a long cable.
00019
00020 For 3V3 operation connect pin 1 to 3V3 and pin 4 to ground.
00021
00022 Connect pin 2 to a gpio.
00023
00024 For 5V operation connect pin 1 to 5V and pin 4 to ground.
00025
00026 The following pin 2 connection works for me. Use at YOUR OWN RISK.
00027
00028 5V--5K_resistor--+--10K_resistor--Ground
00029 |
00030 DHT22 pin 2 -----+
00031 |
00032 gpio ------------+
00033 """
00034
00035 def __init__(self, pi, gpio, LED=None, power=None):
00036 """
00037 Instantiate with the Pi and gpio to which the DHT22 output
00038 pin is connected.
00039
00040 Optionally a LED may be specified. This will be blinked for
00041 each successful reading.
00042
00043 Optionally a gpio used to power the sensor may be specified.
00044 This gpio will be set high to power the sensor. If the sensor
00045 locks it will be power cycled to restart the readings.
00046
00047 Taking readings more often than about once every two seconds will
00048 eventually cause the DHT22 to hang. A 3 second interval seems OK.
00049 """
00050
00051 self.pi = pi
00052 self.gpio = gpio
00053 self.LED = LED
00054 self.power = power
00055
00056 if power is not None:
00057 pi.write(power, 1)
00058 time.sleep(2)
00059
00060 self.powered = True
00061
00062 self.cb = None
00063
00064 atexit.register(self.cancel)
00065
00066 self.bad_CS = 0
00067 self.bad_SM = 0
00068 self.bad_MM = 0
00069 self.bad_SR = 0
00070
00071
00072 self.no_response = 0
00073 self.MAX_NO_RESPONSE = 2
00074
00075 self.rhum = -999
00076 self.temp = -999
00077
00078 self.tov = None
00079
00080 self.high_tick = 0
00081 self.bit = 40
00082
00083 pi.set_pull_up_down(gpio, pigpio.PUD_OFF)
00084
00085 pi.set_watchdog(gpio, 0)
00086
00087 self.cb = pi.callback(gpio, pigpio.EITHER_EDGE, self._cb)
00088
00089 def _cb(self, gpio, level, tick):
00090 """
00091 Accumulate the 40 data bits. Format into 5 bytes, humidity high,
00092 humidity low, temperature high, temperature low, checksum.
00093 """
00094 diff = pigpio.tickDiff(self.high_tick, tick)
00095
00096 if level == 0:
00097
00098
00099
00100 if diff >= 50:
00101 val = 1
00102 if diff >= 200:
00103 self.CS = 256
00104 else:
00105 val = 0
00106
00107 if self.bit >= 40:
00108 self.bit = 40
00109
00110 elif self.bit >= 32:
00111 self.CS = (self.CS << 1) + val
00112
00113 if self.bit == 39:
00114
00115
00116
00117 self.pi.set_watchdog(self.gpio, 0)
00118
00119 self.no_response = 0
00120
00121 total = self.hH + self.hL + self.tH + self.tL
00122
00123 if (total & 255) == self.CS:
00124
00125 self.rhum = ((self.hH << 8) + self.hL) * 0.1
00126
00127 if self.tH & 128:
00128 mult = -0.1
00129 self.tH = self.tH & 127
00130 else:
00131 mult = 0.1
00132
00133 self.temp = ((self.tH << 8) + self.tL) * mult
00134
00135 self.tov = time.time()
00136
00137 if self.LED is not None:
00138 self.pi.write(self.LED, 0)
00139
00140 else:
00141
00142 self.bad_CS += 1
00143
00144 elif self.bit >= 24:
00145 self.tL = (self.tL << 1) + val
00146
00147 elif self.bit >= 16:
00148 self.tH = (self.tH << 1) + val
00149
00150 elif self.bit >= 8:
00151 self.hL = (self.hL << 1) + val
00152
00153 elif self.bit >= 0:
00154 self.hH = (self.hH << 1) + val
00155
00156 else:
00157 pass
00158
00159 self.bit += 1
00160
00161 elif level == 1:
00162 self.high_tick = tick
00163 if diff > 250000:
00164 self.bit = -2
00165 self.hH = 0
00166 self.hL = 0
00167 self.tH = 0
00168 self.tL = 0
00169 self.CS = 0
00170
00171 else:
00172 self.pi.set_watchdog(self.gpio, 0)
00173 if self.bit < 8:
00174 self.bad_MM += 1
00175 self.no_response += 1
00176 if self.no_response > self.MAX_NO_RESPONSE:
00177 self.no_response = 0
00178 self.bad_SR += 1
00179 if self.power is not None:
00180 self.powered = False
00181 self.pi.write(self.power, 0)
00182 time.sleep(2)
00183 self.pi.write(self.power, 1)
00184 time.sleep(2)
00185 self.powered = True
00186 elif self.bit < 39:
00187 self.bad_SM += 1
00188 self.no_response = 0
00189
00190 else:
00191 self.no_response = 0
00192
00193 def temperature(self):
00194 """Return current temperature."""
00195 return self.temp
00196
00197 def humidity(self):
00198 """Return current relative humidity."""
00199 return self.rhum
00200
00201 def staleness(self):
00202 """Return time since measurement made."""
00203 if self.tov is not None:
00204 return time.time() - self.tov
00205 else:
00206 return -999
00207
00208 def bad_checksum(self):
00209 """Return count of messages received with bad checksums."""
00210 return self.bad_CS
00211
00212 def short_message(self):
00213 """Return count of short messages."""
00214 return self.bad_SM
00215
00216 def missing_message(self):
00217 """Return count of missing messages."""
00218 return self.bad_MM
00219
00220 def sensor_resets(self):
00221 """Return count of power cycles because of sensor hangs."""
00222 return self.bad_SR
00223
00224 def trigger(self):
00225 """Trigger a new relative humidity and temperature reading."""
00226 if self.powered:
00227 if self.LED is not None:
00228 self.pi.write(self.LED, 1)
00229
00230 self.pi.write(self.gpio, pigpio.LOW)
00231 time.sleep(0.017)
00232 self.pi.set_mode(self.gpio, pigpio.INPUT)
00233 self.pi.set_watchdog(self.gpio, 200)
00234
00235 def cancel(self):
00236 """Cancel the DHT22 sensor."""
00237
00238 self.pi.set_watchdog(self.gpio, 0)
00239
00240 if self.cb is not None:
00241 self.cb.cancel()
00242 self.cb = None
00243
00244 if __name__ == "__main__":
00245
00246 import time
00247
00248 import pigpio
00249
00250 import DHT22
00251
00252
00253 INTERVAL = 3
00254
00255 pi = pigpio.pi()
00256
00257 s = DHT22.sensor(pi, 22, LED=16, power=8)
00258
00259 r = 0
00260
00261 next_reading = time.time()
00262
00263 while True:
00264
00265 r += 1
00266
00267 s.trigger()
00268
00269 time.sleep(0.2)
00270
00271 print("{} {} {} {:3.2f} {} {} {} {}".format(
00272 r, s.humidity(), s.temperature(), s.staleness(),
00273 s.bad_checksum(), s.short_message(), s.missing_message(),
00274 s.sensor_resets()))
00275
00276 next_reading += INTERVAL
00277
00278 time.sleep(next_reading-time.time())
00279
00280 s.cancel()
00281
00282 pi.stop()
00283