Tech details:

  • Supply voltage: 3.3-5V
  • Supply current (running): 0.5mA typ. (2.5mA max.)
  • Supply current (stand-by): 100uA typ. (150uA max.)
  • Temperature range: 0 / +50°C ±2°C Humidity range 20-90%RH ±5%RH
  • Response time: 6 -10 sec for accurate reading with 2 sec polling time

 

Connectivity:

3/4* pin connector, pins as follows:

  • VCC: 3.3-5V Supply
  • DATA: Trigger Pulse Input
  • *(3rd pin on 4 pin sensor) NC: Not in use
  • GND: 0V Ground

Pull-up resistor required, or enable pull-up on the RPI – more on pull-up here.

What does it do?

Sensor DHT11 Temperature and Humidity  is an indoor solution, as it allows the temperature and humidity measurements within 0-50°C range. If you are interested in taking measurements below 0°C you want to get the twin looking DHT22.  It is taking both measurements,  for temperature and humidity and transmitting this back to the RPI or Arduino board via digital interface.  This is one of the most popular modules to use due to various possible applications. Think home terrarium, thermostat control etc.  Sensor is quick, and able to take an independent results within few seconds of needed.

How to use it?

sensor DHT11 breadboard

sensor DHT11 schematicThe schematics shows you, how to connect the sensor DHT11  to the board.  4-10kΩ resistor is advised and it is placed between Data and power (+). You may want to consider a pull-up resistor as well, (if you don’t know what I’m on about read more about resistors) or enable this on your RPI.  Up to 20m cable requires about 5kΩ pull-up, longer leads needs to be checked for resistance. The sensor itself has 4 pins however only 3 of them are used.  Starting from left 1. VCC, 2. Data, 3. Not in use, 4. GND.

[box type=”info”] When using a 3.5V voltage supply cable length shall not be greater than 20cm. Otherwise, the line voltage drop will cause the sensor power supply shortage, caused by measurement error [/box]

sensor DHT11As one pin isn’t in use, the module itself has 3 pins available and we can connect them directly to 3.3V or 5V  pin. Note that sensor DHT11 allows  you to connect  the module without using an additional resistor.

Lets take a look at the ones I have: As supplied from a different manufacturer layout is reversed  (module alone is upside-down). Inspect your module before connecting to avoid damage. Both modules have 10kΩ included.

Understanding the output

Everything so far has been fairly easy to follow and understand. Brace yourself now, we are dealing with digital interface which returns the data based on request.  Data returned from the sensor DHT11 has a 40 bit structure: 16 bit for Temp, same for humidity and 8bit verification checksum. This data has to be decoded in order to be presented to us in a readable form. If you are interested in the hard way: look up the data sheet for your sensor ie here.

If you want to use the easy way, there is a library written already , and there is no need to decode all of this again. You can modify the sample script to present you the results as needed.

 Sample code:

Before you test the code there is few things to do:

[code language=”bash”]
git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT
[/code]

Once the library is downloaded run:

[code language=”bash”]
sudo apt-get update
sudo apt-get install build-essential python-dev python-openssl
[/code]

and then install it on you RPI.

[code language=”bash”]
sudo python setup.py install
[/code]

You can test the sonar using a python2 code from here. Run the DHT11 Class python file first, then open a new file in the same directory and run the sample script.

[tabs]
[tab title=”DHT11 Sample”]

[code language=”python”]

import RPi.GPIO as GPIO
import dht11
import time
import datetime

# initialize GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.cleanup()

# read data using pin 14
instance = dht11.DHT11(pin = 14)

while True:
result = instance.read()
if result.is_valid():
print("Last valid input: " + str(datetime.datetime.now()))
print("Temperature: %d C" % result.temperature)
print("Humidity: %d %%" % result.humidity)

time.sleep(1)
[/code]

[/tab]
[tab title=”DHT11 Class”]

[code language=”python”]

import time
import RPi.GPIO as GPIO

class DHT11Result:
‘DHT11 sensor result returned by DHT11.read() method’

ERR_NO_ERROR = 0
ERR_MISSING_DATA = 1
ERR_CRC = 2

error_code = ERR_NO_ERROR
temperature = -1
humidity = -1

def __init__(self, error_code, temperature, humidity):
self.error_code = error_code
self.temperature = temperature
self.humidity = humidity

def is_valid(self):
return self.error_code == DHT11Result.ERR_NO_ERROR

