├── .gitignore ├── .stickler.yml ├── LICENSE ├── Makefile ├── README.md ├── documentation └── REFERENCE.md ├── examples ├── advanced │ └── pi-lluminate.py ├── all.py ├── motion_detect.py └── temperature.py ├── library ├── CHANGELOG.txt ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── envirophat │ ├── __init__.py │ ├── ads1015.py │ ├── bmp280.py │ ├── i2c_bus.py │ ├── leds.py │ ├── lsm303d.py │ └── tcs3472.py ├── setup.cfg ├── setup.py └── test_envirophat.py ├── packaging ├── CHANGELOG ├── debian │ ├── README │ ├── changelog │ ├── clean │ ├── compat │ ├── control │ ├── copyright │ ├── docs │ ├── rules │ └── source │ │ ├── format │ │ └── options ├── makeall.sh ├── makedeb.sh ├── makedoc.sh └── makelog.sh ├── sphinx ├── _static │ └── custom.css ├── _templates │ ├── breadcrumbs.html │ └── layout.html ├── conf.py ├── favicon.png ├── index.rst └── shop-logo.png └── terminal.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | _build/ 3 | *.py[cod] 4 | *.swp 5 | dist/ 6 | sdist/ 7 | env/ 8 | build/ 9 | develop-eggs/ 10 | eggs/ 11 | *.egg-info/ 12 | .installed.cfg 13 | *.egg 14 | *.deb 15 | *.dsc 16 | *.build 17 | *.changes 18 | *.orig.* 19 | packaging/*tar.xz 20 | library/debian/ 21 | testing/ 22 | MANIFEST 23 | .idea 24 | pip-log.txt 25 | pip-delete-this-directory.txt 26 | .DS_Store 27 | 28 | -------------------------------------------------------------------------------- /.stickler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | linters: 3 | flake8: 4 | python: 3 5 | max-line-length: 160 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Pimoroni Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIBRARY_VERSION=$(shell grep version library/setup.cfg | awk -F" = " '{print $$2}') 2 | LIBRARY_NAME=$(shell grep name library/setup.cfg | awk -F" = " '{print $$2}') 3 | 4 | .PHONY: usage install uninstall 5 | usage: 6 | @echo "Library: ${LIBRARY_NAME}" 7 | @echo "Version: ${LIBRARY_VERSION}\n" 8 | @echo "Usage: make , where target is one of:\n" 9 | @echo "install: install the library locally from source" 10 | @echo "uninstall: uninstall the local library" 11 | @echo "check: peform basic integrity checks on the codebase" 12 | @echo "python-readme: generate library/README.rst from README.md" 13 | @echo "python-wheels: build python .whl files for distribution" 14 | @echo "python-sdist: build python source distribution" 15 | @echo "python-clean: clean python build and dist directories" 16 | @echo "python-dist: build all python distribution files" 17 | @echo "python-testdeploy: build all and deploy to test PyPi" 18 | @echo "tag: tag the repository with the current version" 19 | 20 | install: 21 | ./install.sh 22 | 23 | uninstall: 24 | ./uninstall.sh 25 | 26 | check: 27 | @echo "Checking for trailing whitespace" 28 | @! grep -IUrn --color "[[:blank:]]$$" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO 29 | @echo "Checking for DOS line-endings" 30 | @! grep -IUrn --color " " --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile 31 | @echo "Checking library/CHANGELOG.txt" 32 | @cat library/CHANGELOG.txt | grep ^${LIBRARY_VERSION} 33 | @echo "Checking library/${LIBRARY_NAME}/__init__.py" 34 | @cat library/${LIBRARY_NAME}/__init__.py | grep "^__version__ = '${LIBRARY_VERSION}'" 35 | 36 | tag: 37 | git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}" 38 | 39 | python-readme: library/README.rst 40 | 41 | python-license: library/LICENSE.txt 42 | 43 | library/README.rst: README.md library/CHANGELOG.txt 44 | pandoc --from=markdown --to=rst -o library/README.rst README.md 45 | echo "" >> library/README.rst 46 | cat library/CHANGELOG.txt >> library/README.rst 47 | 48 | library/LICENSE.txt: LICENSE 49 | cp LICENSE library/LICENSE.txt 50 | 51 | python-wheels: python-readme python-license 52 | cd library; python3 setup.py bdist_wheel 53 | cd library; python setup.py bdist_wheel 54 | 55 | python-sdist: python-readme python-license 56 | cd library; python setup.py sdist 57 | 58 | python-clean: 59 | -rm -r library/dist 60 | -rm -r library/build 61 | -rm -r library/*.egg-info 62 | 63 | python-dist: python-clean python-wheels python-sdist 64 | ls library/dist 65 | 66 | python-testdeploy: python-dist 67 | twine upload --repository-url https://test.pypi.org/legacy/ library/dist/* 68 | 69 | python-deploy: check python-dist 70 | twine upload library/dist/* 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Enviro pHAT 2 | 3 | https://shop.pimoroni.com/products/enviro-phat 4 | 5 | The Pimoroni Enviro pHAT boast a plethora of sensors and connectivity for measuring your environment. 6 | 7 | Enviro pHAT includes: 8 | 9 | * An LSM303D accelerometer/magnetometer for detecting orientation, motion and heading 10 | * A BMP280 temperature/pressure sensor 11 | * A TCS3472 colour sensor, for detecting the amount and colour of light 12 | * An ADS1015 analog sensor with four 3.3v tolerant channels for your external sensors 13 | * A 5v power supply pin for powering your sensors, which you can regulate or divide to 3v if needed 14 | * Two LEDs connected to GPIO #4 for illuminating objects over the colour sensor 15 | 16 | ### Note: for Enviro and Enviro Plus see: https://github.com/pimoroni/enviroplus-python/ 17 | 18 | ## Installing 19 | 20 | ### Full install (recommended): 21 | 22 | We've created an easy installation script that will install all pre-requisites and get your Enviro pHAT 23 | up and running with minimal efforts. To run it, fire up Terminal which you'll find in Menu -> Accessories -> Terminal 24 | on your Raspberry Pi desktop, as illustrated below: 25 | 26 | ![Finding the terminal](http://get.pimoroni.com/resources/github-repo-terminal.png) 27 | 28 | In the new terminal window type the command exactly as it appears below (check for typos) and follow the on-screen instructions: 29 | 30 | ```bash 31 | curl https://get.pimoroni.com/envirophat | bash 32 | ``` 33 | 34 | Alternatively, on Raspbian, you can download the `pimoroni-dashboard` and install your product by browsing to the relevant entry: 35 | 36 | ```bash 37 | sudo apt-get install pimoroni 38 | ``` 39 | (you will find the Dashboard under 'Accessories' too, in the Pi menu - or just run `pimoroni-dashboard` at the command line) 40 | 41 | If you choose to download examples you'll find them in `/home/pi/Pimoroni/envirophat/`. 42 | 43 | ### Manual install: 44 | 45 | #### Library install for Python 3: 46 | 47 | on Raspbian: 48 | 49 | ```bash 50 | sudo apt-get install python3-envirophat 51 | ``` 52 | 53 | other environments: 54 | 55 | ```bash 56 | sudo pip3 install envirophat 57 | ``` 58 | 59 | #### Library install for Python 2: 60 | 61 | on Raspbian: 62 | 63 | ```bash 64 | sudo apt-get install python-envirophat 65 | ``` 66 | 67 | other environments: 68 | 69 | ```bash 70 | sudo pip2 install envirophat 71 | ``` 72 | 73 | ### Development: 74 | 75 | If you want to contribute, or like living on the edge of your seat by having the latest code, you should clone this repository, `cd` to the library directory, and run: 76 | 77 | ```bash 78 | sudo python3 setup.py install 79 | ``` 80 | (or `sudo python setup.py install` whichever your primary Python environment may be) 81 | 82 | In all cases you will have to enable the i2c bus. 83 | 84 | ## Documentation & Support 85 | 86 | * Guides and tutorials - https://learn.pimoroni.com/enviro-phat 87 | * Function reference - http://docs.pimoroni.com/envirophat/ 88 | * GPIO Pinout - https://pinout.xyz/pinout/enviro_phat 89 | * Get help - http://forums.pimoroni.com/c/support 90 | -------------------------------------------------------------------------------- /documentation/REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Enviro pHAT Function Reference 2 | for full API documentation, see http://docs.pimoroni.com/envirophat/ 3 | 4 | You can import one or more devices from the Enviro pHAT library, which has: 5 | 6 | * light 7 | * motion 8 | * weather 9 | * analog 10 | * leds 11 | 12 | For example: 13 | 14 | ```python 15 | from envirophat import motion, light 16 | ``` 17 | 18 | ## Weather 19 | 20 | Weather is monitored by the BMP280 temperature/pressure sensor. 21 | 22 | Get the temperature in degrees C: 23 | 24 | ``` 25 | weather.temperature() 26 | ``` 27 | 28 | Get the pressure in hPA: 29 | 30 | ``` 31 | weather.pressure() 32 | ``` 33 | 34 | ## Light 35 | 36 | Light sensing is provided by a TCS3472 colour sensor, which has 4 light sensors inside with different filters in front of them. 3 of these are red, blue and green, and the 4th is unfiltered to provide a light level for comparison. It's usually referred to as "clear". 37 | 38 | Get the colour of the light, adjusted against clear and scaled to 0-255: 39 | 40 | ``` 41 | r, g, b = light.rgb() 42 | ``` 43 | 44 | Get the amount of light detected: 45 | 46 | ``` 47 | light.light() 48 | ``` 49 | 50 | ## Motion 51 | 52 | The LSM303D can detect the motion, orientation and magnetic heading of your Pi. 53 | 54 | Get the raw accelerometer data: 55 | 56 | ``` 57 | x, y, z = motion.accelerometer() 58 | ``` 59 | 60 | Get your Pi's offset, in degrees, from magnetic north: 61 | 62 | ``` 63 | motion.heading() 64 | ``` 65 | 66 | You can also get the raw magnetometer data, but you'll have to get creative 67 | to do something useful with it! 68 | 69 | ``` 70 | x,y,z = motion.magnetometer() 71 | ``` 72 | 73 | ## Analog 74 | 75 | Enviro pHAT uses an ADS1015 to provide four 3.3v tolerant analog inputs and a 5v power supply pin for your external sensors. 76 | 77 | You can read all of the analog readings at once like so: 78 | 79 | ``` 80 | analog.read_all() 81 | ``` 82 | 83 | This will return 4 floating point values between 0.0 and 3.3v, directly mapping to the detected voltage. 84 | -------------------------------------------------------------------------------- /examples/advanced/pi-lluminate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Use the Enviro pHAT to check how much light is in a room, then trigger a webhook to control 4 | # Philips Hue lights via IFTTT. By Wesley Archer (@raspberrycoulis). 5 | 6 | # Import the relevant modules 7 | 8 | import requests 9 | import time 10 | import datetime 11 | from envirophat import light 12 | 13 | 14 | # Get the current time for displaying in the terminal. 15 | def whats_the_time(): 16 | now = datetime.datetime.now() 17 | return (now.strftime("%H:%M:%S")) 18 | 19 | 20 | # The function to turn off the lights. Sends a webhook to IFTTT which 21 | # triggers Hue. Replace the trigger word and tokens from your account. 22 | def turn_off(): 23 | # Set your trigger word - e.g. "light" - and the IFTTT Webhook token below. 24 | TRIGGER_WORD = "YOUR CHOSEN TRIGGER WORD GOES HERE" 25 | TOKEN = "YOUR IFTTT TOKEN GOES HERE" 26 | 27 | requests.post("https://maker.ifttt.com/trigger/{trigger_word}/with/key/{token}".format(trigger_word=TRIGGER_WORD, token=TOKEN)) 28 | print("Lights off!") 29 | 30 | 31 | # The function to turn on the lights. Sends a webhook to IFTTT which 32 | # triggers Hue. Replace the trigger word and tokens from your account. 33 | def turn_on(): 34 | # Set your trigger word - e.g. "dark" - and the IFTTT Webhook token below. 35 | TRIGGER_WORD = "YOUR CHOSEN TRIGGER WORD GOES HERE" 36 | TOKEN = "YOUR IFTTT TOKEN GOES HERE" 37 | 38 | requests.post("https://maker.ifttt.com/trigger/{trigger_word}/with/key/{token}".format(trigger_word=TRIGGER_WORD, token=TOKEN)) 39 | print("Lights on!") 40 | 41 | 42 | # Check the light level and determine whether the lights need to 43 | # be turned on or off. 44 | def average_lux(): 45 | # Variables for calculating the average lux levels 46 | start_time = time.time() 47 | curr_time = time.time() 48 | collect_light_time = 60 49 | collect_light_data = [] 50 | 51 | # Calculate the average lux level over 60 seconds 52 | print("Calculating average light level...") 53 | while curr_time - start_time < collect_light_time: 54 | curr_time = time.time() 55 | avg = light.light() 56 | collect_light_data.append(avg) 57 | time.sleep(1) 58 | 59 | # Take the last 45 data points taken over 60 seconds to calculate the average 60 | average_light = sum(collect_light_data[-45:]) / 45.0 61 | now = whats_the_time() 62 | print("Average over {collect_time} seconds is: {average} lux. Last checked at {time}".format( 63 | collect_time=collect_light_time, 64 | average=average_light, 65 | time=now 66 | )) 67 | return average_light 68 | 69 | 70 | try: 71 | # Local variables. 72 | low = 260 # Low value for light level (lux). 73 | high = 300 # High value for light level (lux). 74 | period = 90 # Delay, in seconds, between calls. 75 | lights_on = False # Set the state of the lights to off. 76 | 77 | while True: 78 | # Get the average lux level first, 79 | room_light = average_lux() 80 | 81 | # Now check if the room is dark enough then turn on the lights. 82 | if room_light < low and not lights_on: 83 | turn_on() 84 | lights_on = True 85 | elif room_light > high and lights_on: 86 | turn_off() 87 | lights_on = False 88 | 89 | print("Waiting {} seconds before trying again".format(period)) 90 | time.sleep(period) 91 | 92 | except KeyboardInterrupt: 93 | pass 94 | -------------------------------------------------------------------------------- /examples/all.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import time 5 | 6 | from envirophat import light, weather, motion, analog 7 | 8 | unit = 'hPa' # Pressure unit, can be either hPa (hectopascals) or Pa (pascals) 9 | 10 | 11 | def write(line): 12 | sys.stdout.write(line) 13 | sys.stdout.flush() 14 | 15 | 16 | write("--- Enviro pHAT Monitoring ---") 17 | 18 | try: 19 | while True: 20 | rgb = light.rgb() 21 | analog_values = analog.read_all() 22 | mag_values = motion.magnetometer() 23 | acc_values = [round(x, 2) for x in motion.accelerometer()] 24 | 25 | output = """ 26 | Temp: {t:.2f}c 27 | Pressure: {p:.2f}{unit} 28 | Altitude: {a:.2f}m 29 | Light: {c} 30 | RGB: {r}, {g}, {b} 31 | Heading: {h} 32 | Magnetometer: {mx} {my} {mz} 33 | Accelerometer: {ax}g {ay}g {az}g 34 | Analog: 0: {a0}, 1: {a1}, 2: {a2}, 3: {a3} 35 | 36 | """.format( 37 | unit=unit, 38 | a=weather.altitude(), # Supply your local qnh for more accurate readings 39 | t=weather.temperature(), 40 | p=weather.pressure(unit=unit), 41 | c=light.light(), 42 | r=rgb[0], 43 | g=rgb[1], 44 | b=rgb[2], 45 | h=motion.heading(), 46 | a0=analog_values[0], 47 | a1=analog_values[1], 48 | a2=analog_values[2], 49 | a3=analog_values[3], 50 | mx=mag_values[0], 51 | my=mag_values[1], 52 | mz=mag_values[2], 53 | ax=acc_values[0], 54 | ay=acc_values[1], 55 | az=acc_values[2] 56 | ) 57 | 58 | output = output.replace("\n", "\n\033[K") 59 | write(output) 60 | lines = len(output.split("\n")) 61 | write("\033[{}A".format(lines - 1)) 62 | 63 | time.sleep(1) 64 | 65 | except KeyboardInterrupt: 66 | pass 67 | -------------------------------------------------------------------------------- /examples/motion_detect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | 5 | from envirophat import motion, leds 6 | 7 | 8 | print("""This example will detect motion using the accelerometer. 9 | 10 | Press Ctrl+C to exit. 11 | 12 | """) 13 | 14 | threshold = 0.2 15 | readings = [] 16 | last_z = 0 17 | 18 | try: 19 | while True: 20 | readings.append(motion.accelerometer().z) 21 | readings = readings[-4:] 22 | z = sum(readings) / len(readings) 23 | if last_z > 0 and abs(z - last_z) > threshold: 24 | print("Motion Detected!!!") 25 | leds.on() 26 | last_z = z 27 | time.sleep(0.01) 28 | leds.off() 29 | except KeyboardInterrupt: 30 | pass 31 | -------------------------------------------------------------------------------- /examples/temperature.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | 5 | from envirophat import weather, leds 6 | 7 | 8 | print("""Light the LEDs upon temperature increase. 9 | 10 | Press Ctrl+C to exit. 11 | 12 | """) 13 | 14 | threshold = None 15 | 16 | try: 17 | while True: 18 | temperature = weather.temperature() 19 | 20 | if threshold is None: 21 | threshold = temperature + 2 22 | 23 | print("{} degrees Celsius".format(temperature)) 24 | if temperature > threshold: 25 | leds.on() 26 | else: 27 | leds.off() 28 | 29 | time.sleep(0.1) 30 | 31 | except KeyboardInterrupt: 32 | pass 33 | -------------------------------------------------------------------------------- /library/CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | 1.0.1 2 | ----- 3 | 4 | * Fix: Corrected upper bounds check for tilt_heading 5 | 6 | 1.0.0 7 | ----- 8 | 9 | * Fix: Defer setup to avoid import side-effects 10 | * Fix: QNH changed to ISA standard 11 | * Tweak: New Enviro pHAT I2C addr now default 12 | * Added: unit argument to pressure to choose Pa or hPa 13 | 14 | 0.0.6 15 | ----- 16 | 17 | * Added __version__ to module 18 | * Added DocStrings 19 | 20 | 0.0.5 21 | ----- 22 | 23 | * Bug fix to lsm303d raw_heading 24 | 25 | 0.0.4 26 | ----- 27 | 28 | * Tidy up of read functions in bmp280 29 | * Fixed incorrect call to pressure method 30 | 31 | 0.0.3 32 | ----- 33 | 34 | * Python3 fix 35 | 36 | 0.0.2 37 | ----- 38 | 39 | * Bug fixes 40 | 41 | 0.0.1 42 | ----- 43 | 44 | * Initial release 45 | 46 | -------------------------------------------------------------------------------- /library/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Pimoroni Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /library/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG.txt 2 | include LICENSE.txt 3 | include README.rst 4 | include setup.py 5 | include envirophat/* 6 | -------------------------------------------------------------------------------- /library/README.rst: -------------------------------------------------------------------------------- 1 | Enviro pHAT 2 | =========== 3 | 4 | https://shop.pimoroni.com/products/enviro-phat 5 | 6 | The Pimoroni Enviro pHAT boast a plethora of sensors and connectivity 7 | for measuring your environment. 8 | 9 | Enviro pHAT includes: 10 | 11 | - An LSM303D accelerometer/magnetometer for detecting orientation, 12 | motion and heading 13 | - A BMP280 temperature/pressure sensor 14 | - A TCS3472 colour sensor, for detecting the amount and colour of light 15 | - An ADS1015 analog sensor with four 3.3v tolerant channels for your 16 | external sensors 17 | - A 5v power supply pin for powering your sensors, which you can 18 | regulate or divide to 3v if needed 19 | - Two LEDs connected to GPIO #4 for illuminating objects over the 20 | colour sensor 21 | 22 | Installing 23 | ---------- 24 | 25 | Full install (recommended): 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | 28 | We’ve created an easy installation script that will install all 29 | pre-requisites and get your Enviro pHAT up and running with minimal 30 | efforts. To run it, fire up Terminal which you’ll find in Menu -> 31 | Accessories -> Terminal on your Raspberry Pi desktop, as illustrated 32 | below: 33 | 34 | .. figure:: http://get.pimoroni.com/resources/github-repo-terminal.png 35 | :alt: Finding the terminal 36 | 37 | Finding the terminal 38 | 39 | In the new terminal window type the command exactly as it appears below 40 | (check for typos) and follow the on-screen instructions: 41 | 42 | .. code:: bash 43 | 44 | curl https://get.pimoroni.com/envirophat | bash 45 | 46 | Alternatively, on Raspbian, you can download the ``pimoroni-dashboard`` 47 | and install your product by browsing to the relevant entry: 48 | 49 | .. code:: bash 50 | 51 | sudo apt-get install pimoroni 52 | 53 | (you will find the Dashboard under ‘Accessories’ too, in the Pi menu - 54 | or just run ``pimoroni-dashboard`` at the command line) 55 | 56 | If you choose to download examples you’ll find them in 57 | ``/home/pi/Pimoroni/envirophat/``. 58 | 59 | Manual install: 60 | ~~~~~~~~~~~~~~~ 61 | 62 | Library install for Python 3: 63 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 64 | 65 | on Raspbian: 66 | 67 | .. code:: bash 68 | 69 | sudo apt-get install python3-envirophat 70 | 71 | other environments: 72 | 73 | .. code:: bash 74 | 75 | sudo pip3 install envirophat 76 | 77 | Library install for Python 2: 78 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 79 | 80 | on Raspbian: 81 | 82 | .. code:: bash 83 | 84 | sudo apt-get install python-envirophat 85 | 86 | other environments: 87 | 88 | .. code:: bash 89 | 90 | sudo pip2 install envirophat 91 | 92 | Development: 93 | ~~~~~~~~~~~~ 94 | 95 | If you want to contribute, or like living on the edge of your seat by 96 | having the latest code, you should clone this repository, ``cd`` to the 97 | library directory, and run: 98 | 99 | .. code:: bash 100 | 101 | sudo python3 setup.py install 102 | 103 | (or ``sudo python setup.py install`` whichever your primary Python 104 | environment may be) 105 | 106 | In all cases you will have to enable the i2c bus. 107 | 108 | Documentation & Support 109 | ----------------------- 110 | 111 | - Guides and tutorials - https://learn.pimoroni.com/enviro-phat 112 | - Function reference - http://docs.pimoroni.com/envirophat/ 113 | - GPIO Pinout - https://pinout.xyz/pinout/enviro_phat 114 | - Get help - http://forums.pimoroni.com/c/support 115 | 116 | 1.0.1 117 | ----- 118 | 119 | * Fix: Corrected upper bounds check for tilt_heading 120 | 121 | 1.0.0 122 | ----- 123 | 124 | * Fix: Defer setup to avoid import side-effects 125 | * Fix: QNH changed to ISA standard 126 | * Tweak: New Enviro pHAT I2C addr now default 127 | * Added: unit argument to pressure to choose Pa or hPa 128 | 129 | 0.0.6 130 | ----- 131 | 132 | * Added __version__ to module 133 | * Added DocStrings 134 | 135 | 0.0.5 136 | ----- 137 | 138 | * Bug fix to lsm303d raw_heading 139 | 140 | 0.0.4 141 | ----- 142 | 143 | * Tidy up of read functions in bmp280 144 | * Fixed incorrect call to pressure method 145 | 146 | 0.0.3 147 | ----- 148 | 149 | * Python3 fix 150 | 151 | 0.0.2 152 | ----- 153 | 154 | * Bug fixes 155 | 156 | 0.0.1 157 | ----- 158 | 159 | * Initial release 160 | 161 | -------------------------------------------------------------------------------- /library/envirophat/__init__.py: -------------------------------------------------------------------------------- 1 | from .i2c_bus import bus 2 | from .ads1015 import ads1015 3 | from .bmp280 import bmp280 4 | from .leds import leds 5 | from .lsm303d import lsm303d 6 | from .tcs3472 import tcs3472 7 | 8 | 9 | __version__ = '1.0.1' 10 | 11 | leds = leds() 12 | light = tcs3472(bus) 13 | weather = bmp280(bus) 14 | analog = ads1015(bus) 15 | motion = lsm303d(bus) 16 | -------------------------------------------------------------------------------- /library/envirophat/ads1015.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | ADDR = 0x49 5 | ALT = 0x48 6 | 7 | REG_CONV = 0x00 8 | REG_CFG = 0x01 9 | 10 | SAMPLES_PER_SECOND_MAP = {128: 0x0000, 250: 0x0020, 490: 0x0040, 920: 0x0060, 1600: 0x0080, 2400: 0x00A0, 3300: 0x00C0} 11 | CHANNEL_MAP = {0: 0x4000, 1: 0x5000, 2: 0x6000, 3: 0x7000} 12 | PROGRAMMABLE_GAIN_MAP = {6144: 0x0000, 4096: 0x0200, 2048: 0x0400, 1024: 0x0600, 512: 0x0800, 256: 0x0A00} 13 | 14 | PGA_6_144V = 6144 15 | PGA_4_096V = 4096 16 | PGA_2_048V = 2048 17 | PGA_1_024V = 1024 18 | PGA_0_512V = 512 19 | PGA_0_256V = 256 20 | 21 | class ads1015: 22 | def __init__(self, i2c_bus=None, addr=ADDR): 23 | self._is_setup = False 24 | self._over_voltage = [False] * 4 25 | 26 | self.i2c_bus = i2c_bus 27 | if not hasattr(i2c_bus, "write_i2c_block_data") or not hasattr(i2c_bus, "read_i2c_block_data"): 28 | raise TypeError("Object given for i2c_bus must implement write_i2c_block_data and read_i2c_block_data") 29 | 30 | self.addr = addr 31 | self.max_voltage = 5000 32 | self.default_gain = PGA_6_144V 33 | 34 | def setup(self): 35 | if self._is_setup: 36 | return 37 | self._is_setup = True 38 | 39 | # If a read fails to the addr for the 5v Enviro pHAT, 40 | # switch over to the alternate address for old 3.3v 41 | try: 42 | self.i2c_bus.read_byte_data(self.addr, 0x00) 43 | except IOError: 44 | self.addr = ALT 45 | self.max_voltage = 3300 46 | self.default_gain = PGA_4_096V 47 | 48 | def read(self, channel=0, programmable_gain=None, samples_per_second=1600): 49 | """Read a specific ADC channel. 50 | 51 | :param channel: ADC channel, from 0 to 3 52 | :param programmable_gain: Gain amount to use, one of 6144, 4096, 2048, 1024, 512 or 256 (default 4096 or 6144 depending on revision) 53 | :param samples_per_second: Samples per second, one of 128, 250, 498, 920, 1600, 2400, 3300 (default 1600) 54 | """ 55 | self.setup() 56 | 57 | if programmable_gain is None: 58 | programmable_gain = self.default_gain 59 | 60 | # sane defaults 61 | config = 0x0003 | 0x0100 62 | 63 | config |= SAMPLES_PER_SECOND_MAP[samples_per_second] 64 | config |= CHANNEL_MAP[channel] 65 | config |= PROGRAMMABLE_GAIN_MAP[programmable_gain] 66 | 67 | # set "single shot" mode 68 | config |= 0x8000 69 | 70 | # write single conversion flag 71 | self.i2c_bus.write_i2c_block_data(self.addr, REG_CFG, [(config >> 8) & 0xFF, config & 0xFF]) 72 | 73 | delay = (1.0 / samples_per_second) + 0.0001 74 | time.sleep(delay) 75 | 76 | data = self.i2c_bus.read_i2c_block_data(self.addr, REG_CONV) 77 | 78 | value = (data[0] << 4) | (data[1] >> 4) 79 | value /= 2047.0 80 | value *= float(programmable_gain) 81 | 82 | if value > self.max_voltage: 83 | self._over_voltage[channel] = True 84 | 85 | return round(value / 1000.0,3) 86 | 87 | def read_all(self): 88 | """Read all analog channels and return their values in a tuple.""" 89 | return tuple([self.read(channel=x) for x in range(4)]) 90 | 91 | values = read_all 92 | 93 | def available(self): 94 | """Check if the ADC is available.""" 95 | try: 96 | self.read() 97 | return True 98 | except IOError: 99 | return False 100 | -------------------------------------------------------------------------------- /library/envirophat/bmp280.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | 3 | import time 4 | 5 | 6 | ADDR=0x77 7 | 8 | UNIT_PA = "Pa" 9 | UNIT_HPA = "hPa" 10 | 11 | # This value is necessary to calculate the correct height above sealevel 12 | # its also included in airport weather information ATIS named as QNH 13 | # The default is equivilent to the air pressure at mean sea level 14 | # in the International Standard Atmosphere (ISA). 15 | # See: https://en.wikipedia.org/wiki/Pressure_altitude 16 | QNH=1013.25 # hpA 17 | 18 | # power mode 19 | # POWER_MODE=0 # sleep mode 20 | # POWER_MODE=1 # forced mode 21 | # POWER_MODE=2 # forced mode 22 | POWER_MODE=3 # normal mode 23 | 24 | # temperature resolution 25 | # OSRS_T = 0 # skipped 26 | # OSRS_T = 1 # 16 Bit 27 | # OSRS_T = 2 # 17 Bit 28 | # OSRS_T = 3 # 18 Bit 29 | # OSRS_T = 4 # 19 Bit 30 | OSRS_T = 5 # 20 Bit 31 | 32 | # pressure resolution 33 | # OSRS_P = 0 # pressure measurement skipped 34 | # OSRS_P = 1 # 16 Bit ultra low power 35 | # OSRS_P = 2 # 17 Bit low power 36 | # OSRS_P = 3 # 18 Bit standard resolution 37 | # OSRS_P = 4 # 19 Bit high resolution 38 | OSRS_P = 5 # 20 Bit ultra high resolution 39 | 40 | # filter settings 41 | # FILTER = 0 # 42 | # FILTER = 1 # 43 | # FILTER = 2 # 44 | # FILTER = 3 # 45 | FILTER = 4 # 46 | # FILTER = 5 # 47 | # FILTER = 6 # 48 | # FILTER = 7 # 49 | 50 | # standby settings 51 | # T_SB = 0 # 000 0,5ms 52 | # T_SB = 1 # 001 62.5 ms 53 | # T_SB = 2 # 010 125 ms 54 | # T_SB = 3 # 011 250ms 55 | T_SB = 4 # 100 500ms 56 | # T_SB = 5 # 101 1000ms 57 | # T_SB = 6 # 110 2000ms 58 | # T_SB = 7 # 111 4000ms 59 | 60 | 61 | CONFIG = (T_SB <<5) + (FILTER <<2) # combine bits for config 62 | CTRL_MEAS = (OSRS_T <<5) + (OSRS_P <<2) + POWER_MODE # combine bits for ctrl_meas 63 | 64 | # print ("CONFIG:",CONFIG) 65 | # print ("CTRL_MEAS:",CTRL_MEAS) 66 | 67 | REGISTER_DIG_T1 = 0x88 68 | REGISTER_DIG_T2 = 0x8A 69 | REGISTER_DIG_T3 = 0x8C 70 | REGISTER_DIG_P1 = 0x8E 71 | REGISTER_DIG_P2 = 0x90 72 | REGISTER_DIG_P3 = 0x92 73 | REGISTER_DIG_P4 = 0x94 74 | REGISTER_DIG_P5 = 0x96 75 | REGISTER_DIG_P6 = 0x98 76 | REGISTER_DIG_P7 = 0x9A 77 | REGISTER_DIG_P8 = 0x9C 78 | REGISTER_DIG_P9 = 0x9E 79 | REGISTER_CHIPID = 0xD0 80 | REGISTER_VERSION = 0xD1 81 | REGISTER_SOFTRESET = 0xE0 82 | REGISTER_CONTROL = 0xF4 83 | REGISTER_CONFIG = 0xF5 84 | REGISTER_STATUS = 0xF3 85 | REGISTER_TEMPDATA_MSB = 0xFA 86 | REGISTER_TEMPDATA_LSB = 0xFB 87 | REGISTER_TEMPDATA_XLSB = 0xFC 88 | REGISTER_PRESSDATA_MSB = 0xF7 89 | REGISTER_PRESSDATA_LSB = 0xF8 90 | REGISTER_PRESSDATA_XLSB = 0xF9 91 | 92 | class signed_int(int): 93 | def __new__(self, number, bits=16): 94 | if number & ( 1 << ( bits - 1 ) ): 95 | number -= 1 << bits 96 | return int.__new__(self, number) 97 | 98 | class bmp280(object): 99 | def __init__(self, i2c_bus=None, addr=ADDR): 100 | object.__init__(self) 101 | 102 | self._temperature = 0 103 | self._pressure = 0 104 | 105 | self.addr = addr 106 | self.i2c_bus = i2c_bus 107 | self._is_setup = False 108 | 109 | if getattr(i2c_bus, "write_byte_data", None) is None or getattr(i2c_bus, "read_byte_data", None) is None: 110 | raise TypeError("Object given for i2c_bus must implement write_byte_data and read_byte_data methods") 111 | 112 | def _write_byte(self, register, value): 113 | self.i2c_bus.write_byte_data(self.addr, register, value) 114 | 115 | def _read_byte(self, register): 116 | return self.i2c_bus.read_byte_data(self.addr, register) 117 | 118 | def _read_word(self, register): 119 | return self.i2c_bus.read_word_data(self.addr, register) 120 | 121 | def _read_signed_word(self, register): 122 | word = self._read_word(register) 123 | return signed_int(word) 124 | 125 | def _read_unsigned_word(self, register): 126 | return self._read_word(register) 127 | 128 | def temperature(self): 129 | """Return the current temperature. 130 | 131 | Note: This value may be affected by nearby sources of heat, including the Pi itself. 132 | """ 133 | 134 | self.update() 135 | return self._temperature 136 | 137 | def pressure(self, unit=None): 138 | """Return the current air pressure. 139 | 140 | :param unit: String denoting unit scale to return. Value values: 'Pa' and 'hPa' 141 | 142 | """ 143 | 144 | if unit is None: 145 | unit = "Pa" 146 | 147 | self.update() 148 | 149 | if unit.lower() == "hpa": 150 | return self._pressure / 100.0 151 | else: 152 | return self._pressure 153 | 154 | def altitude(self, qnh=QNH): 155 | """Return the current approximate altitude. 156 | 157 | :param qnh: Your local value for atmospheric pressure adjusted to sea level. 158 | 159 | """ 160 | return 44330.0 * (1.0 - pow(self.pressure() / (qnh*100), (1.0/5.255))) # Calculate altitute from pressure & qnh 161 | 162 | def update(self): 163 | """Update stored temperature and pressure values. 164 | 165 | This function is called automatically when calling temperature() or pressure(). 166 | 167 | """ 168 | if not self._is_setup: 169 | id = self._read_byte(REGISTER_CHIPID) 170 | if id in [0x58, 0x60]: # check sensor id 0x58=BMP280, 0x60=BME280 171 | self._write_byte(REGISTER_SOFTRESET,0xB6) # reset sensor 172 | time.sleep(0.2) # little break 173 | self._write_byte(REGISTER_CONTROL,CTRL_MEAS) # 174 | time.sleep(0.2) # little break 175 | self._write_byte(REGISTER_CONFIG,CONFIG) # 176 | time.sleep(0.2) 177 | 178 | self.dig_T1 = self._read_unsigned_word(REGISTER_DIG_T1) # read correction settings 179 | self.dig_T2 = self._read_signed_word(REGISTER_DIG_T2) 180 | self.dig_T3 = self._read_signed_word(REGISTER_DIG_T3) 181 | self.dig_P1 = self._read_unsigned_word(REGISTER_DIG_P1) 182 | self.dig_P2 = self._read_signed_word(REGISTER_DIG_P2) 183 | self.dig_P3 = self._read_signed_word(REGISTER_DIG_P3) 184 | self.dig_P4 = self._read_signed_word(REGISTER_DIG_P4) 185 | self.dig_P5 = self._read_signed_word(REGISTER_DIG_P5) 186 | self.dig_P6 = self._read_signed_word(REGISTER_DIG_P6) 187 | self.dig_P7 = self._read_signed_word(REGISTER_DIG_P7) 188 | self.dig_P8 = self._read_signed_word(REGISTER_DIG_P8) 189 | self.dig_P9 = self._read_signed_word(REGISTER_DIG_P9) 190 | else: 191 | raise IOError("bmp280 not found on address {:x} (ID found: {:x})".format(self.addr, id)) 192 | 193 | self._is_setup = True 194 | 195 | raw_temp_msb=self._read_byte(REGISTER_TEMPDATA_MSB) # read raw temperature msb 196 | raw_temp_lsb=self._read_byte(REGISTER_TEMPDATA_LSB) # read raw temperature lsb 197 | raw_temp_xlsb=self._read_byte(REGISTER_TEMPDATA_XLSB) # read raw temperature xlsb 198 | raw_press_msb=self._read_byte(REGISTER_PRESSDATA_MSB) # read raw pressure msb 199 | raw_press_lsb=self._read_byte(REGISTER_PRESSDATA_LSB) # read raw pressure lsb 200 | raw_press_xlsb=self._read_byte(REGISTER_PRESSDATA_XLSB) # read raw pressure xlsb 201 | 202 | raw_temp=(raw_temp_msb <<12)+(raw_temp_lsb<<4)+(raw_temp_xlsb>>4) # combine 3 bytes msb 12 bits left, lsb 4 bits left, xlsb 4 bits right 203 | raw_press=(raw_press_msb <<12)+(raw_press_lsb <<4)+(raw_press_xlsb >>4) # combine 3 bytes msb 12 bits left, lsb 4 bits left, xlsb 4 bits right 204 | 205 | var1=(raw_temp/16384.0-self.dig_T1/1024.0)*self.dig_T2 # formula for temperature from datasheet 206 | var2=(raw_temp/131072.0-self.dig_T1/8192.0)*(raw_temp/131072.0-self.dig_T1/8192.0)*self.dig_T3 # formula for temperature from datasheet 207 | temp=(var1+var2)/5120.0 # formula for temperature from datasheet 208 | t_fine=(var1+var2) # need for pressure calculation 209 | 210 | var1=t_fine/2.0-64000.0 # formula for pressure from datasheet 211 | var2=var1*var1*self.dig_P6/32768.0 # formula for pressure from datasheet 212 | var2=var2+var1*self.dig_P5*2 # formula for pressure from datasheet 213 | var2=var2/4.0+self.dig_P4*65536.0 # formula for pressure from datasheet 214 | var1=(self.dig_P3*var1*var1/524288.0+self.dig_P2*var1)/524288.0 # formula for pressure from datasheet 215 | var1=(1.0+var1/32768.0)*self.dig_P1 # formula for pressure from datasheet 216 | press=1048576.0-raw_press # formula for pressure from datasheet 217 | press=(press-var2/4096.0)*6250.0/var1 # formula for pressure from datasheet 218 | var1=self.dig_P9*press*press/2147483648.0 # formula for pressure from datasheet 219 | var2=press*self.dig_P8/32768.0 # formula for pressure from datasheet 220 | press=press+(var1+var2+self.dig_P7)/16.0 # formula for pressure from datasheet 221 | 222 | self._temperature = temp 223 | self._pressure = press 224 | 225 | -------------------------------------------------------------------------------- /library/envirophat/i2c_bus.py: -------------------------------------------------------------------------------- 1 | from sys import exit, version_info 2 | 3 | try: 4 | import smbus 5 | except ImportError: 6 | if version_info[0] < 3: 7 | exit("This library requires python-smbus\nInstall with: sudo apt-get install python-smbus") 8 | elif version_info[0] == 3: 9 | exit("This library requires python3-smbus\nInstall with: sudo apt-get install python3-smbus") 10 | 11 | try: 12 | import RPi.GPIO as GPIO 13 | except ImportError: 14 | exit("This library requires the RPi.GPIO module\nInstall with: sudo pip install RPi.GPIO") 15 | 16 | 17 | bus = None 18 | 19 | if GPIO.RPI_REVISION == 2 or GPIO.RPI_REVISION == 3: 20 | bus = smbus.SMBus(1) 21 | else: 22 | bus = smbus.SMBus(0) 23 | -------------------------------------------------------------------------------- /library/envirophat/leds.py: -------------------------------------------------------------------------------- 1 | from sys import exit 2 | 3 | try: 4 | import RPi.GPIO as GPIO 5 | except ImportError: 6 | exit("This library requires the RPi.GPIO module\nInstall with: sudo pip install RPi.GPIO") 7 | 8 | 9 | GPIO.setwarnings(False) 10 | GPIO.setmode(GPIO.BCM) 11 | GPIO.setup(4, GPIO.OUT) 12 | GPIO.output(4, 0) 13 | 14 | class leds: 15 | def __init__(self, status=0): 16 | self.status = status 17 | 18 | def on(self): 19 | """Turn LEDs on.""" 20 | self.status = 1 21 | GPIO.output(4, 1) 22 | return True 23 | 24 | def off(self): 25 | """Turn LEDs off.""" 26 | self.status = 0 27 | GPIO.output(4, 0) 28 | 29 | def is_on(self): 30 | """Return True if LED is on.""" 31 | if self.status == 1: 32 | return True 33 | else: 34 | return False 35 | 36 | def is_off(self): 37 | """Return True if LED is off.""" 38 | if self.status == 0: 39 | return True 40 | else: 41 | return False 42 | -------------------------------------------------------------------------------- /library/envirophat/lsm303d.py: -------------------------------------------------------------------------------- 1 | import math 2 | import struct 3 | import time 4 | 5 | 6 | ### LSM303 Address ### 7 | ADDR = 0x1D # Assuming SA0 grounded 8 | 9 | ### LSM303 Register definitions ### 10 | TEMP_OUT_L = 0x05 11 | TEMP_OUT_H = 0x06 12 | STATUS_REG_M = 0x07 13 | OUT_X_L_M = 0x08 14 | OUT_X_H_M = 0x09 15 | OUT_Y_L_M = 0x0A 16 | OUT_Y_H_M = 0x0B 17 | OUT_Z_L_M = 0x0C 18 | OUT_Z_H_M = 0x0D 19 | WHO_AM_I = 0x0F 20 | INT_CTRL_M = 0x12 21 | INT_SRC_M = 0x13 22 | INT_THS_L_M = 0x14 23 | INT_THS_H_M = 0x15 24 | OFFSET_X_L_M = 0x16 25 | OFFSET_X_H_M = 0x17 26 | OFFSET_Y_L_M = 0x18 27 | OFFSET_Y_H_M = 0x19 28 | OFFSET_Z_L_M = 0x1A 29 | OFFSET_Z_H_M = 0x1B 30 | REFERENCE_X = 0x1C 31 | REFERENCE_Y = 0x1D 32 | REFERENCE_Z = 0x1E 33 | CTRL_REG0 = 0x1F 34 | CTRL_REG1 = 0x20 35 | CTRL_REG2 = 0x21 36 | CTRL_REG3 = 0x22 37 | CTRL_REG4 = 0x23 38 | CTRL_REG5 = 0x24 39 | CTRL_REG6 = 0x25 40 | CTRL_REG7 = 0x26 41 | STATUS_REG_A = 0x27 42 | OUT_X_L_A = 0x28 43 | OUT_X_H_A = 0x29 44 | OUT_Y_L_A = 0x2A 45 | OUT_Y_H_A = 0x2B 46 | OUT_Z_L_A = 0x2C 47 | OUT_Z_H_A = 0x2D 48 | FIFO_CTRL = 0x2E 49 | FIFO_SRC = 0x2F 50 | IG_CFG1 = 0x30 51 | IG_SRC1 = 0x31 52 | IG_THS1 = 0x32 53 | IG_DUR1 = 0x33 54 | IG_CFG2 = 0x34 55 | IG_SRC2 = 0x35 56 | IG_THS2 = 0x36 57 | IG_DUR2 = 0x37 58 | CLICK_CFG = 0x38 59 | CLICK_SRC = 0x39 60 | CLICK_THS = 0x3A 61 | TIME_LIMIT = 0x3B 62 | TIME_LATENCY = 0x3C 63 | TIME_WINDOW = 0x3D 64 | ACT_THS = 0x3E 65 | ACT_DUR = 0x3F 66 | 67 | ### Mag scales ### 68 | MAG_SCALE_2 = 0x00 # full-scale is +/- 2 Gauss 69 | MAG_SCALE_4 = 0x20 # +/- 4 Guass 70 | MAG_SCALE_8 = 0x40 # +/- 8 Guass 71 | MAG_SCALE_12 = 0x60 # +/- 12 Guass 72 | 73 | ACCEL_SCALE = 2 # +/- 2g 74 | 75 | X = 0 76 | Y = 1 77 | Z = 2 78 | 79 | def twos_comp(val, bits): 80 | # Calculate the 2s complement of int:val # 81 | if val&(1<<(bits-1)) != 0: 82 | val = (val&((1< 2*math.pi: 188 | self._heading -= 2*math.pi 189 | 190 | self._heading_degrees = round(math.degrees(self._heading),2) 191 | 192 | return self._heading_degrees 193 | 194 | def heading(self): 195 | """Return a tilt compensated heading calculated from the magnetometer data. 196 | 197 | Returns None in the case of a calculation error. 198 | 199 | """ 200 | 201 | self.update() 202 | 203 | truncate = [0,0,0] 204 | for i in range(X, Z+1): 205 | truncate[i] = math.copysign(min(math.fabs(self._accel[i]), 1.0), self._accel[i]) 206 | try: 207 | pitch = math.asin(-1*truncate[X]) 208 | roll = math.asin(truncate[Y]/math.cos(pitch)) if abs(math.cos(pitch)) >= abs(truncate[Y]) else 0 209 | # set roll to zero if pitch approaches -1 or 1 210 | 211 | self._tiltcomp[X] = self._mag[X] * math.cos(pitch) + self._mag[Z] * math.sin(pitch) 212 | self._tiltcomp[Y] = self._mag[X] * math.sin(roll) * math.sin(pitch) + \ 213 | self._mag[Y] * math.cos(roll) - self._mag[Z] * math.sin(roll) * math.cos(pitch) 214 | self._tiltcomp[Z] = self._mag[X] * math.cos(roll) * math.sin(pitch) + \ 215 | self._mag[Y] * math.sin(roll) + \ 216 | self._mag[Z] * math.cos(roll) * math.cos(pitch) 217 | self._tilt_heading = math.atan2(self._tiltcomp[Y], self._tiltcomp[X]) 218 | 219 | if self._tilt_heading < 0: 220 | self._tilt_heading += 2*math.pi 221 | if self._tilt_heading > 2*math.pi: 222 | self._tilt_heading -= 2*math.pi 223 | 224 | self._tilt_heading_degrees = round(math.degrees(self._tilt_heading),2) 225 | return self._tilt_heading_degrees 226 | 227 | except Exception: 228 | return None 229 | 230 | def is_mag_ready(self): 231 | return (self.i2c_bus.read_byte_data(self.addr, STATUS_REG_M) & 0x03) > 0 232 | 233 | def update(self): 234 | """Update both the accelerometer and magnetometer data.""" 235 | 236 | self.accelerometer() 237 | self.magnetometer() 238 | 239 | -------------------------------------------------------------------------------- /library/envirophat/tcs3472.py: -------------------------------------------------------------------------------- 1 | ADDR = 0x29 2 | 3 | REG_CMD = 0b10000000 4 | REG_CMD_AUTO_INC = 0b00100000 5 | REG_CLEAR_L = REG_CMD | REG_CMD_AUTO_INC | 0x14 6 | REG_RED_L = REG_CMD | REG_CMD_AUTO_INC | 0x16 7 | REG_GREEN_L = REG_CMD | REG_CMD_AUTO_INC | 0x18 8 | REG_BLUE_L = REG_CMD | REG_CMD_AUTO_INC | 0x1A 9 | 10 | REG_ENABLE = REG_CMD | 0 11 | REG_ATIME = REG_CMD | 1 12 | REG_CONTROL = REG_CMD | 0x0f 13 | REG_STATUS = REG_CMD | 0x13 14 | 15 | REG_CONTROL_GAIN_1X = 0b00000000 16 | REG_CONTROL_GAIN_4X = 0b00000001 17 | REG_CONTROL_GAIN_16X = 0b00000010 18 | REG_CONTROL_GAIN_60X = 0b00000011 19 | 20 | REG_ENABLE_INTERRUPT = 1 << 4 21 | REG_ENABLE_WAIT = 1 << 3 22 | REG_ENABLE_RGBC = 1 << 1 23 | REG_ENABLE_POWER = 1 24 | 25 | CH_RED = 0 26 | CH_GREEN = 1 27 | CH_BLUE = 2 28 | CH_CLEAR = 3 29 | 30 | class tcs3472: 31 | def __init__(self, i2c_bus=None, addr=ADDR): 32 | self._is_setup = False 33 | self.addr = addr 34 | self.i2c_bus = i2c_bus 35 | if not hasattr(i2c_bus, "read_word_data") or not hasattr(i2c_bus, "write_byte_data"): 36 | raise TypeError("Object given for i2c_bus must implement read_word_data and write_byte_data") 37 | 38 | def setup(self): 39 | if self._is_setup: 40 | return 41 | 42 | self._is_setup = True 43 | 44 | self.i2c_bus.write_byte_data(ADDR, REG_ENABLE, REG_ENABLE_RGBC | REG_ENABLE_POWER) 45 | self.set_integration_time_ms(511.2) 46 | 47 | def set_integration_time_ms(self, ms): 48 | """Set the sensor integration time in milliseconds. 49 | 50 | :param ms: The integration time in milliseconds from 2.4 to 612, in increments of 2.4. 51 | 52 | """ 53 | if ms < 2.4 or ms > 612: 54 | raise TypeError("Integration time must be between 2.4 and 612ms") 55 | self._atime = int(round(ms / 2.4)) 56 | self._max_count = min(65535, (256 - self._atime) * 1024) 57 | 58 | self.setup() 59 | 60 | self.i2c_bus.write_byte_data(ADDR, REG_ATIME, 256 - self._atime) 61 | 62 | def max_count(self): 63 | """Return the maximum value which can be counted by a channel with the chosen integration time.""" 64 | return self._max_count 65 | 66 | def scaled(self): 67 | """Return a tuple containing the red, green and blue colour values ranging from 0 to 1.0 scaled against the clear value.""" 68 | rgbc = self.raw() 69 | if rgbc[CH_CLEAR] > 0: 70 | return tuple([float(x) / rgbc[CH_CLEAR] for x in rgbc]) 71 | 72 | return (0,0,0) 73 | 74 | def rgb(self): 75 | """Return a tuple containing the red, green and blue colour values ranging 0 to 255 scaled against the clear value.""" 76 | return tuple([int(x * 255) for x in self.scaled()][:CH_CLEAR]) 77 | 78 | def light(self): 79 | """Return the clear/unfiltered light level as an integer.""" 80 | return self.raw()[CH_CLEAR] 81 | 82 | def valid(self): 83 | self.setup() 84 | return (self.i2c_bus.read_byte_data(ADDR, REG_STATUS) & 1) > 0 85 | 86 | def raw(self): 87 | """Return the raw red, green, blue and clear channels""" 88 | self.setup() 89 | 90 | c = self.i2c_bus.read_word_data(ADDR, REG_CLEAR_L) 91 | r = self.i2c_bus.read_word_data(ADDR, REG_RED_L) 92 | g = self.i2c_bus.read_word_data(ADDR, REG_GREEN_L) 93 | b = self.i2c_bus.read_word_data(ADDR, REG_BLUE_L) 94 | 95 | return (r, g, b, c) 96 | -------------------------------------------------------------------------------- /library/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = envirophat 3 | version = 1.0.1 4 | author = Philip Howard 5 | author_email = phil@pimoroni.com 6 | description = Enviro pHAT environmental sensor board driver 7 | long_description = file: README.rst 8 | keywords = Raspberry Pi, IoT, Weather 9 | url = https://www.pimoroni.com 10 | project_urls = 11 | GitHub=https://www.github.com/pimoroni/enviro-phat 12 | license = MIT 13 | license_files = LICENSE.txt 14 | classifiers = 15 | Development Status :: 5 - Production/Stable 16 | Operating System :: POSIX :: Linux 17 | License :: OSI Approved :: MIT License 18 | Intended Audience :: Developers 19 | Programming Language :: Python :: 2.6 20 | Programming Language :: Python :: 2.7 21 | Programming Language :: Python :: 3 22 | Topic :: Software Development 23 | Topic :: Software Development :: Libraries 24 | Topic :: System :: Hardware 25 | -------------------------------------------------------------------------------- /library/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Copyright (c) 2016 Pimoroni 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | """ 24 | 25 | from setuptools import setup, __version__ 26 | from pkg_resources import parse_version 27 | 28 | minimum_version = parse_version('30.4.0') 29 | 30 | if parse_version(__version__) < minimum_version: 31 | raise RuntimeError("Package setuptools must be at least version {}".format(minimum_version)) 32 | 33 | setup( 34 | packages=['envirophat'], 35 | install_requires=['setuptools>={}'.format(minimum_version), 'RPi.GPIO'] 36 | ) 37 | -------------------------------------------------------------------------------- /library/test_envirophat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | 5 | from envirophat import light, motion, weather, analog, leds 6 | 7 | 8 | while True: 9 | print("LEDs on...") 10 | leds.on() 11 | time.sleep(1) 12 | print("LEDs off...") 13 | leds.off() 14 | print("Light...") 15 | print(light.rgb()) 16 | print("Motion...") 17 | print(motion.heading()) 18 | print(motion.magnetometer()) 19 | print(motion.accelerometer()) 20 | print("Weather...") 21 | print(weather.temperature()) 22 | print(weather.pressure()) 23 | print("Analog...") 24 | print(analog.values()) 25 | time.sleep(1) 26 | -------------------------------------------------------------------------------- /packaging/CHANGELOG: -------------------------------------------------------------------------------- 1 | envirophat (1.0.0) stable; urgency=low 2 | 3 | * Fix: Defer setup to avoid import side-effects 4 | * Fix: QNH changed to ISA standard 5 | * Tweak: New Enviro pHAT I2C addr now default 6 | * Added: unit argument to pressure to choose Pa or hPa 7 | 8 | -- Phil Howard Tue, 13 Mar 2018 00:00:00 +0000 9 | 10 | envirophat (0.0.6) stable; urgency=low 11 | 12 | * Added __version__ to module 13 | * Added DocStrings 14 | 15 | -- Phil Howard Thu, 10 Nov 2016 00:00:00 +0000 16 | 17 | envirophat (0.0.5) UNRELEASED; urgency=low 18 | 19 | * Bug fix to lsm303d raw_heading 20 | 21 | -- Phil Howard Fri, 12 Aug 2016 00:00:00 +0000 22 | 23 | envirophat (0.0.4) UNRELEASED; urgency=low 24 | 25 | * Tidy up of read functions in bmp280 26 | * Fixed incorrect call to pressure method 27 | 28 | -- Phil Howard Wed, 6 Jul 2016 00:00:00 +0000 29 | 30 | envirophat (0.0.3) UNRELEASED; urgency=low 31 | 32 | * Python3 fix 33 | 34 | -- Phil Howard Thu, 23 Jun 2016 00:00:00 +0000 35 | 36 | envirophat (0.0.2) UNRELEASED; urgency=low 37 | 38 | * Bug fixes 39 | 40 | -- Phil Howard Fri, 17 Jun 2016 00:00:00 +0000 41 | 42 | envirophat (0.0.1) UNRELEASED; urgency=low 43 | 44 | * Initial release 45 | 46 | -- Phil Howard Thu, 16 Jun 2016 00:00:00 +0000 47 | -------------------------------------------------------------------------------- /packaging/debian/README: -------------------------------------------------------------------------------- 1 | README 2 | 3 | Enviro pHAT is an affordable mix of sensors ideal for monitoring server rooms or anything you might want to observe. It also includes a 4-channel ADC, for adding sensors of your own. 4 | 5 | Learn more: https://shop.pimoroni.com/products/enviro-phat 6 | For examples run: `curl -sS get.pimoroni.com/envirophat | bash` 7 | 8 | IMPORTANT 9 | 10 | Enviro pHAT requires i2c. 11 | To enable run `curl get.pimoroni.com/i2c | bash` 12 | or use raspi-config and reboot your Raspberry Pi. 13 | -------------------------------------------------------------------------------- /packaging/debian/changelog: -------------------------------------------------------------------------------- 1 | envirophat (1.0.0) stable; urgency=low 2 | 3 | * Fix: Defer setup to avoid import side-effects 4 | * Fix: QNH changed to ISA standard 5 | * Tweak: New Enviro pHAT I2C addr now default 6 | * Added: unit argument to pressure to choose Pa or hPa 7 | 8 | -- Phil Howard Tue, 13 Mar 2018 00:00:00 +0000 9 | 10 | envirophat (0.0.6) stable; urgency=low 11 | 12 | * Added __version__ to module 13 | * Added DocStrings 14 | 15 | -- Phil Howard Thu, 10 Nov 2016 00:00:00 +0000 16 | 17 | envirophat (0.0.5) UNRELEASED; urgency=low 18 | 19 | * Bug fix to lsm303d raw_heading 20 | 21 | -- Phil Howard Fri, 12 Aug 2016 00:00:00 +0000 22 | 23 | envirophat (0.0.4) UNRELEASED; urgency=low 24 | 25 | * Tidy up of read functions in bmp280 26 | * Fixed incorrect call to pressure method 27 | 28 | -- Phil Howard Wed, 6 Jul 2016 00:00:00 +0000 29 | 30 | envirophat (0.0.3) UNRELEASED; urgency=low 31 | 32 | * Python3 fix 33 | 34 | -- Phil Howard Thu, 23 Jun 2016 00:00:00 +0000 35 | 36 | envirophat (0.0.2) UNRELEASED; urgency=low 37 | 38 | * Bug fixes 39 | 40 | -- Phil Howard Fri, 17 Jun 2016 00:00:00 +0000 41 | 42 | envirophat (0.0.1) UNRELEASED; urgency=low 43 | 44 | * Initial release 45 | 46 | -- Phil Howard Thu, 16 Jun 2016 00:00:00 +0000 47 | -------------------------------------------------------------------------------- /packaging/debian/clean: -------------------------------------------------------------------------------- 1 | *.egg-info/* 2 | -------------------------------------------------------------------------------- /packaging/debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /packaging/debian/control: -------------------------------------------------------------------------------- 1 | Source: envirophat 2 | Maintainer: Phil Howard 3 | Homepage: https://github.com/pimoroni/enviro-phat 4 | Section: python 5 | Priority: extra 6 | Build-Depends: debhelper (>= 9.0.0), dh-python, python-all (>= 2.7), python-setuptools, python3-all (>= 3.4), python3-setuptools 7 | Standards-Version: 3.9.6 8 | X-Python-Version: >= 2.7 9 | X-Python3-Version: >= 3.4 10 | 11 | Package: python-envirophat 12 | Architecture: all 13 | Section: python 14 | Depends: ${misc:Depends}, ${python:Depends}, python-rpi.gpio, python-smbus 15 | Suggests: i2c-tools 16 | Description: Python library for the Pimoroni Enviro pHAT. 17 | Enviro pHAT is an affordable mix of sensors ideal for monitoring server rooms 18 | or anything you might want to observe. It also includes a 4-channel ADC, 19 | for adding sensors of your own. 20 | . 21 | This is the Python 2 version of the package. 22 | 23 | Package: python3-envirophat 24 | Architecture: all 25 | Section: python 26 | Depends: ${misc:Depends}, ${python3:Depends}, python3-rpi.gpio, python3-smbus 27 | Suggests: i2c-tools 28 | Description: Python library for the Pimoroni Enviro pHAT. 29 | Enviro pHAT is an affordable mix of sensors ideal for monitoring server rooms 30 | or anything you might want to observe. It also includes a 4-channel ADC, 31 | for adding sensors of your own. 32 | . 33 | This is the Python 3 version of the package. 34 | -------------------------------------------------------------------------------- /packaging/debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: envirophat 3 | Source: https://github.com/pimoroni/enviro-phat 4 | 5 | Files: * 6 | Copyright: 2016 Pimoroni Ltd 7 | License: MIT 8 | 9 | License: MIT 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | . 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | . 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /packaging/debian/docs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pimoroni/enviro-phat/3c06e819ea7a9ccd94f7ec2bd499021d734f6638/packaging/debian/docs -------------------------------------------------------------------------------- /packaging/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | #export DH_VERBOSE=1 5 | export DH_OPTIONS 6 | 7 | %: 8 | dh $@ --with python2,python3 --buildsystem=python_distutils 9 | 10 | override_dh_auto_install: 11 | python setup.py install --root debian/python-envirophat --install-layout=deb 12 | python3 setup.py install --root debian/python3-envirophat --install-layout=deb 13 | -------------------------------------------------------------------------------- /packaging/debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /packaging/debian/source/options: -------------------------------------------------------------------------------- 1 | extend-diff-ignore = "^[^/]+\.egg-info/" 2 | -------------------------------------------------------------------------------- /packaging/makeall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # script control variables 4 | 5 | reponame="" # leave this blank for auto-detection 6 | libname="" # leave this blank for auto-detection 7 | packagename="" # leave this blank for auto-selection 8 | 9 | debianlog="debian/changelog" 10 | debcontrol="debian/control" 11 | debcopyright="debian/copyright" 12 | debrules="debian/rules" 13 | debreadme="debian/README" 14 | 15 | debdir="$(pwd)" 16 | rootdir="$(dirname $debdir)" 17 | libdir="$rootdir/library" 18 | 19 | FLAG=false 20 | 21 | # function define 22 | 23 | success() { 24 | echo "$(tput setaf 2)$1$(tput sgr0)" 25 | } 26 | 27 | inform() { 28 | echo "$(tput setaf 6)$1$(tput sgr0)" 29 | } 30 | 31 | warning() { 32 | echo "$(tput setaf 1)$1$(tput sgr0)" 33 | } 34 | 35 | newline() { 36 | echo "" 37 | } 38 | 39 | # assessing repo and library variables 40 | 41 | if [ -z "$reponame" ] || [ -z "$libname" ]; then 42 | inform "detecting reponame and libname..." 43 | else 44 | inform "using reponame and libname overrides" 45 | fi 46 | 47 | if [ -z "$reponame" ]; then 48 | if [[ $rootdir == *"python"* ]]; then 49 | repodir="$(dirname $rootdir)" 50 | reponame="$(basename $repodir)" 51 | else 52 | repodir="$rootdir" 53 | reponame="$(basename $repodir)" 54 | fi 55 | reponame=$(echo "$reponame" | tr "[A-Z]" "[a-z]") 56 | fi 57 | 58 | if [ -z "$libname" ]; then 59 | cd "$libdir" 60 | libname=$(grep "name" setup.py | tr -d "[:space:]" | cut -c 7- | rev | cut -c 3- | rev) 61 | libname=$(echo "$libname" | tr "[A-Z]" "[a-z]") && cd "$debdir" 62 | fi 63 | 64 | if [ -z "$packagename" ]; then 65 | packagename="$libname" 66 | fi 67 | 68 | echo "reponame is $reponame and libname is $libname" 69 | echo "output packages will be python-$packagename and python3-$packagename" 70 | 71 | # checking generating changelog file 72 | 73 | ./makelog.sh 74 | version=$(head -n 1 "$libdir/CHANGELOG.txt") 75 | echo "building $libname version $version" 76 | 77 | # checking debian/changelog file 78 | 79 | inform "checking debian/changelog file..." 80 | 81 | if ! head -n 1 $debianlog | grep "$libname" &> /dev/null; then 82 | warning "library not mentioned in header!" && FLAG=true 83 | elif head -n 1 $debianlog | grep "UNRELEASED"; then 84 | warning "this changelog is not going to generate a release!" 85 | warning "change distribution to 'stable'" && FLAG=true 86 | fi 87 | 88 | # checking debian/copyright file 89 | 90 | inform "checking debian/copyright file..." 91 | 92 | if ! grep "^Source" $debcopyright | grep "$reponame" &> /dev/null; then 93 | warning "$(grep "^Source" $debcopyright)" && FLAG=true 94 | fi 95 | 96 | if ! grep "^Upstream-Name" $debcopyright | grep "$libname" &> /dev/null; then 97 | warning "$(grep "^Upstream-Name" $debcopyright)" && FLAG=true 98 | fi 99 | 100 | # checking debian/control file 101 | 102 | inform "checking debian/control file..." 103 | 104 | if ! grep "^Source" $debcontrol | grep "$libname" &> /dev/null; then 105 | warning "$(grep "^Source" $debcontrol)" && FLAG=true 106 | fi 107 | 108 | if ! grep "^Homepage" $debcontrol | grep "$reponame" &> /dev/null; then 109 | warning "$(grep "^Homepage" $debcontrol)" && FLAG=true 110 | fi 111 | 112 | if ! grep "^Package: python-$packagename" $debcontrol &> /dev/null; then 113 | warning "$(grep "^Package: python-" $debcontrol)" && FLAG=true 114 | fi 115 | 116 | if ! grep "^Package: python3-$packagename" $debcontrol &> /dev/null; then 117 | warning "$(grep "^Package: python3-" $debcontrol)" && FLAG=true 118 | fi 119 | 120 | if ! grep "^Priority: extra" $debcontrol &> /dev/null; then 121 | warning "$(grep "^Priority" $debcontrol)" && FLAG=true 122 | fi 123 | 124 | 125 | # checking debian/rules file 126 | 127 | inform "checking debian/rules file..." 128 | 129 | if ! grep "debian/python-$packagename" $debrules &> /dev/null; then 130 | warning "$(grep "debian/python-" $debrules)" && FLAG=true 131 | fi 132 | 133 | if ! grep "debian/python3-$packagename" $debrules &> /dev/null; then 134 | warning "$(grep "debian/python3-" $debrules)" && FLAG=true 135 | fi 136 | 137 | # checking debian/README file 138 | 139 | inform "checking debian/readme file..." 140 | 141 | if ! grep -e "$libname" -e "$reponame" $debreadme &> /dev/null; then 142 | warning "README does not seem to mention product, repo or lib!" && FLAG=true 143 | fi 144 | 145 | # summary of checks pre build 146 | 147 | if $FLAG; then 148 | warning "Check all of the above and correct!" && exit 1 149 | else 150 | inform "we're good to go... bulding!" 151 | fi 152 | 153 | # building deb and final checks 154 | 155 | ./makedeb.sh 156 | 157 | inform "running lintian..." 158 | lintian -v $(find -name "python*$version*.deb") 159 | lintian -v $(find -name "python3*$version*.deb") 160 | 161 | inform "checking signatures..." 162 | gpg --verify $(find -name "*$version*changes") 163 | gpg --verify $(find -name "*$version*dsc") 164 | 165 | exit 0 166 | -------------------------------------------------------------------------------- /packaging/makedeb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gettools="no" # if set to yes downloads the tools required 4 | setup="yes" # if set to yes populates library folder 5 | buildeb="yes" # if set to yes builds the deb files 6 | cleanup="yes" # if set to yes cleans up build files 7 | pkgfiles=( "build" "changes" "deb" "dsc" "tar.xz" ) 8 | 9 | if [ $gettools == "yes" ]; then 10 | sudo apt-get update && sudo apt-get install build-essential debhelper devscripts dh-make dh-python dput gnupg 11 | sudo apt-get install python-all python-setuptools python3-all python3-setuptools 12 | sudo apt-get install python-mock python-sphinx python-sphinx-rtd-theme 13 | sudo pip install Sphinx --upgrade && sudo pip install sphinx_rtd_theme --upgrade 14 | fi 15 | 16 | if [ $setup == "yes" ]; then 17 | rm -R ../library/build ../library/debian &> /dev/null 18 | cp -R ./debian ../library/ && cp -R ../sphinx ../library/doc 19 | fi 20 | 21 | cd ../library 22 | 23 | if [ $buildeb == "yes" ]; then 24 | debuild -aarmhf 25 | for file in ${pkgfiles[@]}; do 26 | rm ../packaging/*.$file &> /dev/null 27 | mv ../*.$file ../packaging 28 | done 29 | rm -R ../documentation/html &> /dev/null 30 | cp -R ./build/sphinx/html ../documentation 31 | fi 32 | 33 | if [ $cleanup == "yes" ]; then 34 | debuild clean 35 | rm -R ./build ./debian ./doc &> /dev/null 36 | fi 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /packaging/makedoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gettools="no" # if set to yes downloads the tools required 4 | setup="yes" # if set to yes populates library folder 5 | buildoc="yes" # if set to yes builds the deb files 6 | cleanup="yes" # if set to yes cleans up build files 7 | pkgfiles=( "build" "changes" "deb" "dsc" "tar.xz" ) 8 | 9 | if [ $gettools == "yes" ]; then 10 | sudo apt-get update && sudo apt-get install build-essential debhelper devscripts dh-make dh-python 11 | sudo apt-get install python-all python-setuptools python3-all python3-setuptools 12 | sudo apt-get install python-mock python-sphinx python-sphinx-rtd-theme 13 | sudo pip install Sphinx --upgrade && sudo pip install sphinx_rtd_theme --upgrade 14 | fi 15 | 16 | if [ $setup == "yes" ]; then 17 | rm -R ../library/build ../library/debian &> /dev/null 18 | cp -R ./debian ../library/ && cp -R ../sphinx ../library/doc 19 | fi 20 | 21 | cd ../library 22 | 23 | if [ $buildoc == "yes" ]; then 24 | debuild 25 | for file in ${pkgfiles[@]}; do 26 | rm ../*.$file &> /dev/null 27 | done 28 | rm -R ../documentation/html &> /dev/null 29 | cp -R ./build/sphinx/html ../documentation 30 | fi 31 | 32 | if [ $cleanup == "yes" ]; then 33 | debuild clean 34 | rm -R ./build ./debian ./doc &> /dev/null 35 | fi 36 | 37 | exit 0 38 | -------------------------------------------------------------------------------- /packaging/makelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # script control variables 4 | 5 | libname="" # leave this blank for auto-detection 6 | sibname=() # name of sibling in packages list 7 | versionwarn="yes" # set to anything but 'yes' to turn off warning 8 | 9 | debdir="$(pwd)" 10 | rootdir="$(dirname $debdir)" 11 | libdir="$rootdir/library" 12 | 13 | mainlog="CHANGELOG" 14 | debianlog="debian/changelog" 15 | pypilog="$libdir/CHANGELOG.txt" 16 | 17 | # function define 18 | 19 | success() { 20 | echo "$(tput setaf 2)$1$(tput sgr0)" 21 | } 22 | 23 | inform() { 24 | echo "$(tput setaf 6)$1$(tput sgr0)" 25 | } 26 | 27 | warning() { 28 | echo "$(tput setaf 1)$1$(tput sgr0)" 29 | } 30 | 31 | newline() { 32 | echo "" 33 | } 34 | 35 | # generate debian changelog 36 | 37 | cat $mainlog > $debianlog 38 | inform "seeded debian changelog" 39 | 40 | # generate pypi changelog 41 | 42 | sed -e "/--/d" -e "s/ \*/\*/" \ 43 | -e "s/.*\([0-9].[0-9].[0-9]\).*/\1/" \ 44 | -e '/[0-9].[0-9].[0-9]/ a\ 45 | -----' $mainlog | cat -s > $pypilog 46 | 47 | version=$(head -n 1 $pypilog) 48 | inform "pypi changelog generated" 49 | 50 | # touch up version in setup.py file 51 | 52 | if [ -n $(grep version "$libdir/setup.py" &> /dev/null) ]; then 53 | inform "touched up version in setup.py" 54 | sed -i "s/'[0-9].[0-9].[0-9]'/'$version'/" "$libdir/setup.py" 55 | else 56 | warning "couldn't touch up version in setup, no match found" 57 | fi 58 | 59 | # touch up version in lib or package siblings 60 | 61 | if [ -z "$libname" ]; then 62 | cd "$libdir" 63 | libname=$(grep "name" setup.py | tr -d "[:space:]" | cut -c 7- | rev | cut -c 3- | rev) 64 | libname=$(echo "$libname" | tr "[A-Z]" "[a-z]") && cd "$debdir" 65 | sibname+=( "$libname" ) 66 | elif [ "$libname" != "package" ]; then 67 | sibname+=( "$libname" ) 68 | fi 69 | 70 | for sibling in ${sibname[@]}; do 71 | if grep -e "__version__" "$libdir/$sibling.py" &> /dev/null; then 72 | sed -i "s/__version__ = '[0-9].[0-9].[0-9]'/__version__ = '$version'/" "$libdir/$sibling.py" 73 | inform "touched up version in $sibling.py" 74 | elif grep -e "__version__" "$libdir/$sibling/__init__.py" &> /dev/null; then 75 | sed -i "s/__version__ = '[0-9].[0-9].[0-9]'/__version__ = '$version'/" "$libdir/$sibling/__init__.py" 76 | inform "touched up version in $sibling/__init__.py" 77 | elif [ "$versionwarn" == "yes" ]; then 78 | warning "couldn't touch up __version__ in $sibling, no match found" 79 | fi 80 | done 81 | 82 | exit 0 83 | -------------------------------------------------------------------------------- /sphinx/_static/custom.css: -------------------------------------------------------------------------------- 1 | .rst-content a, .rst-content a:focus { 2 | color:#13c0d7; 3 | } 4 | .rst-content a:visited, .rst-content a:active { 5 | color:#87319a; 6 | } 7 | .rst-content .highlighted { 8 | background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAJElEQVQIW2P8//9/PSMjYyMDEmAEsdElwILoEnBBZAkUQZgEABMWE4Kzp1KUAAAAAElFTkSuQmCC),rgba(246,167,4,0.2); 9 | margin:0 -6px; 10 | } 11 | .wy-side-nav-search { 12 | background:#333333; 13 | } 14 | .wy-nav-side { 15 | background:#444444; 16 | } 17 | .rst-content dl:not(.docutils) dt { 18 | background:#e7fafd; 19 | border-top:solid 3px #13c0d7; 20 | color:rgba(0,0,0,0.5); 21 | } 22 | .rst-content .viewcode-link, .rst-content .viewcode-back { 23 | color:#00b09b; 24 | } 25 | code.literal { 26 | color:#e63c2e; 27 | } 28 | .rst-content #at-a-glance { 29 | margin-bottom:24px; 30 | } 31 | .rst-content #at-a-glance dl:not(.docutils) dt { 32 | border:none; 33 | background:#f0f0f0; 34 | } 35 | .rst-content #at-a-glance dl:not(.docutils) dd { 36 | display:none; 37 | } 38 | .rst-content #at-a-glance dl:not(.docutils) { 39 | margin-bottom:0; 40 | } -------------------------------------------------------------------------------- /sphinx/_templates/breadcrumbs.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pimoroni/enviro-phat/3c06e819ea7a9ccd94f7ec2bd499021d734f6638/sphinx/_templates/breadcrumbs.html -------------------------------------------------------------------------------- /sphinx/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% block extrahead %} 3 | 4 | {% endblock %} 5 | {% block footer %} 6 | 43 | {% endblock %} -------------------------------------------------------------------------------- /sphinx/conf.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | 3 | import sys 4 | import site 5 | 6 | import mock 7 | 8 | # Prompte /usr/local/lib to the front of sys.path 9 | #sys.path.insert(0,site.getsitepackages()[0]) 10 | 11 | import sphinx_rtd_theme 12 | 13 | class MockSmbus(): 14 | def __init__(self, bus): 15 | self.bus = bus 16 | 17 | def read_word_data(self, address, register): 18 | return 0 19 | 20 | def write_byte_data(self, address, register, data): 21 | pass 22 | 23 | def read_byte_data(self, address, register): 24 | if register == 0xD0: # Fake CHIPID register for BMP280 25 | return 0x58 26 | 27 | if register == 0x0F: # Fake WHOAMI for LSM303D 28 | return 0x49 29 | 30 | return 0 31 | 32 | def write_i2c_block_data(self, address, register, data): 33 | pass 34 | 35 | def read_i2c_block_data(self, address, register): 36 | return [] 37 | 38 | 39 | sys.modules['smbus'] = mock.Mock() 40 | sys.modules['smbus'].SMBus = MockSmbus 41 | sys.modules['RPi'] = mock.Mock() 42 | sys.modules['RPi.GPIO'] = mock.Mock() 43 | 44 | sys.path.insert(0, '../library/') 45 | 46 | from sphinx.ext import autodoc 47 | 48 | class OutlineMethodDocumenter(autodoc.MethodDocumenter): 49 | objtype = 'methodoutline' 50 | 51 | def add_content(self, more_content, no_docstring=False): 52 | return 53 | 54 | def __init__(self, directive, name, indent=u''): 55 | # Monkey path the Method and Function documenters 56 | sphinx_app.add_autodocumenter(OutlineMethodDocumenter) 57 | autodoc.MethodDocumenter.__init__(self, directive, name, indent) 58 | 59 | def __del__(self): 60 | # Return the Method and Function documenters to normal 61 | sphinx_app.add_autodocumenter(autodoc.MethodDocumenter) 62 | 63 | 64 | def setup(app): 65 | global sphinx_app 66 | sphinx_app = app 67 | app.add_autodocumenter(OutlineMethodDocumenter) 68 | 69 | OutlineMethodDocumenter.objtype = 'method' 70 | 71 | import envirophat 72 | 73 | PACKAGE_NAME = u"Enviro pHAT" 74 | PACKAGE_HANDLE = "EnviropHAT" 75 | PACKAGE_MODULE = "envirophat" 76 | PACKAGE_VERSION = envirophat.__version__ 77 | 78 | suppress_warnings = ["app.add_directive"] 79 | 80 | # -- General configuration ------------------------------------------------ 81 | 82 | # If your documentation needs a minimal Sphinx version, state it here. 83 | # 84 | # needs_sphinx = '1.0' 85 | 86 | # Add any Sphinx extension module names here, as strings. They can be 87 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 88 | # ones. 89 | extensions = [ 90 | 'sphinx.ext.autodoc', 91 | 'sphinx.ext.autosummary', 92 | 'sphinx.ext.viewcode', 93 | ] 94 | 95 | # Add any paths that contain templates here, relative to this directory. 96 | templates_path = ['_templates'] 97 | 98 | # The suffix(es) of source filenames. 99 | # You can specify multiple suffix as a list of string: 100 | # 101 | # source_suffix = ['.rst', '.md'] 102 | source_suffix = '.rst' 103 | 104 | # The encoding of source files. 105 | # 106 | # source_encoding = 'utf-8-sig' 107 | 108 | # The master toctree document. 109 | master_doc = 'index' 110 | 111 | # General information about the project. 112 | project = PACKAGE_NAME 113 | copyright = u'2016, Pimoroni Ltd' 114 | author = u'Phil Howard' 115 | 116 | # The version info for the project you're documenting, acts as replacement for 117 | # |version| and |release|, also used in various other places throughout the 118 | # built documents. 119 | # 120 | # The short X.Y version. 121 | version = u'{}'.format(PACKAGE_VERSION) 122 | # The full version, including alpha/beta/rc tags. 123 | release = u'{}'.format(PACKAGE_VERSION) 124 | 125 | # The language for content autogenerated by Sphinx. Refer to documentation 126 | # for a list of supported languages. 127 | # 128 | # This is also used if you do content translation via gettext catalogs. 129 | # Usually you set "language" from the command line for these cases. 130 | language = None 131 | 132 | # There are two options for replacing |today|: either, you set today to some 133 | # non-false value, then it is used: 134 | # 135 | # today = '' 136 | # 137 | # Else, today_fmt is used as the format for a strftime call. 138 | # 139 | # today_fmt = '%B %d, %Y' 140 | 141 | # List of patterns, relative to source directory, that match files and 142 | # directories to ignore when looking for source files. 143 | # This patterns also effect to html_static_path and html_extra_path 144 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 145 | 146 | # The reST default role (used for this markup: `text`) to use for all 147 | # documents. 148 | # 149 | # default_role = None 150 | 151 | # If true, '()' will be appended to :func: etc. cross-reference text. 152 | # 153 | # add_function_parentheses = True 154 | 155 | # If true, the current module name will be prepended to all description 156 | # unit titles (such as .. function::). 157 | # 158 | # add_module_names = True 159 | 160 | # If true, sectionauthor and moduleauthor directives will be shown in the 161 | # output. They are ignored by default. 162 | # 163 | # show_authors = False 164 | 165 | # The name of the Pygments (syntax highlighting) style to use. 166 | pygments_style = 'sphinx' 167 | 168 | # A list of ignored prefixes for module index sorting. 169 | # modindex_common_prefix = [] 170 | 171 | # If true, keep warnings as "system message" paragraphs in the built documents. 172 | # keep_warnings = False 173 | 174 | # If true, `todo` and `todoList` produce output, else they produce nothing. 175 | todo_include_todos = False 176 | 177 | 178 | # -- Options for HTML output ---------------------------------------------- 179 | 180 | # The theme to use for HTML and HTML Help pages. See the documentation for 181 | # a list of builtin themes. 182 | # 183 | html_theme = 'sphinx_rtd_theme' 184 | #html_theme = 'alabaster' 185 | 186 | # Theme options are theme-specific and customize the look and feel of a theme 187 | # further. For a list of options available for each theme, see the 188 | # documentation. 189 | # 190 | html_theme_options = { 191 | 'collapse_navigation': False, 192 | 'display_version': True 193 | } 194 | 195 | # Add any paths that contain custom themes here, relative to this directory. 196 | html_theme_path = [ 197 | '_themes', 198 | sphinx_rtd_theme.get_html_theme_path() 199 | ] 200 | 201 | # The name for this set of Sphinx documents. 202 | # " v documentation" by default. 203 | # 204 | # html_title = PACKAGE_NAME + u' v0.1.2' 205 | 206 | # A shorter title for the navigation bar. Default is the same as html_title. 207 | # 208 | # html_short_title = None 209 | 210 | # The name of an image file (relative to this directory) to place at the top 211 | # of the sidebar. 212 | # 213 | html_logo = 'shop-logo.png' 214 | 215 | # The name of an image file (relative to this directory) to use as a favicon of 216 | # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 217 | # pixels large. 218 | # 219 | html_favicon = 'favicon.png' 220 | 221 | # Add any paths that contain custom static files (such as style sheets) here, 222 | # relative to this directory. They are copied after the builtin static files, 223 | # so a file named "default.css" will overwrite the builtin "default.css". 224 | html_static_path = ['_static'] 225 | 226 | # Add any extra paths that contain custom files (such as robots.txt or 227 | # .htaccess) here, relative to this directory. These files are copied 228 | # directly to the root of the documentation. 229 | # 230 | # html_extra_path = [] 231 | 232 | # If not None, a 'Last updated on:' timestamp is inserted at every page 233 | # bottom, using the given strftime format. 234 | # The empty string is equivalent to '%b %d, %Y'. 235 | # 236 | # html_last_updated_fmt = None 237 | 238 | # If true, SmartyPants will be used to convert quotes and dashes to 239 | # typographically correct entities. 240 | # 241 | # html_use_smartypants = True 242 | 243 | # Custom sidebar templates, maps document names to template names. 244 | # 245 | # html_sidebars = {} 246 | 247 | # Additional templates that should be rendered to pages, maps page names to 248 | # template names. 249 | # 250 | # html_additional_pages = {} 251 | 252 | # If false, no module index is generated. 253 | # 254 | # html_domain_indices = True 255 | 256 | # If false, no index is generated. 257 | # 258 | html_use_index = False 259 | 260 | # If true, the index is split into individual pages for each letter. 261 | # 262 | # html_split_index = False 263 | 264 | # If true, links to the reST sources are added to the pages. 265 | # 266 | html_show_sourcelink = False 267 | 268 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 269 | # 270 | html_show_sphinx = False 271 | 272 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 273 | # 274 | # html_show_copyright = True 275 | 276 | # If true, an OpenSearch description file will be output, and all pages will 277 | # contain a tag referring to it. The value of this option must be the 278 | # base URL from which the finished HTML is served. 279 | # 280 | # html_use_opensearch = '' 281 | 282 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 283 | # html_file_suffix = None 284 | 285 | # Language to be used for generating the HTML full-text search index. 286 | # Sphinx supports the following languages: 287 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 288 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' 289 | # 290 | # html_search_language = 'en' 291 | 292 | # A dictionary with options for the search language support, empty by default. 293 | # 'ja' uses this config value. 294 | # 'zh' user can custom change `jieba` dictionary path. 295 | # 296 | # html_search_options = {'type': 'default'} 297 | 298 | # The name of a javascript file (relative to the configuration directory) that 299 | # implements a search results scorer. If empty, the default will be used. 300 | # 301 | # html_search_scorer = 'scorer.js' 302 | 303 | # Output file base name for HTML help builder. 304 | htmlhelp_basename = PACKAGE_HANDLE + 'doc' 305 | 306 | # -- Options for LaTeX output --------------------------------------------- 307 | 308 | latex_elements = { 309 | # The paper size ('letterpaper' or 'a4paper'). 310 | # 311 | # 'papersize': 'letterpaper', 312 | 313 | # The font size ('10pt', '11pt' or '12pt'). 314 | # 315 | # 'pointsize': '10pt', 316 | 317 | # Additional stuff for the LaTeX preamble. 318 | # 319 | # 'preamble': '', 320 | 321 | # Latex figure (float) alignment 322 | # 323 | # 'figure_align': 'htbp', 324 | } 325 | 326 | # Grouping the document tree into LaTeX files. List of tuples 327 | # (source start file, target name, title, 328 | # author, documentclass [howto, manual, or own class]). 329 | latex_documents = [ 330 | (master_doc, PACKAGE_HANDLE + '.tex', PACKAGE_NAME + u' Documentation', 331 | u'Phil Howard', 'manual'), 332 | ] 333 | 334 | # The name of an image file (relative to this directory) to place at the top of 335 | # the title page. 336 | # 337 | # latex_logo = None 338 | 339 | # For "manual" documents, if this is true, then toplevel headings are parts, 340 | # not chapters. 341 | # 342 | # latex_use_parts = False 343 | 344 | # If true, show page references after internal links. 345 | # 346 | # latex_show_pagerefs = False 347 | 348 | # If true, show URL addresses after external links. 349 | # 350 | # latex_show_urls = False 351 | 352 | # Documents to append as an appendix to all manuals. 353 | # 354 | # latex_appendices = [] 355 | 356 | # It false, will not define \strong, \code, itleref, \crossref ... but only 357 | # \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added 358 | # packages. 359 | # 360 | # latex_keep_old_macro_names = True 361 | 362 | # If false, no module index is generated. 363 | # 364 | # latex_domain_indices = True 365 | 366 | 367 | # -- Options for manual page output --------------------------------------- 368 | 369 | # One entry per manual page. List of tuples 370 | # (source start file, name, description, authors, manual section). 371 | man_pages = [ 372 | (master_doc, PACKAGE_MODULE, PACKAGE_NAME + u' Documentation', 373 | [author], 1) 374 | ] 375 | 376 | # If true, show URL addresses after external links. 377 | # 378 | # man_show_urls = False 379 | 380 | 381 | # -- Options for Texinfo output ------------------------------------------- 382 | 383 | # Grouping the document tree into Texinfo files. List of tuples 384 | # (source start file, target name, title, author, 385 | # dir menu entry, description, category) 386 | texinfo_documents = [ 387 | (master_doc, PACKAGE_HANDLE, PACKAGE_NAME + u' Documentation', 388 | author, PACKAGE_HANDLE, 'One line description of project.', 389 | 'Miscellaneous'), 390 | ] 391 | 392 | # Documents to append as an appendix to all manuals. 393 | # 394 | # texinfo_appendices = [] 395 | 396 | # If false, no module index is generated. 397 | # 398 | # texinfo_domain_indices = True 399 | 400 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 401 | # 402 | # texinfo_show_urls = 'footnote' 403 | 404 | # If true, do not generate a @detailmenu in the "Top" node's menu. 405 | # 406 | # texinfo_no_detailmenu = False 407 | -------------------------------------------------------------------------------- /sphinx/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pimoroni/enviro-phat/3c06e819ea7a9ccd94f7ec2bd499021d734f6638/sphinx/favicon.png -------------------------------------------------------------------------------- /sphinx/index.rst: -------------------------------------------------------------------------------- 1 | .. role:: python(code) 2 | :language: python 3 | 4 | .. toctree:: 5 | :titlesonly: 6 | :maxdepth: 0 7 | 8 | .. module:: envirophat 9 | 10 | Welcome 11 | ------- 12 | 13 | This documentation will guide you through the methods available in the Enviro pHAT python library. 14 | 15 | Enviro pHAT is an environmental sensor add-on, packing 4 different sensors, letting you measure temperature, pressure, light level, colour, 3-axis motion, compass heading, and analog inputs. 16 | 17 | * More information - https://shop.pimoroni.com/products/enviro-phat 18 | * Getting started - https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-enviro-phat 19 | * GPIO Pinout - http://pinout.xyz/pinout/enviro_phat 20 | * Get the code - https://github.com/pimoroni/enviro-phat 21 | * Get help - http://forums.pimoroni.com/c/support 22 | 23 | At A Glance 24 | ----------- 25 | 26 | .. automethodoutline:: light.rgb 27 | .. automethodoutline:: light.light 28 | .. automethodoutline:: light.raw 29 | .. automethodoutline:: leds.on 30 | .. automethodoutline:: leds.off 31 | .. automethodoutline:: weather.temperature 32 | .. automethodoutline:: weather.pressure 33 | .. automethodoutline:: weather.altitude 34 | .. automethodoutline:: weather.update 35 | .. automethodoutline:: analog.read 36 | .. automethodoutline:: analog.read_all 37 | .. automethodoutline:: analog.available 38 | .. automethodoutline:: motion.magnetometer 39 | .. automethodoutline:: motion.accelerometer 40 | .. automethodoutline:: motion.heading 41 | .. automethodoutline:: motion.raw_heading 42 | .. automethodoutline:: motion.update 43 | 44 | Light 45 | ----- 46 | 47 | Light sensing is provided by a TCS3472 colour sensor, with filtered channels for Red, Green and Blue. plus an unfiltered "Light" channel. 48 | 49 | .. automethod:: light.rgb 50 | .. automethod:: light.light 51 | .. automethod:: light.raw 52 | 53 | For colour sensing, two LEDs are placed either side of the TCS3472 to illuminate the subject. 54 | 55 | .. automethod:: leds.on 56 | .. automethod:: leds.off 57 | 58 | Weather 59 | ------- 60 | 61 | Weather sensing is provided by a BMP280. The altitude is approximated from atmospheric pressure. 62 | 63 | .. automethod:: weather.temperature 64 | .. automethod:: weather.pressure 65 | .. automethod:: weather.altitude 66 | .. automethod:: weather.update 67 | 68 | Analog 69 | ------ 70 | 71 | The four channels of Analog input are provided by an ADS1015. 72 | 73 | .. automethod:: analog.read 74 | .. automethod:: analog.read_all 75 | .. automethod:: analog.available 76 | 77 | Motion 78 | ------ 79 | 80 | Motion sensing is provided by an LSM303D accelerometer and magnetometer. The compass heading is approximated. 81 | 82 | .. automethod:: motion.magnetometer 83 | .. automethod:: motion.accelerometer 84 | .. automethod:: motion.heading 85 | .. automethod:: motion.raw_heading 86 | .. automethod:: motion.update 87 | -------------------------------------------------------------------------------- /sphinx/shop-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pimoroni/enviro-phat/3c06e819ea7a9ccd94f7ec2bd499021d734f6638/sphinx/shop-logo.png -------------------------------------------------------------------------------- /terminal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pimoroni/enviro-phat/3c06e819ea7a9ccd94f7ec2bd499021d734f6638/terminal.jpg --------------------------------------------------------------------------------