From ca81b283b920cbe1aec771411fae06ce8f9e0d68 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 17:11:48 +0100 Subject: [PATCH 01/34] Added docstrings using Google syntax and Sphinx support to generate the API documentation for the Encoder and PWM modules for now. --- .gitignore | 3 + Adafruit_BBIO/Encoder.py | 120 +++++++++++++++++++-------- docs/Makefile | 20 +++++ docs/conf.py | 169 +++++++++++++++++++++++++++++++++++++++ docs/index.rst | 91 +++++++++++++++++++++ 5 files changed, 370 insertions(+), 33 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst diff --git a/.gitignore b/.gitignore index 5c0e38d..e948a66 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ m4/lt~obsolete.m4 missing source/Makefile.in test-driver +docs/_build +docs/_static +docs/_templates diff --git a/Adafruit_BBIO/Encoder.py b/Adafruit_BBIO/Encoder.py index 35fd26f..ecfd27a 100644 --- a/Adafruit_BBIO/Encoder.py +++ b/Adafruit_BBIO/Encoder.py @@ -1,5 +1,62 @@ #!/usr/bin/python +"""Quadrature Encoder Pulse interface. + +This module enables access to the enhanced Quadrature Encoder Pulse (eQEP) +channels, which can be used to seamlessly interface with rotary encoder +hardware. + +The channel identifiers are available as module variables :data:`eQEP0`, +:data:`eQEP1`, :data:`eQEP2` and :data:`eQEP2b`. + +Example: + To use the module, you can connect a rotary encoder to your Beaglebone + and then simply instantiate the :class:`RotaryEncoder` class to read its position:: + + from Adafruit_BBIO.Encoder import RotaryEncoder, eQEP2 + + # Instantiate the class to access channel eQEP2, and initialize + # that channel + myEncoder = RotaryEncoder(eQEP2) + + # Get the current position + cur_position = myEncoder.position + + # Set the current position + next_position = 15 + myEncoder.position = next_position + + # Reset position to 0 + myEncoder.zero() + + # Change mode to relative (default is absolute) + # You can use setAbsolute() to change back to absolute + # Absolute: the position starts at zero and is incremented or + # decremented by the encoder's movement + # Relative: the position is reset when the unit timer overflows. + myEncoder.setRelative() + + # Read the current mode (0: absolute, 1: relative) + # Mode can also be set as a property + mode = myEncoder.mode + + # Get the current frequency of update in Hz + freq = myEncoder.frequency + + # Set the update frequency to 1 kHz + myEncoder.frequency = 1000 + + # Disable the eQEP channel + myEncoder.disable() + + # Check if the channel is enabled + # The 'enabled' property is read-only + # Use the enable() and disable() methods to + # safely enable or disable the module + isEnabled = myEncoder.enabled + +""" + from subprocess import check_output, STDOUT, CalledProcessError import os import logging @@ -15,13 +72,20 @@ 'Your Linux kernel version is {}.'.format(platform.release())) -# eQEP module channel identifiers -# eQEP 2 and 2b are the same channel, exposed on two different sets of pins, -# which are mutually exclusive eQEP0 = 0 +'''eQEP0 channel identifier, pin A-- P9.92, pin B-- P9.27 on Beaglebone +Black.''' eQEP1 = 1 +'''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone +Black.''' eQEP2 = 2 +'''eQEP2 channel identifier, pin A-- P8.12, pin B-- P8.11 on Beaglebone Black. +Note that there is only one eQEP2 module. This is one alternative set of pins +where it is exposed, which is mutually-exclusive with eQEP2b''' eQEP2b = 3 +'''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone Black. +Note that there is only one eQEP2 module. This is one alternative set of pins +where it is exposed, which is mutually-exclusive with eQEP2''' # Definitions to initialize the eQEP modules _OCP_PATH = "/sys/devices/platform/ocp" @@ -37,7 +101,7 @@ ] -class eQEP(object): +class _eQEP(object): '''Enhanced Quadrature Encoder Pulse (eQEP) module class. Abstraction for either of the three available channels (eQEP0, eQEP1, eQEP2) on the Beaglebone''' @@ -51,7 +115,7 @@ def fromdict(cls, d): return cls(**df) def __init__(self, channel, pin_A, pin_B, sys_path): - '''Initialize the eQEP module + '''Initialize the given eQEP channel Attributes: channel (str): eQEP channel name. E.g. "eQEP0", "eQEP1", etc. @@ -79,21 +143,11 @@ class RotaryEncoder(object): ''' Rotary encoder class abstraction to control a given QEP channel. - Constructor: - eqep_num: QEP object that determines which channel to control - - Properties: - position: current position of the encoder - frequency: frequency at which the encoder reports new positions - enabled: (read only) true if the module is enabled, false otherwise - mode: current mode of the encoder (absolute: 0, relative: 1) - - Methods: - enable: enable the QEP channel - disable: disable the QEP channel - setAbsolute: shortcut for setting the mode to absolute - setRelative: shortcut for setting the mode to relative - zero: shortcut for setting the position to 0 + Args: + eqep_num (int): determines which eQEP pins are set up. + Allowed values: EQEP0, EQEP1, EQEP2 or EQEP2b, + based on which pins the physical rotary encoder + is connected to. ''' def _run_cmd(self, cmd): @@ -117,15 +171,8 @@ def _config_pin(self, pin): self._run_cmd(["config-pin", pin, "qep"]) def __init__(self, eqep_num): - '''Creates an instance of the class RotaryEncoder. - - Arguments: - eqep_num: determines which eQEP pins are set up. - Allowed values: EQEP0, EQEP1, EQEP2 or EQEP2b, - based on which pins the physical rotary encoder - is connected to. + '''Creates an instance of the class RotaryEncoder.''' - ''' # nanoseconds factor to convert period to frequency and back self._NS_FACTOR = 1000000000 @@ -134,7 +181,7 @@ def __init__(self, eqep_num): self._logger.addHandler(logging.NullHandler()) # Initialize the eQEP channel structures - self._eqep = eQEP.fromdict(_eQEP_DEFS[eqep_num]) + self._eqep = _eQEP.fromdict(_eQEP_DEFS[eqep_num]) self._logger.info( "Configuring: {}, pin A: {}, pin B: {}, sys path: {}".format( self._eqep.channel, self._eqep.pin_A, self._eqep.pin_B, @@ -154,8 +201,8 @@ def __init__(self, eqep_num): def enabled(self): '''Returns the enabled status of the module: - true: module is enabled - false: module is disabled + Returns: + bool: True if the eQEP channel is enabled, False otherwise. ''' isEnabled = bool(int(self._eqep.node.enabled)) @@ -164,7 +211,11 @@ def enabled(self): def _setEnable(self, enabled): '''Turns the eQEP hardware ON or OFF - value (int): 1 represents enabled, 0 is disabled + Args: + enabled (int): enable the module with 1, disable it with 0. + + Raises: + ValueError: if the value for enabled is < 0 or > 1 ''' enabled = int(enabled) @@ -189,8 +240,11 @@ def disable(self): @property def mode(self): - '''Returns the mode the eQEP hardware is in (absolute or relative). + '''Returns the mode the eQEP hardware is in. + Returns: + int: 0 if the eQEP channel is configured in absolute mode, + 1 if configured in relative mode. ''' mode = int(self._eqep.node.mode) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..4430e8a --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = Adafruit-BBIO +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2ac0431 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# +# Adafruit-BBIO documentation build configuration file, created by +# sphinx-quickstart on Fri Dec 1 12:56:03 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Adafruit-BBIO' +copyright = u'2017, Justin Cooper' +author = u'Justin Cooper' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'' +# The full version, including alpha/beta/rc tags. +release = u'1.0.9' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Adafruit-BBIOdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'Adafruit-BBIO.tex', u'Adafruit-BBIO Documentation', + u'Justin Cooper', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'adafruit-bbio', u'Adafruit-BBIO Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'Adafruit-BBIO', u'Adafruit-BBIO Documentation', + author, 'Adafruit-BBIO', 'One line description of project.', + 'Miscellaneous'), +] + +autodoc_member_order = 'groupwise' +#autoclass_content = 'both' + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..9241ca6 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,91 @@ +.. Adafruit-BBIO documentation master file, created by + sphinx-quickstart on Fri Dec 1 12:56:03 2017. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Adafruit Beaglebone IO Python API +================================= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +:mod:`Encoder` --- Quadrature Encoder interface +----------------------------------------------- + +.. automodule:: Adafruit_BBIO.Encoder + :members: + +:mod:`PWM` --- Pulse Width Modulation interface +----------------------------------------------- + +Enables access to the Pulse Width Modulation (PWM) module, to easily and +accurately generate a PWM output signal of a given duty cycle and +frequency. + +.. module:: Adafruit_BBIO.PWM + +.. function:: start(channel, duty_cycle[, frequency=2000, polarity=0]) + + Set up and start the given PWM channel. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. + :type duty_cycle: int + :param frequency: PWM frequency, in Hz. It must be greater than 0. + :type frequency: int + :param polarity: defines whether the value for ``duty_cycle`` affects the + rising edge or the falling edge of the waveform. Allowed values -- 0 + (rising edge, default) or 1 (falling edge). + :type polarity: int + +.. function:: stop(channel) + + Stop the given PWM channel. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + +.. function:: set_duty_cycle(channel, duty_cycle) + + Change the duty cycle of the given PWM channel. + + :note: You must have started the PWM channel with :func:`start()` + once, before changing the duty cycle. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. + :type duty_cycle: int + +.. function:: set_frequency(channel, frequency) + + Change the frequency of the given PWM channel. + + :note: You must have started the PWM channel with :func:`start()` + once, before changing the frequency. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + :param frequency: PWM frequency. It must be greater than 0. + :type frequency: int + +.. function:: cleanup() + + Clean up by resetting all GPIO channels that have been used by this + program to INPUT, with no pullup/pulldown and no event detection. + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + + From cfdf7552ade444c84b3611fdee7ead65b74510e6 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 18:24:03 +0100 Subject: [PATCH 02/34] Made kernel version check to happen only if running on a beaglebone. The readthedocs builders that import the Encoder module have an old 3.3 kernel and the autodoc build fails --- .gitignore | 3 +++ Adafruit_BBIO/Encoder.py | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index e948a66..facfc35 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ test-driver docs/_build docs/_static docs/_templates + +# vim temp files +*~ diff --git a/Adafruit_BBIO/Encoder.py b/Adafruit_BBIO/Encoder.py index ecfd27a..39c40b6 100644 --- a/Adafruit_BBIO/Encoder.py +++ b/Adafruit_BBIO/Encoder.py @@ -11,7 +11,8 @@ Example: To use the module, you can connect a rotary encoder to your Beaglebone - and then simply instantiate the :class:`RotaryEncoder` class to read its position:: + and then simply instantiate the :class:`RotaryEncoder` class to read its + position:: from Adafruit_BBIO.Encoder import RotaryEncoder, eQEP2 @@ -65,7 +66,8 @@ import platform (major, minor, patch) = platform.release().split("-")[0].split(".") -if not (int(major) >= 4 and int(minor) >= 4): +if not (int(major) >= 4 and int(minor) >= 4) \ + and platform.node() == 'beaglebone': raise ImportError( 'The Encoder module requires Linux kernel version >= 4.4.x.\n' 'Please upgrade your kernel to use this module.\n' @@ -76,16 +78,16 @@ '''eQEP0 channel identifier, pin A-- P9.92, pin B-- P9.27 on Beaglebone Black.''' eQEP1 = 1 -'''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone +'''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone Black.''' eQEP2 = 2 '''eQEP2 channel identifier, pin A-- P8.12, pin B-- P8.11 on Beaglebone Black. Note that there is only one eQEP2 module. This is one alternative set of pins where it is exposed, which is mutually-exclusive with eQEP2b''' eQEP2b = 3 -'''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone Black. -Note that there is only one eQEP2 module. This is one alternative set of pins -where it is exposed, which is mutually-exclusive with eQEP2''' +'''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone +Black. Note that there is only one eQEP2 module. This is one alternative set of +pins where it is exposed, which is mutually-exclusive with eQEP2''' # Definitions to initialize the eQEP modules _OCP_PATH = "/sys/devices/platform/ocp" @@ -318,14 +320,13 @@ def position(self, position): self._logger.debug("Set position: Channel {}, position: {}".format( self._eqep.channel, position)) - @property def frequency(self): '''Sets the frequency in Hz at which the driver reports new positions. ''' - frequency = self._NS_FACTOR / int(self._eqep.node.period) + frequency = self._NS_FACTOR / int(self._eqep.node.period) self._logger.debug( "Set frequency(): Channel {}, frequency: {} Hz, " @@ -352,3 +353,4 @@ def zero(self): '''Resets the current position to 0''' self.position = 0 + From 19134712f7d4162fa84f2e4e8cb07d6ffa1e6389 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 18:47:03 +0100 Subject: [PATCH 03/34] Use the default readthedocs theme --- docs/conf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 2ac0431..556134c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -102,11 +102,15 @@ # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { '**': [ - 'relations.html', # needs 'show_related': True theme option to display 'searchbox.html', + 'localtoc.html' ] } +html_theme = "default" +html_theme_options = { + #"show_related": "true" +} # -- Options for HTMLHelp output ------------------------------------------ From 7de4ccb3754d742365331876ddf580195bedeca0 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 18:56:51 +0100 Subject: [PATCH 04/34] Use readthedocs theme if building docs there, remove redundand search link --- docs/conf.py | 10 ++++++---- docs/index.rst | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 556134c..0412db1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -107,10 +107,12 @@ ] } -html_theme = "default" -html_theme_options = { - #"show_related": "true" -} +# Use the readthedocs theme if the documentation is being built there +on_rtd = os.environ.get('READTHEDOCS') == 'True' +if on_rtd: + html_theme = 'default' +else: + html_theme = 'alabaster' # -- Options for HTMLHelp output ------------------------------------------ diff --git a/docs/index.rst b/docs/index.rst index 9241ca6..4b930ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -86,6 +86,5 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` -* :ref:`search` From c37cf6a5121d5702ec3c2913905e8b9b38f62664 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 19:52:04 +0100 Subject: [PATCH 05/34] Readthedocs theme tweaks --- docs/conf.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0412db1..a620f16 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -100,19 +100,22 @@ # # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'searchbox.html', - 'localtoc.html' - ] -} # Use the readthedocs theme if the documentation is being built there on_rtd = os.environ.get('READTHEDOCS') == 'True' if on_rtd: html_theme = 'default' + html_theme_options = { + 'collapse_navigation': False, + } else: html_theme = 'alabaster' + html_sidebars = { + '**': [ + 'searchbox.html', + 'localtoc.html' + ] + } # -- Options for HTMLHelp output ------------------------------------------ From 7d33f1d85650d19ee118148f6e2b7363de04b56b Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 20:14:42 +0100 Subject: [PATCH 06/34] Removed redundant TOC, added global description --- docs/index.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 4b930ad..2a7fdb4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,9 +6,8 @@ Adafruit Beaglebone IO Python API ================================= -.. toctree:: - :maxdepth: 2 - :caption: Contents: +The Adafruit Beaglebone IO API enables access to the Beaglebone's GPIO, PWM, +ADC, UART and eQEP hardware modules from Python programs. :mod:`Encoder` --- Quadrature Encoder interface ----------------------------------------------- From d1608b44c3dd9033350316e725cad835a77aeaef Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 20:32:16 +0100 Subject: [PATCH 07/34] Added UART documentation --- docs/index.rst | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 2a7fdb4..f4c8830 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -79,6 +79,44 @@ frequency. Clean up by resetting all GPIO channels that have been used by this program to INPUT, with no pullup/pulldown and no event detection. +:mod:`UART` --- UART communications interface +--------------------------------------------- + +UART functionality of a BeagleBone using Python. Generally used to set up +and grant access to a given UART device, which will then be accessed by +other software or modules (e.g. `pyserial`):: + + sudo pip install pyserial + +Example:: + + import Adafruit_BBIO.UART as UART + import serial + + UART.setup("UART1") + + ser = serial.Serial(port = "/dev/ttyO1", baudrate=9600) + ser.close() + ser.open() + if ser.isOpen(): + print "Serial is open!" + ser.write("Hello World!") + ser.close() + +.. function:: setup_uart(channel) + + Set up and start the UART channel. This function will effectively export + the given UART so that it can be accessed by other software that controls + its serial lines. + + :param channel: UART channel to set up. One of "UART1", "UART2", + "UART4" or "UART5" + :type channel: str + +.. function:: cleanup() + + Cleans up the UART. + Indices and tables ================== From 152678a674f6a145e94abd8eebd3341e73b3de63 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 23:23:13 +0100 Subject: [PATCH 08/34] Added documentation badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e4db1e2..5fcaa57 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Adafruit BeagleBone I/O Python Library (Adafruit_BBIO) +[![Documentation Status](https://readthedocs.org/projects/adafruit-beaglebone-io-python/badge/?version=latest)](http://adafruit-beaglebone-io-python.readthedocs.io/en/latest/?badge=latest) + * Adafruit_BBIO is a set of Python tools to allow [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc) and [UART](README.md#uart) access on the BeagleBone * It is recommended to use an [official BeagleBoard.org Debian image](https://beagleboard.org/latest-images) From 6dc5313d856418d7966cc0852248e56b4f3b545d Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 23:38:31 +0100 Subject: [PATCH 09/34] Added ADC API docs, fixed UART module definition --- docs/index.rst | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index f4c8830..899e365 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -103,6 +103,8 @@ Example:: ser.write("Hello World!") ser.close() +.. module:: Adafruit_BBIO.UART + .. function:: setup_uart(channel) Set up and start the UART channel. This function will effectively export @@ -117,6 +119,38 @@ Example:: Cleans up the UART. +:mod:`ADC` --- A/D Converter input interface +-------------------------------------------- + +This module enables reading analog input values from the analog to digital +converter (ADC) on the Beaglebone processor. + +Example:: + + import Adafruit_BBIO.ADC as ADC + + ADC.setup() + + # The read method returns normalized values from 0 to 1.0 + value = ADC.read("P9_40") + + # The read_raw returns non-normalized values + value = ADC.read_raw("P9_40") + +.. module:: Adafruit_BBIO.ADC + +.. function:: setup_adc() + + Setup and start the ADC hardware. + +.. function:: setup_read() + + Read the normalized 0-1.0 analog value for the channel. + +.. function:: setup_read_raw() + + Read the raw analog value for the channel. + Indices and tables ================== From 93b2a23613360304bbb93109b87ea85844f5d308 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 00:59:33 +0100 Subject: [PATCH 10/34] API docs: added SPI module --- docs/index.rst | 124 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 18 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 899e365..7266140 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,25 +28,20 @@ frequency. Set up and start the given PWM channel. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str - :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. - :type duty_cycle: int - :param frequency: PWM frequency, in Hz. It must be greater than 0. - :type frequency: int - :param polarity: defines whether the value for ``duty_cycle`` affects the + :param int duty_cycle: PWM duty cycle. It must have a value from 0 to 100. + :param int frequency: PWM frequency, in Hz. It must be greater than 0. + :param int polarity: defines whether the value for ``duty_cycle`` affects the rising edge or the falling edge of the waveform. Allowed values -- 0 (rising edge, default) or 1 (falling edge). - :type polarity: int .. function:: stop(channel) Stop the given PWM channel. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str .. function:: set_duty_cycle(channel, duty_cycle) @@ -55,11 +50,9 @@ frequency. :note: You must have started the PWM channel with :func:`start()` once, before changing the duty cycle. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str - :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. - :type duty_cycle: int + :param int duty_cycle: PWM duty cycle. It must have a value from 0 to 100. .. function:: set_frequency(channel, frequency) @@ -68,11 +61,9 @@ frequency. :note: You must have started the PWM channel with :func:`start()` once, before changing the frequency. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str - :param frequency: PWM frequency. It must be greater than 0. - :type frequency: int + :param int frequency: PWM frequency. It must be greater than 0. .. function:: cleanup() @@ -151,6 +142,103 @@ Example:: Read the raw analog value for the channel. +:mod:`SPI` --- Serial Peripheral Interface +------------------------------------------ + +This module defines an object type that allows Serial Peripheral Interface +(SPI) bus transactions on hosts running the Linux kernel. The host kernel +must have SPI support and SPI device interface support. + +Because the SPI device interface is opened R/W, users of this module +usually must have root permissions or be members of a group with granted +access rights. + +Example:: + + import Adafruit_BBIO.SPI as SPI + + from Adafruit_BBIO.SPI import SPI + # spi = SPI(bus, device) #/dev/spidev. + + # /dev/spidev0.0 + spi = SPI(1, 0) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + + # /dev/spidev0.1 + spi = SPI(1,1) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + + # /dev/spidev1.0 + spi = SPI(2,0) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + + # /dev/spidev1.1 + spi = SPI(2,1) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + +.. module:: Adafruit_BBIO.SPI + +.. class:: SPI(bus, client) + + :param bus: bus number + :param client: client number + :returns: a new SPI object, optionally connected to the specified SPI + device interface. + :rtype: :class:`SPI` + + .. method:: open(bus, device) + + Connects the object to the specified SPI device. `open(X, Y)` will open + `/dev/spidev-X.Y` + + :param int bus: bus number + :param str device: device number + + .. method:: close() + + Disconnects the object from the interface. + + .. method:: readbytes(len) + + Read the specified length of bytes from the SPI device. + + :param int len: length of bytes to read, 1024 maximum. + :returns: values read + :rtype: list[int] + + .. method:: writebytes(values) + + Write bytes to the SPI device. + + :param values: list of values to write, with a maximum length of 1024. + :type values: list[int] + + .. method:: xfer(values[,delay=0]) + + xfer([values]) -> [values] + Perform an SPI transaction of values. Slave Select (SS or CS) will be + released and reactivated between blocks. + + :param values: list of values to transfer, with a maximum length of 1024. + :type values: list[int] + :param delay: delay in microseconds between blocks. + :returns: values transferred + :rtype: list[int] + + .. method:: xfer2(values) + + xfer2([values]) -> [values] + Perform an SPI transaction of values. Slave Select (SS or CS) will be + held active between blocks. + + :param values: list of values to transfer, with a maximum length of 1024. + :type values: list[int] + :returns: values transferred + :rtype: list[int] Indices and tables ================== From 746c22c0a19a21ddac3153435487f516fe69ffd1 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 01:12:37 +0100 Subject: [PATCH 11/34] Added SPI module attribute docs --- docs/index.rst | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 7266140..1dbb02f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -184,12 +184,40 @@ Example:: .. class:: SPI(bus, client) - :param bus: bus number - :param client: client number + :param bus: bus number. + :param client: client number. :returns: a new SPI object, optionally connected to the specified SPI device interface. :rtype: :class:`SPI` + .. attribute:: bpw + + Bits per word. + + .. attribute:: cshigh + + Chip Select (CS or Slave Select, SS) active high. + + .. attribute:: loop + + Loopback configuration. + + .. attribute:: lsbfirst + + Least Significant Bit (LSB) first. + + .. attribute:: mode + + SPI mode as two bit pattern of Clock Polarity and Phase [CPOL|CPHA]; min-- 0b00 = 0, max-- 0b11 = 3. + + .. attribute:: msh + + Maximum speed in Hz. + + .. attribute:: threewire + + SI/SO signals are shared. + .. method:: open(bus, device) Connects the object to the specified SPI device. `open(X, Y)` will open From c379e3027854818f5afa19a5ad1048e475db1202 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 02:31:21 +0100 Subject: [PATCH 12/34] Added Python badges to README file --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5fcaa57..d501a72 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Adafruit BeagleBone I/O Python Library (Adafruit_BBIO) [![Documentation Status](https://readthedocs.org/projects/adafruit-beaglebone-io-python/badge/?version=latest)](http://adafruit-beaglebone-io-python.readthedocs.io/en/latest/?badge=latest) +[![PyPI version](https://badge.fury.io/py/Adafruit_BBIO.svg)](https://badge.fury.io/py/Adafruit_BBIO) +[![PyPI pyversions](https://img.shields.io/pypi/pyversions/Adafruit_BBIO.svg)](https://pypi.python.org/pypi/Adafruit_BBIO/) * Adafruit_BBIO is a set of Python tools to allow [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc) and [UART](README.md#uart) access on the BeagleBone From c84bc31074910feaac196df83aba228bd3a19e52 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 03:10:26 +0100 Subject: [PATCH 13/34] Added SPI pins table and first shot at GPIO module. Functions still need to be documented --- docs/index.rst | 109 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 1dbb02f..4ae5ced 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -102,9 +102,8 @@ Example:: the given UART so that it can be accessed by other software that controls its serial lines. - :param channel: UART channel to set up. One of "UART1", "UART2", + :param str channel: UART channel to set up. One of "UART1", "UART2", "UART4" or "UART5" - :type channel: str .. function:: cleanup() @@ -153,6 +152,16 @@ Because the SPI device interface is opened R/W, users of this module usually must have root permissions or be members of a group with granted access rights. +Pins used for SPI0 and SPI1 ++++++++++++++++++++++++++++ + +==== ===== ===== ===== ===== +PORT CS0 DO DI SCLK +==== ===== ===== ===== ===== +SPI0 P9_17 P9_21 P9_18 P9_22 +SPI1 P9_28 P9_29 P9_30 P9_31 +==== ===== ===== ===== ===== + Example:: import Adafruit_BBIO.SPI as SPI @@ -166,17 +175,17 @@ Example:: spi.close() # /dev/spidev0.1 - spi = SPI(1,1) + spi = SPI(1, 1) print(spi.xfer2([32, 11, 110, 22, 220])) spi.close() # /dev/spidev1.0 - spi = SPI(2,0) + spi = SPI(2, 0) print(spi.xfer2([32, 11, 110, 22, 220])) spi.close() # /dev/spidev1.1 - spi = SPI(2,1) + spi = SPI(2, 1) print(spi.xfer2([32, 11, 110, 22, 220])) spi.close() @@ -185,7 +194,7 @@ Example:: .. class:: SPI(bus, client) :param bus: bus number. - :param client: client number. + :param client: client device number. :returns: a new SPI object, optionally connected to the specified SPI device interface. :rtype: :class:`SPI` @@ -268,6 +277,94 @@ Example:: :returns: values transferred :rtype: list[int] +:mod:`GPIO` --- General Purpose I/O interface +--------------------------------------------- + +TODO + +Example:: + + # Use the config-pin command line tool to set a pin's function to GPIO + # Then you can control it with the GPIO module from Python + config-pin P9_14 gpio + + import Adafruit_BBIO.GPIO as GPIO + + # Set up pins as inputs or outputs + GPIO.setup("P8_13", GPIO.IN) + GPIO.setup("P8_14", GPIO.OUT) + GPIO.setup("GPIO0_26", GPIO.OUT) # Alternative: use actual pin names + + # Write a logic high or logic low + GPIO.output("P8_14", GPIO.HIGH) # You can also write '1' instead + GPIO.output("P8_14", GPIO.LOW) # You can also write '0' instead + +.. module:: Adafruit_BBIO.GPIO + +.. function:: setup() + + :param str channel: UART channel to set up. One of "UART1", "UART2", + "UART4" or "UART5" + +.. attribute:: ALT0 + + Pin mode-- alternate function 0. + +.. attribute:: BOTH + + Edge detection-- detect both edges. + +.. attribute:: FALLING + + Edge detection-- detect falling edge. + +.. attribute:: HIGH + + Pin status-- logic low. + +.. attribute:: IN + + Pin mode-- input. + +.. attribute:: LOW + + Pin status-- logic low. + +.. attribute:: OUT + + Pin mode-- output. + +.. attribute:: PUD_OFF + + Pull-up/pull-down resistor type-- no pull-up/pull-down. + +.. attribute:: PUD_DOWN + + Pull-up/pull-down resistor type-- pull-down. + +.. attribute:: PUD_UP + + Pull-up/pull-down resistor type-- pull-up. + +.. attribute:: RISING + + Edge detection-- detect rising edge. + +.. attribute:: VERSION + + GPIO module version. + +.. function:: cleanup() +.. function:: output() +.. function:: input() +.. function:: add_event_detect() +.. function:: remove_event_detect() +.. function:: add_event_detected() +.. function:: add_event_callback() +.. function:: wait_for_edge() +.. function:: gpio_function() +.. function:: setwarnings() + Indices and tables ================== From 2b7de7f3cd3feb2d82f7ac0e711a3cd15b65f186 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 14:04:40 +0100 Subject: [PATCH 14/34] Documented the API docs build process --- docs/README.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..abe18a1 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,67 @@ +# Generating API documentation + +This folder contains the required files to automatically generate the Adafruit Beaglebone I/O Python API documentation, partly from the code docstrings and partly from a reStructuredText-formatted `index.rst` file. + +``` +├── conf.py <- Sphinx configuration file +├── index.rst <- Documentation will be generated based on this +└── Makefile <- Auxiliary Makefile to build documentation +``` + +The tools used are [http://www.sphinx-doc.org](Sphinx) to extract the documentation and publish it in HTML format for online viewing, in combination with [Readthedocs](http://readthedocs.io), which automatically executes Sphinx via webhooks triggered by Github commits, and publishes the resulting docs for all tracked branches. Generally Readthedocs will be set up to track stable release branches and master. + +## Building the documentation + +The documentation can also be built on a local checkout of the project: + +First ensure you've got sphinx installed: + +``` +sudo pip install sphinx +``` + +Then you can build the HTML docs: + +``` +cd docs +make html +``` + +Once Sphinx has built the documentation, you can open the main index file with your browser: `_build/html/index.html` + +Notes: + +- The build process will create three additional temporary directories: `_build`, `_static` and `_templates` that will not be version-controlled. You can use `make clean` to remove their contents if you wish to do so. +- The html theme from files built locally is different from the online readthedocs theme. See the `docs/config.py` `html_theme` variable. The main reason is not to introduce another dependency to install the readthedocs theme, but as a side effect, it also helps visually distinguishing the locally-built documentation from the online version. + +## Readthedocs maintenance + +At every release that includes documenation (most probably 1.0.10 will be the first one), the release's branch needs to be selected in the web UI and marked as active. + +After this, documentation will automatically be generated and published for that release. It will be available at the same URL as the main documentation, and a link with the version number will be shown, where it can be accessed from. + +Optionally, the 'stable' URL slug can be pointed to that release branch. Otherwise, the 'stable' slug can also be deactivated for less maintenance overhead. + +The 'latest' URL slug will always be pointing at the repo's master branch. + +## Notes + +Ideally, all API documentation would be written in the source files as Python docstrings, and sphinx would simply extract it. This is actually the case with the `Encoder` module, which is pure Python. + +However, most of the code is written as C extensions. While they do provide docstrings once they are built, Sphinx does not natively support extracting them. There is [a workaround](https://stackoverflow.com/a/30110104/9022675) to do this, but it involves first building the extensions, installing them and hardcoding a path. While it might work for locally-built documentation, it's unlikely that readthedocs support this option. + +For the sake of keeping things simple and with less maintenance, the approach of documenting the C-generated API in the `index.rst` file has been taken. + +This has the advantage of having a definition of the API in one place, but it also poses the disadvantage of some duplication, as the C modules do define some docstrings for their objects. Then again, the API itself has hardly changed in the last few years, and the Beaglebone is a mature platform, so it's unlikely that this will pose a significant maintenance overhead. + +- The documentation in Python modules follows the Google readable docstring markup, which is fully supported by Sphinx. +- The documentation in the `index.rst` file is written in [reStructuredText](http://docutils.sourceforge.net/rst.html), with Sphinx markup for defining the objects. + +## Further reference + +- [Google readable docstring markup](https://google.github.io/styleguide/pyguide.html?showone=Comments#Comments) +- [Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) +- [More Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html)) +- [Sphinx docstring markup](http://www.sphinx-doc.org/en/stable/domains.html#the-python-domain) + + From 32e63c992d8708e24fa0aab53bbe577afe606c81 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 17:11:48 +0100 Subject: [PATCH 15/34] Added docstrings using Google syntax and Sphinx support to generate the API documentation for the Encoder and PWM modules for now. --- .gitignore | 3 + Adafruit_BBIO/Encoder.py | 120 +++++++++++++++++++-------- docs/Makefile | 20 +++++ docs/conf.py | 169 +++++++++++++++++++++++++++++++++++++++ docs/index.rst | 91 +++++++++++++++++++++ 5 files changed, 370 insertions(+), 33 deletions(-) create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst diff --git a/.gitignore b/.gitignore index 5c0e38d..e948a66 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ m4/lt~obsolete.m4 missing source/Makefile.in test-driver +docs/_build +docs/_static +docs/_templates diff --git a/Adafruit_BBIO/Encoder.py b/Adafruit_BBIO/Encoder.py index 35fd26f..ecfd27a 100644 --- a/Adafruit_BBIO/Encoder.py +++ b/Adafruit_BBIO/Encoder.py @@ -1,5 +1,62 @@ #!/usr/bin/python +"""Quadrature Encoder Pulse interface. + +This module enables access to the enhanced Quadrature Encoder Pulse (eQEP) +channels, which can be used to seamlessly interface with rotary encoder +hardware. + +The channel identifiers are available as module variables :data:`eQEP0`, +:data:`eQEP1`, :data:`eQEP2` and :data:`eQEP2b`. + +Example: + To use the module, you can connect a rotary encoder to your Beaglebone + and then simply instantiate the :class:`RotaryEncoder` class to read its position:: + + from Adafruit_BBIO.Encoder import RotaryEncoder, eQEP2 + + # Instantiate the class to access channel eQEP2, and initialize + # that channel + myEncoder = RotaryEncoder(eQEP2) + + # Get the current position + cur_position = myEncoder.position + + # Set the current position + next_position = 15 + myEncoder.position = next_position + + # Reset position to 0 + myEncoder.zero() + + # Change mode to relative (default is absolute) + # You can use setAbsolute() to change back to absolute + # Absolute: the position starts at zero and is incremented or + # decremented by the encoder's movement + # Relative: the position is reset when the unit timer overflows. + myEncoder.setRelative() + + # Read the current mode (0: absolute, 1: relative) + # Mode can also be set as a property + mode = myEncoder.mode + + # Get the current frequency of update in Hz + freq = myEncoder.frequency + + # Set the update frequency to 1 kHz + myEncoder.frequency = 1000 + + # Disable the eQEP channel + myEncoder.disable() + + # Check if the channel is enabled + # The 'enabled' property is read-only + # Use the enable() and disable() methods to + # safely enable or disable the module + isEnabled = myEncoder.enabled + +""" + from subprocess import check_output, STDOUT, CalledProcessError import os import logging @@ -15,13 +72,20 @@ 'Your Linux kernel version is {}.'.format(platform.release())) -# eQEP module channel identifiers -# eQEP 2 and 2b are the same channel, exposed on two different sets of pins, -# which are mutually exclusive eQEP0 = 0 +'''eQEP0 channel identifier, pin A-- P9.92, pin B-- P9.27 on Beaglebone +Black.''' eQEP1 = 1 +'''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone +Black.''' eQEP2 = 2 +'''eQEP2 channel identifier, pin A-- P8.12, pin B-- P8.11 on Beaglebone Black. +Note that there is only one eQEP2 module. This is one alternative set of pins +where it is exposed, which is mutually-exclusive with eQEP2b''' eQEP2b = 3 +'''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone Black. +Note that there is only one eQEP2 module. This is one alternative set of pins +where it is exposed, which is mutually-exclusive with eQEP2''' # Definitions to initialize the eQEP modules _OCP_PATH = "/sys/devices/platform/ocp" @@ -37,7 +101,7 @@ ] -class eQEP(object): +class _eQEP(object): '''Enhanced Quadrature Encoder Pulse (eQEP) module class. Abstraction for either of the three available channels (eQEP0, eQEP1, eQEP2) on the Beaglebone''' @@ -51,7 +115,7 @@ def fromdict(cls, d): return cls(**df) def __init__(self, channel, pin_A, pin_B, sys_path): - '''Initialize the eQEP module + '''Initialize the given eQEP channel Attributes: channel (str): eQEP channel name. E.g. "eQEP0", "eQEP1", etc. @@ -79,21 +143,11 @@ class RotaryEncoder(object): ''' Rotary encoder class abstraction to control a given QEP channel. - Constructor: - eqep_num: QEP object that determines which channel to control - - Properties: - position: current position of the encoder - frequency: frequency at which the encoder reports new positions - enabled: (read only) true if the module is enabled, false otherwise - mode: current mode of the encoder (absolute: 0, relative: 1) - - Methods: - enable: enable the QEP channel - disable: disable the QEP channel - setAbsolute: shortcut for setting the mode to absolute - setRelative: shortcut for setting the mode to relative - zero: shortcut for setting the position to 0 + Args: + eqep_num (int): determines which eQEP pins are set up. + Allowed values: EQEP0, EQEP1, EQEP2 or EQEP2b, + based on which pins the physical rotary encoder + is connected to. ''' def _run_cmd(self, cmd): @@ -117,15 +171,8 @@ def _config_pin(self, pin): self._run_cmd(["config-pin", pin, "qep"]) def __init__(self, eqep_num): - '''Creates an instance of the class RotaryEncoder. - - Arguments: - eqep_num: determines which eQEP pins are set up. - Allowed values: EQEP0, EQEP1, EQEP2 or EQEP2b, - based on which pins the physical rotary encoder - is connected to. + '''Creates an instance of the class RotaryEncoder.''' - ''' # nanoseconds factor to convert period to frequency and back self._NS_FACTOR = 1000000000 @@ -134,7 +181,7 @@ def __init__(self, eqep_num): self._logger.addHandler(logging.NullHandler()) # Initialize the eQEP channel structures - self._eqep = eQEP.fromdict(_eQEP_DEFS[eqep_num]) + self._eqep = _eQEP.fromdict(_eQEP_DEFS[eqep_num]) self._logger.info( "Configuring: {}, pin A: {}, pin B: {}, sys path: {}".format( self._eqep.channel, self._eqep.pin_A, self._eqep.pin_B, @@ -154,8 +201,8 @@ def __init__(self, eqep_num): def enabled(self): '''Returns the enabled status of the module: - true: module is enabled - false: module is disabled + Returns: + bool: True if the eQEP channel is enabled, False otherwise. ''' isEnabled = bool(int(self._eqep.node.enabled)) @@ -164,7 +211,11 @@ def enabled(self): def _setEnable(self, enabled): '''Turns the eQEP hardware ON or OFF - value (int): 1 represents enabled, 0 is disabled + Args: + enabled (int): enable the module with 1, disable it with 0. + + Raises: + ValueError: if the value for enabled is < 0 or > 1 ''' enabled = int(enabled) @@ -189,8 +240,11 @@ def disable(self): @property def mode(self): - '''Returns the mode the eQEP hardware is in (absolute or relative). + '''Returns the mode the eQEP hardware is in. + Returns: + int: 0 if the eQEP channel is configured in absolute mode, + 1 if configured in relative mode. ''' mode = int(self._eqep.node.mode) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..4430e8a --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = Adafruit-BBIO +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..2ac0431 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# +# Adafruit-BBIO documentation build configuration file, created by +# sphinx-quickstart on Fri Dec 1 12:56:03 2017. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Adafruit-BBIO' +copyright = u'2017, Justin Cooper' +author = u'Justin Cooper' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'' +# The full version, including alpha/beta/rc tags. +release = u'1.0.9' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Adafruit-BBIOdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'Adafruit-BBIO.tex', u'Adafruit-BBIO Documentation', + u'Justin Cooper', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'adafruit-bbio', u'Adafruit-BBIO Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'Adafruit-BBIO', u'Adafruit-BBIO Documentation', + author, 'Adafruit-BBIO', 'One line description of project.', + 'Miscellaneous'), +] + +autodoc_member_order = 'groupwise' +#autoclass_content = 'both' + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..9241ca6 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,91 @@ +.. Adafruit-BBIO documentation master file, created by + sphinx-quickstart on Fri Dec 1 12:56:03 2017. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Adafruit Beaglebone IO Python API +================================= + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +:mod:`Encoder` --- Quadrature Encoder interface +----------------------------------------------- + +.. automodule:: Adafruit_BBIO.Encoder + :members: + +:mod:`PWM` --- Pulse Width Modulation interface +----------------------------------------------- + +Enables access to the Pulse Width Modulation (PWM) module, to easily and +accurately generate a PWM output signal of a given duty cycle and +frequency. + +.. module:: Adafruit_BBIO.PWM + +.. function:: start(channel, duty_cycle[, frequency=2000, polarity=0]) + + Set up and start the given PWM channel. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. + :type duty_cycle: int + :param frequency: PWM frequency, in Hz. It must be greater than 0. + :type frequency: int + :param polarity: defines whether the value for ``duty_cycle`` affects the + rising edge or the falling edge of the waveform. Allowed values -- 0 + (rising edge, default) or 1 (falling edge). + :type polarity: int + +.. function:: stop(channel) + + Stop the given PWM channel. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + +.. function:: set_duty_cycle(channel, duty_cycle) + + Change the duty cycle of the given PWM channel. + + :note: You must have started the PWM channel with :func:`start()` + once, before changing the duty cycle. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. + :type duty_cycle: int + +.. function:: set_frequency(channel, frequency) + + Change the frequency of the given PWM channel. + + :note: You must have started the PWM channel with :func:`start()` + once, before changing the frequency. + + :param channel: PWM channel. It can be specified in the form + of of 'P8_10', or 'EHRPWM2A'. + :type channel: str + :param frequency: PWM frequency. It must be greater than 0. + :type frequency: int + +.. function:: cleanup() + + Clean up by resetting all GPIO channels that have been used by this + program to INPUT, with no pullup/pulldown and no event detection. + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + + From 47aa372a5bdaf81fdbca5f530709328d804b194f Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 18:24:03 +0100 Subject: [PATCH 16/34] Made kernel version check to happen only if running on a beaglebone. The readthedocs builders that import the Encoder module have an old 3.3 kernel and the autodoc build fails --- .gitignore | 3 +++ Adafruit_BBIO/Encoder.py | 18 ++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index e948a66..facfc35 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ test-driver docs/_build docs/_static docs/_templates + +# vim temp files +*~ diff --git a/Adafruit_BBIO/Encoder.py b/Adafruit_BBIO/Encoder.py index ecfd27a..39c40b6 100644 --- a/Adafruit_BBIO/Encoder.py +++ b/Adafruit_BBIO/Encoder.py @@ -11,7 +11,8 @@ Example: To use the module, you can connect a rotary encoder to your Beaglebone - and then simply instantiate the :class:`RotaryEncoder` class to read its position:: + and then simply instantiate the :class:`RotaryEncoder` class to read its + position:: from Adafruit_BBIO.Encoder import RotaryEncoder, eQEP2 @@ -65,7 +66,8 @@ import platform (major, minor, patch) = platform.release().split("-")[0].split(".") -if not (int(major) >= 4 and int(minor) >= 4): +if not (int(major) >= 4 and int(minor) >= 4) \ + and platform.node() == 'beaglebone': raise ImportError( 'The Encoder module requires Linux kernel version >= 4.4.x.\n' 'Please upgrade your kernel to use this module.\n' @@ -76,16 +78,16 @@ '''eQEP0 channel identifier, pin A-- P9.92, pin B-- P9.27 on Beaglebone Black.''' eQEP1 = 1 -'''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone +'''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone Black.''' eQEP2 = 2 '''eQEP2 channel identifier, pin A-- P8.12, pin B-- P8.11 on Beaglebone Black. Note that there is only one eQEP2 module. This is one alternative set of pins where it is exposed, which is mutually-exclusive with eQEP2b''' eQEP2b = 3 -'''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone Black. -Note that there is only one eQEP2 module. This is one alternative set of pins -where it is exposed, which is mutually-exclusive with eQEP2''' +'''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone +Black. Note that there is only one eQEP2 module. This is one alternative set of +pins where it is exposed, which is mutually-exclusive with eQEP2''' # Definitions to initialize the eQEP modules _OCP_PATH = "/sys/devices/platform/ocp" @@ -318,14 +320,13 @@ def position(self, position): self._logger.debug("Set position: Channel {}, position: {}".format( self._eqep.channel, position)) - @property def frequency(self): '''Sets the frequency in Hz at which the driver reports new positions. ''' - frequency = self._NS_FACTOR / int(self._eqep.node.period) + frequency = self._NS_FACTOR / int(self._eqep.node.period) self._logger.debug( "Set frequency(): Channel {}, frequency: {} Hz, " @@ -352,3 +353,4 @@ def zero(self): '''Resets the current position to 0''' self.position = 0 + From fa5a786ab3563b0fb0474da8a5e364115860fd14 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 18:47:03 +0100 Subject: [PATCH 17/34] Use the default readthedocs theme --- docs/conf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 2ac0431..556134c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -102,11 +102,15 @@ # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { '**': [ - 'relations.html', # needs 'show_related': True theme option to display 'searchbox.html', + 'localtoc.html' ] } +html_theme = "default" +html_theme_options = { + #"show_related": "true" +} # -- Options for HTMLHelp output ------------------------------------------ From 24337296dd0e25fbd28bcc86617e8588845fd87b Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 18:56:51 +0100 Subject: [PATCH 18/34] Use readthedocs theme if building docs there, remove redundand search link --- docs/conf.py | 10 ++++++---- docs/index.rst | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 556134c..0412db1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -107,10 +107,12 @@ ] } -html_theme = "default" -html_theme_options = { - #"show_related": "true" -} +# Use the readthedocs theme if the documentation is being built there +on_rtd = os.environ.get('READTHEDOCS') == 'True' +if on_rtd: + html_theme = 'default' +else: + html_theme = 'alabaster' # -- Options for HTMLHelp output ------------------------------------------ diff --git a/docs/index.rst b/docs/index.rst index 9241ca6..4b930ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -86,6 +86,5 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` -* :ref:`search` From be0a908142b59a03245922d0f222ebc07c6a6ae6 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 19:52:04 +0100 Subject: [PATCH 19/34] Readthedocs theme tweaks --- docs/conf.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0412db1..a620f16 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -100,19 +100,22 @@ # # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'searchbox.html', - 'localtoc.html' - ] -} # Use the readthedocs theme if the documentation is being built there on_rtd = os.environ.get('READTHEDOCS') == 'True' if on_rtd: html_theme = 'default' + html_theme_options = { + 'collapse_navigation': False, + } else: html_theme = 'alabaster' + html_sidebars = { + '**': [ + 'searchbox.html', + 'localtoc.html' + ] + } # -- Options for HTMLHelp output ------------------------------------------ From f9212b26760477baf55738863918b8bf77c9e2e3 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 20:14:42 +0100 Subject: [PATCH 20/34] Removed redundant TOC, added global description --- docs/index.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 4b930ad..2a7fdb4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,9 +6,8 @@ Adafruit Beaglebone IO Python API ================================= -.. toctree:: - :maxdepth: 2 - :caption: Contents: +The Adafruit Beaglebone IO API enables access to the Beaglebone's GPIO, PWM, +ADC, UART and eQEP hardware modules from Python programs. :mod:`Encoder` --- Quadrature Encoder interface ----------------------------------------------- From 0dc0ca73ab67bee4fb7c29d9ad16a34a22451cea Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 20:32:16 +0100 Subject: [PATCH 21/34] Added UART documentation --- docs/index.rst | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 2a7fdb4..f4c8830 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -79,6 +79,44 @@ frequency. Clean up by resetting all GPIO channels that have been used by this program to INPUT, with no pullup/pulldown and no event detection. +:mod:`UART` --- UART communications interface +--------------------------------------------- + +UART functionality of a BeagleBone using Python. Generally used to set up +and grant access to a given UART device, which will then be accessed by +other software or modules (e.g. `pyserial`):: + + sudo pip install pyserial + +Example:: + + import Adafruit_BBIO.UART as UART + import serial + + UART.setup("UART1") + + ser = serial.Serial(port = "/dev/ttyO1", baudrate=9600) + ser.close() + ser.open() + if ser.isOpen(): + print "Serial is open!" + ser.write("Hello World!") + ser.close() + +.. function:: setup_uart(channel) + + Set up and start the UART channel. This function will effectively export + the given UART so that it can be accessed by other software that controls + its serial lines. + + :param channel: UART channel to set up. One of "UART1", "UART2", + "UART4" or "UART5" + :type channel: str + +.. function:: cleanup() + + Cleans up the UART. + Indices and tables ================== From f0487a7a3368fe9d8e54ff7fdb20dde10536a0e2 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 23:23:13 +0100 Subject: [PATCH 22/34] Added documentation badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e4db1e2..5fcaa57 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Adafruit BeagleBone I/O Python Library (Adafruit_BBIO) +[![Documentation Status](https://readthedocs.org/projects/adafruit-beaglebone-io-python/badge/?version=latest)](http://adafruit-beaglebone-io-python.readthedocs.io/en/latest/?badge=latest) + * Adafruit_BBIO is a set of Python tools to allow [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc) and [UART](README.md#uart) access on the BeagleBone * It is recommended to use an [official BeagleBoard.org Debian image](https://beagleboard.org/latest-images) From 330b0f270a49d1c459f0756a8aaa9896eee27110 Mon Sep 17 00:00:00 2001 From: David Planella Date: Fri, 1 Dec 2017 23:38:31 +0100 Subject: [PATCH 23/34] Added ADC API docs, fixed UART module definition --- docs/index.rst | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index f4c8830..899e365 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -103,6 +103,8 @@ Example:: ser.write("Hello World!") ser.close() +.. module:: Adafruit_BBIO.UART + .. function:: setup_uart(channel) Set up and start the UART channel. This function will effectively export @@ -117,6 +119,38 @@ Example:: Cleans up the UART. +:mod:`ADC` --- A/D Converter input interface +-------------------------------------------- + +This module enables reading analog input values from the analog to digital +converter (ADC) on the Beaglebone processor. + +Example:: + + import Adafruit_BBIO.ADC as ADC + + ADC.setup() + + # The read method returns normalized values from 0 to 1.0 + value = ADC.read("P9_40") + + # The read_raw returns non-normalized values + value = ADC.read_raw("P9_40") + +.. module:: Adafruit_BBIO.ADC + +.. function:: setup_adc() + + Setup and start the ADC hardware. + +.. function:: setup_read() + + Read the normalized 0-1.0 analog value for the channel. + +.. function:: setup_read_raw() + + Read the raw analog value for the channel. + Indices and tables ================== From 191b21408e9f208e7d254a0f8ddf613a34329e8d Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 00:59:33 +0100 Subject: [PATCH 24/34] API docs: added SPI module --- docs/index.rst | 124 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 18 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 899e365..7266140 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,25 +28,20 @@ frequency. Set up and start the given PWM channel. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str - :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. - :type duty_cycle: int - :param frequency: PWM frequency, in Hz. It must be greater than 0. - :type frequency: int - :param polarity: defines whether the value for ``duty_cycle`` affects the + :param int duty_cycle: PWM duty cycle. It must have a value from 0 to 100. + :param int frequency: PWM frequency, in Hz. It must be greater than 0. + :param int polarity: defines whether the value for ``duty_cycle`` affects the rising edge or the falling edge of the waveform. Allowed values -- 0 (rising edge, default) or 1 (falling edge). - :type polarity: int .. function:: stop(channel) Stop the given PWM channel. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str .. function:: set_duty_cycle(channel, duty_cycle) @@ -55,11 +50,9 @@ frequency. :note: You must have started the PWM channel with :func:`start()` once, before changing the duty cycle. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str - :param duty_cycle: PWM duty cycle. It must have a value from 0 to 100. - :type duty_cycle: int + :param int duty_cycle: PWM duty cycle. It must have a value from 0 to 100. .. function:: set_frequency(channel, frequency) @@ -68,11 +61,9 @@ frequency. :note: You must have started the PWM channel with :func:`start()` once, before changing the frequency. - :param channel: PWM channel. It can be specified in the form + :param str channel: PWM channel. It can be specified in the form of of 'P8_10', or 'EHRPWM2A'. - :type channel: str - :param frequency: PWM frequency. It must be greater than 0. - :type frequency: int + :param int frequency: PWM frequency. It must be greater than 0. .. function:: cleanup() @@ -151,6 +142,103 @@ Example:: Read the raw analog value for the channel. +:mod:`SPI` --- Serial Peripheral Interface +------------------------------------------ + +This module defines an object type that allows Serial Peripheral Interface +(SPI) bus transactions on hosts running the Linux kernel. The host kernel +must have SPI support and SPI device interface support. + +Because the SPI device interface is opened R/W, users of this module +usually must have root permissions or be members of a group with granted +access rights. + +Example:: + + import Adafruit_BBIO.SPI as SPI + + from Adafruit_BBIO.SPI import SPI + # spi = SPI(bus, device) #/dev/spidev. + + # /dev/spidev0.0 + spi = SPI(1, 0) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + + # /dev/spidev0.1 + spi = SPI(1,1) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + + # /dev/spidev1.0 + spi = SPI(2,0) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + + # /dev/spidev1.1 + spi = SPI(2,1) + print(spi.xfer2([32, 11, 110, 22, 220])) + spi.close() + +.. module:: Adafruit_BBIO.SPI + +.. class:: SPI(bus, client) + + :param bus: bus number + :param client: client number + :returns: a new SPI object, optionally connected to the specified SPI + device interface. + :rtype: :class:`SPI` + + .. method:: open(bus, device) + + Connects the object to the specified SPI device. `open(X, Y)` will open + `/dev/spidev-X.Y` + + :param int bus: bus number + :param str device: device number + + .. method:: close() + + Disconnects the object from the interface. + + .. method:: readbytes(len) + + Read the specified length of bytes from the SPI device. + + :param int len: length of bytes to read, 1024 maximum. + :returns: values read + :rtype: list[int] + + .. method:: writebytes(values) + + Write bytes to the SPI device. + + :param values: list of values to write, with a maximum length of 1024. + :type values: list[int] + + .. method:: xfer(values[,delay=0]) + + xfer([values]) -> [values] + Perform an SPI transaction of values. Slave Select (SS or CS) will be + released and reactivated between blocks. + + :param values: list of values to transfer, with a maximum length of 1024. + :type values: list[int] + :param delay: delay in microseconds between blocks. + :returns: values transferred + :rtype: list[int] + + .. method:: xfer2(values) + + xfer2([values]) -> [values] + Perform an SPI transaction of values. Slave Select (SS or CS) will be + held active between blocks. + + :param values: list of values to transfer, with a maximum length of 1024. + :type values: list[int] + :returns: values transferred + :rtype: list[int] Indices and tables ================== From 2769792028df6a7c425de8e2c459f428f2665536 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 01:12:37 +0100 Subject: [PATCH 25/34] Added SPI module attribute docs --- docs/index.rst | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 7266140..1dbb02f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -184,12 +184,40 @@ Example:: .. class:: SPI(bus, client) - :param bus: bus number - :param client: client number + :param bus: bus number. + :param client: client number. :returns: a new SPI object, optionally connected to the specified SPI device interface. :rtype: :class:`SPI` + .. attribute:: bpw + + Bits per word. + + .. attribute:: cshigh + + Chip Select (CS or Slave Select, SS) active high. + + .. attribute:: loop + + Loopback configuration. + + .. attribute:: lsbfirst + + Least Significant Bit (LSB) first. + + .. attribute:: mode + + SPI mode as two bit pattern of Clock Polarity and Phase [CPOL|CPHA]; min-- 0b00 = 0, max-- 0b11 = 3. + + .. attribute:: msh + + Maximum speed in Hz. + + .. attribute:: threewire + + SI/SO signals are shared. + .. method:: open(bus, device) Connects the object to the specified SPI device. `open(X, Y)` will open From e955585000eefdc338ae997062f52cb2c4893aa0 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 02:31:21 +0100 Subject: [PATCH 26/34] Added Python badges to README file --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5fcaa57..d501a72 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Adafruit BeagleBone I/O Python Library (Adafruit_BBIO) [![Documentation Status](https://readthedocs.org/projects/adafruit-beaglebone-io-python/badge/?version=latest)](http://adafruit-beaglebone-io-python.readthedocs.io/en/latest/?badge=latest) +[![PyPI version](https://badge.fury.io/py/Adafruit_BBIO.svg)](https://badge.fury.io/py/Adafruit_BBIO) +[![PyPI pyversions](https://img.shields.io/pypi/pyversions/Adafruit_BBIO.svg)](https://pypi.python.org/pypi/Adafruit_BBIO/) * Adafruit_BBIO is a set of Python tools to allow [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc) and [UART](README.md#uart) access on the BeagleBone From 4ab134b57257ee3e1eae2b3babcc6e5c8987d5e9 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 03:10:26 +0100 Subject: [PATCH 27/34] Added SPI pins table and first shot at GPIO module. Functions still need to be documented --- docs/index.rst | 109 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 1dbb02f..4ae5ced 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -102,9 +102,8 @@ Example:: the given UART so that it can be accessed by other software that controls its serial lines. - :param channel: UART channel to set up. One of "UART1", "UART2", + :param str channel: UART channel to set up. One of "UART1", "UART2", "UART4" or "UART5" - :type channel: str .. function:: cleanup() @@ -153,6 +152,16 @@ Because the SPI device interface is opened R/W, users of this module usually must have root permissions or be members of a group with granted access rights. +Pins used for SPI0 and SPI1 ++++++++++++++++++++++++++++ + +==== ===== ===== ===== ===== +PORT CS0 DO DI SCLK +==== ===== ===== ===== ===== +SPI0 P9_17 P9_21 P9_18 P9_22 +SPI1 P9_28 P9_29 P9_30 P9_31 +==== ===== ===== ===== ===== + Example:: import Adafruit_BBIO.SPI as SPI @@ -166,17 +175,17 @@ Example:: spi.close() # /dev/spidev0.1 - spi = SPI(1,1) + spi = SPI(1, 1) print(spi.xfer2([32, 11, 110, 22, 220])) spi.close() # /dev/spidev1.0 - spi = SPI(2,0) + spi = SPI(2, 0) print(spi.xfer2([32, 11, 110, 22, 220])) spi.close() # /dev/spidev1.1 - spi = SPI(2,1) + spi = SPI(2, 1) print(spi.xfer2([32, 11, 110, 22, 220])) spi.close() @@ -185,7 +194,7 @@ Example:: .. class:: SPI(bus, client) :param bus: bus number. - :param client: client number. + :param client: client device number. :returns: a new SPI object, optionally connected to the specified SPI device interface. :rtype: :class:`SPI` @@ -268,6 +277,94 @@ Example:: :returns: values transferred :rtype: list[int] +:mod:`GPIO` --- General Purpose I/O interface +--------------------------------------------- + +TODO + +Example:: + + # Use the config-pin command line tool to set a pin's function to GPIO + # Then you can control it with the GPIO module from Python + config-pin P9_14 gpio + + import Adafruit_BBIO.GPIO as GPIO + + # Set up pins as inputs or outputs + GPIO.setup("P8_13", GPIO.IN) + GPIO.setup("P8_14", GPIO.OUT) + GPIO.setup("GPIO0_26", GPIO.OUT) # Alternative: use actual pin names + + # Write a logic high or logic low + GPIO.output("P8_14", GPIO.HIGH) # You can also write '1' instead + GPIO.output("P8_14", GPIO.LOW) # You can also write '0' instead + +.. module:: Adafruit_BBIO.GPIO + +.. function:: setup() + + :param str channel: UART channel to set up. One of "UART1", "UART2", + "UART4" or "UART5" + +.. attribute:: ALT0 + + Pin mode-- alternate function 0. + +.. attribute:: BOTH + + Edge detection-- detect both edges. + +.. attribute:: FALLING + + Edge detection-- detect falling edge. + +.. attribute:: HIGH + + Pin status-- logic low. + +.. attribute:: IN + + Pin mode-- input. + +.. attribute:: LOW + + Pin status-- logic low. + +.. attribute:: OUT + + Pin mode-- output. + +.. attribute:: PUD_OFF + + Pull-up/pull-down resistor type-- no pull-up/pull-down. + +.. attribute:: PUD_DOWN + + Pull-up/pull-down resistor type-- pull-down. + +.. attribute:: PUD_UP + + Pull-up/pull-down resistor type-- pull-up. + +.. attribute:: RISING + + Edge detection-- detect rising edge. + +.. attribute:: VERSION + + GPIO module version. + +.. function:: cleanup() +.. function:: output() +.. function:: input() +.. function:: add_event_detect() +.. function:: remove_event_detect() +.. function:: add_event_detected() +.. function:: add_event_callback() +.. function:: wait_for_edge() +.. function:: gpio_function() +.. function:: setwarnings() + Indices and tables ================== From 6e0cf949dbd3c58ef6dcf1788d063b6ea9445d42 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 14:04:40 +0100 Subject: [PATCH 28/34] Documented the API docs build process --- docs/README.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..abe18a1 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,67 @@ +# Generating API documentation + +This folder contains the required files to automatically generate the Adafruit Beaglebone I/O Python API documentation, partly from the code docstrings and partly from a reStructuredText-formatted `index.rst` file. + +``` +├── conf.py <- Sphinx configuration file +├── index.rst <- Documentation will be generated based on this +└── Makefile <- Auxiliary Makefile to build documentation +``` + +The tools used are [http://www.sphinx-doc.org](Sphinx) to extract the documentation and publish it in HTML format for online viewing, in combination with [Readthedocs](http://readthedocs.io), which automatically executes Sphinx via webhooks triggered by Github commits, and publishes the resulting docs for all tracked branches. Generally Readthedocs will be set up to track stable release branches and master. + +## Building the documentation + +The documentation can also be built on a local checkout of the project: + +First ensure you've got sphinx installed: + +``` +sudo pip install sphinx +``` + +Then you can build the HTML docs: + +``` +cd docs +make html +``` + +Once Sphinx has built the documentation, you can open the main index file with your browser: `_build/html/index.html` + +Notes: + +- The build process will create three additional temporary directories: `_build`, `_static` and `_templates` that will not be version-controlled. You can use `make clean` to remove their contents if you wish to do so. +- The html theme from files built locally is different from the online readthedocs theme. See the `docs/config.py` `html_theme` variable. The main reason is not to introduce another dependency to install the readthedocs theme, but as a side effect, it also helps visually distinguishing the locally-built documentation from the online version. + +## Readthedocs maintenance + +At every release that includes documenation (most probably 1.0.10 will be the first one), the release's branch needs to be selected in the web UI and marked as active. + +After this, documentation will automatically be generated and published for that release. It will be available at the same URL as the main documentation, and a link with the version number will be shown, where it can be accessed from. + +Optionally, the 'stable' URL slug can be pointed to that release branch. Otherwise, the 'stable' slug can also be deactivated for less maintenance overhead. + +The 'latest' URL slug will always be pointing at the repo's master branch. + +## Notes + +Ideally, all API documentation would be written in the source files as Python docstrings, and sphinx would simply extract it. This is actually the case with the `Encoder` module, which is pure Python. + +However, most of the code is written as C extensions. While they do provide docstrings once they are built, Sphinx does not natively support extracting them. There is [a workaround](https://stackoverflow.com/a/30110104/9022675) to do this, but it involves first building the extensions, installing them and hardcoding a path. While it might work for locally-built documentation, it's unlikely that readthedocs support this option. + +For the sake of keeping things simple and with less maintenance, the approach of documenting the C-generated API in the `index.rst` file has been taken. + +This has the advantage of having a definition of the API in one place, but it also poses the disadvantage of some duplication, as the C modules do define some docstrings for their objects. Then again, the API itself has hardly changed in the last few years, and the Beaglebone is a mature platform, so it's unlikely that this will pose a significant maintenance overhead. + +- The documentation in Python modules follows the Google readable docstring markup, which is fully supported by Sphinx. +- The documentation in the `index.rst` file is written in [reStructuredText](http://docutils.sourceforge.net/rst.html), with Sphinx markup for defining the objects. + +## Further reference + +- [Google readable docstring markup](https://google.github.io/styleguide/pyguide.html?showone=Comments#Comments) +- [Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) +- [More Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html)) +- [Sphinx docstring markup](http://www.sphinx-doc.org/en/stable/domains.html#the-python-domain) + + From 30794971cf0d4464c655d2f9cbf936eb52bc272d Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 14:15:12 +0100 Subject: [PATCH 29/34] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d501a72..66f8414 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Adafruit BeagleBone I/O Python Library (Adafruit_BBIO) +# Adafruit Beaglebone I/O Python API [![Documentation Status](https://readthedocs.org/projects/adafruit-beaglebone-io-python/badge/?version=latest)](http://adafruit-beaglebone-io-python.readthedocs.io/en/latest/?badge=latest) [![PyPI version](https://badge.fury.io/py/Adafruit_BBIO.svg)](https://badge.fury.io/py/Adafruit_BBIO) [![PyPI pyversions](https://img.shields.io/pypi/pyversions/Adafruit_BBIO.svg)](https://pypi.python.org/pypi/Adafruit_BBIO/) -* Adafruit_BBIO is a set of Python tools to allow [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc) and [UART](README.md#uart) access on the BeagleBone +Adafruit BBIO is an API to enable [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc), [UART](README.md#uart), SPI and eQEP hardware access from Python applications running on the Beaglebone. * It is recommended to use an [official BeagleBoard.org Debian image](https://beagleboard.org/latest-images) * **Currently recommended image: [Debian 9.2 "Stretch" iot (2017-10-29)](https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#microSD.2FStandalone:_.28stretch-iot.29_.28All_BeagleBone_Variants_.26_PocketBeagle.29)** From a86300f18480cc3c71f1644efb0f00594a504f17 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 15:56:13 +0100 Subject: [PATCH 30/34] Added some more API doc content --- docs/README.md | 9 +++++---- docs/index.rst | 29 +++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/README.md b/docs/README.md index abe18a1..4f88a47 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,7 +3,7 @@ This folder contains the required files to automatically generate the Adafruit Beaglebone I/O Python API documentation, partly from the code docstrings and partly from a reStructuredText-formatted `index.rst` file. ``` -├── conf.py <- Sphinx configuration file +├── conf.py <- Sphinx configuration file ├── index.rst <- Documentation will be generated based on this └── Makefile <- Auxiliary Makefile to build documentation ``` @@ -54,14 +54,15 @@ For the sake of keeping things simple and with less maintenance, the approach of This has the advantage of having a definition of the API in one place, but it also poses the disadvantage of some duplication, as the C modules do define some docstrings for their objects. Then again, the API itself has hardly changed in the last few years, and the Beaglebone is a mature platform, so it's unlikely that this will pose a significant maintenance overhead. -- The documentation in Python modules follows the Google readable docstring markup, which is fully supported by Sphinx. -- The documentation in the `index.rst` file is written in [reStructuredText](http://docutils.sourceforge.net/rst.html), with Sphinx markup for defining the objects. +- The documentation in the `index.rst` file is written in [reStructuredText](http://docutils.sourceforge.net/rst.html), extended with Sphinx markup for defining the objects. +- The documentation in Python modules follows the Google readable docstring markup, which also builds upon reStructuredText and is fully supported by Sphinx. ## Further reference - [Google readable docstring markup](https://google.github.io/styleguide/pyguide.html?showone=Comments#Comments) - [Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) -- [More Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html)) +- [More Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) - [Sphinx docstring markup](http://www.sphinx-doc.org/en/stable/domains.html#the-python-domain) +- [reStructuredText primer](http://www.sphinx-doc.org/en/stable/rest.html#rst-primer) diff --git a/docs/index.rst b/docs/index.rst index 4ae5ced..4011231 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,6 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. +.. toctree:: + :hidden: + :maxdepth: 2 + Adafruit Beaglebone IO Python API ================================= @@ -22,6 +26,14 @@ Enables access to the Pulse Width Modulation (PWM) module, to easily and accurately generate a PWM output signal of a given duty cycle and frequency. +.. note:: + + You need to be part of the ``pwm`` group of the OS running on the + Beaglebone to be able to run PWM code as a non-root user. The default + user created upon the Debian image installation should already be + part of the group. Otherwise, you can use + ``sudo usermod -a -G pwm userName`` to add ``userName`` to the group. + .. module:: Adafruit_BBIO.PWM .. function:: start(channel, duty_cycle[, frequency=2000, polarity=0]) @@ -256,7 +268,6 @@ Example:: .. method:: xfer(values[,delay=0]) - xfer([values]) -> [values] Perform an SPI transaction of values. Slave Select (SS or CS) will be released and reactivated between blocks. @@ -268,7 +279,6 @@ Example:: .. method:: xfer2(values) - xfer2([values]) -> [values] Perform an SPI transaction of values. Slave Select (SS or CS) will be held active between blocks. @@ -282,6 +292,21 @@ Example:: TODO +.. note:: + + You need to be part of the ``gpio`` group of the OS running on the + Beaglebone to be able to run GPIO code as a non-root user. The default + user created upon the Debian image installation should already be + part of the group. Otherwise, you can use + ``sudo usermod -a -G gpio userName`` to add ``userName`` to the group. + +.. note:: + + When coding with this module, you will often be using pin names for + better readability. For easy reference, you can use the + `Beaglebone pin names table `_ + + Example:: # Use the config-pin command line tool to set a pin's function to GPIO From 6e9ea9245da1db985314f3f55bdcd0042bbee668 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 16:27:48 +0100 Subject: [PATCH 31/34] Minor documentation and configuration improvements --- Adafruit_BBIO/Encoder.py | 2 +- docs/conf.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Adafruit_BBIO/Encoder.py b/Adafruit_BBIO/Encoder.py index 39c40b6..d2915c9 100644 --- a/Adafruit_BBIO/Encoder.py +++ b/Adafruit_BBIO/Encoder.py @@ -246,7 +246,7 @@ def mode(self): Returns: int: 0 if the eQEP channel is configured in absolute mode, - 1 if configured in relative mode. + 1 if configured in relative mode. ''' mode = int(self._eqep.node.mode) diff --git a/docs/conf.py b/docs/conf.py index a620f16..d99d788 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,8 +46,8 @@ # General information about the project. project = u'Adafruit-BBIO' -copyright = u'2017, Justin Cooper' -author = u'Justin Cooper' +copyright = u'2017, Adafruit Industries and contributors' +author = u'Justin Cooper and contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -82,7 +82,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +# html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the From f12715b2772420245ed4368334cd407df4cc7732 Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 18:19:00 +0100 Subject: [PATCH 32/34] Finished documenting GPIO --- .gitignore | 1 + Adafruit_BBIO/Encoder.py | 9 +++ docs/conf.py | 4 +- docs/index.rst | 136 ++++++++++++++++++++++++++++++++------- 4 files changed, 124 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index facfc35..06eca82 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ docs/_templates # vim temp files *~ +*.swp diff --git a/Adafruit_BBIO/Encoder.py b/Adafruit_BBIO/Encoder.py index d2915c9..21c88c1 100644 --- a/Adafruit_BBIO/Encoder.py +++ b/Adafruit_BBIO/Encoder.py @@ -9,6 +9,15 @@ The channel identifiers are available as module variables :data:`eQEP0`, :data:`eQEP1`, :data:`eQEP2` and :data:`eQEP2b`. +======= ======= ======= =================================================== +Channel Pin A Pin B Notes +======= ======= ======= =================================================== +eQEP0 P9.27 P9.92 +eQEP1 P8.33 P8.35 Only available with video disabled +eQEP2 P8.11 P8.12 Only available with eQEP2b unused (same channel) +eQEP2b P8.41 P8.42 Only available with video disabled and eQEP2 unused +======= ======= ======= =================================================== + Example: To use the module, you can connect a rotary encoder to your Beaglebone and then simply instantiate the :class:`RotaryEncoder` class to read its diff --git a/docs/conf.py b/docs/conf.py index d99d788..c002fc2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -54,9 +54,9 @@ # built documents. # # The short X.Y version. -version = u'' +version = u'1.0' # The full version, including alpha/beta/rc tags. -release = u'1.0.9' +release = u'' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/index.rst b/docs/index.rst index 4011231..3d39377 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,7 +22,7 @@ ADC, UART and eQEP hardware modules from Python programs. :mod:`PWM` --- Pulse Width Modulation interface ----------------------------------------------- -Enables access to the Pulse Width Modulation (PWM) module, to easily and +Enables access to the Pulse Width Modulation (PWM) module, to easily and accurately generate a PWM output signal of a given duty cycle and frequency. @@ -160,7 +160,7 @@ This module defines an object type that allows Serial Peripheral Interface (SPI) bus transactions on hosts running the Linux kernel. The host kernel must have SPI support and SPI device interface support. -Because the SPI device interface is opened R/W, users of this module +Because the SPI device interface is opened R/W, users of this module usually must have root permissions or be members of a group with granted access rights. @@ -184,22 +184,22 @@ Example:: # /dev/spidev0.0 spi = SPI(1, 0) print(spi.xfer2([32, 11, 110, 22, 220])) - spi.close() + spi.close() # /dev/spidev0.1 spi = SPI(1, 1) print(spi.xfer2([32, 11, 110, 22, 220])) - spi.close() + spi.close() # /dev/spidev1.0 spi = SPI(2, 0) print(spi.xfer2([32, 11, 110, 22, 220])) - spi.close() + spi.close() # /dev/spidev1.1 spi = SPI(2, 1) print(spi.xfer2([32, 11, 110, 22, 220])) - spi.close() + spi.close() .. module:: Adafruit_BBIO.SPI @@ -290,7 +290,8 @@ Example:: :mod:`GPIO` --- General Purpose I/O interface --------------------------------------------- -TODO +This module provides access and control of pins set up as General Purpose +I/O (GPIO). .. note:: @@ -302,8 +303,10 @@ TODO .. note:: - When coding with this module, you will often be using pin names for - better readability. For easy reference, you can use the + When coding with this module, you will be using pin names for + better readability. As such, you can specify them in the header 8 or 9 + form (e.g. "P8_16") or in pin name form (e.g. "GPIO1_14"). + For easy reference, you can use the `Beaglebone pin names table `_ @@ -326,10 +329,106 @@ Example:: .. module:: Adafruit_BBIO.GPIO -.. function:: setup() +.. function:: setup(channel, direction[, pull_up_down=:data:`PUD_OFF`, initial=None, delay=0]) - :param str channel: UART channel to set up. One of "UART1", "UART2", - "UART4" or "UART5" + Set up the given GPIO channel, its direction and (optional) pull/up down control + + :param str channel: GPIO channel to set up (e.g. "P8_16"). + :param int direction: GPIO channel direction (:data:`IN` or :data:`OUT`). + :param int pull_up_down: pull-up/pull-down resistor configuration + (:data:`PUD_OFF`, :data:`PUD_UP` or :data:`PUD_DOWN`). + :param int initial: initial value for an output channel (:data:`LOW`/:data:`HIGH`). + :param int delay: time in milliseconds to wait after exporting the GPIO pin. + +.. function:: cleanup() + + Clean up by resetting all GPIO channels that have been used by + the application to :data:`IN` with no pullup/pulldown and no event + detection. + +.. function:: output(channel, value) + + Set the given output channel to the given digital value. + + :param str channel: GPIO channel to output the value to (e.g. "P8_16"). + :param value: value to set the output to-- 0/1 or False/True + or :data:`LOW`/:data:`HIGH`. + :type value: int or bool + +.. function:: input(channel) + + Get the given input channel's digital value. + + :param str channel: GPIO channel to read the value from (e.g. "P8_16"). + :returns: Channel value–– 0 or 1. + :rtype: int + +.. function:: add_event_detect(channel, edge[, callback=None, bouncetime=0]) + + Enable edge detection events for the given GPIO channel. + + :param str channel: GPIO channel to detect events from (e.g. "P8_16"). + :param int edge: edge to detect–– :data:`RISING`, :data:`FALLING` + or :data:`BOTH` + :param func callback: a function to call once the event has been detected. + :param int bouncetime: switch bounce timeout in ms for the callback. + +.. function:: remove_event_detect(channel) + + Remove edge detection for the given GPIO channel. + + :param str channel: GPIO channel to remove event detection + from (e.g. "P8_16"). + +.. function:: event_detected(channel) + + Checks if an edge event has occured on a given GPIO. + + :note: You need to enable edge detection using :func:`add_event_detect()` first. + + :param str channel: GPIO channel to check for event detection + for (e.g. "P8_16"). + :returns: True if an edge has occured on a given GPIO, False otherwise + :rtype: bool + +.. function:: add_event_callback(channel, callback[, bouncetime=0]) + + Add a callback for an event already defined using :func:`add_event_detect()` + + :param str channel: GPIO channel to add a callback to (e.g. "P8_16"). + :param func callback: a function to call once the event has been detected. + :param int bouncetime: switch bounce timeout in ms for the callback. + +.. function:: wait_for_edge(channel, edge[, timeout=-1]) + + Wait for an edge on the given channel. + + :param str channel: GPIO channel to wait on (e.g. "P8_16"). + :param int edge: edge to detect–– :data:`RISING`, :data:`FALLING` + or :data:`BOTH` + :param int timeout: time to wait for an edge, in milliseconds. + -1 will wait forever. + +.. function:: gpio_function(channel) + + Return the current GPIO function + (:data:`IN`, :data:`IN`, :data:`ALT0`) of the given pin. + + :warning: Currently only returning the direction of the + pin (input or output) is supported. + + :param str channel: GPIO pin to query the status of. + :returns: 0 if :data:`IN`, 1 if :data:`OUT` + :rtype: int + +.. function:: setwarnings(gpio_warnings) + + Enable or disable GPIO warning messages. + + :warning: Currently enabling or disabling warnings + has no effect. + + :param int gpio_warnings: 0–– disable warnings; 1–– enable warnings .. attribute:: ALT0 @@ -377,18 +476,7 @@ Example:: .. attribute:: VERSION - GPIO module version. - -.. function:: cleanup() -.. function:: output() -.. function:: input() -.. function:: add_event_detect() -.. function:: remove_event_detect() -.. function:: add_event_detected() -.. function:: add_event_callback() -.. function:: wait_for_edge() -.. function:: gpio_function() -.. function:: setwarnings() + GPIO module version. Currently unused. Indices and tables ================== From 55aa0a9da4cefd624680e1066135f3dd207d7f8f Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 18:25:48 +0100 Subject: [PATCH 33/34] rST fixes --- docs/index.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 3d39377..252ce6e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -329,7 +329,7 @@ Example:: .. module:: Adafruit_BBIO.GPIO -.. function:: setup(channel, direction[, pull_up_down=:data:`PUD_OFF`, initial=None, delay=0]) +.. function:: setup(channel, direction[, pull_up_down=PUD_OFF, initial=None, delay=0]) Set up the given GPIO channel, its direction and (optional) pull/up down control @@ -346,6 +346,9 @@ Example:: the application to :data:`IN` with no pullup/pulldown and no event detection. + :note: It's recommended that you call this function upon exiting your + application. + .. function:: output(channel, value) Set the given output channel to the given digital value. From 9d6aa46a61f77594d76cb8759f71e1dff3b4260e Mon Sep 17 00:00:00 2001 From: David Planella Date: Sat, 2 Dec 2017 18:57:58 +0100 Subject: [PATCH 34/34] Update README.md --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 4f88a47..e2b2188 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,7 +8,7 @@ This folder contains the required files to automatically generate the Adafruit B └── Makefile <- Auxiliary Makefile to build documentation ``` -The tools used are [http://www.sphinx-doc.org](Sphinx) to extract the documentation and publish it in HTML format for online viewing, in combination with [Readthedocs](http://readthedocs.io), which automatically executes Sphinx via webhooks triggered by Github commits, and publishes the resulting docs for all tracked branches. Generally Readthedocs will be set up to track stable release branches and master. +The tools used are [Sphinx](http://www.sphinx-doc.org) to extract the documentation and publish it in HTML format for online viewing, in combination with [Readthedocs](http://readthedocs.io), which automatically executes Sphinx via webhooks triggered by Github commits, and publishes the resulting docs for all tracked branches. Generally Readthedocs will be set up to track stable release branches and master. ## Building the documentation