Advertisement
Guest User

DhtLib

a guest
Mar 7th, 2018
437
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.97 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement