fixed duplicate controller folder

This commit is contained in:
Senad Uka
2016-06-11 18:56:47 +02:00
parent cc7aebc6f9
commit 8fc028aaab
48 changed files with 0 additions and 2880 deletions

View File

@@ -1,14 +0,0 @@
# Tfm Controller - little thingy that reads sensors, runs motors and communicates with the cloud
## Installation
1. Go to every subdirectory in drivers directory and follow instructions about installation of drivers
2. edit controller/config/__init__.py and set your controller ID to unique number
3. configure cron to run controller.py every 15 minutes as a superuser:
```
crontab -e -u root
#enter these lines
*/15 * * * * /usr/bin/python /home/pi/projects/tfm/controller/sensors.py "Automatski, Senad Uka" 120
*/1 * * * * /usr/bin/python /home/pi/projects/tfm/controller/sync_state.py "Automatski, Senad Uka" 120
```

View File

@@ -1,15 +0,0 @@
GPIO_PIN_DHT = 4 # BCM
SENSORDATA_URL = 'http://tfm.meteor.com/api/v1.0/sensorData'
GPIO_PIN_TANKLEVEL0 = 5 # BCM
GPIO_PIN_TANKLEVEL1 = 6 # BCM
GPIO_PIN_TANKLEVEL2 = 13 # BCM
GPIO_PIN_TANKLEVEL3 = 19 # BCM
GPIO_PIN_TANKLEVEL4 = 26 # BCM
GPIO_PIN_TANKFULL = 20 # BCM
GPIO_PIN_OUT_VALVE = 21 # BCM
GPIO_PIN_IN_VALVE = 18 # BCM
API_BASE_URL = 'http://tfm.meteor.com/api/v1.0'
CONTROLLER_ID = '120' # every controller must have a different one
STATE_FILE = '/var/run/controller_state'

View File

@@ -1,217 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import re
import common
import Beaglebone_Black_Driver as driver
# Define mapping of pin names to GPIO base and number.
# Adapted from Adafruit_BBIO code Beaglebone Black system reference.
pin_to_gpio = {
"P9_11": (0,30),
"P9_12": (1,28),
"P9_13": (0,31),
"P9_14": (1,18),
"P9_15": (1,16),
"P9_16": (1,19),
"P9_17": (0,5),
"P9_18": (0,4),
"P9_19": (0,13),
"P9_20": (0,12),
"P9_21": (0,3),
"P9_22": (0,2),
"P9_23": (1,17),
"P9_24": (0,15),
"P9_25": (3,21),
"P9_26": (0,14),
"P9_27": (3,19),
"P9_28": (3,17),
"P9_29": (3,15),
"P9_30": (3,16),
"P9_31": (3,14),
"P9_41": (0,20),
"P9_42": (0,7),
"UART4_RXD": (0,30),
"UART4_TXD": (0,31),
"EHRPWM1A": (1,18),
"EHRPWM1B": (1,19),
"I2C1_SCL": (0,5),
"I2C1_SDA": (0,4),
"I2C2_SCL": (0,13),
"I2C2_SDA": (0,12),
"UART2_TXD": (0,3),
"UART2_RXD": (0,2),
"UART1_TXD": (0,15),
"UART1_RXD": (0,14),
"SPI1_CS0": (3,17),
"SPI1_D0": (3,15),
"SPI1_D1": (3,16),
"SPI1_SCLK": (3,14),
"CLKOUT2": (0,20),
"30": (0,30),
"60": (1,28),
"31": (0,31),
"50": (1,18),
"48": (1,16),
"51": (1,19),
"5": (0,5),
"4": (0,4),
"13": (0,13),
"12": (0,12),
"3": (0,3),
"2": (0,2),
"49": (1,17),
"15": (0,15),
"117": (3,21),
"14": (0,14),
"115": (3,19),
"113": (3,17),
"111": (3,15),
"112": (3,16),
"110": (3,14),
"20": (0,20),
"7": (0,7),
"P8_3": (1,6),
"P8_4": (1,7),
"P8_5": (1,2),
"P8_6": (1,3),
"P8_7": (2,2),
"P8_8": (2,3),
"P8_9": (2,5),
"P8_10": (2,4),
"P8_11": (1,13),
"P8_12": (1,12),
"P8_13": (0,23),
"P8_14": (0,26),
"P8_15": (1,15),
"P8_16": (1,14),
"P8_17": (0,27),
"P8_18": (2,1),
"P8_19": (0,22),
"P8_20": (1,31),
"P8_21": (1,30),
"P8_22": (1,5),
"P8_23": (1,4),
"P8_24": (1,1),
"P8_25": (1,0),
"P8_26": (1,29),
"P8_27": (2,22),
"P8_28": (2,24),
"P8_29": (2,23),
"P8_30": (2,25),
"P8_31": (0,10),
"P8_32": (0,11),
"P8_33": (0,9),
"P8_34": (2,17),
"P8_35": (0,8),
"P8_36": (2,16),
"P8_37": (2,14),
"P8_38": (2,15),
"P8_39": (2,12),
"P8_40": (2,13),
"P8_41": (2,10),
"P8_42": (2,11),
"P8_43": (2,8),
"P8_44": (2,9),
"P8_45": (2,6),
"P8_46": (2,7),
"TIMER4": (2,2),
"TIMER7": (2,3),
"TIMER5": (2,5),
"TIMER6": (2,4),
"EHRPWM2B": (0,23),
"EHRPWM2A": (0,22),
"UART5_CTSN": (0,10),
"UART5_RTSN": (0,11),
"UART4_RTSN": (0,9),
"UART3_RTSN": (2,17),
"UART4_CTSN": (0,8),
"UART3_CTSN": (2,16),
"UART5_TXD": (2,14),
"UART5_RXD": (2,15),
"38": (1,6),
"39": (1,7),
"34": (1,2),
"35": (1,3),
"66": (2,2),
"67": (2,3),
"69": (2,5),
"68": (2,4),
"45": (1,13),
"44": (1,12),
"23": (0,23),
"26": (0,26),
"47": (1,15),
"46": (1,14),
"27": (0,27),
"65": (2,1),
"22": (0,22),
"63": (1,31),
"62": (1,30),
"37": (1,5),
"36": (1,4),
"33": (1,1),
"32": (1,0),
"61": (1,29),
"86": (2,22),
"88": (2,24),
"87": (2,23),
"89": (2,25),
"10": (0,10),
"11": (0,11),
"9": (0,9),
"81": (2,17),
"8": (0,8),
"80": (2,16),
"78": (2,14),
"79": (2,15),
"76": (2,12),
"77": (2,13),
"74": (2,10),
"75": (2,11),
"72": (2,8),
"73": (2,9),
"70": (2,6),
"71": (2,7)
}
def read(sensor, pin):
# Validate GPIO and map it to GPIO base and number.
gpio = pin_to_gpio.get(str(pin).upper(), None)
if gpio is None:
# Couldn't find in mapping, check if pin looks like GPIO<base>_<number>
match = re.match('GPIO([0123])_(\d+)', pin, re.IGNORECASE)
if match is not None:
gpio = (int(match.group(1)), int(match.group(2)))
if gpio is None or gpio[0] < 0 or gpio[0] > 3 or gpio[1] < 0 or gpio[1] > 31:
raise ValueError('Pin must be a valid GPIO identifier like P9_12 or GPIO1_28.')
# Get a reading from C driver code.
result, humidity, temp = driver.read(sensor, gpio[0], gpio[1])
if result in common.TRANSIENT_ERRORS:
# Signal no result could be obtained, but the caller can retry.
return (None, None)
elif result == common.DHT_ERROR_GPIO:
raise RuntimeError('Error accessing GPIO. Make sure program is run as root with sudo!')
elif result != common.DHT_SUCCESS:
# Some kind of error occured.
raise RuntimeError('Error calling DHT test driver read: {0}'.format(result))
return (humidity, temp)

View File

@@ -1,38 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import common
import Raspberry_Pi_Driver as driver
def read(sensor, pin):
# Validate pin is a valid GPIO.
if pin is None or int(pin) < 0 or int(pin) > 31:
raise ValueError('Pin must be a valid GPIO number 0 to 31.')
# Get a reading from C driver code.
result, humidity, temp = driver.read(sensor, int(pin))
if result in common.TRANSIENT_ERRORS:
# Signal no result could be obtained, but the caller can retry.
return (None, None)
elif result == common.DHT_ERROR_GPIO:
raise RuntimeError('Error accessing GPIO. Make sure program is run as root with sudo!')
elif result != common.DHT_SUCCESS:
# Some kind of error occured.
raise RuntimeError('Error calling DHT test driver read: {0}'.format(result))
return (humidity, temp)

View File

