diff options
| author | geremy@pubnub.com | 2014-12-28 17:06:19 -0800 | 
|---|---|---|
| committer | geremy@pubnub.com | 2014-12-28 17:06:19 -0800 | 
| commit | b89bc8cb03f0534805c2112d5fa4253f82ab616f (patch) | |
| tree | 4559202652cbd265fe8a84e4933e36d127b2b465 | |
| parent | c2a3ee12ce2c42b05e1ee31d737d9a8703f4a580 (diff) | |
| download | pubnub-python-b89bc8cb03f0534805c2112d5fa4253f82ab616f.tar.bz2 | |
adding open/close files for door, new humid/temp sensor
32 files changed, 2286 insertions, 0 deletions
| diff --git a/python/examples/Adafruit_Python_DHT/.gitignore b/python/examples/Adafruit_Python_DHT/.gitignore new file mode 100644 index 0000000..8051352 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/.gitignore @@ -0,0 +1,5 @@ +build +*.egg-info +*.pyc +setuptools-* + diff --git a/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Beaglebone_Black.py b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Beaglebone_Black.py new file mode 100644 index 0000000..8716482 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Beaglebone_Black.py @@ -0,0 +1,217 @@ +# 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) diff --git a/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Raspberry_Pi.py b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Raspberry_Pi.py new file mode 100644 index 0000000..eaf4488 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Raspberry_Pi.py @@ -0,0 +1,38 @@ +# 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) diff --git a/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Test.py b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Test.py new file mode 100644 index 0000000..57db439 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/Test.py @@ -0,0 +1,33 @@ +# 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) diff --git a/python/examples/Adafruit_Python_DHT/Adafruit_DHT/__init__.py b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/__init__.py new file mode 100644 index 0000000..1c49666 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/__init__.py @@ -0,0 +1,21 @@ +# 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
\ No newline at end of file diff --git a/python/examples/Adafruit_Python_DHT/Adafruit_DHT/common.py b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/common.py new file mode 100644 index 0000000..eec472e --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/common.py @@ -0,0 +1,86 @@ +# 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: +		import Raspberry_Pi +		return Raspberry_Pi +	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) diff --git a/python/examples/Adafruit_Python_DHT/Adafruit_DHT/platform_detect.py b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/platform_detect.py new file mode 100644 index 0000000..154e4b1 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/Adafruit_DHT/platform_detect.py @@ -0,0 +1,56 @@ +# 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 platform + +# Platform identification constants. +UNKNOWN          = 0 +RASPBERRY_PI     = 1 +BEAGLEBONE_BLACK = 2 + + +def platform_detect(plat=platform.platform()): +	"""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 +	# Platform output on Raspbian testing/jessie ~May 2014: +	# Linux-3.10.25+-armv6l-with-debian-7.4 +	if plat.lower().find('armv6l-with-debian') > -1: +		return RASPBERRY_PI +	# Handle pidora distribution. +	elif plat.lower().find('raspberry_pi') > -1: +		return RASPBERRY_PI +	# Handle arch distribution. +	elif plat.lower().find('arch-armv6l') > -1: +		return RASPBERRY_PI +	# Handle Beaglebone Black +	# Platform output on Debian ~May 2014: +	# Linux-3.8.13-bone47-armv7l-with-debian-7.4 +	elif plat.lower().find('armv7l-with-debian') > -1: +		return BEAGLEBONE_BLACK +	# Handle Beaglebone Black +	# Platform output on Ubuntu ~July 2014: +	# Linux-3.8.13-bone56-armv7l-with-Ubuntu-14.04-trusty +	elif plat.lower().find('armv7l-with-ubuntu') > -1: +		return BEAGLEBONE_BLACK	 +	elif plat.lower().find('armv7l-with-glibc2.4') > -1: +		return BEAGLEBONE_BLACK +	else: +		return UNKNOWN diff --git a/python/examples/Adafruit_Python_DHT/LICENSE b/python/examples/Adafruit_Python_DHT/LICENSE new file mode 100644 index 0000000..35a35d3 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/LICENSE @@ -0,0 +1,21 @@ +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.
\ No newline at end of file diff --git a/python/examples/Adafruit_Python_DHT/README.md b/python/examples/Adafruit_Python_DHT/README.md new file mode 100644 index 0000000..c0cd02e --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/README.md @@ -0,0 +1,29 @@ +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: + +```` +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 diff --git a/python/examples/Adafruit_Python_DHT/dist/Adafruit_DHT-1.0.0-py2.7-linux-armv6l.egg b/python/examples/Adafruit_Python_DHT/dist/Adafruit_DHT-1.0.0-py2.7-linux-armv6l.eggBinary files differ new file mode 100644 index 0000000..b0da7fa --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/dist/Adafruit_DHT-1.0.0-py2.7-linux-armv6l.egg diff --git a/python/examples/Adafruit_Python_DHT/examples/AdafruitDHT.py b/python/examples/Adafruit_Python_DHT/examples/AdafruitDHT.py new file mode 100755 index 0000000..daa9770 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/examples/AdafruitDHT.py @@ -0,0 +1,50 @@ +#!/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) + +# 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!' diff --git a/python/examples/Adafruit_Python_DHT/examples/google_spreadsheet.py b/python/examples/Adafruit_Python_DHT/examples/google_spreadsheet.py new file mode 100755 index 0000000..fddda65 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/examples/google_spreadsheet.py @@ -0,0 +1,98 @@ +#!/usr/bin/python + +# Google Spreadsheet DHT Sensor Data-logging Example + +# Depends on the 'gspread' package being installed.  If you have pip installed +# execute: +#   sudo pip install gspread + +# 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 time +import datetime + +import Adafruit_DHT +import gspread + +# 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 account email, password, and spreadsheet name. +GDOCS_EMAIL            = 'your google docs account email address' +GDOCS_PASSWORD         = 'your google docs account password' +GDOCS_SPREADSHEET_NAME = 'your google docs spreadsheet name' + +# How long to wait (in seconds) between measurements. +FREQUENCY_SECONDS      = 30 + + +def login_open_sheet(email, password, spreadsheet): +	"""Connect to Google Docs spreadsheet and return the first worksheet.""" +	try: +		gc = gspread.login(email, password) +		worksheet = gc.open(spreadsheet).sheet1 +		return worksheet +	except: +		print 'Unable to login and get spreadsheet.  Check email, password, spreadsheet name.' +		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_EMAIL, GDOCS_PASSWORD, 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) diff --git a/python/examples/Adafruit_Python_DHT/examples/simpletest.py b/python/examples/Adafruit_Python_DHT/examples/simpletest.py new file mode 100644 index 0000000..e8aa30d --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/examples/simpletest.py @@ -0,0 +1,48 @@ +#!/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.DHT11 + +# 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 pin 23. +pin = 7 + +# 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!' diff --git a/python/examples/Adafruit_Python_DHT/ez_setup.py b/python/examples/Adafruit_Python_DHT/ez_setup.py new file mode 100644 index 0000000..1bcd3e9 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/ez_setup.py @@ -0,0 +1,332 @@ +#!/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()) diff --git a/python/examples/Adafruit_Python_DHT/setup.py b/python/examples/Adafruit_Python_DHT/setup.py new file mode 100644 index 0000000..8f99751 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/setup.py @@ -0,0 +1,55 @@ +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 +if '--force-pi' in sys.argv: +	platform = platform_detect.RASPBERRY_PI +	sys.argv.remove('--force-pi') +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: +	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 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.0.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) diff --git a/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_dht_read.c b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_dht_read.c new file mode 100644 index 0000000..0fa2761 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_dht_read.c @@ -0,0 +1,154 @@ +// 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; +  } +} diff --git a/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_dht_read.h b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_dht_read.h new file mode 100644 index 0000000..949ad2c --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_dht_read.h @@ -0,0 +1,33 @@ +// 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 diff --git a/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_mmio.c b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_mmio.c new file mode 100644 index 0000000..fda1beb --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_mmio.c @@ -0,0 +1,73 @@ +// 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; +} diff --git a/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_mmio.h b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_mmio.h new file mode 100644 index 0000000..b6d5faa --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Beaglebone_Black/bbb_mmio.h @@ -0,0 +1,101 @@ +// 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 diff --git a/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_dht_read.c b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_dht_read.c new file mode 100644 index 0000000..0789e60 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_dht_read.c @@ -0,0 +1,158 @@ +// 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; +  } +} diff --git a/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_dht_read.h b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_dht_read.h new file mode 100644 index 0000000..9132e96 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_dht_read.h @@ -0,0 +1,32 @@ +// 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 diff --git a/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_mmio.c b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_mmio.c new file mode 100644 index 0000000..6755230 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_mmio.c @@ -0,0 +1,55 @@ +// 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; +} diff --git a/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_mmio.h b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_mmio.h new file mode 100644 index 0000000..d47a9c3 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Raspberry_Pi/pi_mmio.h @@ -0,0 +1,61 @@ +// 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 diff --git a/python/examples/Adafruit_Python_DHT/source/Test/test_dht_read.c b/python/examples/Adafruit_Python_DHT/source/Test/test_dht_read.c new file mode 100644 index 0000000..be06744 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Test/test_dht_read.c @@ -0,0 +1,34 @@ +// 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; +} diff --git a/python/examples/Adafruit_Python_DHT/source/Test/test_dht_read.h b/python/examples/Adafruit_Python_DHT/source/Test/test_dht_read.h new file mode 100644 index 0000000..b4d2601 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/Test/test_dht_read.h @@ -0,0 +1,26 @@ +// 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 diff --git a/python/examples/Adafruit_Python_DHT/source/_Beaglebone_Black_Driver.c b/python/examples/Adafruit_Python_DHT/source/_Beaglebone_Black_Driver.c new file mode 100644 index 0000000..329aead --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/_Beaglebone_Black_Driver.c @@ -0,0 +1,49 @@ +// 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); +} diff --git a/python/examples/Adafruit_Python_DHT/source/_Raspberry_Pi_Driver.c b/python/examples/Adafruit_Python_DHT/source/_Raspberry_Pi_Driver.c new file mode 100644 index 0000000..a867597 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/_Raspberry_Pi_Driver.c @@ -0,0 +1,49 @@ +// 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); +} diff --git a/python/examples/Adafruit_Python_DHT/source/_Test_Driver.c b/python/examples/Adafruit_Python_DHT/source/_Test_Driver.c new file mode 100644 index 0000000..36257e5 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/_Test_Driver.c @@ -0,0 +1,49 @@ +// 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); +} diff --git a/python/examples/Adafruit_Python_DHT/source/common_dht_read.c b/python/examples/Adafruit_Python_DHT/source/common_dht_read.c new file mode 100644 index 0000000..3bbb663 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/common_dht_read.c @@ -0,0 +1,66 @@ +// 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); +} diff --git a/python/examples/Adafruit_Python_DHT/source/common_dht_read.h b/python/examples/Adafruit_Python_DHT/source/common_dht_read.h new file mode 100644 index 0000000..bb56c67 --- /dev/null +++ b/python/examples/Adafruit_Python_DHT/source/common_dht_read.h @@ -0,0 +1,51 @@ +// 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 diff --git a/python/examples/close.py b/python/examples/close.py new file mode 100644 index 0000000..72dd340 --- /dev/null +++ b/python/examples/close.py @@ -0,0 +1,103 @@ +#----------------------------------- +# Name: Stepper Motor +# +# Author: matt.hawkins +# +# Created: 11/07/2012 +# Copyright: (c) matt.hawkins 2012 +#----------------------------------- +#!/usr/bin/env python +  +# Import required libraries +import time +import sys +import RPi.GPIO as GPIO + +# Use BCM GPIO references +# instead of physical pin numbers +GPIO.setmode(GPIO.BOARD) +  +# Define GPIO signals to use +# Pins 19,22,24,26 +# GPIO10,GPIO25,GPIO8,GPIO7 + +StepPins = [26,24,22,19] +#StepPins = [24,22,26,19] +  +# Set all pins as output +for pin in StepPins: +  print "Setup pins" +  GPIO.setup(pin,GPIO.OUT) +  GPIO.output(pin, False) +  +# Define some settings +StepCounter = 0 +WaitTime = 0.000001 +#WaitTime = 0.001 +  +# Define simple sequence +StepCount1 = 4 +Seq1 = [] +Seq1 = range(0, StepCount1) + +Seq1[0] = [1,0,0,0] +Seq1[1] = [0,1,0,0] +Seq1[2] = [0,0,1,0] +Seq1[3] = [0,0,0,1] + +#Seq1[3] = [1,0,0,0] +#Seq1[2] = [0,1,0,0] +#Seq1[1] = [0,0,1,0] +#Seq1[0] = [0,0,0,1] +  +# Define advanced sequence +# as shown in manufacturers datasheet +StepCount2 = 8 +Seq2 = [] +Seq2 = range(0, StepCount2) +Seq2[7] = [1,0,0,0] +Seq2[6] = [1,1,0,0] +Seq2[5] = [0,1,0,0] +Seq2[4] = [0,1,1,0] +Seq2[3] = [0,0,1,0] +Seq2[2] = [0,0,1,1] +Seq2[1] = [0,0,0,1] +Seq2[0] = [1,0,0,1] +  +# Choose a sequence to use +Seq = Seq2 +StepCount = StepCount2 +GlobalCount = 1600 +Cycles = 0 +  +# Start main loop +while 1==1: +  +  for pin in range(0, 4): +    xpin = StepPins[pin] + +    pinVal = Seq[StepCounter][pin] + +    if pinVal!=0: +      #print " Step %i Enable %i" %(StepCounter,xpin) +      GPIO.output(xpin, True) +    else: +      GPIO.output(xpin, False) +  +  StepCounter += 1 +  Cycles +=1 + +  print " Stepcounter: %i" %(StepCounter)  +  # If we reach the end of the sequence +  # start again +  if (StepCounter==StepCount): +    StepCounter = 0 + +  if (StepCounter<0): +    StepCounter = StepCount + +  if (GlobalCount == Cycles): +   sys.exit() + +  # Wait before moving on +  time.sleep(WaitTime) diff --git a/python/examples/open.py b/python/examples/open.py new file mode 100644 index 0000000..b5518c6 --- /dev/null +++ b/python/examples/open.py @@ -0,0 +1,103 @@ +#----------------------------------- +# Name: Stepper Motor +# +# Author: matt.hawkins +# +# Created: 11/07/2012 +# Copyright: (c) matt.hawkins 2012 +#----------------------------------- +#!/usr/bin/env python +  +# Import required libraries +import time +import sys +import RPi.GPIO as GPIO + +# Use BCM GPIO references +# instead of physical pin numbers +GPIO.setmode(GPIO.BOARD) +  +# Define GPIO signals to use +# Pins 19,22,24,26 +# GPIO10,GPIO25,GPIO8,GPIO7 + +StepPins = [26,24,22,19] +#StepPins = [24,22,26,19] +  +# Set all pins as output +for pin in StepPins: +  print "Setup pins" +  GPIO.setup(pin,GPIO.OUT) +  GPIO.output(pin, False) +  +# Define some settings +StepCounter = 0 +WaitTime = 0.000001 +#WaitTime = 0.001 +  +# Define simple sequence +StepCount1 = 4 +Seq1 = [] +Seq1 = range(0, StepCount1) + +Seq1[0] = [1,0,0,0] +Seq1[1] = [0,1,0,0] +Seq1[2] = [0,0,1,0] +Seq1[3] = [0,0,0,1] + +#Seq1[3] = [1,0,0,0] +#Seq1[2] = [0,1,0,0] +#Seq1[1] = [0,0,1,0] +#Seq1[0] = [0,0,0,1] +  +# Define advanced sequence +# as shown in manufacturers datasheet +StepCount2 = 8 +Seq2 = [] +Seq2 = range(0, StepCount2) +Seq2[0] = [1,0,0,0] +Seq2[1] = [1,1,0,0] +Seq2[2] = [0,1,0,0] +Seq2[3] = [0,1,1,0] +Seq2[4] = [0,0,1,0] +Seq2[5] = [0,0,1,1] +Seq2[6] = [0,0,0,1] +Seq2[7] = [1,0,0,1] +  +# Choose a sequence to use +Seq = Seq2 +StepCount = StepCount2 +GlobalCount = 1600 +Cycles = 0 +  +# Start main loop +while 1==1: +  +  for pin in range(0, 4): +    xpin = StepPins[pin] + +    pinVal = Seq[StepCounter][pin] + +    if pinVal!=0: +      #print " Step %i Enable %i" %(StepCounter,xpin) +      GPIO.output(xpin, True) +    else: +      GPIO.output(xpin, False) +  +  StepCounter += 1 +  Cycles +=1 + +  print " Stepcounter: %i" %(StepCounter)  +  # If we reach the end of the sequence +  # start again +  if (StepCounter==StepCount): +    StepCounter = 0 + +  if (StepCounter<0): +    StepCounter = StepCount + +  if (GlobalCount == Cycles): +   sys.exit() + +  # Wait before moving on +  time.sleep(WaitTime) | 
