From 0bc62aee73d821226c97141a88723797a0396d77 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 27 Oct 2015 21:08:36 +0000 Subject: [PATCH] Generic docs need reST Conversion of all docs to reST so that the generic docs can link easily with the rest of the docs. --- Makefile | 1 + README.rst | 22 +- debian/control | 13 +- debian/python-gpiozero-doc.doc-base | 10 + debian/python-gpiozero-doc.docs | 1 + debian/rules | 8 +- docs/Makefile | 205 ++ docs/api_boards.rst | 80 + docs/api_generic.rst | 87 + docs/api_input.rst | 59 + docs/api_output.rst | 44 + docs/boards.md | 294 -- docs/changelog.rst | 69 + docs/conf.py | 148 + docs/images/composed_devices.dot | 17 + docs/images/composed_devices.pdf | Bin 0 -> 11729 bytes docs/images/composed_devices.png | Bin 0 -> 17274 bytes docs/images/composed_devices.svg | 98 + docs/images/composite_device_hierarchy.dot | 32 + docs/images/composite_device_hierarchy.pdf | Bin 0 -> 15411 bytes docs/images/composite_device_hierarchy.png | Bin 0 -> 54997 bytes docs/images/composite_device_hierarchy.svg | 228 ++ docs/images/gpio_device_hierarchy.dot | 23 + docs/images/gpio_device_hierarchy.pdf | Bin 0 -> 9615 bytes docs/images/gpio_device_hierarchy.png | Bin 0 -> 39203 bytes docs/images/gpio_device_hierarchy.svg | 148 + docs/images/pin_layout.pdf | Bin 0 -> 21425 bytes docs/images/pin_layout.png | Bin 0 -> 92420 bytes docs/images/pin_layout.svg | 2815 ++++++++++++++++++++ docs/index.md | 113 - docs/index.rst | 16 + docs/inputs.md | 244 -- docs/license.rst | 34 + docs/notes.md | 282 -- docs/notes.rst | 72 + docs/outputs.md | 309 --- docs/recipes.md | 533 ---- docs/recipes.rst | 503 ++++ gpiozero/__init__.py | 8 + gpiozero/boards.py | 241 +- gpiozero/devices.py | 24 +- gpiozero/input_devices.py | 322 ++- gpiozero/output_devices.py | 207 +- mkdocs.yml | 15 - 44 files changed, 5315 insertions(+), 2010 deletions(-) create mode 100644 debian/python-gpiozero-doc.doc-base create mode 100644 debian/python-gpiozero-doc.docs create mode 100644 docs/Makefile create mode 100644 docs/api_boards.rst create mode 100644 docs/api_generic.rst create mode 100644 docs/api_input.rst create mode 100644 docs/api_output.rst delete mode 100644 docs/boards.md create mode 100644 docs/changelog.rst create mode 100644 docs/conf.py create mode 100644 docs/images/composed_devices.dot create mode 100644 docs/images/composed_devices.pdf create mode 100644 docs/images/composed_devices.png create mode 100644 docs/images/composed_devices.svg create mode 100644 docs/images/composite_device_hierarchy.dot create mode 100644 docs/images/composite_device_hierarchy.pdf create mode 100644 docs/images/composite_device_hierarchy.png create mode 100644 docs/images/composite_device_hierarchy.svg create mode 100644 docs/images/gpio_device_hierarchy.dot create mode 100644 docs/images/gpio_device_hierarchy.pdf create mode 100644 docs/images/gpio_device_hierarchy.png create mode 100644 docs/images/gpio_device_hierarchy.svg create mode 100644 docs/images/pin_layout.pdf create mode 100644 docs/images/pin_layout.png create mode 100644 docs/images/pin_layout.svg delete mode 100644 docs/index.md create mode 100644 docs/index.rst delete mode 100644 docs/inputs.md create mode 100644 docs/license.rst delete mode 100644 docs/notes.md create mode 100644 docs/notes.rst delete mode 100644 docs/outputs.md delete mode 100644 docs/recipes.md create mode 100644 docs/recipes.rst delete mode 100644 mkdocs.yml diff --git a/Makefile b/Makefile index d251582..e9843cd 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ DIST_TAR=dist/$(NAME)-$(VER).tar.gz DIST_ZIP=dist/$(NAME)-$(VER).zip DIST_DEB=dist/python-$(NAME)_$(VER)$(DEB_SUFFIX)_all.deb \ dist/python3-$(NAME)_$(VER)$(DEB_SUFFIX)_all.deb \ + dist/python-$(NAME)-doc_$(VER)$(DEB_SUFFIX)_all.deb \ dist/$(NAME)_$(VER)$(DEB_SUFFIX)_$(DEB_ARCH).changes DIST_DSC=dist/$(NAME)_$(VER)$(DEB_SUFFIX).tar.gz \ dist/$(NAME)_$(VER)$(DEB_SUFFIX).dsc \ diff --git a/README.rst b/README.rst index 3b1e2d2..f5d39cd 100644 --- a/README.rst +++ b/README.rst @@ -2,16 +2,15 @@ gpiozero ======== +.. image:: https://badge.fury.io/py/gpiozero.svg + :target: https://badge.fury.io/py/gpiozero + :alt: Latest Version + A simple interface to everyday GPIO components used with Raspberry Pi. Created by `Ben Nuttall`_ of the `Raspberry Pi Foundation`_, `Dave Jones`_, and other contributors. -Latest release -============== - -The latest release is 1.0 released on 16th November 2015. - About ===== @@ -66,19 +65,19 @@ or:: Documentation ============= -Comprehensive documentation is available at `pythonhosted.org/gpiozero`_. +Comprehensive documentation is available at https://gpiozero.readthedocs.org/. Development =========== This project is being developed on `GitHub`_. Join in: -* Provide suggestions, report bugs and ask questions as `Issues`_ +* Provide suggestions, report bugs and ask questions as `issues`_ * Provide examples we can use as `recipes`_ * Contribute to the code -Alternatively, email suggestions and feedback to ben@raspberrypi.org or add to -the `Google Doc`_. +Alternatively, email suggestions and feedback to mailto:ben@raspberrypi.org or +add to the `Google Doc`_. Contributors ============ @@ -91,10 +90,9 @@ Contributors .. _Ben Nuttall: https://github.com/bennuttall .. _Raspberry Pi Foundation: https://www.raspberrypi.org/ .. _Dave Jones: https://github.com/waveform80 -.. _pythonhosted.org/gpiozero: http://pythonhosted.org/gpiozero .. _GitHub: https://github.com/RPi-Distro/python-gpiozero -.. _Issues: https://github.com/RPi-Distro/python-gpiozero/issues -.. _recipes: http://pythonhosted.org/gpiozero/recipes/ +.. _issues: https://github.com/RPi-Distro/python-gpiozero/issues +.. _recipes: http://gpiozero.readthedocs.org/en/latest/recipes.html .. _Google Doc: https://goo.gl/8zJLif .. _Ben Nuttall: https://github.com/bennuttall .. _Dave Jones: https://github.com/waveform80 diff --git a/debian/control b/debian/control index 3713c6c..b84aace 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Maintainer: Ben Nuttall Homepage: http://github.com/RPi-Distro/python-gpiozero Section: python Priority: extra -Build-Depends: debhelper (>= 8), python-all (>= 2.7), python-setuptools, python3-all, python3-setuptools +Build-Depends: debhelper (>= 8), python-all (>= 2.7), python-setuptools, python3-all, python3-setuptools, python-sphinx (>= 1.0.7+dfsg-1~) Standards-Version: 3.9.6 X-Python-Version: >= 2.7 X-Python3-Version: >= 3.2 @@ -32,3 +32,14 @@ Description: Simple API for controlling devices attached to the GPIO pins. . This is the Python 3 version of the package. +Package: python-gpiozero-doc +Architecture: all +Section: doc +Depends: ${sphinxdoc:Depends}, ${misc:Depends} +Description: Documentation for the gpiozero API + gpiozero builds on RPi.GPIO to provide a set of classes designed to simplify + interaction with devices connected to the GPIO pins, from simple buttons and + LEDs, up to various add-on boards. The API tries to adhere closely to Python's + idioms and naming conventions. + . + This is the version independent documentation for the package. diff --git a/debian/python-gpiozero-doc.doc-base b/debian/python-gpiozero-doc.doc-base new file mode 100644 index 0000000..caf7e21 --- /dev/null +++ b/debian/python-gpiozero-doc.doc-base @@ -0,0 +1,10 @@ +Document: python-gpiozero +Title: GPIO Zero Reference +Author: Ben Nuttall +Abstract: Documentation for the gpiozero API +Section: Programming/Python + +Format: HTML +Index: /usr/share/doc/python-gpiozero-doc/html/index.html +Files: /usr/share/doc/python-gpiozero-doc/html/* + diff --git a/debian/python-gpiozero-doc.docs b/debian/python-gpiozero-doc.docs new file mode 100644 index 0000000..f85adaf --- /dev/null +++ b/debian/python-gpiozero-doc.docs @@ -0,0 +1 @@ +build/sphinx/html/ diff --git a/debian/rules b/debian/rules index 01d0107..0f66107 100755 --- a/debian/rules +++ b/debian/rules @@ -5,7 +5,7 @@ export DH_OPTIONS %: - dh $@ --with python2,python3 --buildsystem=python_distutils + dh $@ --with python2,python3,sphinxdoc --buildsystem=python_distutils override_dh_auto_install: python setup.py install --root debian/python-gpiozero --install-layout=deb @@ -14,7 +14,7 @@ override_dh_auto_install: #override_dh_auto_test: # # Don't run the tests! -#override_dh_installdocs: -# python setup.py build_sphinx -b html -# dh_installdocs +override_dh_installdocs: + python setup.py build_sphinx -b html + dh_installdocs diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..45f448e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,205 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build +DOT_DIAGRAMS := $(wildcard images/*.dot) +MSC_DIAGRAMS := $(wildcard images/*.mscgen) +GPI_DIAGRAMS := $(wildcard images/*.gpi) +SVG_IMAGES := $(wildcard images/*.svg) $(DOT_DIAGRAMS:%.dot=%.svg) $(MSC_DIAGRAMS:%.mscgen=%.svg) +PNG_IMAGES := $(wildcard images/*.png) $(GPI_DIAGRAMS:%.gpi=%.png) $(SVG_IMAGES:%.svg=%.png) +PDF_IMAGES := $(SVG_IMAGES:%.svg=%.pdf) $(GPI_DIAGRAMS:%.gpi=%.pdf) $(DOT_DIAGRAMS:%.dot=%.pdf) $(MSC_DIAGRAMS:%.mscgen=%.pdf) + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: $(SVG_IMAGES) $(PNG_IMAGES) + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: $(SVG_IMAGES) $(PNG_IMAGES) + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: $(SVG_IMAGES) $(PNG_IMAGES) + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/picraft.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/picraft.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/picraft" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/picraft" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: $(PDF_IMAGES) + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: $(PDF_IMAGES) + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: $(PDF_IMAGES) + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +%.svg: %.mscgen + mscgen -T svg -o $@ $< + +%.svg: %.dot + dot -T svg -o $@ $< + +%.png: %.gpi common.gp + gnuplot -e "set term pngcairo size 640,480" $< > $@ + +%.png: %.svg + inkscape -e $@ $< + +%.pdf: %.svg + inkscape -A $@ $< + +%.pdf: %.gpi common.gp + gnuplot -e "set term pdfcairo size 10cm,7.5cm" $< > $@ + +%.pdf: %.mscgen + mscgen -T eps -o - $< | ps2pdf -dEPSCrop - $@ + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + diff --git a/docs/api_boards.rst b/docs/api_boards.rst new file mode 100644 index 0000000..3d12a83 --- /dev/null +++ b/docs/api_boards.rst @@ -0,0 +1,80 @@ +====================== +Boards and Accessories +====================== + +.. currentmodule:: gpiozero + +These additional interfaces are provided to group collections of components +together for ease of use, and as examples. They are composites made up of +components from the various :doc:`api_input` and :doc:`api_output` provided by +GPIO Zero. See those pages for more information on using components +individually. + +.. note:: + + All GPIO pin numbers use Broadcom (BCM) numbering. See the :doc:`recipes` + page for more information. + +LED Board +========= + +.. autoclass:: LEDBoard(\*pins, pwm=False) + :inherited-members: + :members: + +Traffic Lights +============== + +.. autoclass:: TrafficLights + :inherited-members: + :members: + +PiLITEr +======= + +.. autoclass:: PiLiter + :inherited-members: + :members: + +PI-TRAFFIC +========== + +.. autoclass:: PiTraffic + :inherited-members: + :members: + +TrafficLightsBuzzer +=================== + +.. autoclass:: TrafficLightsBuzzer + :inherited-members: + :members: + +Fish Dish +========= + +.. autoclass:: FishDish + :inherited-members: + :members: + +Traffic HAT +=========== + +.. autoclass:: TrafficHat + :inherited-members: + :members: + +Robot +===== + +.. autoclass:: Robot + :inherited-members: + :members: + +Ryanteck MCB Robot +================== + +.. autoclass:: RyanteckRobot + :inherited-members: + :members: + diff --git a/docs/api_generic.rst b/docs/api_generic.rst new file mode 100644 index 0000000..f91b4bd --- /dev/null +++ b/docs/api_generic.rst @@ -0,0 +1,87 @@ +=============== +Generic Devices +=============== + +.. currentmodule:: gpiozero + +The GPIO Zero class hierarchy is quite extensive. It contains a couple of base +classes: + +* :class:`GPIODevice` for individual devices that attach to a single GPIO pin + +* :class:`CompositeDevice` for devices composed of multiple other devices like + HATs + +There are also a couple of `mixin classes`_: + +* :class:`ValuesMixin` which defines the ``values`` properties; there is rarely + a need to use this as the base classes mentioned above both include it + (so all classes in GPIO Zero include the ``values`` property) + +* :class:`SourceMixin` which defines the ``source`` property; this is generally + included in novel output device classes + +.. _mixin classes: https://en.wikipedia.org/wiki/Mixin + +The current class hierarchies are displayed below. For brevity, the mixin +classes are omitted: + +.. image:: images/gpio_device_hierarchy.* + +.. image:: images/composite_device_hierarchy.* + +Finally, for composite devices, the following chart shows which devices are +composed of which other devices: + +.. image:: images/composed_devices.* + +Base Classes +============ + +.. autoclass:: GPIODevice(pin) + :inherited-members: + :members: + +.. autoclass:: CompositeDevice + :inherited-members: + :members: + +Input Devices +============= + +.. autoclass:: InputDevice(pin, pull_up=False) + :members: + +.. autoclass:: WaitableInputDevice + :members: + +.. autoclass:: DigitalInputDevice(pin, pull_up=False, bounce_time=None) + :members: + +.. autoclass:: SmoothedInputDevice + :members: + +.. autoclass:: AnalogInputDevice + :members: + +Output Devices +============== + +.. autoclass:: OutputDevice(pin, active_high=True) + :members: + +.. autoclass:: PWMOutputDevice(pin, frequency=100) + :members: + +.. autoclass:: DigitalOutputDevice(pin, active_high=True) + :members: + +Mixin Classes +============= + +.. autoclass:: ValuesMixin(...) + :members: + +.. autoclass:: SourceMixin(...) + :members: + diff --git a/docs/api_input.rst b/docs/api_input.rst new file mode 100644 index 0000000..27ad046 --- /dev/null +++ b/docs/api_input.rst @@ -0,0 +1,59 @@ +============= +Input Devices +============= + +.. currentmodule:: gpiozero + +These input device component interfaces have been provided for simple use of +everyday components. Components must be wired up correctly before use in code. + +.. note:: + + All GPIO pin numbers use Broadcom (BCM) numbering. See the :doc:`recipes` + page for more information. + + +Button +====== + +.. autoclass:: Button(pin, pull_up=True, bounce_time=None) + :members: wait_for_press, wait_for_release, pin, is_pressed, pull_up, when_pressed, when_released + + +Motion Sensor (PIR) +=================== + +.. autoclass:: MotionSensor(pin, queue_len=1, sample_rate=10, threshold=0.5, partial=False) + :members: wait_for_motion, wait_for_no_motion, pin, motion_detected, when_motion, when_no_motion + + +Light Sensor (LDR) +================== + +.. autoclass:: LightSensor(pin, queue_len=5, charge_time_limit=0.01, threshold=0.1, partial=False) + :members: wait_for_light, wait_for_dark, pin, light_detected, when_light, when_dark + +Analog to Digital Converters (ADC) +================================== + +.. autoclass:: MCP3004 + :members: bus, device, channel, value, differential + +.. autoclass:: MCP3008 + :members: bus, device, channel, value, differential + +.. autoclass:: MCP3204 + :members: bus, device, channel, value, differential + +.. autoclass:: MCP3208 + :members: bus, device, channel, value, differential + +.. autoclass:: MCP3301 + :members: bus, device, value + +.. autoclass:: MCP3302 + :members: bus, device, channel, value, differential + +.. autoclass:: MCP3304 + :members: bus, device, channel, value, differential + diff --git a/docs/api_output.rst b/docs/api_output.rst new file mode 100644 index 0000000..906f5c4 --- /dev/null +++ b/docs/api_output.rst @@ -0,0 +1,44 @@ +============== +Output Devices +============== + +.. currentmodule:: gpiozero + +These output device component interfaces have been provided for simple use of +everyday components. Components must be wired up correctly before use in code. + +.. note:: + + All GPIO pin numbers use Broadcom (BCM) numbering. See the :doc:`recipes` + page for more information. + + +LED +=== + +.. autoclass:: LED(pin, active_high=True) + :members: on, off, toggle, blink, pin, is_lit + +PWMLED +====== + +.. autoclass:: PWMLED(pin, frequency=100) + :members: on, off, toggle, blink, pin, is_lit, value + +Buzzer +====== + +.. autoclass:: Buzzer(pin, active_high=True) + :members: on, off, toggle, beep, pin, is_active + +RGBLED +====== + +.. autoclass:: RGBLED(red, green, blue) + :members: on, off, red, green, blue, value + +Motor +===== + +.. autoclass:: Motor(forward, backward) + :members: forward, backward, stop diff --git a/docs/boards.md b/docs/boards.md deleted file mode 100644 index 9fb2a27..0000000 --- a/docs/boards.md +++ /dev/null @@ -1,294 +0,0 @@ -# Add-on boards and accessories - -These additional interfaces have been provided to group collections of -components together for ease of use, and as examples. They are made up of -components from the various [input devices](inputs.md) and -[output devices](outputs.md) provided by `gpiozero`. See those pages for more -information on using components individually. - -*Note all GPIO pin numbers use BCM numbering. See the [notes](notes.md) page -for more information.* - -## LED Board - -A Generic LED Board or collection of LEDs. - -### Code - -Ensure the `LEDBoard` class is imported at the top of the file: - -```python -from gpiozero import LEDBoard -``` - -Create an `LEDBoard` object by passing in the LED pin numbers: - -```python -leds = LEDBoard(2, 3, 4, 5, 6) -``` - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn all the LEDs on. | None | -| `off()` | Turn all the LEDs off. | None | -| `toggle()` | Toggle all the LEDs. For each LED, if it's on, turn it off; if it's off, turn it on. | None | -| `blink()` | Make the LEDs turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. Default: `1` | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. Default: `1` | -| | | `n` - The number of iterations. `None` means infinite. Default: `None` | -| | | `background` - If True, start a background thread to continue blinking and return immediately. If False, only return when the blink is finished (warning: the default value of n will result in this method never returning). Default: `True` | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `leds` | A collection of LEDs to access each one individually, or to iterate over them in sequence. | Tuple | - -## Traffic Lights - -Generic Traffic Lights set. - -### Code - -Ensure the `TrafficLights` class is imported at the top of the file: - -```python -from gpiozero import TrafficLights -``` - -Create a `TrafficLights` object by passing in the LED pin numbers by name: - -```python -traffic = TrafficLights(red=2, amber=3, green=4) -``` - -or just in order (red, amber, green): - -```python -traffic = TrafficLights(2, 3, 4) -``` - -#### Initialisation options - -```python -TrafficLights(red=None, amber=None, green=None) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `red` | The GPIO pin number the red LED is connected to. | Integer: `0` to `25` | *Required* | -| `amber` | The GPIO pin number the amber LED is connected to. | Integer: `0` to `25` | *Required* | -| `green` | The GPIO pin number the green LED is connected to. | Integer: `0` to `25` | *Required* | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn all three LEDs on. | None | -| `off()` | Turn all three LEDs off. | None | -| `toggle()` | Toggle all three LEDs. For each LED, if it's on, turn it off; if it's off, turn it on. | None | -| `blink()` | Make the LEDs turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. Default: `1` | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. Default: `1` | -| | | `n` - The number of iterations. `None` means infinite. Default: `None` | -| | | `background` - If True, start a background thread to continue blinking and return immediately. If False, only return when the blink is finished (warning: the default value of n will result in this method never returning). Default: `True` | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `red` | Direct access to the red light as a single `LED` object. | LED | -| `amber` | Direct access to the amber light as a single `LED` object. | LED | -| `green` | Direct access to the green light as a single `LED` object. | LED | -| `leds` | A collection of LEDs to access each one individually, or to iterate over them in sequence. | Tuple | - -## PiLITEr - -Ciseco Pi-LITEr: strip of 8 very bright LEDs. - -### Code - -Ensure the `PiLiter` class is imported at the top of the file: - -```python -from gpiozero import PiLiter -``` - -Create a `PiLiter` object: - -```python -lite = PiLiter() -``` - -#### Initialisation options - -None - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn all eight LEDs on. | None | -| `off()` | Turn all eight LEDs off. | None | -| `toggle()` | Toggle all eight LEDs. For each LED, if it's on, turn it off; if it's off, turn it on. | None | -| `blink()` | Make all the LEDs turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. Default: `1` | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. Default: `1` | -| | | `n` - The number of iterations. `None` means infinite. Default: `None` | -| | | `background` - If True, start a background thread to continue blinking and return immediately. If False, only return when the blink is finished (warning: the default value of n will result in this method never returning). Default: `True` | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `leds` | A collection of LEDs to access each one individually, or to iterate over them in sequence. | Tuple | - -## PI-TRAFFIC - -Low Voltage Labs PI-TRAFFIC: vertical traffic lights board on pins 9, 10 and 11. - -Ensure the `PiTraffic` class is imported at the top of the file: - -```python -from gpiozero import PiTraffic -``` - -Create a `PiTraffic` object: - -```python -traffic = PiTraffic() -``` - -`PiTraffic` provides an identical interface to the generic `TrafficLights` -interface, without the need to specify the pin numbers to be used. - -The interface is identical to the generic `TrafficLights` interface. - -To use the PI-TRAFFIC board on another set of pins, just use the generic -`TrafficLights` interface. - -## Fish Dish - -Pi Supply Fish Dish: traffic light LEDs, a button and a buzzer. - -### Code - -Ensure the `FishDish` class is imported at the top of the file: - -```python -from gpiozero import FishDish -``` - -Create a `FishDish` object: - -```python -fish = FishDish() -``` - -#### Initialisation options - -None - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn all the board's output components on. | None | -| `off()` | Turn all the board's output components off. | None | -| `toggle()` | Toggle all the board's output components. For each component, if it's on, turn it off; if it's off, turn it on. | None || `toggle()` | Toggle all the LEDs. For each LED, if it's on, turn it off; if it's off, turn it on. | None | -| `blink()` | Make the LEDs turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. Default: `1` | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. Default: `1` | -| | | `n` - The number of iterations. `None` means infinite. Default: `None` | -| | | `background` - If True, start a background thread to continue blinking and return immediately. If False, only return when the blink is finished (warning: the default value of n will result in this method never returning). Default: `True` | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `lights` | Access to the three LEDs as a `TrafficLights` object. | TrafficLights | -| `buzzer` | Direct access to the buzzer as a single `Buzzer` object. | LED | -| `button` | Direct access to the button as a single `Button` object. | LED | -| `all` | A collection of the board's output components to access each one individually, or to iterate over them in sequence. | Tuple | - -## Traffic HAT - -Ryanteck Traffic HAT: traffic light LEDs, a button and a buzzer. - -### Code - -Ensure the `TrafficHat` class is imported at the top of the file: - -```python -from gpiozero import TrafficHat -``` - -Create a `TrafficHat` object by passing in the LED pin numbers by name: - -```python -traffic = TrafficHat() -``` - -The interface is identical to the `FishDish`. - -## Robot - -Generic two-motor robot. - -### Code - -Ensure the `Robot` class is imported at the top of the file: - -```python -from gpiozero import Robot -``` - -Create a `Robot` object by passing in the pin numbers of the forward and back -pairs for each motor: - -```python -robot = Robot(left=(4, 14), right=(17, 18)) -``` - -#### Initialisation options - -```python -Robot(left=None, right=None)) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `left` | The GPIO pins (forward and reverse) used by the left motor. | Tuple | *Required* | -| `right` | The GPIO pins (forward and reverse) used by the right motor. | Tuple | *Required* | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `forward()` | Drive the robot forwards. | `speed` - Speed at which to drive the motors, `0` to `1`. Default: `1` | -| `backward()` | Drive the robot backwards. | `speed` - Speed at which to drive the motors, `0` to `1`. Default: `1` | -| `left()` | Make the robot turn left. | `speed` - Speed at which to drive the motors, `0` to `1`. Default: `1` | -| `right()` | Make the robot turn right. | `speed` - Speed at which to drive the motors, `0` to `1`. Default: `1` | -| `stop()` | Stop the robot. | None | - -## Ryanteck MCB Robot - -Generic robot controller with pre-configured pin numbers. - -Ensure the `RyanteckRobot` class is imported at the top of the file: - -```python -from gpiozero import RyanteckRobot -``` - -Create a `RyanteckRobot` object: - -```python -robot = RyanteckRobot() -``` - -The interface is identical to the generic `Robot` interface. - -There's no need to configure the pins if you're using the default pins -`(17, 18)` for the left motor and `(22, 23)` for the right motor. - -To use the Ryanteck MCB on another set of pins, just use the generic `Robot` -interface. diff --git a/docs/changelog.rst b/docs/changelog.rst new file mode 100644 index 0000000..7a6c6b5 --- /dev/null +++ b/docs/changelog.rst @@ -0,0 +1,69 @@ +========= +Changelog +========= + +Release 1.0.0 (2015-11-16) +========================== + +* Debian packaging added (`#44`_) +* :class:`~gpiozero.PWMLED` class added (`#58`_) +* ``TemperatureSensor`` removed pending further work (`#93`_) +* :meth:`~gpiozero.Buzzer.beep` alias method added (`#75`_) +* :class:`~gpiozero.Motor` PWM devices exposed, and :class:`~gpiozero.Robot` + motor devices exposed (`#107`_) + +.. _#44: https://github.com/RPi-Distro/python-gpiozero/issues/44 +.. _#58: https://github.com/RPi-Distro/python-gpiozero/issues/58 +.. _#93: https://github.com/RPi-Distro/python-gpiozero/issues/93 +.. _#75: https://github.com/RPi-Distro/python-gpiozero/issues/75 +.. _#107: https://github.com/RPi-Distro/python-gpiozero/issues/107 + +Release 0.9.0 (2015-10-25) +========================== + +Fourth public beta + +* Added source and values properties to all relevant classes (`#76`_) +* Fix names of parameters in :class:`~gpiozero.Motor` constructor (`#79`_) +* Added wrappers for LED groups on add-on boards (`#81`_) + +.. _#76: https://github.com/RPi-Distro/python-gpiozero/issues/76 +.. _#79: https://github.com/RPi-Distro/python-gpiozero/issues/79 +.. _#81: https://github.com/RPi-Distro/python-gpiozero/issues/81 + +Release 0.8.0 (2015-10-16) +========================== + +Third public beta + +* Added generic :class:`~gpiozero.AnalogInputDevice` class along with specific + classes for the :class:`~gpiozero.MCP3008` and :class:`~gpiozero.MCP3004` + (`#41`_) +* Fixed :meth:`~gpiozero.DigitalOutputDevice.blink` (`#57`_) + +.. _#41: https://github.com/RPi-Distro/python-gpiozero/issues/41 +.. _#57: https://github.com/RPi-Distro/python-gpiozero/issues/57 + +Release 0.7.0 (2015-10-09) +========================== + +Second public beta + +Release 0.6.0 (2015-09-28) +========================== + +First public beta + +Release 0.5.0 (2015-09-24) +========================== + +Release 0.4.0 (2015-09-23) +========================== + +Release 0.3.0 (2015-09-22) +========================== + +Release 0.2.0 (2015-09-21) +========================== + +Initial release diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..d8c655f --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 + +import sys +import os +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +import setup as _setup + +# Mock out certain modules while building documentation +class Mock(object): + __all__ = [] + + def __init__(self, *args, **kw): + pass + + def __call__(self, *args, **kw): + return Mock() + + def __mul__(self, other): + return Mock() + + def __and__(self, other): + return Mock() + + def __bool__(self): + return False + + def __nonzero__(self): + return False + + @classmethod + def __getattr__(cls, name): + if name in ('__file__', '__path__'): + return '/dev/null' + else: + return Mock() + +sys.modules['RPi'] = Mock() +sys.modules['RPi.GPIO'] = sys.modules['RPi'].GPIO +sys.modules['w1thermsensor'] = Mock() +sys.modules['spidev'] = Mock() + +# -- General configuration ------------------------------------------------ + +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.intersphinx'] +templates_path = ['_templates'] +source_suffix = '.rst' +#source_encoding = 'utf-8-sig' +master_doc = 'index' +project = _setup.__project__.title() +copyright = '2015 %s' % _setup.__author__ +version = _setup.__version__ +release = _setup.__version__ +#language = None +#today_fmt = '%B %d, %Y' +exclude_patterns = ['_build'] +#default_role = None +#add_function_parentheses = True +#add_module_names = True +#show_authors = False +pygments_style = 'sphinx' +#modindex_common_prefix = [] +#keep_warnings = False + +# -- Autodoc configuration ------------------------------------------------ + +autodoc_member_order = 'groupwise' + +# -- Intersphinx configuration -------------------------------------------- + +intersphinx_mapping = { + 'python': ('http://docs.python.org/3.4', None), + } + +# -- Options for HTML output ---------------------------------------------- + +if on_rtd: + html_theme = 'sphinx_rtd_theme' + #html_theme_options = {} + #html_sidebars = {} +else: + html_theme = 'default' + #html_theme_options = {} + #html_sidebars = {} +#html_theme_path = [] +#html_title = None +#html_short_title = None +#html_logo = None +#html_favicon = None +html_static_path = ['_static'] +#html_extra_path = [] +#html_last_updated_fmt = '%b %d, %Y' +#html_use_smartypants = True +#html_additional_pages = {} +#html_domain_indices = True +#html_use_index = True +#html_split_index = False +#html_show_sourcelink = True +#html_show_sphinx = True +#html_show_copyright = True +#html_use_opensearch = '' +#html_file_suffix = None +htmlhelp_basename = '%sdoc' % _setup.__project__ + +# Hack to make wide tables work properly in RTD +# See https://github.com/snide/sphinx_rtd_theme/issues/117 for details +#def setup(app): +# app.add_stylesheet('style_override.css') + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + 'papersize': 'a4paper', + 'pointsize': '10pt', + #'preamble': '', +} + +latex_documents = [ + ( + 'index', # source start file + '%s.tex' % _setup.__project__, # target filename + '%s Documentation' % project, # title + _setup.__author__, # author + 'manual', # documentclass + ), +] + +#latex_logo = None +#latex_use_parts = False +#latex_show_pagerefs = False +#latex_show_urls = False +#latex_appendices = [] +#latex_domain_indices = True + +# -- Options for manual page output --------------------------------------- + +man_pages = [] + +#man_show_urls = False + +# -- Options for Texinfo output ------------------------------------------- + +texinfo_documents = [] + +#texinfo_appendices = [] +#texinfo_domain_indices = True +#texinfo_show_urls = 'footnote' +#texinfo_no_detailmenu = False diff --git a/docs/images/composed_devices.dot b/docs/images/composed_devices.dot new file mode 100644 index 0000000..0459ede --- /dev/null +++ b/docs/images/composed_devices.dot @@ -0,0 +1,17 @@ +/* vim: set et sw=4 sts=4: */ + +digraph classes { + graph [rankdir=TB]; + node [shape=rect, style=filled, color="#298029", fontname=Sans, fontcolor="#ffffff", fontsize=10]; + edge [arrowhead=onormal, style=dashed]; + + RGBLED->PWMLED; + LEDBoard->LED; + LEDBoard->PWMLED; + + TrafficLightsBuzzer->TrafficLights; + TrafficLightsBuzzer->Buzzer; + TrafficLightsBuzzer->Button; + + Robot->Motor; +} diff --git a/docs/images/composed_devices.pdf b/docs/images/composed_devices.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1f464a0a5e28edb70f4bd3aa19a433a1ce4beca4 GIT binary patch literal 11729 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 literal 0 HcmV?d00001 diff --git a/docs/images/composed_devices.png b/docs/images/composed_devices.png new file mode 100644 index 0000000000000000000000000000000000000000..c5830cb77fcbd6c27f1897d800cea9937a505b99 GIT binary patch literal 17274 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 literal 0 HcmV?d00001 diff --git a/docs/images/composed_devices.svg b/docs/images/composed_devices.svg new file mode 100644 index 0000000..c4fa63a --- /dev/null +++ b/docs/images/composed_devices.svg @@ -0,0 +1,98 @@ + + + + + + +classes + + +RGBLED + +RGBLED + + +PWMLED + +PWMLED + + +RGBLED->PWMLED + + + + +LEDBoard + +LEDBoard + + +LEDBoard->PWMLED + + + + +LED + +LED + + +LEDBoard->LED + + + + +TrafficLightsBuzzer + +TrafficLightsBuzzer + + +TrafficLights + +TrafficLights + + +TrafficLightsBuzzer->TrafficLights + + + + +Buzzer + +Buzzer + + +TrafficLightsBuzzer->Buzzer + + + + +Button + +Button + + +TrafficLightsBuzzer->Button + + + + +Robot + +Robot + + +Motor + +Motor + + +Robot->Motor + + + + + diff --git a/docs/images/composite_device_hierarchy.dot b/docs/images/composite_device_hierarchy.dot new file mode 100644 index 0000000..3fc04c6 --- /dev/null +++ b/docs/images/composite_device_hierarchy.dot @@ -0,0 +1,32 @@ +/* vim: set et sw=4 sts=4: */ + +digraph classes { + graph [rankdir=BT]; + node [shape=rect, style=filled, color="#2980b9", fontname=Sans, fontcolor="#ffffff", fontsize=10]; + edge []; + + AnalogInputDevice->CompositeDevice; + MCP3xxx->AnalogInputDevice; + MCP33xx->MCP3xxx; + MCP3004->MCP3xxx; + MCP3008->MCP3xxx; + MCP3204->MCP3xxx; + MCP3208->MCP3xxx; + MCP3301->MCP33xx; + MCP3302->MCP33xx; + MCP3304->MCP33xx; + + RGBLED->CompositeDevice; + Motor->CompositeDevice; + LEDBoard->CompositeDevice; + PiLiter->LEDBoard; + TrafficLights->LEDBoard; + PiTraffic->TrafficLights; + + TrafficLightsBuzzer->CompositeDevice; + FishDish->TrafficLightsBuzzer; + TrafficHat->TrafficLightsBuzzer; + + Robot->CompositeDevice; + RyanteckRobot->Robot; +} diff --git a/docs/images/composite_device_hierarchy.pdf b/docs/images/composite_device_hierarchy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..80f6d255769db010e339156cf4af385459248f31 GIT binary patch literal 15411 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 + + + + + +classes + + +AnalogInputDevice + +AnalogInputDevice + + +CompositeDevice + +CompositeDevice + + +AnalogInputDevice->CompositeDevice + + + + +MCP3xxx + +MCP3xxx + + +MCP3xxx->AnalogInputDevice + + + + +MCP33xx + +MCP33xx + + +MCP33xx->MCP3xxx + + + + +MCP3004 + +MCP3004 + + +MCP3004->MCP3xxx + + + + +MCP3008 + +MCP3008 + + +MCP3008->MCP3xxx + + + + +MCP3204 + +MCP3204 + + +MCP3204->MCP3xxx + + + + +MCP3208 + +MCP3208 + + +MCP3208->MCP3xxx + + + + +MCP3301 + +MCP3301 + + +MCP3301->MCP33xx + + + + +MCP3302 + +MCP3302 + + +MCP3302->MCP33xx + + + + +MCP3304 + +MCP3304 + + +MCP3304->MCP33xx + + + + +RGBLED + +RGBLED + + +RGBLED->CompositeDevice + + + + +Motor + +Motor + + +Motor->CompositeDevice + + + + +LEDBoard + +LEDBoard + + +LEDBoard->CompositeDevice + + + + +PiLiter + +PiLiter + + +PiLiter->LEDBoard + + + + +TrafficLights + +TrafficLights + + +TrafficLights->LEDBoard + + + + +PiTraffic + +PiTraffic + + +PiTraffic->TrafficLights + + + + +TrafficLightsBuzzer + +TrafficLightsBuzzer + + +TrafficLightsBuzzer->CompositeDevice + + + + +FishDish + +FishDish + + +FishDish->TrafficLightsBuzzer + + + + +TrafficHat + +TrafficHat + + +TrafficHat->TrafficLightsBuzzer + + + + +Robot + +Robot + + +Robot->CompositeDevice + + + + +RyanteckRobot + +RyanteckRobot + + +RyanteckRobot->Robot + + + + + diff --git a/docs/images/gpio_device_hierarchy.dot b/docs/images/gpio_device_hierarchy.dot new file mode 100644 index 0000000..8dbe9d3 --- /dev/null +++ b/docs/images/gpio_device_hierarchy.dot @@ -0,0 +1,23 @@ +/* vim: set et sw=4 sts=4: */ + +digraph classes { + graph [rankdir=BT]; + node [shape=rect, style=filled, color="#2980b9", fontname=Sans, fontcolor="#ffffff", fontsize=10]; + edge []; + + InputDevice->GPIODevice; + WaitableInputDevice->InputDevice; + DigitalInputDevice->WaitableInputDevice; + SmoothedInputDevice->WaitableInputDevice; + Button->DigitalInputDevice; + MotionSensor->SmoothedInputDevice; + LightSensor->SmoothedInputDevice; + + OutputDevice->GPIODevice; + DigitalOutputDevice->OutputDevice; + LED->DigitalOutputDevice; + Buzzer->DigitalOutputDevice; + PWMOutputDevice->DigitalOutputDevice; + PWMLED->PWMOutputDevice; +} + diff --git a/docs/images/gpio_device_hierarchy.pdf b/docs/images/gpio_device_hierarchy.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3299c2dc0964b36ef0060dc0fb73b7cac6619356 GIT binary patch literal 9615 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