@@ -1,38 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import common
import Raspberry_Pi_2_Driver as driver
def read(sensor, pin):
# Validate pin is a valid GPIO.
if pin is None or int(pin) < 0 or int(pin) > 31:
raise ValueError('Pin must be a valid GPIO number 0 to 31.')
# Get a reading from C driver code.
result, humidity, temp = driver.read(sensor, int(pin))
if result in common.TRANSIENT_ERRORS:
# Signal no result could be obtained, but the caller can retry.
return (None, None)
elif result == common.DHT_ERROR_GPIO:
raise RuntimeError('Error accessing GPIO. Make sure program is run as root with sudo!')
elif result != common.DHT_SUCCESS:
# Some kind of error occured.
raise RuntimeError('Error calling DHT test driver read: {0}'.format(result))
return (humidity, temp)

View File

@@ -1,33 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import common
import Test_Driver as driver
def read(sensor, pin):
# Get a reading from C driver code.
result, humidity, temp = driver.read(sensor, pin)
if result in common.TRANSIENT_ERRORS:
# Signal no result could be obtained, but the caller can retry.
return (None, None)
elif result != common.DHT_SUCCESS:
# Some kind of error occured.
raise RuntimeError('Error calling DHT test driver read: {0}'.format(result))
return (humidity, temp)

View File

@@ -1,21 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
from common import DHT11, DHT22, AM2302, read, read_retry

View File

@@ -1,94 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import time
import platform_detect
# Define error constants.
DHT_SUCCESS = 0
DHT_ERROR_TIMEOUT = -1
DHT_ERROR_CHECKSUM = -2
DHT_ERROR_ARGUMENT = -3
DHT_ERROR_GPIO = -4
TRANSIENT_ERRORS = [DHT_ERROR_CHECKSUM, DHT_ERROR_TIMEOUT]
# Define sensor type constants.
DHT11 = 11
DHT22 = 22
AM2302 = 22
SENSORS = [DHT11, DHT22, AM2302]
def get_platform():
"""Return a DHT platform interface for the currently detected platform."""
plat = platform_detect.platform_detect()
if plat == platform_detect.RASPBERRY_PI:
# Check for version 1 or 2 of the pi.
version = platform_detect.pi_version()
if version == 1:
import Raspberry_Pi
return Raspberry_Pi
elif version == 2:
import Raspberry_Pi_2
return Raspberry_Pi_2
else:
raise RuntimeError('No driver for detected Raspberry Pi version available!')
elif plat == platform_detect.BEAGLEBONE_BLACK:
import Beaglebone_Black
return Beaglebone_Black
else:
raise RuntimeError('Unknown platform.')
def read(sensor, pin, platform=None):
"""Read DHT sensor of specified sensor type (DHT11, DHT22, or AM2302) on
specified pin and return a tuple of humidity (as a floating point value
in percent) and temperature (as a floating point value in Celsius). Note that
because the sensor requires strict timing to read and Linux is not a real
time OS, a result is not guaranteed to be returned! In some cases this will
return the tuple (None, None) which indicates the function should be retried.
Also note the DHT sensor cannot be read faster than about once every 2 seconds.
Platform is an optional parameter which allows you to override the detected
platform interface--ignore this parameter unless you receive unknown platform
errors and want to override the detection.
"""
if sensor not in SENSORS:
raise ValueError('Expected DHT11, DHT22, or AM2302 sensor value.')
if platform is None:
platform = get_platform()
return platform.read(sensor, pin)
def read_retry(sensor, pin, retries=15, delay_seconds=2, platform=None):
"""Read DHT sensor of specified sensor type (DHT11, DHT22, or AM2302) on
specified pin and return a tuple of humidity (as a floating point value
in percent) and temperature (as a floating point value in Celsius).
Unlike the read function, this read_retry function will attempt to read
multiple times (up to the specified max retries) until a good reading can be
found. If a good reading cannot be found after the amount of retries, a tuple
of (None, None) is returned. The delay between retries is by default 2
seconds, but can be overridden.
"""
for i in range(retries):
humidity, temperature = read(sensor, pin, platform)
if humidity is not None and temperature is not None:
return (humidity, temperature)
time.sleep(delay_seconds)
return (None, None)

View File

@@ -1,103 +0,0 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
# This is a direct copy of what's in the Adafruit Python GPIO library:
# https://raw.githubusercontent.com/adafruit/Adafruit_Python_GPIO/master/Adafruit_GPIO/Platform.py
# TODO: Add dependency on Adafruit Python GPIO and use its platform detect
# functions.
import platform
import re
# Platform identification constants.
UNKNOWN = 0
RASPBERRY_PI = 1
BEAGLEBONE_BLACK = 2
def platform_detect():
"""Detect if running on the Raspberry Pi or Beaglebone Black and return the
platform type. Will return RASPBERRY_PI, BEAGLEBONE_BLACK, or UNKNOWN."""
# Handle Raspberry Pi
pi = pi_version()
if pi is not None:
return RASPBERRY_PI
# Handle Beaglebone Black
# TODO: Check the Beaglebone Black /proc/cpuinfo value instead of reading
# the platform.
plat = platform.platform()
if plat.lower().find('armv7l-with-debian') > -1:
return BEAGLEBONE_BLACK
elif plat.lower().find('armv7l-with-ubuntu') > -1:
return BEAGLEBONE_BLACK
elif plat.lower().find('armv7l-with-glibc2.4') > -1:
return BEAGLEBONE_BLACK
# Couldn't figure out the platform, just return unknown.
return UNKNOWN
def pi_revision():
"""Detect the revision number of a Raspberry Pi, useful for changing
functionality like default I2C bus based on revision."""
# Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History
with open('/proc/cpuinfo', 'r') as infile:
for line in infile:
# Match a line of the form "Revision : 0002" while ignoring extra
# info in front of the revsion (like 1000 when the Pi was over-volted).
match = re.match('Revision\s+:\s+.*(\w{4})$', line, flags=re.IGNORECASE)
if match and match.group(1) in ['0000', '0002', '0003']:
# Return revision 1 if revision ends with 0000, 0002 or 0003.
return 1
elif match:
# Assume revision 2 if revision ends with any other 4 chars.
return 2
# Couldn't find the revision, throw an exception.
raise RuntimeError('Could not determine Raspberry Pi revision.')
def pi_version():
"""Detect the version of the Raspberry Pi. Returns either 1, 2 or
None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+),
Raspberry Pi 2 (model B+), or not a Raspberry Pi.
"""
# Check /proc/cpuinfo for the Hardware field value.
# 2708 is pi 1
# 2709 is pi 2
# Anything else is not a pi.
with open('/proc/cpuinfo', 'r') as infile:
cpuinfo = infile.read()
# Match a line like 'Hardware : BCM2709'
match = re.search('^Hardware\s+:\s+(\w+)$', cpuinfo,
flags=re.MULTILINE | re.IGNORECASE)
if not match:
# Couldn't find the hardware, assume it isn't a pi.
return None
if match.group(1) == 'BCM2708':
# Pi 1
return 1
elif match.group(1) == 'BCM2709':
# Pi 2
return 2
else:
# Something else, not a pi.
return None

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Adafruit Industries
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.

View File

@@ -1,29 +0,0 @@
Adafruit Python DHT Sensor Library
==================================
Python library to read the DHT series of humidity and temperature sensors on a Raspberry Pi or Beaglebone Black.
Designed specifically to work with the Adafruit DHT series sensors ----> https://www.adafruit.com/products/385
Currently the library is only tested with Python 2.6/2.7.
For all platforms (Raspberry Pi and Beaglebone Black) make sure your system is able to compile Python extensions. On Raspbian or Beaglebone Black's Debian/Ubuntu image you can ensure your system is ready by executing:
````
sudo apt-get update
sudo apt-get install build-essential python-dev
````
Install the library by downloading with the download link on the right, unzipping the archive, and executing:
````
sudo python setup.py install
````
See example of usage in the examples folder.
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Tony DiCola for Adafruit Industries.
MIT license, all text above must be included in any redistribution

View File

@@ -1,54 +0,0 @@
#!/usr/bin/python
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import sys
import Adafruit_DHT
# Parse command line parameters.
sensor_args = { '11': Adafruit_DHT.DHT11,
'22': Adafruit_DHT.DHT22,
'2302': Adafruit_DHT.AM2302 }
if len(sys.argv) == 3 and sys.argv[1] in sensor_args:
sensor = sensor_args[sys.argv[1]]
pin = sys.argv[2]
else:
print 'usage: sudo ./Adafruit_DHT.py [11|22|2302] GPIOpin#'
print 'example: sudo ./Adafruit_DHT.py 2302 4 - Read from an AM2302 connected to GPIO #4'
sys.exit(1)
# Try to grab a sensor reading. Use the read_retry method which will retry up
# to 15 times to get a sensor reading (waiting 2 seconds between each retry).
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
# Un-comment the line below to convert the temperature to Fahrenheit.
# temperature = temperature * 9/5.0 + 32
# Note that sometimes you won't get a reading and
# the results will be null (because Linux can't
# guarantee the timing of calls to read the sensor).
# If this happens try again!
if humidity is not None and temperature is not None:
print 'Temp={0:0.1f}* Humidity={1:0.1f}%'.format(temperature, humidity)
else:
print 'Failed to get reading. Try again!'
sys.exit(1)

