Compare commits
2 Commits
93e6e5e211
...
7e96b4cadd
Author | SHA1 | Date | |
---|---|---|---|
7e96b4cadd | |||
5b706691be |
21
DHT11_Python/LICENSE.md
Normal file
21
DHT11_Python/LICENSE.md
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Zoltan Szarvas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
44
DHT11_Python/README.md
Normal file
44
DHT11_Python/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# DHT11 Python library
|
||||
|
||||
This simple class can be used for reading temperature and humidity values from DHT11 sensor on Raspberry Pi.
|
||||
|
||||
# Installation
|
||||
|
||||
To install, just run following:
|
||||
|
||||
```
|
||||
pip install dht11
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
1. Instantiate the `DHT11` class with the pin number as constructor parameter.
|
||||
2. Call `read()` method, which will return `DHT11Result` object with actual values and error code.
|
||||
|
||||
For example:
|
||||
|
||||
```python
|
||||
import RPi.GPIO as GPIO
|
||||
import dht11
|
||||
|
||||
# initialize GPIO
|
||||
GPIO.setwarnings(False)
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.cleanup()
|
||||
|
||||
# read data using pin 14
|
||||
instance = dht11.DHT11(pin = 14)
|
||||
result = instance.read()
|
||||
|
||||
if result.is_valid():
|
||||
print("Temperature: %-3.1f C" % result.temperature)
|
||||
print("Humidity: %-3.1f %%" % result.humidity)
|
||||
else:
|
||||
print("Error: %d" % result.error_code)
|
||||
```
|
||||
|
||||
For working example, see `dht11_example.py` (you probably need to adjust pin for your configuration)
|
||||
|
||||
# License
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
203
DHT11_Python/dht11/__init__.py
Normal file
203
DHT11_Python/dht11/__init__.py
Normal file
@ -0,0 +1,203 @@
|
||||
import time
|
||||
import RPi
|
||||
|
||||
|
||||
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):
|
||||
RPi.GPIO.setup(self.__pin, RPi.GPIO.OUT)
|
||||
|
||||
# send initial high
|
||||
self.__send_and_sleep(RPi.GPIO.HIGH, 0.05)
|
||||
|
||||
# pull down to low
|
||||
self.__send_and_sleep(RPi.GPIO.LOW, 0.02)
|
||||
|
||||
# change to input using pull up
|
||||
RPi.GPIO.setup(self.__pin, RPi.GPIO.IN, RPi.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
|
||||
|
||||
# The meaning of the return sensor values
|
||||
# the_bytes[0]: humidity int
|
||||
# the_bytes[1]: humidity decimal
|
||||
# the_bytes[2]: temperature int
|
||||
# the_bytes[3]: temperature decimal
|
||||
|
||||
temperature = the_bytes[2] + float(the_bytes[3]) / 10
|
||||
humidity = the_bytes[0] + float(the_bytes[1]) / 10
|
||||
|
||||
return DHT11Result(DHT11Result.ERR_NO_ERROR, temperature, humidity)
|
||||
|
||||
def __send_and_sleep(self, output, sleep):
|
||||
RPi.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 = RPi.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 == RPi.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 == RPi.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 == RPi.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 == RPi.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 == RPi.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
|
26
DHT11_Python/example.py
Normal file
26
DHT11_Python/example.py
Normal file
@ -0,0 +1,26 @@
|
||||
import RPi.GPIO as GPIO
|
||||
import dht11
|
||||
import time
|
||||
import datetime
|
||||
|
||||
# initialize GPIO
|
||||
GPIO.setwarnings(True)
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
|
||||
# read data using pin 14
|
||||
instance = dht11.DHT11(pin=14)
|
||||
|
||||
try:
|
||||
while True:
|
||||
result = instance.read()
|
||||
if result.is_valid():
|
||||
print("Last valid input: " + str(datetime.datetime.now()))
|
||||
|
||||
print("Temperature: %-3.1f C" % result.temperature)
|
||||
print("Humidity: %-3.1f %%" % result.humidity)
|
||||
|
||||
time.sleep(6)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Cleanup")
|
||||
GPIO.cleanup()
|
23
DHT11_Python/setup.py
Normal file
23
DHT11_Python/setup.py
Normal file
@ -0,0 +1,23 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setup(
|
||||
name="dht11",
|
||||
version="0.1.0",
|
||||
author="Zoltán Szarvas",
|
||||
author_email="",
|
||||
description="Pure Python library for reading DHT11 sensor on Raspberry Pi",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/szazo/DHT11_Python",
|
||||
packages=find_packages(),
|
||||
install_requires=["RPi.GPIO"],
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
],
|
||||
python_requires='>=3.6',
|
||||
)
|
9
setup.sh
9
setup.sh
@ -56,6 +56,7 @@ if [ ! -d "$PROJECT_DIR" ]; then
|
||||
echo -e "$line\nCreating 'dht11-sensor' in Desktop directory for current user.\n$line\n"
|
||||
mkdir -p "$PROJECT_DIR"
|
||||
cp "./temp-calc.py" "$PROJECT_DIR/"
|
||||
cp -r "./DHT11_Python/" "$PROJECT_DIR/DHT11_Python"
|
||||
echo -e "$line\nCreated '$PROJECT_DIR' directory.\n$line\n"
|
||||
else
|
||||
echo -e "$line\n$PROJECT_DIR already exists. Please delete the folder before running this script.\n$line\n\nExiting..."
|
||||
@ -71,6 +72,12 @@ echo -e "$line\nActivating virtual environment...\n$line\n"
|
||||
source $PROJECT_DIR/bin/activate
|
||||
|
||||
echo -e "$line\nInstalling dependencies...\n$line\n"
|
||||
pip3 install --upgrade RPi.GPIO setuptools dht11
|
||||
pip install --upgrade RPi.GPIO setuptools
|
||||
# Alternatively, instead of executing the next four lines, you can also run "pip install dht11"
|
||||
# but I've decided to keep the files for "dht11" package locally available for installation in the script.
|
||||
cd "$PROJECT_DIR/DHT11_Python"
|
||||
pip install .
|
||||
pip show dht11
|
||||
cd "$PROJECT_DIR/"
|
||||
|
||||
echo -e "\n\n\n$line$line$line\nSetup completed.\nExecute the command 'python3 temp-calc.py' to calculate the temperature.\n# DESIGNED AND ENGINEERED BY KSHITIJ.\n# END OF SCRIPT\n$line$line$line\n\n\n"
|
||||
|
19
temp-calc.py
19
temp-calc.py
@ -2,20 +2,25 @@
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
import dht11
|
||||
import time
|
||||
|
||||
# initialize GPIO
|
||||
GPIO.setwarnings(False)
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.cleanup()
|
||||
|
||||
# read data using pin 16
|
||||
instance = dht11.DHT11(pin = 16)
|
||||
result = instance.read()
|
||||
try:
|
||||
while True:
|
||||
# read data using pin 16
|
||||
instance = dht11.DHT11(pin = 16)
|
||||
result = instance.read()
|
||||
|
||||
if result.is_valid():
|
||||
if result.is_valid():
|
||||
print("Temperature: %-3.1f C" % result.temperature)
|
||||
print("Humidity: %-3.1f %%" % result.humidity)
|
||||
else:
|
||||
else:
|
||||
print("Error: %d" % result.error_code)
|
||||
|
||||
GPIO.cleanup()
|
||||
time.sleep(3)
|
||||
except KeyboardInterrupt:
|
||||
print("Program stopped by user.")
|
||||
GPIO.cleanup()
|
||||
|
Loading…
Reference in New Issue
Block a user