class DHT11:
‘DHT11 sensor reader class for Raspberry’

__pin = 0

def __init__(self, pin):
self.__pin = pin

def read(self):
GPIO.setup(self.__pin, GPIO.OUT)

# send initial high
self.__send_and_sleep(GPIO.HIGH, 0.05)

# pull down to low
self.__send_and_sleep(GPIO.LOW, 0.02)

# change to input using pull up
GPIO.setup(self.__pin, GPIO.IN, GPIO.PUD_UP)

# collect data into an array
data = self.__collect_input()

# parse lengths of all data pull up periods
pull_up_lengths = self.__parse_data_pull_up_lengths(data)

# if bit count mismatch, return error (4 byte data + 1 byte checksum)
if len(pull_up_lengths) != 40:
return DHT11Result(DHT11Result.ERR_MISSING_DATA, 0, 0)

# calculate bits from lengths of the pull up periods
bits = self.__calculate_bits(pull_up_lengths)

# we have the bits, calculate bytes
the_bytes = self.__bits_to_bytes(bits)

# calculate checksum and check
checksum = self.__calculate_checksum(the_bytes)
if the_bytes[4] != checksum:
return DHT11Result(DHT11Result.ERR_CRC, 0, 0)

# ok, we have valid data, return it
return DHT11Result(DHT11Result.ERR_NO_ERROR, the_bytes[2], the_bytes[0])

def __send_and_sleep(self, output, sleep):
GPIO.output(self.__pin, output)
time.sleep(sleep)

def __collect_input(self):

# collect the data while unchanged found
unchanged_count = 0

# this is used to determine where is the end of the data
max_unchanged_count = 100

last = -1
data = []
while True:
current = GPIO.input(self.__pin)
data.append(current)
if last != current:
unchanged_count = 0
last = current
else:
unchanged_count += 1
if unchanged_count > max_unchanged_count:
break

return data

def __parse_data_pull_up_lengths(self, data):

STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5

state = STATE_INIT_PULL_DOWN

lengths = [] # will contain the lengths of data pull up periods
current_length = 0 # will contain the length of the previous period

for i in range(len(data)):

current = data[i]
current_length += 1

if state == STATE_INIT_PULL_DOWN:
if current == GPIO.LOW:
# ok, we got the initial pull down
state = STATE_INIT_PULL_UP
continue
else:
continue

if state == STATE_INIT_PULL_UP:
if current == GPIO.HIGH:
# ok, we got the initial pull up
state = STATE_DATA_FIRST_PULL_DOWN
continue
else:
continue

if state == STATE_DATA_FIRST_PULL_DOWN:
if current == GPIO.LOW:
# we have the initial pull down, the next will be the data pull up
state = STATE_DATA_PULL_UP
continue
else:
continue

if state == STATE_DATA_PULL_UP:
if current == GPIO.HIGH:
# data pulled up, the length of this pull up will determine whether it is 0 or 1
current_length = 0
state = STATE_DATA_PULL_DOWN
continue
else:
continue

if state == STATE_DATA_PULL_DOWN:
if current == GPIO.LOW:
# pulled down, we store the length of the previous pull up period
lengths.append(current_length)
state = STATE_DATA_PULL_UP
continue
else:
continue

return lengths

def __calculate_bits(self, pull_up_lengths):

# find shortest and longest period
shortest_pull_up = 1000
longest_pull_up = 0

for i in range(0, len(pull_up_lengths)):

length = pull_up_lengths[i]
if length < shortest_pull_up: shortest_pull_up = length if length > longest_pull_up:
longest_pull_up = length

# use the halfway to determine whether the period it is long or short
halfway = shortest_pull_up + (longest_pull_up – shortest_pull_up) / 2

bits = []

for i in range(0, len(pull_up_lengths)):

bit = False
if pull_up_lengths[i] > halfway:
bit = True

bits.append(bit)

return bits

def __bits_to_bytes(self, bits):

the_bytes = []
byte = 0

for i in range(0, len(bits)):

byte = byte << 1
if (bits[i]):
byte = byte | 1
else:
byte = byte | 0

if ((i + 1) % 8 == 0):
the_bytes.append(byte)
byte = 0

return the_bytes

def __calculate_checksum(self, the_bytes):
return the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3] & 255
[/code]

[/tab]

[/tabs]

1 COMMENT

Comments are closed.