View File

@@ -1,131 +0,0 @@
#!/usr/bin/python
# Google Spreadsheet DHT Sensor Data-logging Example
# Depends on the 'gspread' and 'oauth2client' package being installed. If you
# have pip installed execute:
# sudo pip install gspread oauth2client
# Also it's _very important_ on the Raspberry Pi to install the python-openssl
# package because the version of Python is a bit old and can fail with Google's
# new OAuth2 based authentication. Run the following command to install the
# the package:
# sudo apt-get update
# sudo apt-get install python-openssl
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import json
import sys
import time
import datetime
import Adafruit_DHT
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
# Type of sensor, can be Adafruit_DHT.DHT11, Adafruit_DHT.DHT22, or Adafruit_DHT.AM2302.
DHT_TYPE = Adafruit_DHT.DHT22
# Example of sensor connected to Raspberry Pi pin 23
DHT_PIN = 23
# Example of sensor connected to Beaglebone Black pin P8_11
#DHT_PIN = 'P8_11'
# Google Docs OAuth credential JSON file. Note that the process for authenticating
# with Google docs has changed as of ~April 2015. You _must_ use OAuth2 to log
# in and authenticate with the gspread library. Unfortunately this process is much
# more complicated than the old process. You _must_ carefully follow the steps on
# this page to create a new OAuth service in your Google developer console:
# http://gspread.readthedocs.org/en/latest/oauth2.html
#
# Once you've followed the steps above you should have downloaded a .json file with
# your OAuth2 credentials. This file has a name like SpreadsheetData-<gibberish>.json.
# Place that file in the same directory as this python script.
#
# Now one last _very important_ step before updating the spreadsheet will work.
# Go to your spreadsheet in Google Spreadsheet and share it to the email address
# inside the 'client_email' setting in the SpreadsheetData-*.json file. For example
# if the client_email setting inside the .json file has an email address like:
# 149345334675-md0qff5f0kib41meu20f7d1habos3qcu@developer.gserviceaccount.com
# Then use the File -> Share... command in the spreadsheet to share it with read
# and write acess to the email address above. If you don't do this step then the
# updates to the sheet will fail!
GDOCS_OAUTH_JSON = 'your SpreadsheetData-*.json file name'
# Google Docs spreadsheet name.
GDOCS_SPREADSHEET_NAME = 'your google docs spreadsheet name'
# How long to wait (in seconds) between measurements.
FREQUENCY_SECONDS = 30
def login_open_sheet(oauth_key_file, spreadsheet):
"""Connect to Google Docs spreadsheet and return the first worksheet."""
try:
json_key = json.load(open(oauth_key_file))
credentials = SignedJwtAssertionCredentials(json_key['client_email'],
json_key['private_key'],
['https://spreadsheets.google.com/feeds'])
gc = gspread.authorize(credentials)
worksheet = gc.open(spreadsheet).sheet1
return worksheet
except Exception as ex:
print 'Unable to login and get spreadsheet. Check OAuth credentials, spreadsheet name, and make sure spreadsheet is shared to the client_email address in the OAuth .json file!'
print 'Google sheet login failed with error:', ex
sys.exit(1)
print 'Logging sensor measurements to {0} every {1} seconds.'.format(GDOCS_SPREADSHEET_NAME, FREQUENCY_SECONDS)
print 'Press Ctrl-C to quit.'
worksheet = None
while True:
# Login if necessary.
if worksheet is None:
worksheet = login_open_sheet(GDOCS_OAUTH_JSON, GDOCS_SPREADSHEET_NAME)
# Attempt to get sensor reading.
humidity, temp = Adafruit_DHT.read(DHT_TYPE, DHT_PIN)
# Skip to the next reading if a valid measurement couldn't be taken.
# This might happen if the CPU is under a lot of load and the sensor
# can't be reliably read (timing is critical to read the sensor).
if humidity is None or temp is None:
time.sleep(2)
continue
print 'Temperature: {0:0.1f} C'.format(temp)
print 'Humidity: {0:0.1f} %'.format(humidity)
# Append the data in the spreadsheet, including a timestamp
try:
worksheet.append_row((datetime.datetime.now(), temp, humidity))
except:
# Error appending data, most likely because credentials are stale.
# Null out the worksheet so a login is performed at the top of the loop.
print 'Append error, logging in again'
worksheet = None
time.sleep(FREQUENCY_SECONDS)
continue
# Wait 30 seconds before continuing
print 'Wrote a row to {0}'.format(GDOCS_SPREADSHEET_NAME)
time.sleep(FREQUENCY_SECONDS)

View File

@@ -1,48 +0,0 @@
#!/usr/bin/python
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
# 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.
import Adafruit_DHT
# Sensor should be set to Adafruit_DHT.DHT11,
# Adafruit_DHT.DHT22, or Adafruit_DHT.AM2302.
sensor = Adafruit_DHT.DHT22
# Example using a Beaglebone Black with DHT sensor
# connected to pin P8_11.
pin = 'P8_11'
# Example using a Raspberry Pi with DHT sensor
# connected to GPIO23.
#pin = 23
# Try to grab a sensor reading. Use the read_retry method which will retry up
# to 15 times to get a sensor reading (waiting 2 seconds between each retry).
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
# Note that sometimes you won't get a reading and
# the results will be null (because Linux can't
# guarantee the timing of calls to read the sensor).
# If this happens try again!
if humidity is not None and temperature is not None:
print 'Temp={0:0.1f}*C Humidity={1:0.1f}%'.format(temperature, humidity)
else:
print 'Failed to get reading. Try again!'

View File

