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 0000000..1f464a0 Binary files /dev/null and b/docs/images/composed_devices.pdf differ diff --git a/docs/images/composed_devices.png b/docs/images/composed_devices.png new file mode 100644 index 0000000..c5830cb Binary files /dev/null and b/docs/images/composed_devices.png differ 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 0000000..80f6d25 Binary files /dev/null and b/docs/images/composite_device_hierarchy.pdf differ diff --git a/docs/images/composite_device_hierarchy.png b/docs/images/composite_device_hierarchy.png new file mode 100644 index 0000000..349d838 Binary files /dev/null and b/docs/images/composite_device_hierarchy.png differ diff --git a/docs/images/composite_device_hierarchy.svg b/docs/images/composite_device_hierarchy.svg new file mode 100644 index 0000000..851a7ae --- /dev/null +++ b/docs/images/composite_device_hierarchy.svg @@ -0,0 +1,228 @@ + + + + + + +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 0000000..3299c2d Binary files /dev/null and b/docs/images/gpio_device_hierarchy.pdf differ diff --git a/docs/images/gpio_device_hierarchy.png b/docs/images/gpio_device_hierarchy.png new file mode 100644 index 0000000..5d61a8b Binary files /dev/null and b/docs/images/gpio_device_hierarchy.png differ diff --git a/docs/images/gpio_device_hierarchy.svg b/docs/images/gpio_device_hierarchy.svg new file mode 100644 index 0000000..f6fc6af --- /dev/null +++ b/docs/images/gpio_device_hierarchy.svg @@ -0,0 +1,148 @@ + + + + + + +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 0000000..bdab4a4 Binary files /dev/null and b/docs/images/pin_layout.pdf differ diff --git a/docs/images/pin_layout.png b/docs/images/pin_layout.png new file mode 100644 index 0000000..9254990 Binary files /dev/null and b/docs/images/pin_layout.png differ diff --git a/docs/images/pin_layout.svg b/docs/images/pin_layout.svg new file mode 100644 index 0000000..f5d87d3 --- /dev/null +++ b/docs/images/pin_layout.svg @@ -0,0 +1,2815 @@ + + + + + + + + + + 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'