EJ 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 + + + + + +classes + + +InputDevice + +InputDevice + + +GPIODevice + +GPIODevice + + +InputDevice->GPIODevice + + + + +WaitableInputDevice + +WaitableInputDevice + + +WaitableInputDevice->InputDevice + + + + +DigitalInputDevice + +DigitalInputDevice + + +DigitalInputDevice->WaitableInputDevice + + + + +SmoothedInputDevice + +SmoothedInputDevice + + +SmoothedInputDevice->WaitableInputDevice + + + + +Button + +Button + + +Button->DigitalInputDevice + + + + +MotionSensor + +MotionSensor + + +MotionSensor->SmoothedInputDevice + + + + +LightSensor + +LightSensor + + +LightSensor->SmoothedInputDevice + + + + +OutputDevice + +OutputDevice + + +OutputDevice->GPIODevice + + + + +DigitalOutputDevice + +DigitalOutputDevice + + +DigitalOutputDevice->OutputDevice + + + + +LED + +LED + + +LED->DigitalOutputDevice + + + + +Buzzer + +Buzzer + + +Buzzer->DigitalOutputDevice + + + + +PWMOutputDevice + +PWMOutputDevice + + +PWMOutputDevice->DigitalOutputDevice + + + + +PWMLED + +PWMLED + + +PWMLED->PWMOutputDevice + + + + + diff --git a/docs/images/pin_layout.pdf b/docs/images/pin_layout.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bdab4a45fd57425155c4712d28786e192115da87 GIT binary patch literal 21425 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 SyDBHE0EPoZMYRoe0RI6w5*gS4 literal 0 HcmV?d00001 diff --git a/docs/images/pin_layout.png b/docs/images/pin_layout.png new file mode 100644 index 0000000000000000000000000000000000000000..9254990df8a69fa7e31ce8735310fa6d7d5545e6 GIT binary patch literal 92420 zcmZU4bx>SSur(IoM{sut5Zv9}-7UDgyGyX(4#C~s-QC^Y-QC{Jt9pNY^-;UE%jGUR z)6>)4=k%E{d08Y)zb8^&N~sTwPsh&220l4fXAeX>A=$(=NHO zK|lyWB!mT&-O|r9T-}rx7DKj}Sd1C}JBfr4lpy3k#-pGlB-GY~7zhZ;ebT(@p!@?j zR6EH-O>Q*9FtZd{v;C6Ng!t?X<=hNu8xYG9bjigDH^49G1!VOV! z{GGK$H{vb|e3VvJ2qm9Vg&JUBRrGc~D8 z1%?F+87RY1w<4{oik?iXU0UZIKO!tD3W-6hm0et1jCHkt*nfjEFCG^chbR)u>-}2o zdZmMmg7P0cyp5u^zrTNeQIV3my11Yq*yrb`k*TQ~FC8W2?$efUQGGpXs&p_RG%P-M zN~85!Tw>zDV#TkL;$r^189ip~*pc$Ckb!}L_s_Shgv7)gWlDPo2ZL@uP}UD>3JU#! zKWOY696#bm$Z2Q}I^QlGBcvm{8NgWL`um0FEm-h4ow}Enk`oe8BSa13PhsHU2RAk{ zQc^G#6%|7xA`-ayoQ@F-3JTU;)~v@<7{Ch@M>2Ulfhok3$tmjSOg`W2wLC2TnmKVw zJcz>O5R{Pkk61K9Z#G{76BhFEV$F2U2e1=*c#zM>D}(tg31H{gu>%bhd36=oB0^P0foLBpnox5QzBrlP7aUVWFYL=>ggTWeag> zX;Q!v`uO`c=@fcU0s;bI1rjo{ zp+X-&g*;JxX6&%&=%eeMzQi;_cfE}n@H+?=H)PT`bP*9jF zc1RY)jl`3!c`xRPA=K8^F4vo*zyyJX5Aa(Aly@&K;QWBgOiU>XvqSr4D6QYmlypS_2H3`9Kfq1MFX?4bSo^gHNAFhUcWoTgIi>SZkz-0 zhBr!^{a>`{^ZWnf$^V9-KEF@FdB*RIm0Pq$qXq&#Ojor!;J8pFYX3#{@|#-Y$6mTW zmyX%19oxsHAt8~oP*5W2lY znO31gn<-#{N4*p64*C_dq%@_^1S~P>R+ok~ID0BhgxplFs}2$)S6(EDSp+GwC`!)( z=j#EwJZ*9vMR&+XXXXSp!9+BlPut6Mj_O45u5Gj+V!!cH8_E(Kfpy&<*TqA|24f-{ zn6)={=bb`&#En~Kh07LdIcvEviG}>fzHq5j9|jZzp}qDVU|OVw#xn)QzYB8w_sbGw zEOgIjjb|o!qc|4%Wx6$Nb}wV*xTiTgZT65(Ki#;@9batSU^jS9JMUFd8btOh=cVyw zTh*IxmhJH?WY^*tGkH^`ySUdZj{p}ogqs&%PxQdI#0g23G`*9)whC##AUDbhL|O+! zn!nUz_@TP5KO)f`SBvL3D@w1rLG7%N(oA-bTA?kap0U}u`KT>pa!8grq-$!~EGRCu z-)Aern@u1nPZ-dKK5o+AD@YwCq3&|k*X~YbAYpEdMHU`Zg24z)MRQanA3|(yXpbpR zj0n-pwO?OxGmJ{^F(EYL4G+zd&Tv2pAp_zd19H3AlyiJTK6o)@FcO+*)Hc8snXl*? zh4wPP5>kS}WF09+D#Tz3Im+?muV@ZT;6~tbFVKsh5A|s)@aAA3<%uA{=qyofm?QH0 zTSxv44(@!UAjhR2kEs((ws$JpK5!SF_X^%~txfCHj&@*0UmUYo%p@o*Ahnw{gB+ z4S7G-NPHjV6U1ux*>~)Ib#vI12D0pa3=4jxJuXJ&B7Q6P{xr1Cd1UPbNgUnPl0F

S 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 + + + + + + + + + image/svg+xml + + + + + + + + + + + + + 3V3Power + + + + GPIO2SDA I²C + + + + GPIO3SCL I²C + + + + GPIO4 + + + + Ground + + + + GPIO17 + + + + GPIO27 + + + + GPIO22 + + + + 3V3Power + + + + GPIO10SPI MOSI + + + + GPIO9SPI MISO + + + + GPIO11SPI SCLK + + + Ground + + + + ID SDI²C ID + + + + GPIO5 + + + + GPIO6 + + + + GPIO13 + + + + GPIO19 + + + + GPIO26 + + + + Ground + + + + 5VPower + + + + 5VPower + + + + Ground + + + + GPIO14UART0 TXD + + + + GPIO15UART0 RXD + + + + GPIO18 + + + + Ground + + + + GPIO23 + + + + GPIO24 + + + + Ground + + + + GPIO25 + + + + GPIO8SPI CE0 + + + + GPIO7SPI CE1 + + + + ID SCI²C ID + + + + Ground + + + + GPIO12 + + + + Ground + + + + GPIO16 + + + + GPIO20 + + + + GPIO21 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + All Models + A+,B+,2B + 1 + 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 + 17 + 19 + 21 + 23 + 25 + 27 + 29 + 31 + 33 + 35 + 37 + 39 + 2 + 4 + 6 + 8 + 10 + 12 + 14 + 16 + 18 + 20 + 22 + 24 + 26 + 28 + 30 + 32 + 34 + 36 + 38 + 40 + + diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index e58b11b..0000000 --- a/docs/index.md +++ /dev/null @@ -1,113 +0,0 @@ -# GPIO Zero - -A simple interface to everyday GPIO components used with Raspberry Pi. - -Created by [Ben Nuttall](https://github.com/bennuttall) of the [Raspberry Pi -Foundation](https://www.raspberrypi.org/), [Dave -Jones](https://github.com/waveform80), and other contributors. - -## Latest release - -The latest release is 1.0 released on 16th November 2015. - -## About - -Component interfaces are provided to allow a frictionless way to get started -with physical computing: - -```python -from gpiozero import LED -from time import sleep - -led = LED(2) - -while True: - led.on() - sleep(1) - led.off() - sleep(1) -``` - -With very little code, you can quickly get going connecting your components -together: - -```python -from gpiozero import LED, Button -from signal import pause - -led = LED(2) -button = Button(3) - -button.when_pressed = led.on -button.when_released = led.off - -pause() -``` - -The library includes interfaces to many simple everyday components, as well as -some more complex things like sensors, analogue-to-digital converters, full -colour LEDs, robotics kits and more. - -## Install - -First, update your repositories list: - -```python -sudo apt-get update -``` - -Then install the package of your choice. Both Python 3 and Python 2 are -supported. Python 3 is recommended! - -```python -sudo apt-get install python3-gpiozero -``` - -or: - -```python -sudo apt-get install python-gpiozero -``` - -### Upgrade - -Upgrade to the latest version with: - -```bash -sudo apt-get install python3-gpiozero -``` - -or: - -```bash -sudo apt-get install python-gpiozero -``` - -## Getting started - -See the [input devices](inputs.md) and [output devices](outputs.md) to get -started. Also see the [boards & accessories](boards.md) page for examples of -using the included accessories. - -For common programs using multiple components together, see the -[recipes](recipes.md) page. - -## Development - -This project is being developed on -[GitHub](https://github.com/RPi-Distro/python-gpiozero). Join in: - -* Provide suggestions, report bugs and ask questions as -[Issues](https://github.com/RPi-Distro/python-gpiozero/issues) -* Provide examples we can use as -[recipes](http://pythonhosted.org/gpiozero/recipes/) -* Contribute to the code - -Alternatively, email suggestions and feedback to ben@raspberrypi.org or add to -the [Google Doc](https://goo.gl/8zJLif). - -## Contributors - -- [Ben Nuttall](https://github.com/bennuttall) (project maintainer) -- [Dave Jones](https://github.com/waveform80) -- [Martin O'Hanlon](https://github.com/martinohanlon) diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..71ffc0a --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,16 @@ +.. include:: ../README.rst + +Table of Contents +================= + +.. toctree:: + :maxdepth: 2 + + recipes + notes + api_input + api_output + api_boards + api_generic + changelog + license diff --git a/docs/inputs.md b/docs/inputs.md deleted file mode 100644 index 7fc6015..0000000 --- a/docs/inputs.md +++ /dev/null @@ -1,244 +0,0 @@ -# Input Devices - -These input device component interfaces have been provided for simple use of -everyday components. - -Components must be wired up correctly before used in code. - -*Note all GPIO pin numbers use BCM numbering. See the [notes](notes.md) page -for more information.* - -## Button - -A physical push button or switch. - -### Wiring - -Connect one side of the button to a ground pin, and the other to any GPIO pin: - -![GPIO Button wiring](images/button.png) - -*Alternatively, connect to 3V3 and to a GPIO, and set `pull_up` to `False` when -you create your `Button` object.* - -### Code - -Ensure the `Button` class is imported at the top of the file: - -```python -from gpiozero import Button -``` - -Create a `Button` object by passing in the pin number the button is connected -to: - -```python -button = Button(2) -``` - -#### Initialisation options - -```python -Button(pin=None, pull_up=True, bounce_time=None) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `pin` | The GPIO pin number the button is connected to. | Integer | *Required* | -| `pull_up` | The pull state of the pin. `True` means pull up, `False` means pull down. | Boolean | `True` | -| `bounce_time` | Specifies the length of time (in seconds) that the component will ignore changes in state after an initial change. | Integer or Float | `None` | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `wait_for_press()` | Halt the program until the button is pressed. | `timeout` - The number of seconds to wait before proceeding if no event is detected. **Default: `None`** | -| `wait_for_release()` | Halt the program until the button is released. | `timeout` - The number of seconds to wait before proceeding if no event is detected. **Default: `None`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `pin` | The GPIO pin number the button is connected to. | Integer | -| `is_pressed` | The current state of the pin (`True` if pressed; otherwise `False`). | Boolean | -| `pull_up` | The pull state of the pin (`True` if pulled up; `False` if pulled down). | Boolean | -| `when_pressed` | A reference to the function to be called when the button is pressed. | `None` or Function | -| `when_released` | A reference to the function to be called when the button is released. | `None` or Function | -| `value` | The current value of the button. 0 if off; 1 if on. | Float | -| `values` | A generator continuously yielding the button's current value. | Generator | - -## Motion Sensor - -A PIR (Passive Infra-Red) motion sensor. - -### Wiring - -Connect the pin labelled `VCC` to a 5V pin; connect the one labelled `GND` to -a ground pin; and connect the one labelled `OUT` to any GPIO pin: - -![Motion Sensor wiring](images/motion-sensor.png) - -### Code - -Ensure the `MotionSensor` class is imported at the top of the file: - -```python -from gpiozero import MotionSensor -``` - -Create a `MotionSensor` object by passing in the pin number the sensor is -connected to: - -```python -pir = MotionSensor(4) -``` - -#### Initialisation options - -```python -MotionSensor(pin=None, queue_len=1, sample_rate=10, threshold=0.5, partial=False) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `pin` | The GPIO pin number the sensor is connected to. | Integer | *Required* | -| `queue_len` | ??? | Integer | `1` | -| `sample_rate` | ??? | Integer | `10` | -| `threshold` | Proportion of sensor values required to determine motion state. | Float: `0` to `1` | `0.5` | -| `partial` | ??? | Boolean | `False` | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `wait_for_motion()` | Halt the program until motion is detected. | `timeout` - The number of seconds to wait before proceeding if no motion is detected. **Default: `None`** | -| `wait_for_no_motion()` | Halt the program until no motion is detected. | `timeout` - The number of seconds to wait before proceeding if motion is still detected. **Default: `None`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `pin` | The GPIO pin number the sensor is connected to. | Integer | -| `motion_detected` | The current state of the sensor (`True` if motion is detected; otherwise `False`). | Boolean | -| `when_motion` | A reference to the function to be called when motion is detected. | `None` or Function | -| `when_no_motion` | A reference to the function to be called when no motion is detected. | `None` or Function | -| `value` | The current value of the sensor. 0 if still; 1 if motion. | Float | -| `values` | A generator continuously yielding the sensor's current value. | Generator | - -## Light Sensor - -An LDR (Light Dependent Resistor) Light Sensor. - -### Wiring - -... - -### Code - -Ensure the `LightSensor` class is imported at the top of the file: - -```python -from gpiozero import LightSensor -``` - -Create a `LightSensor` object by passing in the pin number the sensor is -connected to: - -```python -light = LightSensor(4) -``` - -#### Initialisation options - -```python -LightSensor(pin=None, queue_len=5, charge_time_limit=10, - threshold=0.1, partial=False) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `pin` | The GPIO pin number the sensor is connected to. | Integer | *Required* | -| `queue_len` | ??? | Integer | `5` | -| `charge_time_limit` | Maximum amount of time allowed to determine darkness. | Integer | `10` | -| `threshold` | Proportion of sensor values required to determine light level. | Float: `0` to `1` | `0.1` | -| `partial` | ??? | Boolean | `False` | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `wait_for_light()` | Halt the program until light is detected. | `timeout` - The number of seconds to wait before proceeding if light is not detected. **Default: `None`** | -| `wait_for_dark()` | Halt the program until darkness is detected. | `timeout` - The number of seconds to wait before proceeding if darkness is not detected. **Default: `None`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `pin` | The GPIO pin number the sensor is connected to. | Integer | -| `light_detected` | The current state of the sensor (`True` if light; otherwise `False`). | Boolean | -| `when_light` | A reference to the function to be called when light is detected. | `None` or Function | -| `when_dark` | A reference to the function to be called when darkness is detected. | `None` or Function | -| `value` | The current value of the sensor. 0 if dark; 1 if light. | Float | -| `values` | A generator continuously yielding the sensor's current value. | Generator | - -## MCP3008 Analogue-to-Digital Converter - -MCP3008 ADC (Analogue-to-Digital converter). - -The MCP3008 chip provides access to up to 8 analogue inputs, such as -potentiometers, and reads their values in digital form. - -### Wiring - -... - -### Code - -Ensure the `MCP3008` class is imported at the top of the file: - -```python -from gpiozero import MCP3008 -``` - -Create an `MCP3008` object: - -```python -pot = MCP3008() -``` - -Alternatively, access an input value with the `MCP3008`'s context manager: - -```python -with MCP3008() as pot: - # do something with pot -``` - -#### Initialisation options - -```python -MCP3008(channel=0, device=0) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `channel` | Which of the 8 ADC channels to access. | Integer: `0` to `7` | `0` | -| `device` | Which of the two Chip Select SPI pins to access. | Integer: `0` or `1` | `0` | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `channel` | The ADC channel the device is connected to. | Integer | -| `device` | The chip select pin the device is connected to. | Integer | -| `value` | The current value of the device. | Float | -| `values` | A generator continuously yielding the device's current value. | Generator | - -## MCP3004 Analogue-to-Digital Converter - -MCP3004 ADC (Analogue-to-Digital converter). - -The MCP3004 chip provides access to up to 4 analogue inputs, such as -potentiometers, and reads their values in digital form. - -The interface is identical to `MCP3008`, except that only channels `0` to `3` -are accessible. diff --git a/docs/license.rst b/docs/license.rst new file mode 100644 index 0000000..31ca3e0 --- /dev/null +++ b/docs/license.rst @@ -0,0 +1,34 @@ +.. _license: + +======= +License +======= + +Copyright 2015 `Raspberry Pi Foundation`_. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +.. _Raspberry Pi Foundation: http://raspberrypi.org/ diff --git a/docs/notes.md b/docs/notes.md deleted file mode 100644 index 0adfcc5..0000000 --- a/docs/notes.md +++ /dev/null @@ -1,282 +0,0 @@ -# Notes - -## BCM pin numbering - -This library uses Broadcom (BCM) pin numbering for the GPIO pins, as -opposed to BOARD. Unlike the `RPi.GPIO` library, this is not configurable. - -Any pin marked `GPIO` can be used for generic components. - -The BCM pin layout is as follows: - -| | | -|-----------:|:-----------| -| 3V3 | 5V | -| **GPIO2** | 5V | -| **GPIO3** | GND | -| **GPIO4** | **GPIO14** | -| GND | **GPIO15** | -| **GPIO17** | **GPIO18** | -| **GPIO27** | GND | -| **GPIO22** | **GPIO23** | -| 3V3 | **GPIO24** | -| **GPIO10** | GND | -| **GPIO9** | **GPIO25** | -| **GPIO11** | **GPIO8** | -| GND | **GPIO7** | -| DNC | DNC | -| **GPIO5** | GND | -| **GPIO6** | **GPIO12** | -| **GPIO13** | GND | -| **GPIO19** | **GPIO16** | -| **GPIO26** | **GPIO20** | -| GND | **GPIO21** | - -- *GND = Ground* -- *3V3 = 3.3 Volts* -- *5V = 5 Volts* -- *DNC = Do not connect (special use pins)* - -## Wiring - -All components must be wired up correctly before using with this library. - -## Keep your program alive with `signal.pause` - -The following program looks like it should turn an LED on: - -```python -from gpiozero import LED - -led = LED(2) -led.on() -``` - -And it does, if you're using the Python shell, IPython shell or IDLE shell, -but if you saved this program as a Python file and ran it, it would flash -on for a moment then the program would end and it would turn off. - -The following file includes an intentional `pause` to keep the program -alive: - -```python -from gpiozero import LED -from signal import pause - -led = LED(2) -led.on() -pause() -``` - -Now running the program will stay running, leaving the LED on, until it is -forced to quit. - -Similarly, when setting up callbacks on button presses or other input -devices, the program needs to be running for the events to be detected: - -```python -from gpiozero import Button -from signal import pause - -def hello(): - print("Hello") - -button = Button(2) -button.when_pressed = hello -pause() -``` - -## Importing from GPIO Zero - -In Python, libraries and functions used in a script must be imported by name at -the top of the file, with the exception of the functions built in to Python by -default. - -For example, to use the `Button` interface from the GPIO Zero library, it -should be explicitly imported: - -```python -from gpiozero import Button -``` - -Now `Button` is available directly in the script: - -```python -button = Button(2) -``` - -Alternatively, the whole GPIO Zero library can be imported: - -```python -import gpiozero -``` - -In this case, all references to interfaces within GPIO Zero must be prefixed: - -```python -button = gpiozero.Button(2) -``` - -## Programming terms - -The following terms are used in the documentation. - -### Class - -A class is the blueprint for a data type. A class defines the way an instance -of its own can behave, and has specific functionality relating to the kinds of -things a user would expect to be able to do with it. - -An example of a class in GPIO Zero is `Button`. Note class names are given with -each word capitalised. - -### Object - -An object is an instance of a class. Any variable in Python is an object of a -given type (e.g. Integer, String, Float), and comprises the functionality -defined by its class. - -To create an object, you must assign a variable name to an instance of a class: - -```python -my_button = Button(2) -``` - -Now the variable `my_button` is an instance of the class `Button`. Check its -type with Python's `type()` function: - -```python -print(type(my_button)) -``` - -which shows: - -``` -gpiozero.Button -``` - -### Initialisation options - -Most classes in GPIO Zero require some arguments to create an object, for -example the `LED` and `Button` examples require the pin number the device is -attached to: - -```python -my_button = Button(2) -``` - -Some classes have multiple arguments, usually with some being optional. When -arguments are optional, common default values are used. The following example: - -```python -my_button = Button(2) -``` - -is equivalent to: - -```python -my_button = Button(2, True) -``` - -because the second argument defaults to `True`. - -Arguments can be given unnamed, as long as they are in order: - -```python -my_button = Button(2, False) -``` - -though this may be confusing, so named is better in this case: - -```python -my_button = Button(pin=2, pull_up=False) -``` - -Alternatively, they can be given in any order, as long as they are named: - -```python -my_button = Button(pin=2, bounce_time=0.5, pull_up=False) -``` - -### Method - -A method is a function defined within a class. With an object of a given type, -you can call a method on that object. For example if `my_led` is a `LED` -object: - -```python -my_led.on() -``` - -will call the `LED` class's `on()` function, relating to that instance of -`LED`. If other `LED` objects have been created, they will not be affected by -this action. - -In many cases, no arguments are required to call the method (like -`my_led.on()`). In other cases, optional arguments are available. For example: - -```python -my_led.blink(2, 3) -``` - -Here, the arguments `2` and `3` have been passed in as arguments. The `blink` -method allows configuration of `on_time` and `off_time`. This example means the -LED will flash on for 2 seconds and stay off for 3. This example may benefit -from use of named arguments: - -```python -my_led.blink(on_time=2, off_time=3) -``` - -arguments can also be passed in by name, which means order is irrelevant. For -example: - -```python -my_led.blink(off_time=3) -``` - -Here, only the `off_time` argument has been provided, and all other arguments -will use their default values. Methods in GPIO Zero use sensible common default -values, but are configurable when necessary. - -### Property - -A property is an attribute relating to the state of an object. For example: - -```python -my_led.is_lit -``` - -This will return `True` or `False` depending on whether or not the LED is -currently lit. - -Some properties allow you to change their value. For example an `RGBLED` object: - -```python -rgb_led.green = 0.5 -``` - -or: - -```python -rgb_led.color = (0.2, 0.3, 0.7) -``` - -### Context manager - -A context manager is an alternative interface provided by classes which require -"closing" the object when it's finished with. The following example (using a -context manager): - -```python -with MCP3008() as pot: - print(pot.value) -``` - -is identical to: - -```python -pot = MCP3008() -print(pot.value) -pot.close() -``` diff --git a/docs/notes.rst b/docs/notes.rst new file mode 100644 index 0000000..5bae981 --- /dev/null +++ b/docs/notes.rst @@ -0,0 +1,72 @@ +===== +Notes +===== + +.. currentmodule:: gpiozero + +.. _keep-your-script-running: + +Keep your script running +======================== + +The following script looks like it should turn an LED on:: + + from gpiozero import led + + led = LED(2) + led.on() + +And it does, if you're using the Python (or IPython or IDLE) shell. However, +if you saved this script as a Python file and ran it, it would flash on +briefly, then the script would end and it would turn off. + +The following file includes an intentional :func:`~signal.pause` to keep the +script alive:: + + from gpiozero import led + from signal import pause + + led = LED(2) + led.on() + pause() + +Now the script will stay running, leaving the LED on, until it is terminated +manually (e.g. by pressing Ctrl+C). Similarly, when setting up callbacks on +button presses or other input devices, the script needs to be running for the +events to be detected:: + + + from gpiozero import Button + from signal import pause + + def hello(): + print("Hello") + + button = Button(2) + button.when_pressed = hello + pause() + +Importing from GPIO Zero +======================== + +In Python, libraries and functions used in a script must be imported by name +at the top of the file, with the exception of the functions built into Python +by default. + +For example, to use the :class:`Button` interface from GPIO Zero, it +should be explicitly imported:: + + from gpiozero import Button + +Now :class:`~gpiozero.Button` is available directly in your script:: + + button = Button(2) + +Alternatively, the whole GPIO Zero library can be imported:: + + import gpiozero + +In this case, all references to items within GPIO Zero must be prefixed:: + + button = gpiozero.Button(2) + diff --git a/docs/outputs.md b/docs/outputs.md deleted file mode 100644 index f7ee708..0000000 --- a/docs/outputs.md +++ /dev/null @@ -1,309 +0,0 @@ -# Output Devices - -These output device component interfaces have been provided for simple use of -everyday components. - -Components must be wired up correctly before used in code. - -*Note all GPIO pin numbers use BCM numbering. See the [notes](notes.md) page -for more information.* - -## LED - -An LED (Light emitting diode) component. - -### Wiring - -Connect the cathode (the short leg) of the LED to a ground pin, and connect the -anode (the longer leg) to any GPIO pin, with a current limiting resistor in -between: - -![LED wiring](images/led.png) - -*Altenatively, use a breadboard to wire up the LED in the same way* - -### Code - -Ensure the `LED` class is imported at the top of the file: - -```python -from gpiozero import LED -``` - -Create an `LED` object by passing in the pin number the LED is connected to: - -```python -led = LED(17) -``` - -#### Initialisation options - -```python -LED(pin=None, active_high=True) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `pin` | The GPIO pin number the LED is connected to. | Integer | *Required* | -| `active_high` | Whether high or low voltage turns the LED on. | Boolean | `True` | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn the LED on. | None | -| `off()` | Turn the LED off. | None | -| `toggle()` | Toggle the LED. If it's on, turn it off; if it's off, turn it on. | None | -| `blink()` | Make the LED turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. **Default: `1`** | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. **Default: `1`** | -| | | `n` - The number of iterations. `None` means infinite. **Default: `None`** | -| | | `background` - If `True`, start a background thread to continue blinking and return immediately. If `False`, only return when the blink is finished (warning: the default value of n will result in this method never returning). **Default: `True`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `pin` | The GPIO pin number the LED is connected to. | Integer | -| `is_lit` | The current state of the LED (`True` if on; `False` if off). | Boolean | -| `value` | The current state of the LED (`True` if on; `False` if off). | Boolean | -| `values` | A generator continuously yielding the LED's current value. | Generator | -| `source` | A generator which can be used to continuously set the LED's value. | `None` or Generator | - -## PWMLED - -An LED (Light emitting diode) component with the ability to set brightness. - -*Note this interface does not require a special LED component. Any regular LED -can be used in this way.* - -### Wiring - -A PWMLED is wired the same as a regular LED. - -### Code - -Ensure the `PWMLED` class is imported at the top of the file: - -```python -from gpiozero import PWMLED -``` - -Create an `LED` object by passing in the pin number the LED is connected to: - -```python -led = PWMLED(17) -``` - -#### Initialisation options - -```python -PWMLED(pin=None, active_high=True) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `pin` | The GPIO pin number the LED is connected to. | Integer | *Required* | -| `active_high` | Whether high or low voltage turns the LED on. | Boolean | `True` | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn the LED on. | None | -| `off()` | Turn the LED off. | None | -| `toggle()` | Toggle the LED. If it's on, turn it off; if it's off, turn it on. | None | -| `blink()` | Make the LED turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. **Default: `1`** | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. **Default: `1`** | -| | | `n` - The number of iterations. `None` means infinite. **Default: `None`** | -| | | `background` - If `True`, start a background thread to continue blinking and return immediately. If `False`, only return when the blink is finished (warning: the default value of n will result in this method never returning). **Default: `True`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `pin` | The GPIO pin number the LED is connected to. | Integer | -| `is_lit` | The current state of the LED (`True` if on; `False` if off). | Boolean | -| `value` | The current brightness of the LED `0` to `1`. | Float | -| `values` | A generator continuously yielding the LED's current value. | Generator | -| `source` | A generator which can be used to continuously set the LED's value. | `None` or Generator | - -## Buzzer - -A digital Buzzer component. - -### Wiring - -Connect the negative pin of the buzzer to a ground pin, and connect the -positive side to any GPIO pin: - -... - -### Code - -Ensure the `Buzzer` class is imported at the top of the file: - -```python -from gpiozero import Buzzer -``` - -Create a `Buzzer` object by passing in the pin number the buzzer is connected -to: - -```python -buzzer = Buzzer(3) -``` - -#### Initialisation options - -```python -Buzzer(pin=None, active_high=True) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `pin` | The GPIO pin number the buzzer is connected to. | Integer | *Required* | -| `active_high` | Whether high or low voltage turns the buzzer on. | Boolean | `True` | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn the buzzer on. | None | -| `off()` | Turn the buzzer off. | None | -| `toggle()` | Toggle the buzzer. If it's on, turn it off; if it's off, turn it on. | None | -| `beep()` | Make the buzzer turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the buzzer to be on each iteration. **Default: `1`** | -| | | `off_time` - The amount of time (in seconds) for the buzzer to be off each iteration. **Default: `1`** | -| | | `n` - The number of iterations. `None` means infinite. **Default: `None`** | -| | | `background` - If `True`, start a background thread to continue beeping and return immediately. If `False`, only return when the blink is finished (warning: the default value of n will result in this method never returning). **Default: `True`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `pin` | The GPIO pin number the buzzer is connected to. | Integer | -| `is_active` | The current state of the buzzer (`True` if on; `False` if off). | Boolean | -| `value` | The current state of the buzzer (`True` if on; `False` if off). | Boolean | -| `values` | A generator continuously yielding the buzzer's current value. | Generator | -| `source` | A generator which can be used to continuously set the buzzer's value. | `None` or Generator | - -## RGB LED - -A full colour LED component (made up of Red, Green and Blue LEDs). - -### Wiring - -Connect the common cathode (the longest leg) to a ground pin; connect each of -the other legs (representing the red, green and blue components of the LED) to -any GPIO pins, each with a current limiting resistor in between: - -... - -### Code - -Ensure the `RGBLED` class is imported at the top of the file: - -```python -from gpiozero import RGBLED -``` - -Create a `RGBLED` object by passing in the LED pin numbers by name: - -```python -led = RGBLED(red=2, green=3, blue=4) -``` - -or just in order (red, green, blue): - -```python -led = RGBLED(2, 3, 4) -``` - -#### Initialisation options - -```python -RGBLED(red=None, green=None, blue=None) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `red` | The GPIO pin number the red LED is connected to. | Integer | *Required* | -| `green` | The GPIO pin number the green LED is connected to. | Integer | *Required* | -| `blue` | The GPIO pin number the blue LED is connected to. | Integer | *Required* | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `on()` | Turn all the LEDs on (makes white light). | None | -| `off()` | Turn all the LEDs off. | None | -| `toggle()` | Toggle the LED. If it's on (at all), turn it off; if it's off, turn it on. | None | -| `blink()` | Make the LED turn on and off repeatedly. | `on_time` - The amount of time (in seconds) for the LED to be on each iteration. **Default: `1`** | -| | | `off_time` - The amount of time (in seconds) for the LED to be off each iteration. **Default: `1`** | -| | | `n` - The number of iterations. `None` means infinite. **Default: `None`** | -| | | `background` - If `True`, start a background thread to continue blinking and return immediately. If `False`, only return when the blink is finished (warning: the default value of n will result in this method never returning). **Default: `True`** | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `red` | The brightness value of the red LED (`0` to `1`). | Float | -| `green` | The brightness value of the green LED (`0` to `1`). | Float | -| `blue` | The brightness value of the blue LED (`0` to `1`). | Float | -| `color` | The brightness values of the three LEDs `(0, 0, 0)` to `(1, 1, 1)`. | Tuple | -| `value` | The brightness values of the three LEDs `(0, 0, 0)` to `(1, 1, 1)`. | Tuple | -| `values` | A generator continuously yielding the LED's current values. | Generator | -| `source` | A generator which can be used to continuously set the LED's values. | `None` or Generator | - -## Motor - -Generic bi-directional motor. - -### Wiring - -Attach a Motor Controller Board to your Pi, connect a battery pack to the Motor -Controller Board, and connect each side of the motor to any GPIO pin: - -... - -### Code - -Ensure the `Motor` class is imported at the top of the file: - -```python -from gpiozero import Motor -``` - -Create a `Motor` object by passing in the pin numbers the motor is connected to: - -```python -motor = Motor(forward=17, backward=18) -``` - -#### Initialisation options - -```python -Motor(forward=None, backward=None) -``` - -| Argument | Description | Values | Default | -| -------- | ----------- | ------ | ------- | -| `forward` | The GPIO pin number the forward gear of the motor is connected to. | Integer | *Required* | -| `backward` | The GPIO pin number the reverse gear of the motor is connected to. | Integer | *Required* | - -#### Methods - -| Method | Description | Arguments | -| ------ | ----------- | --------- | -| `forward()` | Drive the motor forwards. | `speed` - Speed at which to drive the motor, `0` to `1`. **Default: `1`** | -| `backward()` | Drive the motor backwards. | `speed` - Speed at which to drive the motor, `0` to `1`. **Default: `1`** | -| `stop()` | Stop the motor. | None | -| `reverse()` | Reverse direction of the motor. | None | - -#### Properties - -| Property | Description | Type | -| -------- | ----------- | ---- | -| `is_active` | The current state of the motor. `True` if moving, otherwise `False`. | Boolean | -| `value` | The current speed and direction of the motor. `-1.0` if full speed backward, `0.0` if still, `1.0` if full speed forward. | Float | -| `values` | A generator continuously yielding the motor's current value. | Generator | -| `source` | A generator which can be used to continuously set the motor's value. | `None` or Generator | diff --git a/docs/recipes.md b/docs/recipes.md deleted file mode 100644 index 49674f7..0000000 --- a/docs/recipes.md +++ /dev/null @@ -1,533 +0,0 @@ -# Recipes - -*Note that reaching the end of a Python file will terminate the process and -GPIOs may be reset. Keep your program alive with `signal.pause` - see the -[notes](notes.md) page for more information.* - -## LED - -Turn an LED on and off repeatedly: - -```python -from gpiozero import LED -from time import sleep - -red = LED(2) - -while True: - red.on() - sleep(1) - red.off() - sleep(1) -``` - -Alternatively: - -```python -from gpiozero import LED -from signal import pause - -red = LED(2) - -red.blink() - -pause() -``` - -## Button - -Check if a button is pressed: - -```python -from gpiozero import Button - -button = Button(4) - -while True: - if button.is_pressed: - print("Button is pressed") - else: - print("Button is not pressed") -``` - -Wait for a button to be pressed before continuing: - -```python -from gpiozero import Button - -button = Button(4) - -button.wait_for_press() -print("Button was pressed") -``` - -Run a function every time the button is pressed: - -```python -from gpiozero import Button -from signal import pause - -def say_hello(): - print("Hello!") - -button = Button(4) - -button.when_pressed = say_hello - -pause() -``` - -## Button controlled LED - -Turn on an LED when a button is pressed: - -```python -from gpiozero import LED, Button -from signal import pause - -led = LED(2) -button = Button(3) - -button.when_pressed = led.on -button.when_released = led.off - -pause() -``` - -## Traffic Lights - -A full traffic lights system. - -Using a Traffic Lights kit like Pi-Stop: - -```python -from gpiozero import TrafficLights -from time import sleep - -lights = TrafficLights(2, 3, 4) - -lights.green.on() - -while True: - sleep(10) - lights.green.off() - lights.amber.on() - sleep(1) - lights.amber.off() - lights.red.on() - sleep(10) - lights.amber.on() - sleep(1) - lights.green.on() - lights.amber.off() - lights.red.off() -``` - -Using components: - -```python -from gpiozero import LED -from time import sleep - -red = LED(2) -amber = LED(3) -green = LED(4) - -green.on() -amber.off() -red.off() - -while True: - sleep(10) - green.off() - amber.on() - sleep(1) - amber.off() - red.on() - sleep(10) - amber.on() - sleep(1) - green.on() - amber.off() - red.off() -``` - -## Push button stop motion - -Capture a picture with the camera module every time a button is pressed: - -```python -from gpiozero import Button -from picamera import PiCamera - -button = Button(17) - -with PiCamera() as camera: - camera.start_preview() - frame = 1 - while True: - button.wait_for_press() - camera.capture('/home/pi/frame%03d.jpg' % frame) - frame += 1 -``` - -See -[Push Button Stop -Motion](https://www.raspberrypi.org/learning/quick-reaction-game/) for a full -resource. - -## Reaction Game - -When you see the light come on, the first person to press their button wins! - -```python -from gpiozero import Button, LED -from time import sleep -import random - -led = LED(4) - -player_1 = Button(2) -player_2 = Button(3) - -time = random.uniform(5, 10) -sleep(time) -led.on() - -while True: - if player_1.is_pressed: - print("Player 1 wins!") - break - if player_2.is_pressed: - print("Player 2 wins!") - break - -led.off() -``` - -See -[Quick Reaction Game](https://www.raspberrypi.org/learning/quick-reaction-game/) -for a full resource. - -## GPIO Music Box - -Each button plays a different sound! - -```python -from gpiozero import Button -import pygame.mixer -from pygame.mixer import Sound -from signal import pause - -pygame.mixer.init() - -sound_pins = { - 2: Sound("samples/drum_tom_mid_hard.wav"), - 3: Sound("samples/drum_cymbal_open.wav"), -} - -buttons = [Button(pin) for pin in sound_pins] -for button in buttons: - sound = sound_pins[button.pin] - button.when_pressed = sound.play - -pause() -``` - -See [GPIO Music Box](https://www.raspberrypi.org/learning/gpio-music-box/) -for a full resource. - -## All on when pressed - -While the button is pressed down, the buzzer and all the lights come on. - -FishDish: - -```python -from gpiozero import FishDish -from signal import pause - -fish = FishDish() - -fish.button.when_pressed = fish.on -fish.button.when_released = fish.off - -pause() -``` - -Ryanteck Traffic HAT: - -```python -from gpiozero import TrafficHat -from signal import pause - -th = TrafficHat() - -th.button.when_pressed = th.on -th.button.when_released = th.off - -pause() -``` - -Using components: - -```python -from gpiozero import LED, Buzzer, Button -from signal import pause - -button = Button(2) -buzzer = Buzzer(3) -red = LED(4) -amber = LED(5) -green = LED(6) - -things = [red, amber, green, buzzer] - -def things_on(): - for thing in things: - thing.on() - -def things_off(): - for thing in things: - thing.off() - -button.when_pressed = things_on -button.when_released = things_off - -pause() -``` - -## RGB LED - -Making colours with an RGB LED: - -```python -from gpiozero import RGBLED -from time import sleep - -led = RGBLED(red=9, green=10, blue=11) - -led.red = 1 # full red -led.red = 0.5 # half red - -led.color = (0, 1, 0) # full green - -led.color = (1, 0, 1) # magenta -led.color = (1, 1, 0) # yellow -led.color = (0, 1, 1) # cyan -led.color = (1, 1, 1) # white - -led.color = (0, 0, 0) # off - -# slowly increase intensity of blue -for n in range(100): - led.blue = n/100 - sleep(0.1) -``` - -## Motion Sensor - -Light an LED when motion is detected: - -```python -from gpiozero import MotionSensor, LED -from signal import pause - -pir = MotionSensor(5) -led = LED(16) - -pir.when_motion = led.on -pir.when_no_motion = led.off - -pause() -``` - -## Light Sensor - -Wait for light and dark: - -```python -from gpiozero import LightSensor - -sensor = LightSensor(18) - -while True: - sensor.wait_for_light() - print("It's light! :)") - sensor.wait_for_dark() - print("It's dark :(") -``` - -Run a function when the light changes: - -```python -from gpiozero import LightSensor, LED -from signal import pause - -sensor = LightSensor(18) -led = LED(16) - -sensor.when_dark = led.on -sensor.when_light = led.off - -pause() -``` - -## Motors - -Spin a motor around forwards and backwards: - -```python -from gpiozero import Motor -from time import sleep - -motor = Motor(forward=4, back=14) - -while True: - motor.forward() - sleep(5) - motor.backward() - sleep(5) -``` - -## Robot - -Make a robot drive around in (roughly) a square: - -```python -from gpiozero import Robot -from time import sleep - -robot = Robot(left=(4, 14), right=(17, 18)) - -for i in range(4): - robot.forward() - sleep(10) - robot.right() - sleep(1) -``` - -## Button controlled Robot - -Use four GPIO buttons as forward/back/left/right controls for a robot: - -```python -from gpiozero import RyanteckRobot, Button -from signal import pause - -robot = RyanteckRobot() - -left = Button(26) -right = Button(16) -fw = Button(21) -bw = Button(20) - -fw.when_pressed = robot.forward -fw.when_released = robot.stop - -left.when_pressed = robot.left -left.when_released = robot.stop - -right.when_pressed = robot.right -right.when_released = robot.stop - -bw.when_pressed = robot.backward -bw.when_released = robot.stop - -pause() -``` - -## Keyboard controlled Robot - -Use up/down/left/right keys to control a robot: - -```python -from gpiozero import RyanteckRobot -from evdev import InputDevice, list_devices, ecodes - -robot = RyanteckRobot() - -devices = [InputDevice(device) for device in list_devices()] -keyboard = devices[0] # this may vary - -keypress_actions = { - ecodes.KEY_UP: robot.forward, - ecodes.KEY_DOWN: robot.backward, - ecodes.KEY_LEFT: robot.left, - ecodes.KEY_RIGHT: robot.right, -} - -for event in keyboard.read_loop(): - if event.type == ecodes.EV_KEY: - if event.value == 1: # key down - keypress_actions[event.code]() - if event.value == 0: # key up - robot.stop() -``` - -## Motion Sensor Robot - -Make a robot drive forward when it detects motion: - -```python -from gpiozero import Robot, MotionSensor -from signal import pause - -robot = Robot(left=(4, 14), right=(17, 18)) -pir = MotionSensor(5) - -pir.when_motion = robot.forward -pir.when_no_motion = robot.stop - -pause() -``` - -## Potentiometer - -Continually print the value of a potentiometer (values between 0 and 1): - -```python -from gpiozero import MCP3008 - -while True: - with MCP3008(channel=0) as pot: - print(pot.value) -``` - -## Full Colour LED controlled by 3 Potentiometers - -Wire up three potentiometers (for red, green and blue) and use each of their -values to make up the colour of the LED: - -```python -from gpiozero import RGBLED, MCP3008 - -led = RGBLED(red=2, green=3, blue=4) -red_pot = MCP3008(channel=0) -green_pot = MCP3008(channel=1) -blue_pot = MCP3008(channel=2) - -while True: - led.red = red_pot.value - led.green = green_pot.value - led.blue = blue_pot.value -``` - -Alternatively, the following example is identical and uses the `source` property -rather than a `while` loop: - -```python -from gpiozero import RGBLED, MCP3008 -from signal import pause - -led = RGBLED(red=2, green=3, blue=4) -red_pot = MCP3008(channel=0) -green_pot = MCP3008(channel=1) -blue_pot = MCP3008(channel=2) - -led.red.source = red_pot.values -led.green.source = green_pot.values -led.blue.source = blue_pot.values - -pause() -``` diff --git a/docs/recipes.rst b/docs/recipes.rst new file mode 100644 index 0000000..1229dab --- /dev/null +++ b/docs/recipes.rst @@ -0,0 +1,503 @@ +======= +Recipes +======= + +.. currentmodule:: gpiozero + +Pin Numbering +============= + +This library uses Broadcom (BCM) pin numbering for the GPIO pins, as opposed +to physical (BOARD) numbering. Unlike in the `RPi.GPIO`_ library, this is not +configurable. + +.. _RPi.GPIO: https://pypi.python.org/pypi/RPi.GPIO + +Any pin marked ``GPIO`` in the diagram below can be used for generic +components: + +.. image:: images/pin_layout.* + +LED +=== + +.. image:: images/led.* + +Turn an :class:`LED` on and off repeatedly:: + + from gpiozero import LED + from time import sleep + + red = LED(17) + + while True: + red.on() + sleep(1) + red.off() + sleep(1) + +Alternatively:: + + from gpiozero import LED + from signal import pause + + red = LED(17) + + red.blink() + pause() + +.. note:: + + Reaching the end of a Python script will terminate the process and GPIOs + may be reset. Keep your script alive with :func:`signal.pause`. See + :ref:`keep-your-script-running` for more information. + +Button +====== + +.. image:: images/button.* + +Check if a :class:`Button` is pressed:: + + from gpiozero import Button + + button = Button(2) + + while True: + if button.is_pressed: + print("Button is pressed") + else: + print("Button is not pressed") + +Wait for a button to be pressed before continuing:: + + from gpiozero import Button + + button = Button(2) + + button.wait_for_press() + print("Button was pressed") + +Run a function every time the button is pressed:: + + from gpiozero import Button + from signal import pause + + def say_hello(): + print("Hello!") + + button = Button(2) + + button.when_pressed = say_hello + pause() + +Button controlled LED +===================== + +Turn on an :class:`LED` when a :class:`Button` is pressed:: + + from gpiozero import LED, Button + from signal import pause + + led = LED(17) + button = Button(2) + + button.when_pressed = led.on + button.when_released = led.off + + pause() + +Traffic Lights +============== + +A full traffic lights system. + +Using a :class:`TrafficLights` kit like Pi-Stop:: + + from gpiozero import TrafficLights + from time import sleep + + lights = TrafficLights(2, 3, 4) + + lights.green.on() + + while True: + sleep(10) + lights.green.off() + lights.amber.on() + sleep(1) + lights.amber.off() + lights.red.on() + sleep(10) + lights.amber.on() + sleep(1) + lights.green.on() + lights.amber.off() + lights.red.off() + +Using :class:`LED` components:: + + from gpiozero import LED + from time import sleep + + red = LED(2) + amber = LED(3) + green = LED(4) + + green.on() + amber.off() + red.off() + + while True: + sleep(10) + green.off() + amber.on() + sleep(1) + amber.off() + red.on() + sleep(10) + amber.on() + sleep(1) + green.on() + amber.off() + red.off() + +Push button stop motion +======================= + +Capture a picture with the camera module every time a button is pressed:: + + from gpiozero import Button + from picamera import PiCamera + + button = Button(2) + + with PiCamera() as camera: + camera.start_preview() + frame = 1 + while True: + button.wait_for_press() + camera.capture('/home/pi/frame%03d.jpg' % frame) + frame += 1 + +See `Push Button Stop Motion`_ for a full resource. + +Reaction Game +============= + +When you see the light come on, the first person to press their button wins! + +:: + + from gpiozero import Button, LED + from time import sleep + import random + + led = LED(17) + + player_1 = Button(2) + player_2 = Button(3) + + time = random.uniform(5, 10) + sleep(time) + led.on() + + while True: + if player_1.is_pressed: + print("Player 1 wins!") + break + if player_2.is_pressed: + print("Player 2 wins!") + break + + led.off() + +See `Quick Reaction Game`_ for a full resource. + +GPIO Music Box +============== + +Each button plays a different sound! + +:: + + from gpiozero import Button + import pygame.mixer + from pygame.mixer import Sound + + pygame.mixer.init() + + def play(pin): + sound = sound_pins[pin] + print("playing note from pin %s" % pin) + sound.play() + + sound_pins = { + 2: Sound("samples/drum_tom_mid_hard.wav"), + 3: Sound("samples/drum_cymbal_open.wav"), + } + + buttons = [Button(pin) for pin in sound_pins] + for button in buttons: + sound = sound_pins[button.pin] + button.when_pressed = sound.play + +See `GPIO Music Box`_ for a full resource. + +All on when pressed +=================== + +While the button is pressed down, the buzzer and all the lights come on. + +:class:`FishDish`:: + + from gpiozero import FishDish + + fish = FishDish() + + fish.button.when_pressed = fish.on + fish.button.when_released = fish.off + +Ryanteck :class:`TrafficHat`:: + + from gpiozero import TrafficHat + + th = TrafficHat() + + th.button.when_pressed = th.on + th.button.when_released = th.off + +Using :class:`LED`, :class:`Buzzer`, and :class:`Button` components:: + + from gpiozero import LED, Buzzer, Button + + button = Button(2) + buzzer = Buzzer(3) + red = LED(4) + amber = LED(5) + green = LED(6) + + things = [red, amber, green, buzzer] + + def things_on(): + for thing in things: + thing.on() + + def things_off(): + for thing in things: + thing.off() + + button.when_pressed = things_on + button.when_released = things_off + +RGB LED +======= + +Making colours with an :class:`RGBLED`:: + + from gpiozero import RGBLED + from time import sleep + + led = RGBLED(red=9, green=10, blue=11) + + led.red = 1 # full red + led.red = 0.5 # half red + + led.color = (0, 1, 0) # full green + + led.color = (1, 0, 1) # magenta + led.color = (1, 1, 0) # yellow + led.color = (0, 1, 1) # cyan + led.color = (1, 1, 1) # white + + led.color = (0, 0, 0) # off + + # slowly increase intensity of blue + for n in range(100): + led.blue = n/100 + sleep(0.1) + +Motion sensor +============= + +.. image:: images/motion-sensor.* + +Light an :class:`LED` when a :class:`MotionSensor` detects motion:: + + from gpiozero import MotionSensor, LED + + pir = MotionSensor(4) + led = LED(16) + + pir.when_motion = led.on + pir.when_no_motion = led.off + +Light sensor +============ + +.. IMAGE TBD + +Have a :class:`LightSensor` detect light and dark:: + + from gpiozero import LightSensor + + sensor = LightSensor(18) + + while True: + sensor.wait_for_light() + print("It's light! :)") + sensor.wait_for_dark() + print("It's dark :(") + +Run a function when the light changes:: + + from gpiozero import LightSensor, LED + + sensor = LightSensor(18) + led = LED(16) + + sensor.when_dark = led.on + sensor.when_light = led.off + +Motors +====== + +.. IMAGE TBD + +Spin a :class:`Motor` around forwards and backwards:: + + from gpiozero import Motor + from time import sleep + + motor = Motor(forward=4, back=14) + + while True: + motor.forward() + sleep(5) + motor.backward() + sleep(5) + +Robot +===== + +.. IMAGE TBD + +Make a :class:`Robot` drive around in (roughly) a square:: + + from gpiozero import Robot + from time import sleep + + robot = Robot(left=(4, 14), right=(17, 18)) + + for i in range(4): + robot.forward() + sleep(10) + robot.right() + sleep(1) + +Button controlled robot +======================= + +Use four GPIO buttons as forward/back/left/right controls for a robot:: + + from gpiozero import RyanteckRobot, Button + from signal import pause + + robot = RyanteckRobot() + + left = Button(26) + right = Button(16) + fw = Button(21) + bw = Button(20) + + fw.when_pressed = robot.forward + fw.when_released = robot.stop + + left.when_pressed = robot.left + left.when_released = robot.stop + + right.when_pressed = robot.right + right.when_released = robot.stop + + bw.when_pressed = robot.backward + bw.when_released = robot.stop + + pause() + +Keyboard controlled robot +========================= + +Use up/down/left/right keys to control a robot:: + + from gpiozero import RyanteckRobot + from evdev import InputDevice, list_devices, ecodes + + robot = RyanteckRobot() + + devices = [InputDevice(device) for device in list_devices()] + keyboard = devices[0] # this may vary + + keypress_actions = { + ecodes.KEY_UP: robot.forward, + ecodes.KEY_DOWN: robot.backward, + ecodes.KEY_LEFT: robot.left, + ecodes.KEY_RIGHT: robot.right, + } + + for event in keyboard.read_loop(): + if event.type == ecodes.EV_KEY: + if event.value == 1: # key down + keypress_actions[event.code]() + if event.value == 0: # key up + robot.stop() + +Motion sensor robot +=================== + +Make a robot drive forward when it detects motion:: + + from gpiozero import Robot, MotionSensor + + robot = Robot(left=(4, 14), right=(17, 18)) + pir = MotionSensor(5) + + pir.when_motion = robot.forward + pir.when_no_motion = robot.stop + +Potentiometer +============= + +.. IMAGE TBD + +Continually print the value of a potentiometer (values between 0 and 1) +connected to a :class:`MCP3008` analog to digital converter:: + + from gpiozero import MCP3008 + + while True: + with MCP3008(channel=0) as pot: + print(pot.read()) + +Full color LED controlled by 3 potentiometers +============================================= + +Wire up three potentiometers (for red, green and blue) and use each of their +values to make up the colour of the LED:: + + from gpiozero import RGBLED, MCP3008 + + led = RGBLED(red=2, green=3, blue=4) + red_pot = MCP3008(channel=0) + green_pot = MCP3008(channel=1) + blue_pot = MCP3008(channel=2) + + while True: + led.red = red_pot.value + led.green = green_pot.value + led.blue = blue_pot.value + + +.. _Push Button Stop Motion: https://www.raspberrypi.org/learning/quick-reaction-game/ +.. _Quick Reaction Game: https://www.raspberrypi.org/learning/quick-reaction-game/ +.. _GPIO Music Box: https://www.raspberrypi.org/learning/gpio-music-box/ + diff --git a/gpiozero/__init__.py b/gpiozero/__init__.py index fbb8a33..a155055 100644 --- a/gpiozero/__init__.py +++ b/gpiozero/__init__.py @@ -13,9 +13,16 @@ from .exc import ( ) from .devices import ( GPIODevice, + CompositeDevice, + SourceMixin, + ValuesMixin, ) from .input_devices import ( InputDevice, + WaitableInputDevice, + DigitalInputDevice, + SmoothedInputDevice, + AnalogInputDevice, Button, LineSensor, MotionSensor, @@ -31,6 +38,7 @@ from .input_devices import ( ) from .output_devices import ( OutputDevice, + DigitalOutputDevice, PWMOutputDevice, PWMLED, LED, diff --git a/gpiozero/boards.py b/gpiozero/boards.py index a0975a3..3b1d986 100644 --- a/gpiozero/boards.py +++ b/gpiozero/boards.py @@ -20,7 +20,25 @@ from .devices import CompositeDevice, SourceMixin class LEDBoard(SourceMixin, CompositeDevice): """ - A Generic LED Board or collection of LEDs. + Extends :class:`CompositeDevice` and represents a generic LED board or + collection of LEDs. + + The following example turns on all the LEDs on a board containing 5 LEDs + attached to GPIO pins 2 through 6:: + + from gpiozero import LEDBoard + + leds = LEDBoard(2, 3, 4, 5, 6) + leds.on() + + :param int \*pins: + Specify the GPIO pins that the LEDs of the board are attached to. You + can designate as many pins as necessary. + + :param bool pwm: + If ``True``, construct :class:`PWMLED` instances for each pin. If + ``False`` (the default), construct regular :class:`LED` instances. This + parameter can only be specified as a keyword parameter. """ def __init__(self, *pins, **kwargs): super(LEDBoard, self).__init__() @@ -39,15 +57,16 @@ class LEDBoard(SourceMixin, CompositeDevice): @property def leds(self): """ - A tuple of all the `LED` objects contained by the instance. + A tuple of all the :class:`LED` or :class:`PWMLED` objects contained by + the instance. """ return self._leds @property def value(self): """ - A tuple containing a boolean value for each LED on the board. This - property can also be set to update the state of all LEDs on the board. + A tuple containing a value for each LED on the board. This property can + also be set to update the state of all LEDs on the board. """ return tuple(led.value for led in self._leds) @@ -82,19 +101,19 @@ class LEDBoard(SourceMixin, CompositeDevice): """ Make all the LEDs turn on and off repeatedly. - on_time: `1` - Number of seconds to be on + :param float on_time: + Number of seconds on - off_time: `1` - Number of seconds to be off + :param float off_time: + Number of seconds off - n: `None` - Number of times to blink; None means forever + :param int n: + Number of times to blink; ``None`` means forever - background: `True` - If `True`, start a background thread to continue blinking and - return immediately. If `False`, only return when the blink is - finished (warning: the default value of `n` will result in this + :param bool background: + If ``True``, start a background thread to continue blinking and + return immediately. If ``False``, only return when the blink is + finished (warning: the default value of *n* will result in this method never returning). """ # XXX This isn't going to work for background=False @@ -104,7 +123,22 @@ class LEDBoard(SourceMixin, CompositeDevice): class PiLiter(LEDBoard): """ - Ciseco Pi-LITEr: strip of 8 very bright LEDs. + Extends :class:`LEDBoard` for the Ciseco Pi-LITEr: a strip of 8 very bright + LEDs. + + The Pi-LITEr pins are fixed and therefore there's no need to specify them + when constructing this class. The following example turns on all the LEDs + of the Pi-LITEr:: + + from gpiozero import PiLiter + + lite = PiLiter() + lite.on() + + :param bool pwm: + If ``True``, construct :class:`PWMLED` instances for each pin. If + ``False`` (the default), construct regular :class:`LED` instances. This + parameter can only be specified as a keyword parameter. """ def __init__(self, pwm=False): super(PiLiter, self).__init__(4, 17, 27, 18, 22, 23, 24, 25, pwm=pwm) @@ -115,16 +149,30 @@ TrafficLightTuple = namedtuple('TrafficLightTuple', ('red', 'amber', 'green')) class TrafficLights(LEDBoard): """ - Generic Traffic Lights set. + Extends :class:`LEDBoard` for devices containing red, amber, and green + LEDs. - red: `None` - Red LED pin + The following example initializes a device connected to GPIO pins 2, 3, + and 4, then lights the amber LED attached to GPIO 3:: - amber: `None` - Amber LED pin + from gpiozero import TrafficLights - green: `None` - Green LED pin + traffic = TrafficLights(2, 3, 4) + traffic.amber.on() + + :param int red: + The GPIO pin that the red LED is attached to. + + :param int amber: + The GPIO pin that the amber LED is attached to. + + :param int green: + The GPIO pin that the green LED is attached to. + + :param bool pwm: + If ``True``, construct :class:`PWMLED` instances to represent each + LED. If ``False`` (the default), construct regular :class:`LED` + instances. """ def __init__(self, red=None, amber=None, green=None, pwm=False): if not all([red, amber, green]): @@ -135,6 +183,10 @@ class TrafficLights(LEDBoard): @property def value(self): + """ + A 3-tuple containing values for the red, amber, and green LEDs. This + property can also be set to alter the state of the LEDs. + """ return TrafficLightTuple(*super(TrafficLights, self).value) @value.setter @@ -145,29 +197,41 @@ class TrafficLights(LEDBoard): @property def red(self): """ - The `LED` object representing the red LED. + The :class:`LED` or :class:`PWMLED` object representing the red LED. """ return self.leds[0] @property def amber(self): """ - The `LED` object representing the red LED. + The :class:`LED` or :class:`PWMLED` object representing the red LED. """ return self.leds[1] @property def green(self): """ - The `LED` object representing the green LED. + The :class:`LED` or :class:`PWMLED` object representing the green LED. """ return self.leds[2] class PiTraffic(TrafficLights): """ - Low Voltage Labs PI-TRAFFIC: vertical traffic lights board on pins 9, 10 - and 11. + Extends :class:`TrafficLights` for the Low Voltage Labs PI-TRAFFIC: + vertical traffic lights board when attached to GPIO pins 9, 10, and 11. + + There's no need to specify the pins if the PI-TRAFFIC is connected to the + default pins (9, 10, 11). The following example turns on the amber LED on + the PI-TRAFFIC:: + + from gpiozero import PiTraffic + + traffic = PiTraffic() + traffic.amber.on() + + To use the PI-TRAFFIC board when attached to a non-standard set of pins, + simply use the parent class, :class:`TrafficLights`. """ def __init__(self): super(PiTraffic, self).__init__(9, 10, 11) @@ -179,7 +243,18 @@ TrafficLightsBuzzerTuple = namedtuple('TrafficLightsBuzzerTuple', ( class TrafficLightsBuzzer(SourceMixin, CompositeDevice): """ - A generic class for HATs with traffic lights, a button and a buzzer. + Extends :class:`CompositeDevice` and is a generic class for HATs with + traffic lights, a button and a buzzer. + + :param TrafficLights lights: + An instance of :class:`TrafficLights` representing the traffic lights + of the HAT. + + :param Buzzer buzzer: + An instance of :class:`Buzzer` representing the buzzer on the HAT. + + :param Button button: + An instance of :class:`Button` representing the button on the HAT. """ def __init__(self, lights, buzzer, button): super(TrafficLightsBuzzer, self).__init__() @@ -201,7 +276,7 @@ class TrafficLightsBuzzer(SourceMixin, CompositeDevice): def all(self): """ A tuple containing objects for all the items on the board (several - `LED` objects, a `Buzzer`, and a `Button`). + :class:`LED` objects, a :class:`Buzzer`, and a :class:`Button`). """ return self._all @@ -250,19 +325,19 @@ class TrafficLightsBuzzer(SourceMixin, CompositeDevice): """ Make all the board's components turn on and off repeatedly. - on_time: `1` - Number of seconds to be on + :param float on_time: + Number of seconds on - off_time: `1` - Number of seconds to be off + :param float off_time: + Number of seconds off - n: `None` - Number of times to blink; None means forever + :param int n: + Number of times to blink; ``None`` means forever - background: `True` - If `True`, start a background thread to continue blinking and - return immediately. If `False`, only return when the blink is - finished (warning: the default value of `n` will result in this + :param bool background: + If ``True``, start a background thread to continue blinking and + return immediately. If ``False``, only return when the blink is + finished (warning: the default value of *n* will result in this method never returning). """ # XXX This isn't going to work for background=False @@ -272,7 +347,23 @@ class TrafficLightsBuzzer(SourceMixin, CompositeDevice): class FishDish(TrafficLightsBuzzer): """ - Pi Supply FishDish: traffic light LEDs, a button and a buzzer. + Extends :class:`TrafficLightsBuzzer` for the Pi Supply FishDish: traffic + light LEDs, a button and a buzzer. + + The FishDish pins are fixed and therefore there's no need to specify them + when constructing this class. The following example waits for the button + to be pressed on the FishDish, then turns on all the LEDs:: + + from gpiozero import FishDish + + fish = FishDish() + fish.button.wait_for_press() + fish.lights.on() + + :param bool pwm: + If ``True``, construct :class:`PWMLED` instances to represent each + LED. If ``False`` (the default), construct regular :class:`LED` + instances. """ def __init__(self, pwm=False): super(FishDish, self).__init__( @@ -284,7 +375,23 @@ class FishDish(TrafficLightsBuzzer): class TrafficHat(TrafficLightsBuzzer): """ - Ryanteck Traffic HAT: traffic light LEDs, a button and a buzzer. + Extends :class:`TrafficLightsBuzzer` for the Ryanteck Traffic HAT: traffic + light LEDs, a button and a buzzer. + + The Traffic HAT pins are fixed and therefore there's no need to specify + them when constructing this class. The following example waits for the + button to be pressed on the Traffic HAT, then turns on all the LEDs:: + + from gpiozero import TrafficHat + + hat = TrafficHat() + hat.button.wait_for_press() + hat.lights.on() + + :param bool pwm: + If ``True``, construct :class:`PWMLED` instances to represent each + LED. If ``False`` (the default), construct regular :class:`LED` + instances. """ def __init__(self, pwm=False): super(TrafficHat, self).__init__( @@ -299,7 +406,26 @@ RobotTuple = namedtuple('RobotTuple', ('left', 'right')) class Robot(SourceMixin, CompositeDevice): """ - Generic dual-motor Robot. + Extends :class:`CompositeDevice` to represent a generic dual-motor robot. + + This class is constructed with two tuples representing the forward and + backward pins of the left and right controllers respectively. For example, + if the left motor's controller is connected to GPIOs 4 and 14, while the + right motor's controller is connected to GPIOs 17 and 18 then the following + example will turn the robot left:: + + from gpiozero import Robot + + robot = Robot(left=(4, 14), right=(17, 18)) + robot.left() + + :param tuple left: + A tuple of two GPIO pins representing the forward and backward inputs + of the left motor's controller. + + :param tuple right: + A tuple of two GPIO pins representing the forward and backward inputs + of the right motor's controller. """ def __init__(self, left=None, right=None): if not all([left, right]): @@ -349,8 +475,9 @@ class Robot(SourceMixin, CompositeDevice): """ Drive the robot forward by running both motors forward. - speed: `1` - Speed at which to drive the motors, 0 to 1. + :param float speed: + Speed at which to drive the motors, as a value between 0 (stopped) + and 1 (full speed). The default is 1. """ self._left.forward(speed) self._right.forward(speed) @@ -359,8 +486,9 @@ class Robot(SourceMixin, CompositeDevice): """ Drive the robot backward by running both motors backward. - speed: `1` - Speed at which to drive the motors, 0 to 1. + :param float speed: + Speed at which to drive the motors, as a value between 0 (stopped) + and 1 (full speed). The default is 1. """ self._left.backward(speed) self._right.backward(speed) @@ -370,8 +498,9 @@ class Robot(SourceMixin, CompositeDevice): Make the robot turn left by running the right motor forward and left motor backward. - speed: `1` - Speed at which to drive the motors, 0 to 1. + :param float speed: + Speed at which to drive the motors, as a value between 0 (stopped) + and 1 (full speed). The default is 1. """ self._right.forward(speed) self._left.backward(speed) @@ -381,8 +510,9 @@ class Robot(SourceMixin, CompositeDevice): Make the robot turn right by running the left motor forward and right motor backward. - speed: `1` - Speed at which to drive the motors, 0 to 1. + :param float speed: + Speed at which to drive the motors, as a value between 0 (stopped) + and 1 (full speed). The default is 1. """ self._left.forward(speed) self._right.backward(speed) @@ -407,7 +537,16 @@ class Robot(SourceMixin, CompositeDevice): class RyanteckRobot(Robot): """ - RTK MCB Robot. Generic robot controller with pre-configured pin numbers. + Extends :class:`Robot` for the Ryanteck MCB robot. + + The Ryanteck MCB pins are fixed and therefore there's no need to specify + them when constructing this class. The following example turns the robot + left:: + + from gpiozero import RyanteckRobot + + robot = RyanteckRobot() + robot.left() """ def __init__(self): super(RyanteckRobot, self).__init__(left=(17, 18), right=(22, 23)) diff --git a/gpiozero/devices.py b/gpiozero/devices.py index c6d98f3..47856b2 100644 --- a/gpiozero/devices.py +++ b/gpiozero/devices.py @@ -100,9 +100,9 @@ class GPIOBase(GPIOMeta(nstr('GPIOBase'), (), {})): @property def closed(self): """ - Returns `True` if the device is closed (see the `close` method). Once a - device is closed you can no longer use any other methods or properties - to control or query the device. + Returns ``True`` if the device is closed (see the :meth:`close` + method). Once a device is closed you can no longer use any other + methods or properties to control or query the device. """ return False @@ -182,12 +182,12 @@ class GPIODevice(ValuesMixin, GPIOBase): This is the class at the root of the gpiozero class hierarchy. It handles ensuring that two GPIO devices do not share the same pin, and provides - basic services applicable to all devices (specifically the `pin` property, - `is_active` property, and the `close` method). + basic services applicable to all devices (specifically the :attr:`pin` + property, :attr:`is_active` property, and the :attr:`close` method). - pin: `None` + :param int pin: The GPIO pin (in BCM numbering) that the device is connected to. If - this is `None` a `GPIODeviceError` will be raised. + this is ``None`` a :exc:`GPIODeviceError` will be raised. """ def __init__(self, pin=None): super(GPIODevice, self).__init__() @@ -248,8 +248,8 @@ class GPIODevice(ValuesMixin, GPIOBase): >>> led = LED(16) >>> led.blink() - GPIODevice descendents can also be used as context managers using the - `with` statement. For example: + :class:`GPIODevice` descendents can also be used as context managers + using the :keyword:`with` statement. For example: >>> from gpiozero import * >>> with Buzzer(16) as bz: @@ -276,14 +276,16 @@ class GPIODevice(ValuesMixin, GPIOBase): def pin(self): """ The pin (in BCM numbering) that the device is connected to. This will - be `None` if the device has been closed (see the `close` method). + be ``None`` if the device has been closed (see the :meth:`close` + method). """ return self._pin @property def value(self): """ - Returns `True` if the device is currently active and `False` otherwise. + Returns ``True`` if the device is currently active and ``False`` + otherwise. """ return self._read() diff --git a/gpiozero/input_devices.py b/gpiozero/input_devices.py index 412fbfe..7382a23 100644 --- a/gpiozero/input_devices.py +++ b/gpiozero/input_devices.py @@ -1,3 +1,5 @@ +# vim: set fileencoding=utf-8: + from __future__ import ( unicode_literals, print_function, @@ -22,19 +24,19 @@ class InputDevice(GPIODevice): """ Represents a generic GPIO input device. - This class extends `GPIODevice` to add facilities common to GPIO input - devices. The constructor adds the optional `pull_up` parameter to specify - how the pin should be pulled by the internal resistors. The `is_active` - property is adjusted accordingly so that `True` still means active - regardless of the `pull_up` setting. + This class extends :class:`GPIODevice` to add facilities common to GPIO + input devices. The constructor adds the optional *pull_up* parameter to + specify how the pin should be pulled by the internal resistors. The + :attr:`~GPIODevice.is_active` property is adjusted accordingly so that + ``True`` still means active regardless of the :attr:`pull_up` setting. - pin: `None` - The GPIO pin (in BCM numbering) that the device is connected to. If - this is `None` a GPIODeviceError will be raised. + :param int pin: + The GPIO pin (in Broadcom numbering) that the device is connected to. + If this is ``None`` a :exc:`GPIODeviceError` will be raised. - pull_up: `False` - If `True`, the pin will be pulled high with an internal resistor. If - `False` (the default), the pin will be pulled low. + :param bool pull_up: + If ``True``, the pin will be pulled high with an internal resistor. If + ``False`` (the default), the pin will be pulled low. """ def __init__(self, pin=None, pull_up=False): if pin in (2, 3) and not pull_up: @@ -74,8 +76,8 @@ class InputDevice(GPIODevice): @property def pull_up(self): """ - If `True`, the device uses a pull-up resistor to set the GPIO pin - "high" by default. Defaults to `False`. + If ``True``, the device uses a pull-up resistor to set the GPIO pin + "high" by default. Defaults to ``False``. """ return self._pull_up @@ -91,11 +93,11 @@ class WaitableInputDevice(InputDevice): """ Represents a generic input device with distinct waitable states. - This class extends `InputDevice` with methods for waiting on the device's - status (`wait_for_active` and `wait_for_inactive`), and properties that - hold functions to be called when the device changes state (`when_activated` - and `when_deactivated`). These are aliased appropriately in various - subclasses. + This class extends :class:`InputDevice` with methods for waiting on the + device's status (:meth:`wait_for_active` and :meth:`wait_for_inactive`), + and properties that hold functions to be called when the device changes + state (:meth:`when_activated` and :meth:`when_deactivated`). These are + aliased appropriately in various subclasses. Note that this class provides no means of actually firing its events; it's effectively an abstract base class. @@ -113,9 +115,9 @@ class WaitableInputDevice(InputDevice): Pause the script until the device is activated, or the timeout is reached. - timeout: `None` - Number of seconds to wait before proceeding. If this is `None` (the - default), then wait indefinitely until the device is active. + :param float timeout: + Number of seconds to wait before proceeding. If this is ``None`` + (the default), then wait indefinitely until the device is active. """ return self._active_event.wait(timeout) @@ -124,9 +126,9 @@ class WaitableInputDevice(InputDevice): Pause the script until the device is deactivated, or the timeout is reached. - timeout: `None` - Number of seconds to wait before proceeding. If this is `None` (the - default), then wait indefinitely until the device is inactive. + :param float timeout: + Number of seconds to wait before proceeding. If this is ``None`` + (the default), then wait indefinitely until the device is inactive. """ return self._inactive_event.wait(timeout) @@ -142,9 +144,7 @@ class WaitableInputDevice(InputDevice): single mandatory parameter, the device that activated will be passed as that parameter. - Set this property to `None` (the default) to disable the event. - - See also: when_deactivated. + Set this property to ``None`` (the default) to disable the event. """ return self._when_activated @@ -164,9 +164,7 @@ class WaitableInputDevice(InputDevice): single mandatory parameter, the device that deactivated will be passed as that parameter. - Set this property to `None` (the default) to disable the event. - - See also: when_activated. + Set this property to ``None`` (the default) to disable the event. """ return self._when_deactivated @@ -234,15 +232,15 @@ class DigitalInputDevice(WaitableInputDevice): """ Represents a generic input device with typical on/off behaviour. - This class extends `WaitableInputDevice` with machinery to fire the active - and inactive events for devices that operate in a typical digital manner: - straight forward on / off states with (reasonably) clean transitions - between the two. + This class extends :class:`WaitableInputDevice` with machinery to fire the + active and inactive events for devices that operate in a typical digital + manner: straight forward on / off states with (reasonably) clean + transitions between the two. - bounce_time: `None` + :param float bouncetime: Specifies the length of time (in seconds) that the component will ignore changes in state after an initial change. This defaults to - `None` which indicates that no bounce compensation will be performed. + ``None`` which indicates that no bounce compensation will be performed. """ def __init__(self, pin=None, pull_up=False, bounce_time=None): super(DigitalInputDevice, self).__init__(pin, pull_up) @@ -267,32 +265,33 @@ class SmoothedInputDevice(WaitableInputDevice): Represents a generic input device which takes its value from the mean of a queue of historical values. - This class extends `WaitableInputDevice` with a queue which is filled by a - background thread which continually polls the state of the underlying - device. The mean of the values in the queue is compared to a threshold - which is used to determine the state of the `is_active` property. + This class extends :class:`WaitableInputDevice` with a queue which is + filled by a background thread which continually polls the state of the + underlying device. The mean of the values in the queue is compared to a + threshold which is used to determine the state of the :attr:`is_active` + property. This class is intended for use with devices which either exhibit analog behaviour (such as the charging time of a capacitor with an LDR), or those which exhibit "twitchy" behaviour (such as certain motion sensors). - threshold: `0.5` + :param float threshold: The value above which the device will be considered "on". - queue_len: `5` + :param int queue_len: The length of the internal queue which is filled by the background thread. - sample_wait: `0.0` + :param float sample_wait: The length of time to wait between retrieving the state of the underlying device. Defaults to 0.0 indicating that values are retrieved as fast as possible. - partial: `False` - If `False` (the default), attempts to read the state of the device - (from the `is_active` property) will block until the queue has filled. - If `True`, a value will be returned immediately, but be aware that this - value is likely to fluctuate excessively. + :param bool partial: + If ``False`` (the default), attempts to read the state of the device + (from the :attr:`is_active` property) will block until the queue has + filled. If ``True``, a value will be returned immediately, but be + aware that this value is likely to fluctuate excessively. """ def __init__( self, pin=None, pull_up=False, threshold=0.5, @@ -338,7 +337,7 @@ class SmoothedInputDevice(WaitableInputDevice): def queue_len(self): """ The length of the internal queue of values which is averaged to - determine the overall state of the device. This defaults to `5`. + determine the overall state of the device. This defaults to 5. """ self._check_open() return self._queue.queue.maxlen @@ -346,8 +345,8 @@ class SmoothedInputDevice(WaitableInputDevice): @property def partial(self): """ - If `False` (the default), attempts to read the `value` or `is_active` - properties will block until the queue has filled. + If ``False`` (the default), attempts to read the :attr:`value` or + :attr:`is_active` properties will block until the queue has filled. """ self._check_open() return self._queue.partial @@ -355,8 +354,9 @@ class SmoothedInputDevice(WaitableInputDevice): @property def value(self): """ - Returns the mean of the values in the internal queue. This is - compared to `threshold` to determine whether `is_active` is `True`. + Returns the mean of the values in the internal queue. This is compared + to :attr:`threshold` to determine whether :attr:`is_active` is + ``True``. """ self._check_open() return self._queue.value @@ -364,7 +364,8 @@ class SmoothedInputDevice(WaitableInputDevice): @property def threshold(self): """ - If `value` exceeds this amount, then `is_active` will return `True`. + If :attr:`value` exceeds this amount, then :attr:`is_active` will + return ``True``. """ return self._threshold @@ -379,18 +380,44 @@ class SmoothedInputDevice(WaitableInputDevice): @property def is_active(self): """ - Returns `True` if the device is currently active and `False` otherwise. + Returns ``True`` if the device is currently active and ``False`` + otherwise. """ return self.value > self.threshold class Button(DigitalInputDevice): """ - A physical push button or switch. + Extends :class:`DigitalInputDevice` and represents a simple push button + or switch. - A typical configuration of such a device is to connect a GPIO pin to one - side of the switch, and ground to the other (the default `pull_up` value - is `True`). + Connect one side of the button to a ground pin, and the other to any GPIO + pin. Alternatively, connect one side of the button to the 3V3 pin, and the + other to any GPIO pin, then set *pull_up* to ``False`` in the + :class:`Button` constructor. + + The following example will print a line of text when the button is pushed:: + + from gpiozero import Button + + button = Button(4) + button.wait_for_press() + print("The button was pressed!") + + :param int pin: + The GPIO pin which the button is attached to. See :doc:`notes` for + valid pin numbers. + + :param bool pull_up: + If ``True`` (the default), the GPIO pin will be pulled high by default. + In this case, connect the other side of the button to ground. If + ``False``, the GPIO pin will be pulled low by default. In this case, + connect the other side of the button to 3V3. + + :param float bounce_time: + If ``None`` (the default), no software bounce compensation will be + performed. Otherwise, this is the length in time (in seconds) that the + component will ignore changes in state after an initial change. """ def __init__(self, pin=None, pull_up=True, bounce_time=None): super(Button, self).__init__(pin, pull_up, bounce_time) @@ -418,17 +445,48 @@ LineSensor.wait_for_no_line = LineSensor.wait_for_inactive class MotionSensor(SmoothedInputDevice): """ - A PIR (Passive Infra-Red) motion sensor. + Extends :class:`SmoothedInputDevice` and represents a passive infra-red + (PIR) motion sensor like the sort found in the `CamJam #2 EduKit`_. + + .. _CamJam #2 EduKit: http://camjam.me/?page_id=623 A typical PIR device has a small circuit board with three pins: VCC, OUT, - and GND. VCC should be connected to the Pi's +5V pin, GND to one of the - Pi's ground pins, and finally OUT to the GPIO specified as the value of the - `pin` parameter in the constructor. + and GND. VCC should be connected to a 5V pin, GND to one of the ground + pins, and finally OUT to the GPIO specified as the value of the *pin* + parameter in the constructor. - This class defaults `queue_len` to 1, effectively removing the averaging - of the internal queue. If your PIR sensor has a short fall time and is - particularly "jittery" you may wish to set this to a higher value (e.g. 5) - to mitigate this. + The following code will print a line of text when motion is detected:: + + from gpiozero import MotionSensor + + pir = MotionSensor(4) + pir.wait_for_motion() + print("Motion detected!") + + :param int pin: + The GPIO pin which the button is attached to. See :doc:`notes` for + valid pin numbers. + + :param int queue_len: + The length of the queue used to store values read from the sensor. This + defaults to 1 which effectively disables the queue. If your motion + sensor is particularly "twitchy" you may wish to increase this value. + + :param float sample_rate: + The number of values to read from the device (and append to the + internal queue) per second. Defaults to 10. + + :param float threshold: + Defaults to 0.5. When the mean of all values in the internal queue + rises above this value, the sensor will be considered "active" by the + :attr:`~SmoothedInputDevice.is_active` property, and all appropriate + events will be fired. + + :param bool partial: + When ``False`` (the default), the object will not return a value for + :attr:`~SmoothedInputDevice.is_active` until the internal queue has + filled with values. Only set this to ``True`` if you require values + immediately after object construction. """ def __init__( self, pin=None, queue_len=1, sample_rate=10, threshold=0.5, @@ -452,12 +510,50 @@ MotionSensor.wait_for_no_motion = MotionSensor.wait_for_inactive class LightSensor(SmoothedInputDevice): """ - An LDR (Light Dependent Resistor) Light Sensor. + Extends :class:`SmoothedInputDevice` and represents a light dependent + resistor (LDR). - A typical LDR circuit connects one side of the LDR to the 3v3 line from the - Pi, and the other side to a GPIO pin, and a capacitor tied to ground. This - class repeatedly discharges the capacitor, then times the duration it takes - to charge (which will vary according to the light falling on the LDR). + Connect one leg of the LDR to the 3V3 pin; connect one leg of a 1µf + capacitor to a ground pin; connect the other leg of the LDR and the other + leg of the capacitor to the same GPIO pin. This class repeatedly discharges + the capacitor, then times the duration it takes to charge (which will vary + according to the light falling on the LDR). + + The following code will print a line of text when light is detected:: + + from gpiozero import LightSensor + + ldr = LightSensor(18) + ldr.wait_for_light() + print("Light detected!") + + :param int pin: + The GPIO pin which the button is attached to. See :doc:`notes` for + valid pin numbers. + + :param int queue_len: + The length of the queue used to store values read from the circuit. + This defaults to 5. + + :param float charge_time_limit: + If the capacitor in the circuit takes longer than this length of time + to charge, it is assumed to be dark. The default (0.01 seconds) is + appropriate for a 0.01µf capacitor coupled with the LDR from the + `CamJam #2 EduKit`_. You may need to adjust this value for different + valued capacitors or LDRs. + + :param float threshold: + Defaults to 0.1. When the mean of all values in the internal queue + rises above this value, the area will be considered "light", and all + appropriate events will be fired. + + :param bool partial: + When ``False`` (the default), the object will not return a value for + :attr:`~SmoothedInputDevice.is_active` until the internal queue has + filled with values. Only set this to ``True`` if you require values + immediately after object construction. + + .. _CamJam #2 EduKit: http://camjam.me/?page_id=623 """ def __init__( self, pin=None, queue_len=5, charge_time_limit=0.01, @@ -506,6 +602,31 @@ LightSensor.wait_for_dark = LightSensor.wait_for_inactive class AnalogInputDevice(CompositeDevice): """ Represents an analog input device connected to SPI (serial interface). + + Typical analog input devices are `analog to digital converters`_ (ADCs). + Several classes are provided for specific ADC chips, including + :class:`MCP3004`, :class:`MCP3008`, :class:`MCP3204`, and :class:`MCP3208`. + + The following code demonstrates reading the first channel of an MCP3008 + chip attached to the Pi's SPI pins:: + + from gpiozero import MCP3008 + + pot = MCP3008(0) + print(pot.value) + + The :attr:`value` attribute is normalized such that its value is always + between 0.0 and 1.0 (or in special cases, such as differential sampling, + -1 to +1). Hence, you can use an analog input to control the brightness of + a :class:`PWMLED` like so:: + + from gpiozero import MCP3008, PWMLED + + pot = MCP3008(0) + led = PWMLED(17) + led.source = pot.values + + .. _analog to digital converters: https://en.wikipedia.org/wiki/Analog-to-digital_converter """ def __init__(self, device=0, bits=None): @@ -572,6 +693,11 @@ class AnalogInputDevice(CompositeDevice): class MCP3xxx(AnalogInputDevice): + """ + Extends :class:`AnalogInputDevice` to implement an interface for all ADC + chips with a protocol similar to the Microchip MCP3xxx series of devices. + """ + def __init__(self, channel=0, device=0, bits=10, differential=False): self._channel = channel self._bits = bits @@ -583,20 +709,22 @@ class MCP3xxx(AnalogInputDevice): """ The channel to read data from. The MCP3008/3208/3304 have 8 channels (0-7), while the MCP3004/3204/3302 have 4 channels (0-3), and the - MCP3301 only has 2 channels. + MCP3301 only has 1 channel. """ return self._channel @property def differential(self): """ - If True, the device is operated in pseudo-differential mode. In this - mode one channel (specified by the channel attribute) is read relative - to the value of a second channel (implied by the chip's design). + If ``True``, the device is operated in pseudo-differential mode. In + this mode one channel (specified by the channel attribute) is read + relative to the value of a second channel (implied by the chip's + design). Please refer to the device data-sheet to determine which channel is - used as the relative base value (for example, when using an MCP3008 - in differential mode, channel 0 is read relative to channel 1). + used as the relative base value (for example, when using an + :class:`MCP3008` in differential mode, channel 0 is read relative to + channel 1). """ return self._differential @@ -625,6 +753,12 @@ class MCP3xxx(AnalogInputDevice): class MCP33xx(MCP3xxx): + """ + Extends :class:`MCP3xxx` with functionality specific to the MCP33xx family + of ADCs; specifically this handles the full differential capability of + these chips supporting the full 13-bit signed range of output values. + """ + def __init__(self, channel=0, device=0, differential=False): super(MCP33xx, self).__init__(channel, device, 12, differential) @@ -669,7 +803,10 @@ class MCP33xx(MCP3xxx): class MCP3004(MCP3xxx): """ - The MCP3004 is a 10-bit analog to digital converter with 4 channels (0-3). + The `MCP3004`_ is a 10-bit analog to digital converter with 4 channels + (0-3). + + .. _MCP3004: http://www.farnell.com/datasheets/808965.pdf """ def __init__(self, channel=0, device=0, differential=False): if not 0 <= channel < 4: @@ -679,7 +816,10 @@ class MCP3004(MCP3xxx): class MCP3008(MCP3xxx): """ - The MCP3008 is a 10-bit analog to digital converter with 8 channels (0-7). + The `MCP3008`_ is a 10-bit analog to digital converter with 8 channels + (0-7). + + .. _MCP3008: http://www.farnell.com/datasheets/808965.pdf """ def __init__(self, channel=0, device=0, differential=False): if not 0 <= channel < 8: @@ -689,7 +829,10 @@ class MCP3008(MCP3xxx): class MCP3204(MCP3xxx): """ - The MCP3204 is a 12-bit analog to digital converter with 4 channels (0-3). + The `MCP3204`_ is a 12-bit analog to digital converter with 4 channels + (0-3). + + .. _MCP3204: http://www.farnell.com/datasheets/808967.pdf """ def __init__(self, channel=0, device=0, differential=False): if not 0 <= channel < 4: @@ -699,7 +842,10 @@ class MCP3204(MCP3xxx): class MCP3208(MCP3xxx): """ - The MCP3208 is a 12-bit analog to digital converter with 8 channels (0-7). + The `MCP3208`_ is a 12-bit analog to digital converter with 8 channels + (0-7). + + .. _MCP3208: http://www.farnell.com/datasheets/808967.pdf """ def __init__(self, channel=0, device=0, differential=False): if not 0 <= channel < 8: @@ -709,9 +855,11 @@ class MCP3208(MCP3xxx): class MCP3301(MCP33xx): """ - The MCP3301 is a signed 13-bit analog to digital converter. Please note + The `MCP3301`_ is a signed 13-bit analog to digital converter. Please note that the MCP3301 always operates in differential mode between its two channels and the output value is scaled from -1 to +1. + + .. _MCP3301: http://www.farnell.com/datasheets/1669397.pdf """ def __init__(self, device=0): super(MCP3301, self).__init__(0, device, differential=True) @@ -722,11 +870,13 @@ class MCP3301(MCP33xx): class MCP3302(MCP33xx): """ - The MCP3302 is a 12/13-bit analog to digital converter with 4 channels + The `MCP3302`_ is a 12/13-bit analog to digital converter with 4 channels (0-3). When operated in differential mode, the device outputs a signed 13-bit value which is scaled from -1 to +1. When operated in single-ended mode (the default), the device outputs an unsigned 12-bit value scaled from 0 to 1. + + .. _MCP3302: http://www.farnell.com/datasheets/1486116.pdf """ def __init__(self, channel=0, device=0, differential=False): if not 0 <= channel < 4: @@ -736,11 +886,13 @@ class MCP3302(MCP33xx): class MCP3304(MCP33xx): """ - The MCP3304 is a 12/13-bit analog to digital converter with 8 channels + The `MCP3304`_ is a 12/13-bit analog to digital converter with 8 channels (0-7). When operated in differential mode, the device outputs a signed 13-bit value which is scaled from -1 to +1. When operated in single-ended mode (the default), the device outputs an unsigned 12-bit value scaled from 0 to 1. + + .. _MCP3304: http://www.farnell.com/datasheets/1486116.pdf """ def __init__(self, channel=0, device=0, differential=False): if not 0 <= channel < 8: diff --git a/gpiozero/output_devices.py b/gpiozero/output_devices.py index 2b58933..6e5590c 100644 --- a/gpiozero/output_devices.py +++ b/gpiozero/output_devices.py @@ -20,14 +20,18 @@ class OutputDevice(SourceMixin, GPIODevice): """ Represents a generic GPIO output device. - This class extends `GPIODevice` to add facilities common to GPIO output - devices: an `on` method to switch the device on, and a corresponding `off` - method. + This class extends :class:`GPIODevice` to add facilities common to GPIO + output devices: an :meth:`on` method to switch the device on, and a + corresponding :meth:`off` method. - active_high: `True` - If `True` (the default), the `on` method will set the GPIO to HIGH. If - `False`, the `on` method will set the GPIO to LOW (the `off` method - always does the opposite). + :param int pin: + The GPIO pin (in BCM numbering) that the device is connected to. If + this is ``None`` a :exc:`GPIODeviceError` will be raised. + + :param bool active_high: + If ``True`` (the default), the :meth:`on` method will set the GPIO to + HIGH. If ``False``, the :meth:`on` method will set the GPIO to LOW (the + :meth:`off` method always does the opposite). """ def __init__(self, pin=None, active_high=True): self._active_high = active_high @@ -94,10 +98,10 @@ class DigitalOutputDevice(OutputDevice): """ Represents a generic output device with typical on/off behaviour. - This class extends `OutputDevice` with a `toggle` method to switch the - device between its on and off states, and a `blink` method which uses an - optional background thread to handle toggling the device state without - further interaction. + This class extends :class:`OutputDevice` with a :meth:`toggle` method to + switch the device between its on and off states, and a :meth:`blink` method + which uses an optional background thread to handle toggling the device + state without further interaction. """ def __init__(self, pin=None, active_high=True): self._blink_thread = None @@ -109,16 +113,10 @@ class DigitalOutputDevice(OutputDevice): super(DigitalOutputDevice, self).close() def on(self): - """ - Turns the device on. - """ self._stop_blink() self._write(self._active_state) def off(self): - """ - Turns the device off. - """ self._stop_blink() self._write(self._inactive_state) @@ -137,19 +135,19 @@ class DigitalOutputDevice(OutputDevice): """ Make the device turn on and off repeatedly. - on_time: `1` + :param float on_time: Number of seconds on - off_time: `1` + :param float off_time: Number of seconds off - n: `None` - Number of times to blink; `None` means forever + :param int n: + Number of times to blink; ``None`` means forever - background: `True` - If `True`, start a background thread to continue blinking and - return immediately. If `False`, only return when the blink is - finished (warning: the default value of n will result in this + :param bool background: + If ``True``, start a background thread to continue blinking and + return immediately. If ``False``, only return when the blink is + finished (warning: the default value of *n* will result in this method never returning). """ self._stop_blink() @@ -179,11 +177,28 @@ class DigitalOutputDevice(OutputDevice): class LED(DigitalOutputDevice): """ - An LED (Light Emmitting Diode) component. + Extends :class:`DigitalOutputDevice` and represents a light emitting diode + (LED). - A typical configuration of such a device is to connect a GPIO pin to the - anode (long leg) of the LED, and the cathode (short leg) to ground, with - an optional resistor to prevent the LED from burning out. + Connect the cathode (short leg, flat side) of the LED to a ground pin; + connect the anode (longer leg) to a limiting resistor; connect the other + side of the limiting resistor to a GPIO pin (the limiting resistor can be + placed either side of the LED). + + The following example will light the LED:: + + from gpiozero import LED + + led = LED(17) + led.on() + + :param int pin: + The GPIO pin which the button is attached to. See :doc:`notes` for + valid pin numbers. + + :param bool active_high: + If ``True`` (the default), then the LED will be lit when the GPIO port + is high. """ pass @@ -192,10 +207,26 @@ LED.is_lit = LED.is_active class Buzzer(DigitalOutputDevice): """ - A digital Buzzer component. + Extends :class:`DigitalOutputDevice` and represents a digital buzzer + component. - A typical configuration of such a device is to connect a GPIO pin to the - anode (long leg) of the buzzer, and the cathode (short leg) to ground. + Connect the cathode (negative pin) of the buzzer to a ground pin; connect + the other side to any GPIO pin. + + The following example will sound the buzzer:: + + from gpiozero import Buzzer + + bz = Buzzer(3) + bz.on() + + :param int pin: + The GPIO pin which the buzzer is attached to. See :doc:`notes` for + valid pin numbers. + + :param bool active_high: + If ``True`` (the default), then the buzzer will sound when the GPIO + port is high. """ pass @@ -204,7 +235,15 @@ Buzzer.beep = Buzzer.blink class PWMOutputDevice(DigitalOutputDevice): """ - Generic Output device configured for PWM (Pulse-Width Modulation). + Generic output device configured for pulse-width modulation (PWM). + + :param int pin: + The GPIO pin which the device is attached to. See :doc:`notes` for + valid pin numbers. + + :param int frequency: + The frequency (in Hz) of pulses emitted to drive the device. Defaults + to 100Hz. """ def __init__(self, pin=None, frequency=100): self._pwm = None @@ -259,16 +298,17 @@ class PWMOutputDevice(DigitalOutputDevice): def toggle(self): """ Toggle the state of the device. If the device is currently off - (`value` is 0.0), this changes it to "fully" on (`value` is 1.0). If - the device has a duty cycle (`value`) of 0.1, this will toggle it to - 0.9, and so on. + (:attr:`value` is 0.0), this changes it to "fully" on (:attr:`value` is + 1.0). If the device has a duty cycle (:attr:`value`) of 0.1, this will + toggle it to 0.9, and so on. """ self.value = 1.0 - self.value @property def is_active(self): """ - Returns `True` if the device is currently active and `False` otherwise. + Returns ``True`` if the device is currently active (:attr:`value` is + non-zero) and ``False`` otherwise. """ return self.value > 0.0 @@ -276,7 +316,7 @@ class PWMOutputDevice(DigitalOutputDevice): def frequency(self): """ The frequency of the pulses used with the PWM device, in Hz. The - default is 100. + default is 100Hz. """ return self._frequency @@ -288,11 +328,20 @@ class PWMOutputDevice(DigitalOutputDevice): class PWMLED(PWMOutputDevice): """ - An LED (Light Emmitting Diode) component with variable brightness. + Extends :class:`PWMOutputDevice` and represents a light emitting diode + (LED) with variable brightness. A typical configuration of such a device is to connect a GPIO pin to the anode (long leg) of the LED, and the cathode (short leg) to ground, with an optional resistor to prevent the LED from burning out. + + :param int pin: + The GPIO pin which the device is attached to. See :doc:`notes` for + valid pin numbers. + + :param int frequency: + The frequency (in Hz) of pulses emitted to drive the device. Defaults + to 100Hz. """ pass @@ -309,22 +358,35 @@ def _led_property(index, doc=None): class RGBLED(SourceMixin, CompositeDevice): """ - Single LED with individually controllable red, green and blue components. + Extends :class:`CompositeDevice` and represents a full color LED component + (composed of red, green, and blue LEDs). - red: `None` + Connect the common cathode (longest leg) to a ground pin; connect each of + the other legs (representing the red, green, and blue anodes) to any GPIO + pins. You can either use three limiting resistors (one per anode) or a + single limiting resistor on the cathode. + + The following code will make the LED purple:: + + from gpiozero import RGBLED + + led = RGBLED(2, 3, 4) + led.color = (1, 0, 1) + + :param int red: The GPIO pin that controls the red component of the RGB LED. - green: `None` + :param int green: The GPIO pin that controls the green component of the RGB LED. - blue: `None` + :param int blue: The GPIO pin that controls the blue component of the RGB LED. """ def __init__(self, red=None, green=None, blue=None): if not all([red, green, blue]): raise OutputDeviceError('red, green, and blue pins must be provided') super(RGBLED, self).__init__() - self._leds = tuple(PWMOutputDevice(pin) for pin in (red, green, blue)) + self._leds = tuple(PWMLED(pin) for pin in (red, green, blue)) red = _led_property(0) green = _led_property(1) @@ -333,11 +395,11 @@ class RGBLED(SourceMixin, CompositeDevice): @property def value(self): """ - Represents the color of the LED as an RGB 3-tuple of `(red, green, - blue)` where each value is between 0 and 1. + Represents the color of the LED as an RGB 3-tuple of ``(red, green, + blue)`` where each value is between 0 and 1. - For example, purple would be `(1, 0, 1)` and yellow would be `(1, 1, - 0)`, while orange would be `(1, 0.5, 0)`. + For example, purple would be ``(1, 0, 1)`` and yellow would be ``(1, 1, + 0)``, while orange would be ``(1, 0.5, 0)``. """ return (self.red, self.green, self.blue) @@ -348,7 +410,8 @@ class RGBLED(SourceMixin, CompositeDevice): @property def is_active(self): """ - Returns `True` if the LED is currently active and `False` otherwise. + Returns ``True`` if the LED is currently active (not black) and + ``False`` otherwise. """ return self.value != (0, 0, 0) @@ -357,14 +420,14 @@ class RGBLED(SourceMixin, CompositeDevice): def on(self): """ Turn the device on. This equivalent to setting the device color to - white `(1, 1, 1)`. + white ``(1, 1, 1)``. """ self.value = (1, 1, 1) def off(self): """ Turn the device off. This is equivalent to setting the device color - to black `(0, 0, 0)`. + to black ``(0, 0, 0)``. """ self.value = (0, 0, 0) @@ -375,7 +438,30 @@ class RGBLED(SourceMixin, CompositeDevice): class Motor(SourceMixin, CompositeDevice): """ - Generic bi-directional motor. + Extends :class:`CompositeDevice` and represents a generic motor connected + to a bi-directional motor driver circuit (i.e. an `H-bridge`_). + + Attach an `H-bridge`_ motor controller to your Pi; connect a power source + (e.g. a battery pack or the 5V pin) to the controller; connect the outputs + of the controller board to the two terminals of the motor; connect the + inputs of the controller board to two GPIO pins. + + .. _H-bridge: https://en.wikipedia.org/wiki/H_bridge + + The following code will make the motor turn "forwards":: + + from gpiozero import Motor + + motor = Motor(17, 18) + motor.forward() + + :param int forward: + The GPIO pin that the forward input of the motor driver chip is + connected to. + + :param int backward: + The GPIO pin that the backward input of the motor driver chip is + connected to. """ def __init__(self, forward=None, backward=None): if not all([forward, backward]): @@ -432,20 +518,29 @@ class Motor(SourceMixin, CompositeDevice): @property def is_active(self): """ - Returns `True` if the motor is currently active and `False` otherwise. + Returns ``True`` if the motor is currently running and ``False`` + otherwise. """ return self.value != 0 def forward(self, speed=1): """ - Drive the motor forwards + Drive the motor forwards. + + :param float speed: + The speed at which the motor should turn. Can be any value between + 0 (stopped) and the default 1 (maximum speed). """ self._backward.off() self._forward.value = speed def backward(self, speed=1): """ - Drive the motor backwards + Drive the motor backwards. + + :param float speed: + The speed at which the motor should turn. Can be any value between + 0 (stopped) and the default 1 (maximum speed). """ self._forward.off() self._backward.value = speed @@ -460,7 +555,7 @@ class Motor(SourceMixin, CompositeDevice): def stop(self): """ - Stop the motor + Stop the motor. """ self._forward.off() self._backward.off() diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 0964442..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,15 +0,0 @@ -site_name: GPIO Zero -theme: readthedocs -site_url: http://pythonhosted.org/gpiozero -repo_url: https://github.com/RPi-Distro/python-gpiozero -site_description: A simple interface to everyday GPIO components used with Raspberry Pi -site_author: Ben Nuttall -site_dir: pythonhosted -google_analytics: ['UA-46270871-6', 'pythonhosted.org/gpiozero'] -pages: -- 'Home': 'index.md' -- 'Input Devices': 'inputs.md' -- 'Output Devices': 'outputs.md' -- 'Boards and Accessories': 'boards.md' -- 'Notes': 'notes.md' -- 'Recipes': 'recipes.md'