@@ -1,332 +0,0 @@
#!/usr/bin/env python
"""Bootstrap setuptools installation
To use setuptools in your package's setup.py, include this
file in the same directory and add this to the top of your setup.py::
from ez_setup import use_setuptools
use_setuptools()
To require a specific version of setuptools, set a download
mirror, or use an alternate download directory, simply supply
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import os
import shutil
import sys
import tempfile
import zipfile
import optparse
import subprocess
import platform
import textwrap
import contextlib
from distutils import log
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
try:
from site import USER_SITE
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "4.0.1"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
"""
Return True if the command succeeded.
"""
args = (sys.executable,) + args
return subprocess.call(args) == 0
def _install(archive_filename, install_args=()):
with archive_context(archive_filename):
# installing
log.warn('Installing Setuptools')
if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
# exitcode will be 2
return 2
def _build_egg(egg, archive_filename, to_dir):
with archive_context(archive_filename):
# building an egg
log.warn('Building a Setuptools egg in %s', to_dir)
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
raise IOError('Could not build the egg.')
class ContextualZipFile(zipfile.ZipFile):
"""
Supplement ZipFile class to support context manager for Python 2.6
"""
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def __new__(cls, *args, **kwargs):
"""
Construct a ZipFile or ContextualZipFile as appropriate
"""
if hasattr(zipfile.ZipFile, '__exit__'):
return zipfile.ZipFile(*args, **kwargs)
return super(ContextualZipFile, cls).__new__(cls)
@contextlib.contextmanager
def archive_context(filename):
# extracting the archive
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
with ContextualZipFile(filename) as archive:
archive.extractall()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
yield
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _do_download(version, download_base, to_dir, download_delay):
egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
% (version, sys.version_info[0], sys.version_info[1]))
if not os.path.exists(egg):
archive = download_setuptools(version, download_base,
to_dir, download_delay)
_build_egg(egg, archive, to_dir)
sys.path.insert(0, egg)
# Remove previously-imported pkg_resources if present (see
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
if 'pkg_resources' in sys.modules:
del sys.modules['pkg_resources']
import setuptools
setuptools.bootstrap_install_from = egg
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, download_delay=15):
to_dir = os.path.abspath(to_dir)
rep_modules = 'pkg_resources', 'setuptools'
imported = set(sys.modules).intersection(rep_modules)
try:
import pkg_resources
except ImportError:
return _do_download(version, download_base, to_dir, download_delay)
try:
pkg_resources.require("setuptools>=" + version)
return
except pkg_resources.DistributionNotFound:
return _do_download(version, download_base, to_dir, download_delay)
except pkg_resources.VersionConflict as VC_err:
if imported:
msg = textwrap.dedent("""
The required version of setuptools (>={version}) is not available,
and can't be installed while this script is running. Please
install a more recent version first, using
'easy_install -U setuptools'.
(Currently using {VC_err.args[0]!r})
""").format(VC_err=VC_err, version=version)
sys.stderr.write(msg)
sys.exit(2)
# otherwise, reload ok
del pkg_resources, sys.modules['pkg_resources']
return _do_download(version, download_base, to_dir, download_delay)
def _clean_check(cmd, target):
"""
Run the command to download target. If the command fails, clean up before
re-raising the error.
"""
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
if os.access(target, os.F_OK):
os.unlink(target)
raise
def download_file_powershell(url, target):
"""
Download the file at url to target using Powershell (which will validate
trust). Raise an exception if the command cannot complete.
"""
target = os.path.abspath(target)
ps_cmd = (
"[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
"[System.Net.CredentialCache]::DefaultCredentials; "
"(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
% vars()
)
cmd = [
'powershell',
'-Command',
ps_cmd,
]
_clean_check(cmd, target)
def has_powershell():
if platform.system() != 'Windows':
return False
cmd = ['powershell', '-Command', 'echo test']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_powershell.viable = has_powershell
def download_file_curl(url, target):
cmd = ['curl', url, '--silent', '--output', target]
_clean_check(cmd, target)
def has_curl():
cmd = ['curl', '--version']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_curl.viable = has_curl
def download_file_wget(url, target):
cmd = ['wget', url, '--quiet', '--output-document', target]
_clean_check(cmd, target)
def has_wget():
cmd = ['wget', '--version']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_wget.viable = has_wget
def download_file_insecure(url, target):
"""
Use Python to download the file, even though it cannot authenticate the
connection.
"""
src = urlopen(url)
try:
# Read all the data in one block.
data = src.read()
finally:
src.close()
# Write all the data in one block to avoid creating a partial file.
with open(target, "wb") as dst:
dst.write(data)
download_file_insecure.viable = lambda: True
def get_best_downloader():
downloaders = (
download_file_powershell,
download_file_curl,
download_file_wget,
download_file_insecure,
)
viable_downloaders = (dl for dl in downloaders if dl.viable())
return next(viable_downloaders, None)
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader):
"""
Download setuptools from a specified location and return its filename
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
``downloader_factory`` should be a function taking no arguments and
returning a function for downloading a URL to a target.
"""
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
zip_name = "setuptools-%s.zip" % version
url = download_base + zip_name
saveto = os.path.join(to_dir, zip_name)
if not os.path.exists(saveto): # Avoid repeated downloads
log.warn("Downloading %s", url)
downloader = downloader_factory()
downloader(url, saveto)
return os.path.realpath(saveto)
def _build_install_args(options):
"""
Build the arguments to 'python setup.py install' on the setuptools package
"""
return ['--user'] if options.user_install else []
def _parse_args():
"""
Parse the command line for options
"""
parser = optparse.OptionParser()
parser.add_option(
'--user', dest='user_install', action='store_true', default=False,
help='install in user site package (requires Python 2.6 or later)')
parser.add_option(
'--download-base', dest='download_base', metavar="URL",
default=DEFAULT_URL,
help='alternative URL from where to download the setuptools package')
parser.add_option(
'--insecure', dest='downloader_factory', action='store_const',
const=lambda: download_file_insecure, default=get_best_downloader,
help='Use internal, non-validating downloader'
)
parser.add_option(
'--version', help="Specify which version to download",
default=DEFAULT_VERSION,
)
options, args = parser.parse_args()
# positional arguments are ignored
return options
def main():
"""Install or upgrade setuptools and EasyInstall"""
options = _parse_args()
archive = download_setuptools(
version=options.version,
download_base=options.download_base,
downloader_factory=options.downloader_factory,
)
return _install(archive, _build_install_args(options))
if __name__ == '__main__':
sys.exit(main())

View File

@@ -1,73 +0,0 @@
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages, Extension
import sys
import Adafruit_DHT.platform_detect as platform_detect
# Check if an explicit platform was chosen with a command line parameter.
# Kind of hacky to manipulate the argument list before calling setup, but it's
# the best simple option for adding optional config to the setup.
platform = platform_detect.UNKNOWN
pi_version = None
if '--force-pi' in sys.argv:
platform = platform_detect.RASPBERRY_PI
pi_version = 1
sys.argv.remove('--force-pi')
elif '--force-pi2' in sys.argv:
platform = platform_detect.RASPBERRY_PI
pi_version = 2
sys.argv.remove('--force-pi2')
elif '--force-bbb' in sys.argv:
platform = platform_detect.BEAGLEBONE_BLACK
sys.argv.remove('--force-bbb')
elif '--force-test' in sys.argv:
platform = 'TEST'
sys.argv.remove('--force-test')
else:
# No explicit platform chosen, detect the current platform.
platform = platform_detect.platform_detect()
# Pick the right extension to compile based on the platform.
extensions = []
if platform == platform_detect.RASPBERRY_PI:
# Get the Pi version (1 or 2)
if pi_version is None:
pi_version = platform_detect.pi_version()
# Build the right extension depending on the Pi version.
if pi_version == 1:
extensions.append(Extension("Adafruit_DHT.Raspberry_Pi_Driver",
["source/_Raspberry_Pi_Driver.c", "source/common_dht_read.c", "source/Raspberry_Pi/pi_dht_read.c", "source/Raspberry_Pi/pi_mmio.c"],
libraries=['rt'],
extra_compile_args=['-std=gnu99']))
elif pi_version == 2:
extensions.append(Extension("Adafruit_DHT.Raspberry_Pi_2_Driver",
["source/_Raspberry_Pi_2_Driver.c", "source/common_dht_read.c", "source/Raspberry_Pi_2/pi_2_dht_read.c", "source/Raspberry_Pi_2/pi_2_mmio.c"],
libraries=['rt'],
extra_compile_args=['-std=gnu99']))
else:
raise RuntimeError('Detected Pi version that has no appropriate driver available.')
elif platform == platform_detect.BEAGLEBONE_BLACK:
extensions.append(Extension("Adafruit_DHT.Beaglebone_Black_Driver",
["source/_Beaglebone_Black_Driver.c", "source/common_dht_read.c", "source/Beaglebone_Black/bbb_dht_read.c", "source/Beaglebone_Black/bbb_mmio.c"],
libraries=['rt'],
extra_compile_args=['-std=gnu99']))
elif platform == 'TEST':
extensions.append(Extension("Adafruit_DHT.Test_Driver",
["source/_Test_Driver.c", "source/Test/test_dht_read.c"],
extra_compile_args=['-std=gnu99']))
else:
print 'Could not detect if running on the Raspberry Pi or Beaglebone Black. If this failure is unexpected, you can run again with --force-pi or --force-bbb parameter to force using the Raspberry Pi or Beaglebone Black respectively.'
sys.exit(1)
# Call setuptools setup function to install package.
setup(name = 'Adafruit_DHT',
version = '1.1.0',
author = 'Tony DiCola',
author_email = 'tdicola@adafruit.com',
description = 'Library to get readings from the DHT11, DHT22, and AM2302 humidity and temperature sensors on a Raspberry Pi or Beaglebone Black.',
license = 'MIT',
url = 'https://github.com/adafruit/Adafruit_Python_DHT/',
packages = find_packages(),
ext_modules = extensions)

View File

@@ -1,154 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <stdlib.h>
#include <string.h>
#include "bbb_dht_read.h"
#include "bbb_mmio.h"
// This is the only processor specific magic value, the maximum amount of time to
// spin in a loop before bailing out and considering the read a timeout. This should
// be a high value, but if you're running on a much faster platform than a Raspberry
// Pi or Beaglebone Black then it might need to be increased.
#define DHT_MAXCOUNT 32000
// Number of bit pulses to expect from the DHT. Note that this is 41 because
// the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
// the data afterwards.
#define DHT_PULSES 41
int bbb_dht_read(int type, int gpio_base, int gpio_number, float* humidity, float* temperature) {
// Validate humidity and temperature arguments and set them to zero.
if (humidity == NULL || temperature == NULL) {
return DHT_ERROR_ARGUMENT;
}
*temperature = 0.0f;
*humidity = 0.0f;
// Store the count that each DHT bit pulse is low and high.
// Make sure array is initialized to start at zero.
int pulseCounts[DHT_PULSES*2] = {0};
// Get GPIO pin and set it as an output.
gpio_t pin;
if (bbb_mmio_get_gpio(gpio_base, gpio_number, &pin) < 0) {
return DHT_ERROR_GPIO;
}
bbb_mmio_set_output(pin);
// Bump up process priority and change scheduler to try to try to make process more 'real time'.
set_max_priority();
// Set pin high for ~500 milliseconds.
bbb_mmio_set_high(pin);
sleep_milliseconds(500);
// The next calls are timing critical and care should be taken
// to ensure no unnecssary work is done below.
// Set pin low for ~20 milliseconds.
bbb_mmio_set_low(pin);
busy_wait_milliseconds(20);
// Set pin as input.
bbb_mmio_set_input(pin);
// Wait for DHT to pull pin low.
uint32_t count = 0;
while (bbb_mmio_input(pin)) {
if (++count >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
// Record pulse widths for the expected result bits.
for (int i=0; i < DHT_PULSES*2; i+=2) {
// Count how long pin is low and store in pulseCounts[i]
while (!bbb_mmio_input(pin)) {
if (++pulseCounts[i] >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
// Count how long pin is high and store in pulseCounts[i+1]
while (bbb_mmio_input(pin)) {
if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
}
// Done with timing critical code, now interpret the results.
// Drop back to normal priority.
set_default_priority();
// Compute the average low pulse width to use as a 50 microsecond reference threshold.
// Ignore the first two readings because they are a constant 80 microsecond pulse.
uint32_t threshold = 0;
for (int i=2; i < DHT_PULSES*2; i+=2) {
threshold += pulseCounts[i];
}
threshold /= DHT_PULSES-1;
// Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
// If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
// then it must be a ~70us 1 pulse.
uint8_t data[5] = {0};
for (int i=3; i < DHT_PULSES*2; i+=2) {
int index = (i-3)/16;
data[index] <<= 1;
if (pulseCounts[i] >= threshold) {
// One bit for long pulse.
data[index] |= 1;
}
// Else zero bit for short pulse.
}
// Useful debug info:
//printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]);
// Verify checksum of received data.
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
if (type == DHT11) {
// Get humidity and temp for DHT11 sensor.
*humidity = (float)data[0];
*temperature = (float)data[2];
}
else if (type == DHT22) {
// Calculate humidity and temp for DHT22 sensor.
*humidity = (data[0] * 256 + data[1]) / 10.0f;
*temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f;
if (data[2] & 0x80) {
*temperature *= -1.0f;
}
}
return DHT_SUCCESS;
}
else {
return DHT_ERROR_CHECKSUM;
}
}

View File

@@ -1,33 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#ifndef BBB_DHT_READ_H
#define BBB_DHT_READ_H
#include "../common_dht_read.h"
// Read DHT sensor connected to GPIO bin GPIO<base>_<number>, for example P8_11 is GPIO1_13 with
// base = 1 and number = 13. Humidity and temperature will be returned in the provided parameters.
// If a successfull reading could be made a value of 0 (DHT_SUCCESS) will be returned. If there
// was an error reading the sensor a negative value will be returned. Some errors can be ignored
// and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM.
int bbb_dht_read(int type, int gpio_base, int gpio_number, float* humidity, float* temperature);
#endif

View File

@@ -1,73 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "bbb_mmio.h"
#define GPIO_LENGTH 4096
#define GPIO0_ADDR 0x44E07000
#define GPIO1_ADDR 0x4804C000
#define GPIO2_ADDR 0x481AC000
#define GPIO3_ADDR 0x481AF000
// Store mapping of GPIO base number to GPIO address.
static uint32_t gpio_addresses[4] = { GPIO0_ADDR, GPIO1_ADDR, GPIO2_ADDR, GPIO3_ADDR };
// Cache memory-mapped GPIO addresses.
static volatile uint32_t* gpio_base[4] = { NULL };
int bbb_mmio_get_gpio(int base, int number, gpio_t* gpio) {
// Validate input parameters.
if (gpio == NULL) {
return MMIO_ERROR_ARGUMENT;
}
if (base < 0 || base > 3) {
return MMIO_ERROR_ARGUMENT;
}
if (number < 0 || number > 31) {
return MMIO_ERROR_ARGUMENT;
}
// Map GPIO memory if its hasn't been mapped already.
if (gpio_base[base] == NULL) {
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
// Error opening /dev/mem. Probably not running as root.
return MMIO_ERROR_DEVMEM;
}
// Map GPIO memory to location in process space.
gpio_base[base] = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, gpio_addresses[base]);
if (gpio_base[base] == MAP_FAILED) {
// Don't save the result if the memory mapping failed.
gpio_base[base] = NULL;
return MMIO_ERROR_MMAP;
}
}
// Initialize and set GPIO fields.
memset(gpio, 0, sizeof(gpio));
gpio->base = gpio_base[base];
gpio->number = number;
return MMIO_SUCCESS;
}

View File

@@ -1,101 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
// Simple fast memory-mapped GPIO library for the Beaglebone Black.
// Allows reading and writing GPIO at very high speeds, up to ~2.6mhz!
/*
// Example usage:
#include <stdio.h>
#include "bbb_mmio.h"
int main(int argc, char* argv[]) {
// Get GPIO pin.
// See the giant table of of pins in the system reference manual for details
// on the base and number for a given GPIO:
// https://github.com/CircuitCo/BeagleBone-Black/blob/master/BBB_SRM.pdf?raw=true
// Section 7 Connectors, table 12 shows P8_11 maps to GPIO1_13, so 1 is the
// gpio base and 13 is the gpio number.
gpio_t p8_11;
if (bbb_mmio_get_gpio(1, 13, &p8_11) < 0) {
printf("Couldn't get requested GPIO pin!\n");
return 1;
}
// Set pin as output.
bbb_mmio_set_output(p8_11);
// Toggle the pin high and low as fast as possible.
// This generates a signal at about 2.6mhz in my tests.
// Each pulse high/low is only about 200 nanoseconds long!
while (1) {
bbb_mmio_set_high(p8_11);
bbb_mmio_set_low(p8_11);
}
return 0;
}
*/
#ifndef BBB_MMIO_H
#define BBB_MMIO_H
#include <stdint.h>
#define MMIO_SUCCESS 0
#define MMIO_ERROR_ARGUMENT -1
#define MMIO_ERROR_DEVMEM -2
#define MMIO_ERROR_MMAP -3
#define MMIO_OE_ADDR 0x134
#define MMIO_GPIO_DATAOUT 0x13C
#define MMIO_GPIO_DATAIN 0x138
#define MMIO_GPIO_CLEARDATAOUT 0x190
#define MMIO_GPIO_SETDATAOUT 0x194
// Define struct to represent a GPIO pin based on its base memory address and number.
typedef struct {
volatile uint32_t* base;
int number;
} gpio_t;
int bbb_mmio_get_gpio(int base, int number, gpio_t* gpio);
static inline void bbb_mmio_set_output(gpio_t gpio) {
gpio.base[MMIO_OE_ADDR/4] &= (0xFFFFFFFF ^ (1 << gpio.number));
}
static inline void bbb_mmio_set_input(gpio_t gpio) {
gpio.base[MMIO_OE_ADDR/4] |= (1 << gpio.number);
}
static inline void bbb_mmio_set_high(gpio_t gpio) {
gpio.base[MMIO_GPIO_SETDATAOUT/4] = 1 << gpio.number;
}
static inline void bbb_mmio_set_low(gpio_t gpio) {
gpio.base[MMIO_GPIO_CLEARDATAOUT/4] = 1 << gpio.number;
}
static inline uint32_t bbb_mmio_input(gpio_t gpio) {
return gpio.base[MMIO_GPIO_DATAIN/4] & (1 << gpio.number);
}
#endif

View File

@@ -1,158 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <stdbool.h>
#include <stdlib.h>
#include "pi_dht_read.h"
#include "pi_mmio.h"
// This is the only processor specific magic value, the maximum amount of time to
// spin in a loop before bailing out and considering the read a timeout. This should
// be a high value, but if you're running on a much faster platform than a Raspberry
// Pi or Beaglebone Black then it might need to be increased.
#define DHT_MAXCOUNT 32000
// Number of bit pulses to expect from the DHT. Note that this is 41 because
// the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
// the data afterwards.
#define DHT_PULSES 41
int pi_dht_read(int type, int pin, float* humidity, float* temperature) {
// Validate humidity and temperature arguments and set them to zero.
if (humidity == NULL || temperature == NULL) {
return DHT_ERROR_ARGUMENT;
}
*temperature = 0.0f;
*humidity = 0.0f;
// Initialize GPIO library.
if (pi_mmio_init() < 0) {
return DHT_ERROR_GPIO;
}
// Store the count that each DHT bit pulse is low and high.
// Make sure array is initialized to start at zero.
int pulseCounts[DHT_PULSES*2] = {0};
// Set pin to output.
pi_mmio_set_output(pin);
// Bump up process priority and change scheduler to try to try to make process more 'real time'.
set_max_priority();
// Set pin high for ~500 milliseconds.
pi_mmio_set_high(pin);
sleep_milliseconds(500);
// The next calls are timing critical and care should be taken
// to ensure no unnecssary work is done below.
// Set pin low for ~20 milliseconds.
pi_mmio_set_low(pin);
busy_wait_milliseconds(20);
// Set pin at input.
pi_mmio_set_input(pin);
// Need a very short delay before reading pins or else value is sometimes still low.
for (volatile int i = 0; i < 50; ++i) {
}
// Wait for DHT to pull pin low.
uint32_t count = 0;
while (pi_mmio_input(pin)) {
if (++count >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
// Record pulse widths for the expected result bits.
for (int i=0; i < DHT_PULSES*2; i+=2) {
// Count how long pin is low and store in pulseCounts[i]
while (!pi_mmio_input(pin)) {
if (++pulseCounts[i] >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
// Count how long pin is high and store in pulseCounts[i+1]
while (pi_mmio_input(pin)) {
if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
}
// Done with timing critical code, now interpret the results.
// Drop back to normal priority.
set_default_priority();
// Compute the average low pulse width to use as a 50 microsecond reference threshold.
// Ignore the first two readings because they are a constant 80 microsecond pulse.
uint32_t threshold = 0;
for (int i=2; i < DHT_PULSES*2; i+=2) {
threshold += pulseCounts[i];
}
threshold /= DHT_PULSES-1;
// Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
// If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
// then it must be a ~70us 1 pulse.
uint8_t data[5] = {0};
for (int i=3; i < DHT_PULSES*2; i+=2) {
int index = (i-3)/16;
data[index] <<= 1;
if (pulseCounts[i] >= threshold) {
// One bit for long pulse.
data[index] |= 1;
}
// Else zero bit for short pulse.
}
// Useful debug info:
//printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]);
// Verify checksum of received data.
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
if (type == DHT11) {
// Get humidity and temp for DHT11 sensor.
*humidity = (float)data[0];
*temperature = (float)data[2];
}
else if (type == DHT22) {
// Calculate humidity and temp for DHT22 sensor.
*humidity = (data[0] * 256 + data[1]) / 10.0f;
*temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f;
if (data[2] & 0x80) {
*temperature *= -1.0f;
}
}
return DHT_SUCCESS;
}
else {
return DHT_ERROR_CHECKSUM;
}
}

View File

@@ -1,32 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#ifndef PI_DHT_READ_H
#define PI_DHT_READ_H
#include "../common_dht_read.h"
// Read DHT sensor connected to GPIO pin (using BCM numbering). Humidity and temperature will be
// returned in the provided parameters. If a successfull reading could be made a value of 0
// (DHT_SUCCESS) will be returned. If there was an error reading the sensor a negative value will
// be returned. Some errors can be ignored and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM.
int pi_dht_read(int sensor, int pin, float* humidity, float* temperature);
#endif

View File

@@ -1,55 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
// 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.
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "pi_mmio.h"
#define BASE 0x20000000
#define GPIO_BASE (BASE + 0x200000)
#define GPIO_LENGTH 4096
volatile uint32_t* pi_mmio_gpio = NULL;
int pi_mmio_init(void) {
if (pi_mmio_gpio == NULL) {
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
// Error opening /dev/mem. Probably not running as root.
return MMIO_ERROR_DEVMEM;
}
// Map GPIO memory to location in process space.
pi_mmio_gpio = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
close(fd);
if (pi_mmio_gpio == MAP_FAILED) {
// Don't save the result if the memory mapping failed.
pi_mmio_gpio = NULL;
return MMIO_ERROR_MMAP;
}
}
return MMIO_SUCCESS;
}

View File

@@ -1,61 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
// 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.
// Simple fast memory-mapped GPIO library for the Raspberry Pi.
#ifndef PI_MMIO_H
#define PI_MMIO_H
#include <stdint.h>
#define MMIO_SUCCESS 0
#define MMIO_ERROR_DEVMEM -1
#define MMIO_ERROR_MMAP -2
volatile uint32_t* pi_mmio_gpio;
int pi_mmio_init(void);
static inline void pi_mmio_set_input(const int gpio_number) {
// Set GPIO register to 000 for specified GPIO number.
*(pi_mmio_gpio+((gpio_number)/10)) &= ~(7<<(((gpio_number)%10)*3));
}
static inline void pi_mmio_set_output(const int gpio_number) {
// First set to 000 using input function.
pi_mmio_set_input(gpio_number);
// Next set bit 0 to 1 to set output.
*(pi_mmio_gpio+((gpio_number)/10)) |= (1<<(((gpio_number)%10)*3));
}
static inline void pi_mmio_set_high(const int gpio_number) {
*(pi_mmio_gpio+7) = 1 << gpio_number;
}
static inline void pi_mmio_set_low(const int gpio_number) {
*(pi_mmio_gpio+10) = 1 << gpio_number;
}
static inline uint32_t pi_mmio_input(const int gpio_number) {
return *(pi_mmio_gpio+13) & (1 << gpio_number);
}
#endif

View File

@@ -1,158 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <stdbool.h>
#include <stdlib.h>
#include "pi_2_dht_read.h"
#include "pi_2_mmio.h"
// This is the only processor specific magic value, the maximum amount of time to
// spin in a loop before bailing out and considering the read a timeout. This should
// be a high value, but if you're running on a much faster platform than a Raspberry
// Pi or Beaglebone Black then it might need to be increased.
#define DHT_MAXCOUNT 32000
// Number of bit pulses to expect from the DHT. Note that this is 41 because
// the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
// the data afterwards.
#define DHT_PULSES 41
int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) {
// Validate humidity and temperature arguments and set them to zero.
if (humidity == NULL || temperature == NULL) {
return DHT_ERROR_ARGUMENT;
}
*temperature = 0.0f;
*humidity = 0.0f;
// Initialize GPIO library.
if (pi_2_mmio_init() < 0) {
return DHT_ERROR_GPIO;
}
// Store the count that each DHT bit pulse is low and high.
// Make sure array is initialized to start at zero.
int pulseCounts[DHT_PULSES*2] = {0};
// Set pin to output.
pi_2_mmio_set_output(pin);
// Bump up process priority and change scheduler to try to try to make process more 'real time'.
set_max_priority();
// Set pin high for ~500 milliseconds.
pi_2_mmio_set_high(pin);
sleep_milliseconds(500);
// The next calls are timing critical and care should be taken
// to ensure no unnecssary work is done below.
// Set pin low for ~20 milliseconds.
pi_2_mmio_set_low(pin);
busy_wait_milliseconds(20);
// Set pin at input.
pi_2_mmio_set_input(pin);
// Need a very short delay before reading pins or else value is sometimes still low.
for (volatile int i = 0; i < 50; ++i) {
}
// Wait for DHT to pull pin low.
uint32_t count = 0;
while (pi_2_mmio_input(pin)) {
if (++count >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
// Record pulse widths for the expected result bits.
for (int i=0; i < DHT_PULSES*2; i+=2) {
// Count how long pin is low and store in pulseCounts[i]
while (!pi_2_mmio_input(pin)) {
if (++pulseCounts[i] >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
// Count how long pin is high and store in pulseCounts[i+1]
while (pi_2_mmio_input(pin)) {
if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
// Timeout waiting for response.
set_default_priority();
return DHT_ERROR_TIMEOUT;
}
}
}
// Done with timing critical code, now interpret the results.
// Drop back to normal priority.
set_default_priority();
// Compute the average low pulse width to use as a 50 microsecond reference threshold.
// Ignore the first two readings because they are a constant 80 microsecond pulse.
uint32_t threshold = 0;
for (int i=2; i < DHT_PULSES*2; i+=2) {
threshold += pulseCounts[i];
}
threshold /= DHT_PULSES-1;
// Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
// If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
// then it must be a ~70us 1 pulse.
uint8_t data[5] = {0};
for (int i=3; i < DHT_PULSES*2; i+=2) {
int index = (i-3)/16;
data[index] <<= 1;
if (pulseCounts[i] >= threshold) {
// One bit for long pulse.
data[index] |= 1;
}
// Else zero bit for short pulse.
}
// Useful debug info:
//printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]);
// Verify checksum of received data.
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
if (type == DHT11) {
// Get humidity and temp for DHT11 sensor.
*humidity = (float)data[0];
*temperature = (float)data[2];
}
else if (type == DHT22) {
// Calculate humidity and temp for DHT22 sensor.
*humidity = (data[0] * 256 + data[1]) / 10.0f;
*temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f;
if (data[2] & 0x80) {
*temperature *= -1.0f;
}
}
return DHT_SUCCESS;
}
else {
return DHT_ERROR_CHECKSUM;
}
}

View File

@@ -1,32 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#ifndef PI_2_DHT_READ_H
#define PI_2_DHT_READ_H
#include "../common_dht_read.h"
// Read DHT sensor connected to GPIO pin (using BCM numbering). Humidity and temperature will be
// returned in the provided parameters. If a successfull reading could be made a value of 0
// (DHT_SUCCESS) will be returned. If there was an error reading the sensor a negative value will
// be returned. Some errors can be ignored and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM.
int pi_2_dht_read(int sensor, int pin, float* humidity, float* temperature);
#endif

View File

@@ -1,71 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
// 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.
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "pi_2_mmio.h"
#define GPIO_BASE_OFFSET 0x200000
#define GPIO_LENGTH 4096
volatile uint32_t* pi_2_mmio_gpio = NULL;
int pi_2_mmio_init(void) {
if (pi_2_mmio_gpio == NULL) {
// Check for GPIO and peripheral addresses from device tree.
// Adapted from code in the RPi.GPIO library at:
// http://sourceforge.net/p/raspberry-gpio-python/
FILE *fp = fopen("/proc/device-tree/soc/ranges", "rb");
if (fp == NULL) {
return MMIO_ERROR_OFFSET;
}
fseek(fp, 4, SEEK_SET);
unsigned char buf[4];
if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) {
return MMIO_ERROR_OFFSET;
}
uint32_t peri_base = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0;
uint32_t gpio_base = peri_base + GPIO_BASE_OFFSET;
fclose(fp);
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
// Error opening /dev/mem. Probably not running as root.
return MMIO_ERROR_DEVMEM;
}
// Map GPIO memory to location in process space.
pi_2_mmio_gpio = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, gpio_base);
close(fd);
if (pi_2_mmio_gpio == MAP_FAILED) {
// Don't save the result if the memory mapping failed.
pi_2_mmio_gpio = NULL;
return MMIO_ERROR_MMAP;
}
}
return MMIO_SUCCESS;
}

View File

@@ -1,62 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
// 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.
// Simple fast memory-mapped GPIO library for the Raspberry Pi.
#ifndef PI_2_MMIO_H
#define PI_2_MMIO_H
#include <stdint.h>
#define MMIO_SUCCESS 0
#define MMIO_ERROR_DEVMEM -1
#define MMIO_ERROR_MMAP -2
#define MMIO_ERROR_OFFSET -3
volatile uint32_t* pi_2_mmio_gpio;
int pi_2_mmio_init(void);
static inline void pi_2_mmio_set_input(const int gpio_number) {
// Set GPIO register to 000 for specified GPIO number.
*(pi_2_mmio_gpio+((gpio_number)/10)) &= ~(7<<(((gpio_number)%10)*3));
}
static inline void pi_2_mmio_set_output(const int gpio_number) {
// First set to 000 using input function.
pi_2_mmio_set_input(gpio_number);
// Next set bit 0 to 1 to set output.
*(pi_2_mmio_gpio+((gpio_number)/10)) |= (1<<(((gpio_number)%10)*3));
}
static inline void pi_2_mmio_set_high(const int gpio_number) {
*(pi_2_mmio_gpio+7) = 1 << gpio_number;
}
static inline void pi_2_mmio_set_low(const int gpio_number) {
*(pi_2_mmio_gpio+10) = 1 << gpio_number;
}
static inline uint32_t pi_2_mmio_input(const int gpio_number) {
return *(pi_2_mmio_gpio+13) & (1 << gpio_number);
}
#endif

View File

@@ -1,34 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <stdlib.h>
#include "test_dht_read.h"
int test_dht_read(int type, int pin, float* humidity, float* temperature) {
// Validate humidity and temperature arguments and set them to zero.
if (humidity == NULL || temperature == NULL) {
return -1;
}
*temperature = 42.0f;
*humidity = 50.0f;
return 0;
}

View File

@@ -1,26 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#ifndef TEST_DHT_READ_H
#define TEST_DHT_READ_H
int test_dht_read(int sensor, int pin, float* humidity, float* temperature);
#endif

View File

@@ -1,49 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <Python.h>
#include "Beaglebone_Black/bbb_dht_read.h"
// Wrap calling dht_read function and expose it as a DHT.read Python module & function.
static PyObject* Beaglebone_Black_Driver_read(PyObject *self, PyObject *args)
{
// Parse sensor and pin integer arguments.
int sensor, base, number;
if (!PyArg_ParseTuple(args, "iii", &sensor, &base, &number)) {
return NULL;
}
// Call dht_read and return result code, humidity, and temperature.
float humidity = 0, temperature = 0;
int result = bbb_dht_read(sensor, base, number, &humidity, &temperature);
return Py_BuildValue("iff", result, humidity, temperature);
}
// Boilerplate python module method list and initialization functions below.
static PyMethodDef module_methods[] = {
{"read", Beaglebone_Black_Driver_read, METH_VARARGS, "Read DHT sensor value on a Beaglebone Black."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initBeaglebone_Black_Driver(void)
{
Py_InitModule("Beaglebone_Black_Driver", module_methods);
}

View File

@@ -1,49 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <Python.h>
#include "Raspberry_Pi_2/pi_2_dht_read.h"
// Wrap calling dht_read function and expose it as a DHT.read Python module & function.
static PyObject* Raspberry_Pi_2_Driver_read(PyObject *self, PyObject *args)
{
// Parse sensor and pin integer arguments.
int sensor, pin;
if (!PyArg_ParseTuple(args, "ii", &sensor, &pin)) {
return NULL;
}
// Call dht_read and return result code, humidity, and temperature.
float humidity = 0, temperature = 0;
int result = pi_2_dht_read(sensor, pin, &humidity, &temperature);
return Py_BuildValue("iff", result, humidity, temperature);
}
// Boilerplate python module method list and initialization functions below.
static PyMethodDef module_methods[] = {
{"read", Raspberry_Pi_2_Driver_read, METH_VARARGS, "Read DHT sensor value on a Raspberry Pi 2."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initRaspberry_Pi_2_Driver(void)
{
Py_InitModule("Raspberry_Pi_2_Driver", module_methods);
}

View File

@@ -1,49 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <Python.h>
#include "Raspberry_Pi/pi_dht_read.h"
// Wrap calling dht_read function and expose it as a DHT.read Python module & function.
static PyObject* Raspberry_Pi_Driver_read(PyObject *self, PyObject *args)
{
// Parse sensor and pin integer arguments.
int sensor, pin;
if (!PyArg_ParseTuple(args, "ii", &sensor, &pin)) {
return NULL;
}
// Call dht_read and return result code, humidity, and temperature.
float humidity = 0, temperature = 0;
int result = pi_dht_read(sensor, pin, &humidity, &temperature);
return Py_BuildValue("iff", result, humidity, temperature);
}
// Boilerplate python module method list and initialization functions below.
static PyMethodDef module_methods[] = {
{"read", Raspberry_Pi_Driver_read, METH_VARARGS, "Read DHT sensor value on a Raspberry Pi."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initRaspberry_Pi_Driver(void)
{
Py_InitModule("Raspberry_Pi_Driver", module_methods);
}

View File

@@ -1,49 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <Python.h>
#include "Test/test_dht_read.h"
// Wrap calling dht_read function and expose it as a DHT.read Python module & function.
static PyObject* Test_Driver_read(PyObject *self, PyObject *args)
{
// Parse sensor and pin integer arguments.
int sensor, pin;
if (!PyArg_ParseTuple(args, "ii", &sensor, &pin)) {
return NULL;
}
// Call dht_read and return result code, humidity, and temperature.
float humidity = 0, temperature = 0;
int result = test_dht_read(sensor, pin, &humidity, &temperature);
return Py_BuildValue("iff", result, humidity, temperature);
}
// Boilerplate python module method list and initialization functions below.
static PyMethodDef module_methods[] = {
{"read", Test_Driver_read, METH_VARARGS, "Mock DHT read function."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initTest_Driver(void)
{
Py_InitModule("Test_Driver", module_methods);
}

View File

@@ -1,66 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include "common_dht_read.h"
void busy_wait_milliseconds(uint32_t millis) {
// Set delay time period.
struct timeval deltatime;
deltatime.tv_sec = millis / 1000;
deltatime.tv_usec = (millis % 1000) * 1000;
struct timeval walltime;
// Get current time and add delay to find end time.
gettimeofday(&walltime, NULL);
struct timeval endtime;
timeradd(&walltime, &deltatime, &endtime);
// Tight loop to waste time (and CPU) until enough time as elapsed.
while (timercmp(&walltime, &endtime, <)) {
gettimeofday(&walltime, NULL);
}
}
void sleep_milliseconds(uint32_t millis) {
struct timespec sleep;
sleep.tv_sec = millis / 1000;
sleep.tv_nsec = (millis % 1000) * 1000000L;
while (clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, &sleep) && errno == EINTR);
}
void set_max_priority(void) {
struct sched_param sched;
memset(&sched, 0, sizeof(sched));
// Use FIFO scheduler with highest priority for the lowest chance of the kernel context switching.
sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &sched);
}
void set_default_priority(void) {
struct sched_param sched;
memset(&sched, 0, sizeof(sched));
// Go back to default scheduler with default 0 priority.
sched.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &sched);
}

View File

@@ -1,51 +0,0 @@
// Copyright (c) 2014 Adafruit Industries
// Author: Tony DiCola
// 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.
#ifndef COMMON_DHT_READ_H
#define COMMON_DHT_READ_H
#include <stdint.h>
// Define errors and return values.
#define DHT_ERROR_TIMEOUT -1
#define DHT_ERROR_CHECKSUM -2
#define DHT_ERROR_ARGUMENT -3
#define DHT_ERROR_GPIO -4
#define DHT_SUCCESS 0
// Define sensor types.
#define DHT11 11
#define DHT22 22
#define AM2302 22
// Busy wait delay for most accurate timing, but high CPU usage.
// Only use this for short periods of time (a few hundred milliseconds at most)!
void busy_wait_milliseconds(uint32_t millis);
// General delay that sleeps so CPU usage is low, but accuracy is potentially bad.
void sleep_milliseconds(uint32_t millis);
// Increase scheduling priority and algorithm to try to get 'real time' results.
void set_max_priority(void);
// Drop scheduling priority back to normal/default.
void set_default_priority(void);
#endif

View File

@@ -1,5 +0,0 @@
from state.dweet_server import DweetServer
import config
server = DweetServer(config.CONTROLLER_ID)
server.send_message("I am aliveeee (again)!");

View File

@@ -1,3 +0,0 @@
#!/bin/bash
curl -H "Content-Type: application/json" -X POST -d '{"message": "I am aliveeee"}' https://dweet.io:443/dweet/quietly/for/5410ab1e-319c-4f14-a2e4-04725df69121

View File

@@ -1,3 +0,0 @@
import state
state.safely_panic()

View File

@@ -1,2 +0,0 @@
requests==2.4.3
rpi.gpio==0.6.0a3

View File

@@ -1,60 +0,0 @@
#!/usr/bin/python
import sys
import requests
import Adafruit_DHT
import config
import RPi.GPIO as GPIO
# Try to read the state of GPIO_PIN_TANKLEVELx and GPIO_PIN_TANKFULL
GPIO.setmode(GPIO.BCM)
GPIO.setup(config.GPIO_PIN_TANKLEVEL0, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(config.GPIO_PIN_TANKLEVEL1, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(config.GPIO_PIN_TANKLEVEL2, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(config.GPIO_PIN_TANKLEVEL3, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(config.GPIO_PIN_TANKLEVEL4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(config.GPIO_PIN_TANKFULL, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
# tank sensor has inverse logic - 0 when it is full 1 when it is not
# so we are inverting its value here
tankLevel0 = (GPIO.input(config.GPIO_PIN_TANKLEVEL0) == GPIO.LOW)
tankLevel1 = (GPIO.input(config.GPIO_PIN_TANKLEVEL1) == GPIO.LOW)
tankLevel2 = (GPIO.input(config.GPIO_PIN_TANKLEVEL2) == GPIO.LOW)
tankLevel3 = (GPIO.input(config.GPIO_PIN_TANKLEVEL3) == GPIO.LOW)
tankLevel4 = (GPIO.input(config.GPIO_PIN_TANKLEVEL4) == GPIO.LOW)
tankFull = (GPIO.input(config.GPIO_PIN_TANKFULL) == GPIO.LOW)
GPIO.cleanup()
print 'Bacva Level0: {}'.format(tankLevel0)
print 'Bacva Level1: {}'.format(tankLevel1)
print 'Bacva Level2: {}'.format(tankLevel2)
print 'Bacva Level3: {}'.format(tankLevel3)
print 'Bacva Level4: {}'.format(tankLevel4)
print 'Bacva puna: {}'.format(tankFull)
# Go on to DHT
SENSOR_TYPE = Adafruit_DHT.DHT11
controller_id = config.CONTROLLER_ID
owner = "Controller: %s" % controller_id
# Try to grab a sensor reading. Use the read_retry method which will retry up
# to 15 times to get a sensor reading (waiting 2 seconds between each retry).
humidity, temperature = Adafruit_DHT.read_retry(SENSOR_TYPE, config.GPIO_PIN_DHT)
# Un-comment the line below to convert the temperature to Fahrenheit.
# temperature = temperature * 9/5.0 + 32
# Note that sometimes you won't get a reading and
# the results will be null (because Linux can't
# guarantee the timing of calls to read the sensor).
# If this happens try again!
if temperature is not None and humidity is not None:
response = requests.post(config.SENSORDATA_URL, json={"owner": owner, "temperatureValue": temperature, "humidityValue":humidity, "tankLevel0": "1" if tankLevel0 else "0","tankLevel1": "1" if tankLevel1 else "0","tankLevel2": "1" if tankLevel2 else "0","tankLevel3": "1" if tankLevel3 else "0", "tankLevel4": "1" if tankLevel4 else "0", "tankFull": "1" if tankFull else "0",
"controllerId": controller_id
})
print 'Temp={0:0.1f}*C'.format(temperature)
print 'Humidity={0:0.1f}%'.format(humidity)
if response.status_code != 200:
print 'Failed to send temperature!'
else:
print 'Failed to get reading. Try again!'

View File

@@ -1,39 +0,0 @@
import config
from state.server import Server
from state.changer import Changer
from state.file import File
import commands
def safely_panic():
safe_state = {}
changer = Changer(safe_state,safe_state)
changer.stop_everything()
def sync():
try:
server = Server(config.API_BASE_URL, config.CONTROLLER_ID)
local = File(config.STATE_FILE)
server_state = server.get_state()
if local.present():
local.load()
print "local present: " + repr(local.data)
else:
local.data = server_state
print "local not present, server: " + repr(local.data)
local.save()
local_state = local.data
changer = Changer(local_state, server_state)
current_state = changer.process_change()
server.post_state(current_state)
print " everything ok, canceling shutdown "
commands.getoutput('/sbin/shutdown -c')
except:
print " panicking safely ! "
safely_panic()
print " rebooting "
commands.getoutput('/sbin/shutdown -r +3')

View File

@@ -1,69 +0,0 @@
import RPi.GPIO as GPIO
import config
class Changer(object):
def __init__(self, local_state, remote_state):
self.local_state = local_state
self.remote_state = remote_state
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
GPIO.setup(config.GPIO_PIN_OUT_VALVE, GPIO.OUT)
GPIO.setup(config.GPIO_PIN_IN_VALVE, GPIO.OUT)
self.out_valve_states = {
'opening': self.open_out_valve,
'closing': self.close_out_valve,
'open': self.open_out_valve,
'closed': self.close_out_valve
}
self.in_valve_states = {
'opening': self.open_in_valve,
'closing': self.close_in_valve,
'open': self.open_in_valve,
'closed': self.close_in_valve
}
def stop_everything(self):
self.close_in_valve()
self.close_out_valve()
def safe_remote_state(self, key):
if key in ['out_valve', 'in_valve']:
return self.remote_state.get(key, 'closed')
else:
return self.remote_state.get(key,'');
def process_change(self):
self.validate_states()
out_valve_change = self.out_valve_states.get(self.safe_remote_state('out_valve'), None )
if out_valve_change is not None:
out_valve_change()
in_valve_change = self.in_valve_states.get(self.safe_remote_state('in_valve'), None )
if in_valve_change is not None:
in_valve_change()
return self.local_state
def open_in_valve(self):
GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.HIGH)
self.local_state['in_valve'] = 'open'
def close_in_valve(self):
GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.LOW)
self.local_state['in_valve'] = 'closed'
def open_out_valve(self):
GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.HIGH)
self.local_state['out_valve'] = 'open'
def close_out_valve(self):
GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.LOW)
self.local_state['out_valve'] = 'closed'
def validate_states(self):
if self.local_state is None or self.remote_state is None:
raise ClassNotReadyException("Both local and remote states must be present!")
# TODO: add detailed validation

View File

@@ -1,14 +0,0 @@
class ClassNotReadyException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class ErrorCommunicatingWithServerException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)

View File

@@ -1,27 +0,0 @@
import json
import os.path
class File(object):
"Holds controller state in the file"
def __init__(self, filename=None):
self.filename = filename
def present(self):
os.path.isfile(self.filename)
def load(self):
if self.filename is None:
raise ClassNotReadyException("Filename not set!")
with open(self.filename) as input_file:
self.data = json.load(input_file)
def save(self):
if self.filename is None:
raise ClassNotReadyException("Filename not set!")
if self.data is None:
raise ClassNotReadyException("Data not loaded!")
with open(self.filename, 'w') as out_file:
json.dump(self.data, out_file)

View File

@@ -1,31 +0,0 @@
import json
import requests
class Server(object):
"Gets state from server and sends it to the server after change"
def __init__(self, url_base=None, controller_id=None):
self.url_base = url_base
self.controller_id = controller_id
def get_state(self):
result = requests.get(self.full_url('state/%s') % self.controller_id)
return handle_response(result)
def post_state(self, local_state):
result = requests.post(self.full_url('state/%s') % self.controller_id, local_state)
return handle_response(result)
def full_url(self, action):
if self.controller_id is None:
raise ClassNotReadyException("Controller id not set!")
if self.url_base is None:
raise ClassNotReadyException("URL base not set!")
return self.url_base + '/' + action
def handle_response(response):
if response.status_code != 200:
raise ErrorCommunicatingWithServerException("Response not 200!")
else:
return response.json()

View File

@@ -1,3 +0,0 @@
import state
state.sync()