SHARE
TWEET

DhtLib

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