""" pigpio is a Python module for the Raspberry Pi which allows control of the general purpose input outputs (gpios). There are 54 gpios in total, arranged in two banks. Bank 1 contains gpios 0-31. Bank 2 contains gpios 32-54. Most of the gpios are dedicated to system use. A user should only manipulate gpios in bank 1. For a Rev.1 board only use gpios 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25. For a Rev.2 board only use gpios 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27, 28, 29, 30, 31. It is safe to read all the gpios. If you try to write a system gpio or change its mode you can crash the Pi or corrupt the data on the SD card. Features The pigpio module's main features are: - provision of PWM on any number of gpios 0-31 simultaneously. - provision of servo pulses on any number of gpios 0-31 simultaneously. - callbacks when any of gpios 0-31 change state. - reading/writing gpios and setting their modes (typically input or output). - reading/writing all of the gpios in a bank (0-31, 32-53) as a single operation. Notes ALL gpios are identified by their Broadcom number. This module uses the services of the C pigpio library. That library must be running on the Pi whose gpios are to be manipulated. The normal way to start the library is as a daemon (during system start). sudo pigpiod Your Python program should wrap the use of the module up in calls to pigpio.start() and pigpio.stop(). Settings A number of settings are determined when the pigpiod daemon is started. - the sample rate (1, 2, 4, 5, 8, or 10us, default 5us). - the set of gpios which may be updated (generally written to). The default set is those listed above for the Rev.1 or Rev.2 boards. - the available PWM frequencies (see set_PWM_frequency()). Exceptions By default a fatal exception is raised if you pass an invalid argument to a pigpio function. If you wish to handle the returned status yourself you should set pigpio.exceptions = False. """ import socket import struct import time import threading import os import atexit VERSION = "1.0" # gpio levels OFF = 0 LOW = 0 CLEAR = 0 ON = 1 HIGH = 1 SET = 1 TIMEOUT = 2 # gpio edges EITHER_EDGE = 0 RISING_EDGE = 1 FALLING_EDGE = 2 # gpio modes INPUT = 0 OUTPUT = 1 ALT0 = 4 ALT1 = 5 ALT2 = 6 ALT3 = 7 ALT4 = 3 ALT5 = 2 # gpio Pull Up Down PUD_OFF = 0 PUD_DOWN = 1 PUD_UP = 2 # pigpio command numbers _PI_CMD_MODES= 0 _PI_CMD_MODEG= 1 _PI_CMD_PUD= 2 _PI_CMD_READ= 3 _PI_CMD_WRITE= 4 _PI_CMD_PWM= 5 _PI_CMD_PRS= 6 _PI_CMD_PFS= 7 _PI_CMD_SERVO= 8 _PI_CMD_WDOG= 9 _PI_CMD_BR1= 10 _PI_CMD_BR2= 11 _PI_CMD_BC1= 12 _PI_CMD_BC2= 13 _PI_CMD_BS1= 14 _PI_CMD_BS2= 15 _PI_CMD_TICK= 16 _PI_CMD_HWVER=17 _PI_CMD_NO= 18 _PI_CMD_NB= 19 _PI_CMD_NP= 20 _PI_CMD_NC= 21 _PI_CMD_PRG= 22 _PI_CMD_PFG= 23 _PI_CMD_PRRG= 24 _PI_CMD_NOIB= 99 # pigpio error numbers _PI_INIT_FAILED =-1 PI_BAD_USER_GPIO =-2 PI_BAD_GPIO =-3 PI_BAD_MODE =-4 PI_BAD_LEVEL =-5 PI_BAD_PUD =-6 PI_BAD_PULSEWIDTH =-7 PI_BAD_DUTYCYCLE =-8 _PI_BAD_TIMER =-9 _PI_BAD_MS =-10 _PI_BAD_TIMETYPE =-11 _PI_BAD_SECONDS =-12 _PI_BAD_MICROS =-13 _PI_TIMER_FAILED =-14 PI_BAD_WDOG_TIMEOUT =-15 _PI_NO_ALERT_FUNC =-16 _PI_BAD_CLK_PERIPH =-17 _PI_BAD_CLK_SOURCE =-18 _PI_BAD_CLK_MICROS =-19 _PI_BAD_BUF_MILLIS =-20 PI_BAD_DUTYRANGE =-21 _PI_BAD_SIGNUM =-22 _PI_BAD_PATHNAME =-23 PI_NO_HANDLE =-24 PI_BAD_HANDLE =-25 _PI_BAD_IF_FLAGS =-26 _PI_BAD_CHANNEL =-27 _PI_BAD_PRIM_CHANNEL=-27 _PI_BAD_SOCKET_PORT =-28 _PI_BAD_FIFO_COMMAND=-29 _PI_BAD_SECO_CHANNEL=-30 _PI_NOT_INITIALISED =-31 _PI_INITIALISED =-32 _PI_BAD_WAVE_MODE =-33 _PI_BAD_CFG_INTERNAL=-34 _PI_BAD_WAVE_BAUD =-35 _PI_TOO_MANY_PULSES =-36 _PI_TOO_MANY_CHARS =-37 _PI_NOT_SERIAL_GPIO =-38 _PI_BAD_SERIAL_STRUC=-39 _PI_BAD_SERIAL_BUF =-40 PI_NOT_PERMITTED =-41 PI_SOME_PERMITTED =-42 # pigpio error text _errors=[ [_PI_INIT_FAILED , "pigpio initialisation failed"], [PI_BAD_USER_GPIO , "gpio not 0-31"], [PI_BAD_GPIO , "gpio not 0-53"], [PI_BAD_MODE , "mode not 0-7"], [PI_BAD_LEVEL , "level not 0-1"], [PI_BAD_PUD , "pud not 0-2"], [PI_BAD_PULSEWIDTH , "pulsewidth not 0 or 500-2500"], [PI_BAD_DUTYCYCLE , "dutycycle not 0-255"], [_PI_BAD_TIMER , "timer not 0-9"], [_PI_BAD_MS , "ms not 10-60000"], [_PI_BAD_TIMETYPE , "timetype not 0-1"], [_PI_BAD_SECONDS , "seconds < 0"], [_PI_BAD_MICROS , "micros not 0-999999"], [_PI_TIMER_FAILED , "gpioSetTimerFunc failed"], [PI_BAD_WDOG_TIMEOUT , "timeout not 0-60000"], [_PI_NO_ALERT_FUNC , "DEPRECATED"], [_PI_BAD_CLK_PERIPH , "clock peripheral not 0-1"], [_PI_BAD_CLK_SOURCE , "clock source not 0-1"], [_PI_BAD_CLK_MICROS , "clock micros not 1, 2, 4, 5, 8, or 10"], [_PI_BAD_BUF_MILLIS , "buf millis not 100-10000"], [PI_BAD_DUTYRANGE , "dutycycle range not 25-40000"], [_PI_BAD_SIGNUM , "signum not 0-63"], [_PI_BAD_PATHNAME , "can't open pathname"], [PI_NO_HANDLE , "no handle available"], [PI_BAD_HANDLE , "unknown notify handle"], [_PI_BAD_IF_FLAGS , "ifFlags > 3"], [_PI_BAD_CHANNEL , "DMA channel not 0-14"], [_PI_BAD_SOCKET_PORT , "socket port not 1024-30000"], [_PI_BAD_FIFO_COMMAND , "unknown fifo command"], [_PI_BAD_SECO_CHANNEL , "DMA secondary channel not 0-6"], [_PI_NOT_INITIALISED , "function called before gpioInitialise"], [_PI_INITIALISED , "function called after gpioInitialise"], [_PI_BAD_WAVE_MODE , "waveform mode not 0-1"], [_PI_BAD_CFG_INTERNAL , "bad parameter in gpioCfgInternals call"], [_PI_BAD_WAVE_BAUD , "baud rate not 100-250000"], [_PI_TOO_MANY_PULSES , "waveform has too many pulses"], [_PI_TOO_MANY_CHARS , "waveform has too many chars"], [_PI_NOT_SERIAL_GPIO , "no serial read in progress on gpio"], [PI_NOT_PERMITTED , "no permission to update gpio"], [PI_SOME_PERMITTED , "no permission to update one or more gpios"] ] _control = None _notify = None _host = '' _port = 8888 exceptions = True class _pigpioError(Exception): """pigpio module exception""" def __init__(self, value): self.value = value def __str__(self): return repr(self.value) def error(pigpio_error): """Converts a pigpio error number to a text description. pigpio_error: an error number (<0) returned by pigpio. Example ... print(pigpio.error(-5)) level not 0-1 ... """ for e in _errors: if e[0] == pigpio_error: return e[1] return "unknown error" def tickDiff(tStart, tEnd): """Calculate the time difference between two ticks. tStart: the earlier tick. tEnd: the later tick. The function handles wrap around as the tick overflows 32 bits. The returned value is in microseconds. Example ... print(pigpio.tickDiff(4294967272, 12)) 36 ... """ tDiff = tEnd - tStart if tDiff < 0: tDiff += (1 << 32) return tDiff def _u2i(number): """Converts a number from unsigned to signed. number: a 32 bit unsigned number """ mask = (2 ** 32) - 1 if number & (1 << 31): v = number | ~mask else: v = number & mask if v >= 0: return v; else: if exceptions: raise _pigpioError(error(v)) else: return v def _pigpio_command(sock, cmd, p1, p2): """Executes a pigpio socket command. sock: command socket. cmd: the command to be executed. p1: command paramter 1 (if applicable). p2: command paramter 2 (if applicable). """ if sock is not None: sock.send(struct.pack('IIII', cmd, p1, p2, 0)) x, y, z, res = struct.unpack('IIII', sock.recv(16)) return res else: raise _pigpioError("*** Module not started, call pigpio.start() ***") class _callback: """An ADT class to hold callback information.""" def __init__(self, gpio, edge, func): """Initialises a callback ADT. gpio: Broadcom gpio number. edge: EITHER_EDGE, RISING_EDGE, or FALLING_EDGE. func: a user function taking three arguments (gpio, level, tick). """ self.gpio = gpio self.edge = edge self.func = func self.bit = 1<= 0: pigpio.notify_begin(h, 1234) ... """ r=_u2i(_pigpio_command(_control, _PI_CMD_NO, 0, 0)) return r def notify_begin(handle, bits): """Start notifications on a previously opened handle. Returns 0 if OK, otherwise PI_BAD_HANDLE. handle: 0-31 (as returned by notify_open()) bits: a mask indicating the gpios to be notified. The notification sends state changes for each gpio whose corresponding bit in bits is set. Example ... h = pigpio.notify_open() if h >= 0: pigpio.notify_begin(h, 1234) ... This will start notifications for gpios 1, 4, 6, 7, 10 (1234 = 0x04D2 = 0b0000010011010010). Notes Each notification occupies 12 bytes in the fifo as follows: H (16 bit) seqno H (16 bit) flags I (32 bit) tick I (32 bit) level """ r=_u2i(_pigpio_command(_control, _PI_CMD_NB, handle, bits)) return r def notify_pause(handle): """Pause notifications on a previously opened handle. Returns 0 if OK, otherwise PI_BAD_HANDLE. handle: 0-31 (as returned by notify_open()) Notifications for the handle are suspended until notify_begin() is called again. Example ... h = pigpio.notify_open() if h >= 0: pigpio.notify_begin(h, 1234) ... pigpio.notify_pause(h) ... pigpio.notify_begin(h, 1234) ... ... """ r=_u2i(_pigpio_command(_control, _PI_CMD_NB, handle, 0)) return r def notify_close(handle): """Stop notifications on a previously opened handle and release the handle for reuse. Returns 0 if OK, otherwise PI_BAD_HANDLE. handle: 0-31 (as returned by notify_open()) Example ... h = pigpio.notify_open() if h >= 0: pigpio.notify_begin(h, 1234) ... pigpio.notify_close(h) ... ... """ r=_u2i(_pigpio_command(_control, _PI_CMD_NC, handle, 0)) return r def set_watchdog(user_gpio, timeout): """Sets a watchdog for a gpio. Returns 0 if OK, otherwise PI_BAD_USER_GPIO or PI_BAD_WDOG_TIMEOUT. user_gpio: 0-31. timeout: 0-60000. The watchdog is nominally in milliseconds. Only one watchdog may be registered per gpio. The watchdog may be cancelled by setting timeout to 0. If no level change has been detected for the gpio for timeout milliseconds any notification for the gpio has a report written to the fifo with the flags set to indicate a watchdog timeout. The callback() class interprets the flags and will call registered callbacks for the gpio with level TIMEOUT. Example #!/usr/bin/python import pigpio import time def cbf(g, L, t): message = "gpio=" + str(g) + " level=" + str(L) + " at " + str(t) print(message) pigpio.start() cb = pigpio.callback(22, pigpio.EITHER_EDGE, cbf) print("callback started, 5 second delay") time.sleep(5) pigpio.set_watchdog(22, 1000) # 1000ms watchdog print("watchdog started, 5 second delay") time.sleep(5) pigpio.set_watchdog(22, 0) # cancel watchdog print("watchdog cancelled, 5 second delay") time.sleep(5) cb.cancel() pigpio.stop() will print lines such as callback started, 5 second delay watchdog started, 5 second delay gpio=22 level=2 at 3547411617 gpio=22 level=2 at 3548411254 gpio=22 level=2 at 3549411927 gpio=22 level=2 at 3550412060 gpio=22 level=2 at 3551411622 watchdog cancelled, 5 second delay """ r=_u2i(_pigpio_command(_control, _PI_CMD_WDOG, user_gpio, timeout)) return r def read_bank_1(): """Read the levels of the bank 1 gpios (gpios 0-31). The returned 32 bit integer has a bit set if the corresponding gpio is logic 1. Gpio n has bit value (1<