Advertisement
rabirajkhadka

dht11.py

Aug 12th, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.34 KB | None | 0 0
  1. import time
  2. import RPi
  3.  
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement