piripherals’ documentation¶
Version 0.1a9
This library is intended to be used on the RaspberryPi primarily, but it also works on other platforms. The things, that are related to the hardware of the Pi, will not work on other devices, of course.
Attention
This is still in the beginning and work in progress! Many things will change!
Note
This is a Python 3 only library! - https://pythonclock.org/
Dependencies¶
This package has some soft dependencies. If you need them, depends on which partes of this library you actually want to use.
rpi_ws281x
https://pypi.python.org/pypi/rpi_ws281xRPi.GPIO
https://pypi.python.org/pypi/RPi.GPIOsmbus2
https://pypi.python.org/pypi/smbus2, but other smbus implementations like Raspbianspython-smbus
may work, toopython-mpd2
https://pypi.python.org/pypi/python-mpd2
Modules¶
piripherals.bus module¶
Wrapper classes to abstract bus access.
-
class
piripherals.bus.
Bus
(bus=1)[source]¶ Bases:
object
Abstraction for a data bus, i.e. I2C.
Parameters: bus – something with read and write methods. It does not have such methods, bus is passed to SMBus(bus)
.The
bus
need to have at least the following methodsread_byte_data(addr,reg)
->byte
write_byte_data(addr,reg,byte)
and additionally
read_word_data(addr,reg)
->word
write_word_data(addr,reg,work)
read_i2c_block_data(addr,reg,size)
->[byte,...]
write_i2c_block_data(addr,reg,[byte,...])
If these are not present, it will read/write words and blocks using
read_byte_data
andwrite_byte_data
.The bus usually is an
smbus.SMBus
orsmbus2.SMBus
instance.- https://pypi.python.org/pypi/smbus2/
- https://pypi.python.org/pypi/smbus-cffi/
- https://packages.debian.org/de/stretch/python-smbus
-
device
(addr)[source]¶ Get a Device.
Parameters: addr (int) – device address Returns: device at given address Return type: Device
-
read_block
(addr, reg, n)[source]¶ read a block of bytes.
Parameters: - addr (int) – address of device to read the block from
- reg (int) – base register, first byte of the block
- n (int) – # of bytes to read n<=32
Returns: bytes, that were read
Return type: list of int
-
read_byte
(addr, reg)[source]¶ read a byte.
Parameters: - addr (int) – address of device to read the byte from
- reg (int) – register to be read
Returns: the byte, that was read
Return type: int
-
read_word
(addr, reg)[source]¶ read a word (2 bytes).
Parameters: - addr (int) – address of device to read the word from
- reg (int) – base register, low byte of the word is there, high byte is at reg+1
Returns: the word, that was read
Return type: int
-
write_block
(addr, reg, block)[source]¶ write a block of bytes.
Parameters: - addr (int) – address of device to write the block to
- reg (int) – base register, first byte of the block
- block (list of int) – bytes to be written, len(block)<=32
piripherals.button module¶
Things that have to do with buttons, digital inputs.
Use GPIO pins as button inputs with debouncing and multi-click and hold-detection.
Bases:
object
Representation of a button with multi-click and hold-detection.
This was inspired by http://www.mathertel.de/Arduino/OneButtonLibrary.aspx, but extended to n-clicks and click-hold.
Note
Most debouncing code out there is wrong. The debounce functionality of RPi.GPIO just suppresses events, but does not debounce. Debouncing correctly in software is tricky but doable. Read this http://www.ganssle.com/debouncing.htm.
This button can be bound to GPIO pins but it can be used with other input sources as well.
What is click, hold, up/down, pressed/released?
The state of the button is updated by calling
update()
withTrue
orFalse
as argument (equivalently just calling the button, callingpress()
,release()
). Updating the state toTrue
is called press, updating the state toFalse
is called release.The state is changed when
update()
was called with a parameter different from the previous call. If the state did not change for a time >click_time
, the button in considered down (stated changed to pressed) or up (state changed to released). This effectivly debounces the input. The final state wins, but quick jumps between states are filtered out.The button is considered clicked when
- it was pressed for >
click_time
(click is counted) - and then released for >
double_click_time
(click is fired)
If it was pressed again after beeing released within <
double_click_time
, another click may be counted (start again at 1.). This way n-clicks can be detected.The button is considered held when it was pressed for >
hold_time
(enter hold state). There might have been preceding clicks, that have been counted, but not fired. This way we get n-hold, with n beeing the number of clicks preceding the hold. Hold events are fired as long as the button stays held withhold_repeat
delay, ifhold_repeat
> 0.Attention
Setting
when_clicked
orwhen_held
disables any handlers registered withon_click()
oron_hold()
. So there is either a single click/hold handler or a handler for each type of click/hold.Parameters: - pin (int) – BCM pin to bind to, 0 = do not use GPIO
- when_clicked (callable(n)) – click handler, n = # of clicks
- when_held (callable(n)) – hold handler, n = # of clicks before hold
- click_time (float) – seconds button needs to stay in pressed/released state to consider it a click (this does the debouncing)
- double_click_time (float) – max. seconds between clicks to count them as double clicks (or triple, or quadruple, …)
- hold_time (float) – seconds in pressed state after which button is considered held
- hold_repeat (float) – seconds between repeated hold events, when button stays held, 0 = disable hole repeat
- name (str) – name of the button for str() and debugging
bind to GPIO pin.
Note
The state of the GPIO will be polled regularly, but the polling is only started on demand after edge detection and runs for a limited time.
Parameters: - pin (int) – BCM pin number
- low_active (bool) – low means pressed
- pullup (int) – 1 = pullup, -1 = pulldown, 0 = nothing
- delay (float) – delay between polls in seconds
- count (int) – # of polls after button was released, this allows the polling to be paused if the button is untouched
check if button is down, respecting click_time
The button itself evaluated as
bool(button)
is equivalent tois_down()
:Returns: if down for > click_time Return type: bool
check if button is held, respecting hold_time
Returns: if down for > hold_time Return type: bool
check if button is up, respecting click_time
Returns: if up for > click_time Return type: bool
register a click handler.
Parameters: - n (int) – # of click to register the handler with, see
when_clicked()
- callback (callable) – the handler
- *args – args passed to handler
- **kwargs – kwargs passed to handler
- n (int) – # of click to register the handler with, see
register a hold handler.
Parameters: - n (int) – # of click to register the handler with, see
when_held()
- callback (callable) – the handler
- *args – args passed to handler
- **kwargs – kwargs passed to handler
- n (int) – # of click to register the handler with, see
update()
withpressed=True
update()
withpressed=False
update state.
When bound to GPIO this called automatically. You need to call this, when you want bind this button a different input source.
This can (and must be) call ed repeatedly (even with teh same pressed state) to allow the click and hold detection to work.
The button itself is callable, calling the button is equivalent to call
update()
.Parameters: - pressed (bool) – True = button is down, False = button is up
- now (float) – time when it change state (optional)
fired when clicked.
Parameters: n (int) – # of clicks, 1 = single click, 2 = double click, …
fired when held.
Parameters: n (int) – # of clicks before hold, 0 = hold, 1 = click + hold 2 = double click + hold
- it was pressed for >
piripherals.event module¶
-
class
piripherals.event.
Event
(name='event', condition=<function Event.<lambda>>)[source]¶ Bases:
object
Event with attached handlers and optional condition.
Parameters: - name (str) – name of the event, usuful for debugging
- condition (callable) – condition to suppress firing, if it evaluates to False
-
add
(handler)[source]¶ add an event handler.
Handlers can be added with
Event >> handler
.Parameters: handler (callable) – handler to attach. If the handler is an Event, its fire()
method will be attach as handler.
-
conditional
(cond)[source]¶ derive a new conditional event
A conditional Event can created with
Event & condition
.Parameters: condition (callable) – see Event
Returns: conditional Event, with this Event’s fire()
as handlerReturn type: Event
-
fire
(*args, **kwargs)[source]¶ Fire the event, call all attached handlers.
The event is only fired, if the condition evaluates to True. All arguments are passed to the handlers.
-
join
(other)[source]¶ derive Event as combination of two Events
Events can be joined with
EventA + EventB
. This differs fromadd()
, because it creates a new Event and leaves this untouched.Parameters: other (callable) – handler to join with, can be another Event Returns: Event with this and other’s fire()
as handlersReturn type: Event
-
queue
(*args, **kwargs)[source]¶ Enqueue the event on eventloop.
This is equivalent to just calling the Event itself.
fire()
will be enqueued in the eventloop, such that it will be called on the loop thread and not on the thread callingqueue()
. All arguments are passed to the handlers.
-
loop
= <piripherals.event.EventLoop object>¶
piripherals.led module¶
Things that have to do with controlling LEDs
-
class
piripherals.led.
NeoPixels
(*args, **kwargs)[source]¶ Bases:
object
an interface to NeoPixel LEDs based on rpi_ws281x.
This wraps around PixelStrip and adds additional functionality, especially asynchronous animation support.
Constructor arguments are passed to PixelStrip.
Parameters: - num (int) – # of LEDs on the strip
- pin (int) – BCM pin number of data pin. not all pins are allowed, see pin usage information of rpi_ws281x.
-
animate
(func, atexit=None, freq=1, period=0, timeout=0, cycles=0, fade=0, delay=0.01, wait=False)[source]¶ asynchronous animation
The animation is executed on a separate thread. The animation is stopped, when any function, that changes the state of the LEDs, is called. The animation is defined in
func
. This function gets passed 3 arguments:p
- raw PixelStrip, call methods of this to manipulate the LEDs,- which results in the animation
s
- normalized time in [0,1] in animation period, use this- to create cyclic animations
t
- time in seconds since startof animation
func
is called repeatedly withdelay
between the calls.Parameters: - func (callable(p,s,t)) – animation function
- atexit (callable()) – exit hook, function to call after animation
- freq (float) – animation frequency in Hz
- period (float) – animation period in seconds (freq=1/period), give either freq or period, period has higher priority
- timeout (float) – animation duration in seconds
- cycles (float) – animation cycle count, (timeout=cycles/freq) give either timeout or cycles, cycles has higher priority
- fade (float) – fade out animation over this number of seconds (sets timeout=fade)
- delay (float) – delay in seconds between calls of func
- wait (bool) – wait for animation to finish, synchronous animation, requires timeout
-
blink
(pattern='10', fade=0, color=None, **kwargs)[source]¶ blink LEDs on strip with given blink pattern.
Parameters: - pattern (str) – the blink pattern, that is played back in each
- period. It is either a str of 1 and 0 without space, (animation) –
- a str with space separated float brightness values. (or) –
for other args see
animate()
-
breathe
(n=1, fade=0, color=None, **kwargs)[source]¶ brightness breathing animation.
This was inspired by http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/.
Parameters: - n (float) – nonlinearity of brightness function
- color (tuple(r,g,b)) – color set on animation start
for other args see
animate()
-
brightness
(b=1)[source]¶ set brightness, affects all LEDs
Parameters: b (float) – brightness in range [0,1]
-
clock
(secs=1, **kwargs)[source]¶ a clock.
Works best on a circular strip with 12 LEDs. Hours are red, minutes are green, seconds are blue.
Parameters: secs (int) – show blue seconds 0 = do not show seconds, 1 = show blue seconds, 2 = flash white seconds in 12th position, 3 = run white seconds around in loop for other args see
animate()
-
color
(led=None, r=0, g=-1, b=-1, v=-1)[source]¶ set color
Parameters: - led (int) – # of LED on strip to set the color for, None = all LEDs
- r (float) – red value from range [0,1], if not given r = 0
- g (float) – green value from range [0,1], if not given g = r
- b (float) – blue value from range [0,1], if not given b = g
- v (float) – brightness, see
brightness()
, is applied to all LEDs
piripherals.mpd module¶
-
class
piripherals.mpd.
MPD
(maxvol=100, *args, **kwargs)[source]¶ Bases:
object
Wrapper for MPDClient that adds
- automatic reconnect on connection loss, see issue64.
- custom methods
- volume limit
It supports all methods of
MPDClient
.Parameters: - maxvol (int) – volume limit
- *args – args for
MPDClient
- **kwargs – kwargs for
MPDClient
-
connect
(*args, **kwargs)[source]¶ establish connection
disconnects if already connected, host and port are stored, will reconnect automatically if connection is lost
All parameters are passed to
MPDClient.connect()
.Parameters: - host (str) – hostname/ip/socket
- port (int) – port, usually 6600
-
del_playlist
(name)[source]¶ delete playlist
if playlist exists, this does nothing
Parameters: name (str) – name of the playlist to delete
-
has_playlist
(name)[source]¶ check for playlist
Parameters: name (str) – name of the playlist to look for Returns: true if playlist exists Return type: bool
-
load_playlist
(name)[source]¶ load a playlist
- replaces current playlist with the named playlist
- if the given playlist does not exists, this does nothing
Parameters: name (str) – name of the playlist to load
-
class
piripherals.mpd.
MPDPlaylist
(mpd, field='title')[source]¶ Bases:
object
the current playlist
Parameters: - mpd (MPD) – MPD instance to get the playlist from
- field (str) – metadata field to look for when getting metadata for an playlist entry. If this field is not present, play the track to retrieve the metadata, then switch back to previous state
-
find_next
(field='album')[source]¶ find next song with different field
Find the next song, where
field
has a different value than the currently playing song. Withfield='album'
, this gets the beginning of the next album.If there is only a single album in the playlist or the currently playing song is of the last album,
None
is returned.Returns: # of playlist entry or None Return type: int
-
find_prev
(field='album')[source]¶ find previous song with different field
Find the previous song, where
field
has a different value than the currently playing song. Withfield='album'
, this gets the beginning of the previous album.If there is only a single album in the playlist or the currently playing song is of the first album,
None
is returned.Returns: # of playlist entry or None Return type: int
piripherals.mpr121 module¶
a sane and complete interface to the MPR121 touch sensor
This is thought to be a replacement of the incomplete and undocumented Adafruit.MPR121 library.
Note
To fully understand this device, please read the datasheet.
Wiring the MPR121 to the RaspberryPi¶
Connect the pins of the MPR121 to the RaspberryPi according to the following table. In this doc and in the code, all Pi pin numbers are BCM pin numbers, physical pin numbers are set in round braces.
MPR121 | RaspberryPi |
---|---|
3.3V | 3.3V (1) |
GND | GND (6) |
SDA | BCM 2 (3) |
SCL | BCM 3 (5) |
IRQ* | BCM 4 (7) |
Connecting the IRQ line is optional but highly recommended to avoid unneccessary bus
traffic and CPU load due to polling. To be able to use the IRQ, you need to have
RPi.GPIO installed (apt-get install python-rpi.gpio
or pip install RPi.GPIO
).
You may use a different pin, adjust the number accordingly.
If you want to connect multiple MPR121s to the same bus, you can change their address with the address pin. Refer to the datasheet on how to do this.
Enable I2C access¶
The MPR121 uses I2C for communication. On the RaspberryPi running
Raspbian Stretch, you need to enable the I2C bus. To /boot/config.txt
add the lines:
dtparam=i2c_arm=on
dtparam=i2c1=on
and to /etc/modules
add:
i2c-dev
This should enable the /dev/i2c-1
(bus=1) device on boot. Install i2c-tools with:
apt-get install i2c-tools
and list the addresses of connected devices:
i2cdetect -y 1
For MPR121 being able to access the I2C bus, you need to have a Python smbus
implementation installed. Use python-smbus
from the distro or smbus2
(apt-get install python-smbus
or pip install smbus2
). Other implementations
may work, too.
Using MPR121¶
Attach the MPR121 to the Pi as described above and use it like:
from piripherals import MPR121
# MPR121 should come up and be running with 12 channels
mpr = MPR121(irq=4)
for i in range(12): # print status on touch and release
mpr.on_touch(i, lambda *x: print(x))
Simply instanciante it and assign touch handlers. For fine tuning and to userthe GPIO functionality, see the doc below.
Tip
Use the mpr121-dump
script to examine the MPR121’s response and to tune
the settings.
-
class
piripherals.mpr121.
MPR121
(bus=1, addr=90, irq=0, handlers=1, setup=1, reset=1, **kwargs)[source]¶ Bases:
object
MPR121 capacitive touch sensor and GPIO/LED controller.
It will be configured with sane defaults and started immediately.
Parameters: - bus (int) – I2C bus, 1 = /dev/i2c-1
- addr (int) – I2C address of the device
- irq (int) – BCM pin # that is connect to interrupt line, 0 disables IRQ, uses polling instead
- handlers (bool) – enable IRQ handler/polling, if disabled
update_touch_state()
has to be called explicitly - setup (bool) – configure with (sane) defaults
- reset (bool) – reset on initialization
- **kwargs – arguments to setup()
-
auto_config
(ace=1, are=1, bva=3, retry=2, afes=1, scts=0, acfie=1, arfie=1, oorie=1, usl=200, lsl=130, tl=180)[source]¶ Configure automatic adjustment eletrode change current and time.
Parameters: - ace (bool) – enable auto configuration
- are (bool) – enable auto reconfiguration
- bva (int) – baseline adjustment after current and time have been set: 0 = no change, 1 = set to zero, 2 = set 5MSBs to measured value, 3 = set to measured value.
- retry (int) – # of retries for auto configuration: 0-3 (0,2,4,8)
- afes (int) – # of AFE sample during search process, set to values as filter(ffi): 0-3 (6,10,18,34)
- scts (bool) – skip charge time search
- acfie (bool) – enable IRQ on auto config failure
- arfie (bool) – enable IRQ on auto reconfig failure
- oorie (bool) – enable IRQ on out of range event
-
baseline
(rft=-1, mhd=0, nhd=0, ncl=0, fdl=0, prox=0)[source]¶ Get raw baslines or configure baseline tracking.
Parameters: - rft (int) – scenario to set the values for: 0 = rising, raw eletrode data > current baseline, 1 = falling, raw eletrode data < current baseline, 2 = touched, eletrode in touch status.
- mhd (int) – max. half delta 0-63 (for rft=0 or 1 only), largest magnitude of variation to pass through the baseline filter.
- nhd (int) – noise half delta 0-63, incremental change when non-noise drift is detected.
- ncl (int) – noise count limit 0-255, number of samples consecutively greater than mhd necessary before if can be determined that it is non-noise.
- fdl (int) – filter delay count limit 0-255, rate of operation of the filer, greater values makes it operate slower.
- prox (bool) – if True set values for proximity mode.
Returns: raw 10 bit baseline values per eletrode, if invoked with no args.
Return type: list of ints
-
charge
(channel, cdc=0, cdt=0)[source]¶ Configure change current and time per channel.
These values are determined automatically when
auto_config()
is activated.Parameters: - channel (int) – channel to configure 0-11
- cdc (int) – charge-discharge-current 0-63 (uA)
- cdt (int) – charge-discharge-time 0-7 (0.5*2**(cdt-1) us)
-
configure
(cl=3, prox=0, touch=12)[source]¶ activate/deactivate measurement.
Measurement is activated when setting prox>0 or touch>0 (run mode). Deactivate measurement with prox=0 and touch=0 (stop mode).
Parameters: - cl (int) – calibration lock: 0 = baseline tracking enabled, 1 = baseline tracking disabled, 2 = baseline tracking enabled, init 5MSBs with initial measurement, 3 = baseline tracking enabled, init with initial measurement.
- prox (int) – proximity detection: 0 = disabled, 1 = enabled on electrodes 0-1, 2 = enabled on electrodes 0-3, 3 = enabled on electrodes 0-11.
- touch (int) – enable electrodes: 0 = disabled, 1 = enable electrode 0, 2 = enable electrodes 0-1, 3 = enable electrodes 0-2, …, 12 = enable electrodes 0-11.
-
debounce
(touch=0, release=-1)[source]¶ Configure debouncing.
# of consecutiv measurements with same result needed to trigger state change.
Parameters: - touch (int) – for touch 0-7
- release (int) – for release 0-7, if ommited release=touch
-
dump
(regs=1, up=1, loop=1)[source]¶ Dump raw values, baseline and touch status to console.
Uses this repeatedly to adjust the configuration.
Parameters: - regs (bool) – dump register values
- up (bool) – move cursor up after dump
- loop (int) – run in loop for given # of rounds
-
electrode_data
()[source]¶ Get raw eletrode measurement data.
Returns: raw 10 bit eletrode measurement per eletrode Return type: list of int
-
filter
(cdc=16, cdt=1, ffi=0, sfi=0, esi=4)[source]¶ Settings for global eletrode charging, sampling and filtering.
Effective measurement cycle period is sfi*esi.
Parameters: - cdc (int) – charge-discharge-current 0-63 (uA)
- cdt (int) – charge-discharge-time 0-7 (0.5*2**(cdt-1) us)
- ffi (int) – first filter iterations 0-3 (6,10,18,34)
- sfi (int) – second filter iterations 0-3 (4,6,10,18)
- esi (int) – eletrode sample interval 0-7 (2**esi ms)
-
gpio_set
(channel, value)[source]¶ Set GPIO channel.
Parameters: - channel (int) – channel to set 4-11
- value (bool) – set 1=HIGH or 0=LOW
-
gpio_setup
(channel, output, mode=0, enable=1)[source]¶ Setup GPIO configuration.
If the channel is configured as touch eletrode with
configure()
, then this GPIO setting has not effect. Sensing eletrode have precedence.Parameters: - channel (int) – channel to configure (4-11)
- output (bool) – configure as 1=output or 0=input
- mode (int) – pin mode, when output: 0 = CMOS output, 2 = open drain output, low side MOS only, 3 = open drain output, high side MOS only, when input: 0 = input, 2 = input with pull-down, 3 = input with pull-up.
- enable (bool) – enable/disbale GPIO functionality
-
is_touched
(channel)[source]¶ Get touch status.
Parameters: channel (int) – channel to get status for, 0-12 Returns: True if touched Return type: bool
-
on_touch
(channel, handler)[source]¶ Register touch handler, invoked on state change.
Parameters: - channel (int) – channel to attach the handler to (0-12, 12=proximity)
- handler (callable(boolean, [channel])) – handler, it gets passed a channel number [optional] and a boolean (True=touched), Pass None to remove any assigned handler.
-
out_of_range
(raise_on_failure=1)[source]¶ get out of range status.
Returns: first 12 bits contain oor status. Return type: int Parameters: raise_on_failure (bool) – raise if failure bits are set Raises: Exception
– if auto (re)config has failed
-
setup
(reset=1, channels=12, prox=0, threshold=50, debounce=2, auto_config=1)[source]¶ Configure the device with sane defaults.
Parameters: - reset (bool) – perform soft reset
- channels (int) – number of channels to activate 0-12
- threshold (int) – touch threshold 0-255
- debounce (int) – debounce count 0-7
- auto_config (bool) – enable charge auto config
-
threshold
(touch, release=-1, channel=-1)[source]¶ Set touch and release thresholds.
Usually touch > release for hysteresis.
Parameters: - touch (int) – touch threshold 0-255
- release (int) – release threshold 0-255 if ommited release=0.6*touch
- channel (int) – channel to set thresholds for 0-12 (12=proximity) if ommited apply thresholds to all channels
piripherals.util module¶
utility functions and classes
-
class
piripherals.util.
IRQHandler
(pin, callback, edge=0, pullup=1)[source]¶ Bases:
object
Abstraction of an IRQ handler.
An edge on the IRQ pin sets a flag. The callback is invoked on a separate thread when the flag was set. The flag is reset when the pin is high again. The callback may be invoked repeatedly if the pin does not reset. So you have to reset the IRQ inside the callback, such that when the callback returns, the IRQ line is high again.
This uses RPi.GPIO internally.
Parameters: - pin (int) – BCM pin number attached to IRQ line. 0 disables use of GPIO
pins, call
interrupt
explicitly - callback – function invoked on IRQ.
- edge (int) – fire interrupt on falling=0 or rising=1 edge. 1 inverts the logic, so IRQ is considered reset when low.
- pullup (int) – activate internal pullup 1=pullup, 0=nothing, -1=pulldown.
- pin (int) – BCM pin number attached to IRQ line. 0 disables use of GPIO
pins, call
-
class
piripherals.util.
Poller
(callback, delay=0.01)[source]¶ Bases:
object
Polling loop as replacement for IRQHandler.
Use it if using the IRQ line is not possible or desired.
Parameters: - callcack – function that is called continously. The actuall polling happens in this callback.
- delay (float) – delay in seconds between invocations of callback
-
piripherals.util.
not_raising
(func)[source]¶ Wraps a function and swallows exceptions.
Parameters: func – function to wrap Returns: wrapped function, that does not raise Exceptions, Exceptions are printed to console
-
piripherals.util.
noop
(*x)¶