|
| 1 | +# MPR121 capacitive touch breakout driver. Port of Raspberry Pi/BeagleBone Black |
| 2 | +# code from: https://github.com/adafruit/Adafruit_Python_MPR121/ |
| 3 | +# Author: Tony DiCola |
| 4 | +# License: MIT License (https://opensource.org/licenses/MIT) |
| 5 | +import time |
| 6 | + |
| 7 | +import adafruit_bus_device.i2c_device as i2c_device |
| 8 | + |
| 9 | + |
| 10 | +# Register addresses. Unused registers commented out to save memory. |
| 11 | +MPR121_I2CADDR_DEFAULT = const(0x5A) |
| 12 | +MPR121_TOUCHSTATUS_L = const(0x00) |
| 13 | +#MPR121_TOUCHSTATUS_H = const(0x01) |
| 14 | +MPR121_FILTDATA_0L = const(0x04) |
| 15 | +#MPR121_FILTDATA_0H = const(0x05) |
| 16 | +MPR121_BASELINE_0 = const(0x1E) |
| 17 | +MPR121_MHDR = const(0x2B) |
| 18 | +MPR121_NHDR = const(0x2C) |
| 19 | +MPR121_NCLR = const(0x2D) |
| 20 | +MPR121_FDLR = const(0x2E) |
| 21 | +MPR121_MHDF = const(0x2F) |
| 22 | +MPR121_NHDF = const(0x30) |
| 23 | +MPR121_NCLF = const(0x31) |
| 24 | +MPR121_FDLF = const(0x32) |
| 25 | +MPR121_NHDT = const(0x33) |
| 26 | +MPR121_NCLT = const(0x34) |
| 27 | +MPR121_FDLT = const(0x35) |
| 28 | +MPR121_TOUCHTH_0 = const(0x41) |
| 29 | +MPR121_RELEASETH_0 = const(0x42) |
| 30 | +MPR121_DEBOUNCE = const(0x5B) |
| 31 | +MPR121_CONFIG1 = const(0x5C) |
| 32 | +MPR121_CONFIG2 = const(0x5D) |
| 33 | +#MPR121_CHARGECURR_0 = const(0x5F) |
| 34 | +#MPR121_CHARGETIME_1 = const(0x6C) |
| 35 | +MPR121_ECR = const(0x5E) |
| 36 | +#MPR121_AUTOCONFIG0 = const(0x7B) |
| 37 | +#MPR121_AUTOCONFIG1 = const(0x7C) |
| 38 | +#MPR121_UPLIMIT = const(0x7D) |
| 39 | +#MPR121_LOWLIMIT = const(0x7E) |
| 40 | +#MPR121_TARGETLIMIT = const(0x7F) |
| 41 | +#MPR121_GPIODIR = const(0x76) |
| 42 | +#MPR121_GPIOEN = const(0x77) |
| 43 | +#MPR121_GPIOSET = const(0x78) |
| 44 | +#MPR121_GPIOCLR = const(0x79) |
| 45 | +#MPR121_GPIOTOGGLE = const(0x7A) |
| 46 | +MPR121_SOFTRESET = const(0x80) |
| 47 | + |
| 48 | + |
| 49 | +class MPR121: |
| 50 | + |
| 51 | + def __init__(self, i2c, address=MPR121_I2CADDR_DEFAULT): |
| 52 | + self._i2c = i2c_device.I2CDevice(i2c, address) |
| 53 | + self._buffer = bytearray(2) |
| 54 | + self.reset() |
| 55 | + |
| 56 | + def _write_register_byte(self, register, value): |
| 57 | + # Write a byte value to the specifier register address. |
| 58 | + with self._i2c: |
| 59 | + self._i2c.writeto(bytes([register, value])) |
| 60 | + |
| 61 | + def _read_register_bytes(self, register, result, length=None): |
| 62 | + # Read the specified register address and fill the specified result byte |
| 63 | + # array with result bytes. Make sure result buffer is the desired size |
| 64 | + # of data to read. |
| 65 | + if length is None: |
| 66 | + length = len(result) |
| 67 | + with self._i2c: |
| 68 | + self._i2c.writeto(bytes([register]), stop=False) |
| 69 | + self._i2c.readfrom_into(result, start=0, end=length) |
| 70 | + |
| 71 | + def reset(self): |
| 72 | + """Reset the MPR121 into a default state ready to detect touch inputs. |
| 73 | + """ |
| 74 | + # Write to the reset register. |
| 75 | + self._write_register_byte(MPR121_SOFTRESET, 0x63) |
| 76 | + time.sleep(0.001) # This 1ms delay here probably isn't necessary but can't hurt. |
| 77 | + # Set electrode configuration to default values. |
| 78 | + self._write_register_byte(MPR121_ECR, 0x00) |
| 79 | + # Check CDT, SFI, ESI configuration is at default values. |
| 80 | + self._read_register_bytes(MPR121_CONFIG2, self._buffer, 1) |
| 81 | + if self._buffer[0] != 0x24: |
| 82 | + raise RuntimeError('Failed to find MPR121 in expected config state!') |
| 83 | + self.set_thresholds(12, 6) |
| 84 | + # Configure baseline filtering control registers. |
| 85 | + self._write_register_byte(MPR121_MHDR, 0x01) |
| 86 | + self._write_register_byte(MPR121_NHDR, 0x01) |
| 87 | + self._write_register_byte(MPR121_NCLR, 0x0E) |
| 88 | + self._write_register_byte(MPR121_FDLR, 0x00) |
| 89 | + self._write_register_byte(MPR121_MHDF, 0x01) |
| 90 | + self._write_register_byte(MPR121_NHDF, 0x05) |
| 91 | + self._write_register_byte(MPR121_NCLF, 0x01) |
| 92 | + self._write_register_byte(MPR121_FDLF, 0x00) |
| 93 | + self._write_register_byte(MPR121_NHDT, 0x00) |
| 94 | + self._write_register_byte(MPR121_NCLT, 0x00) |
| 95 | + self._write_register_byte(MPR121_FDLT, 0x00) |
| 96 | + # Set other configuration registers. |
| 97 | + self._write_register_byte(MPR121_DEBOUNCE, 0) |
| 98 | + self._write_register_byte(MPR121_CONFIG1, 0x10) # default, 16uA charge current |
| 99 | + self._write_register_byte(MPR121_CONFIG2, 0x20) # 0.5uS encoding, 1ms period |
| 100 | + # Enable all electrodes. |
| 101 | + self._write_register_byte(MPR121_ECR, 0x8F) # start with first 5 bits of baseline tracking |
| 102 | + |
| 103 | + def set_thresholds(self, touch, release): |
| 104 | + """Set the touch and release threshold for all inputs to the provided |
| 105 | + values. Both touch and release should be a value between 0 to 255 |
| 106 | + (inclusive). |
| 107 | + """ |
| 108 | + if touch < 0 or touch > 255 or release < 0 or release > 255: |
| 109 | + raise ValueError('Touch/release must be a byte value 0-255.') |
| 110 | + # Set the touch and release register value for all the inputs. |
| 111 | + for i in range(12): |
| 112 | + self._write_register_byte(MPR121_TOUCHTH_0 + 2*i, touch) |
| 113 | + self._write_register_byte(MPR121_RELEASETH_0 + 2*i, release) |
| 114 | + |
| 115 | + def filtered_data(self, pin): |
| 116 | + """Return filtered data register value for the provided pin (0-11). |
| 117 | + Useful for debugging. |
| 118 | + """ |
| 119 | + if pin < 0 or pin > 11: |
| 120 | + raise ValueError('Pin must be a value 0-11.') |
| 121 | + self._read_register_bytes(MPR121_FILTDATA_0L + pin*2, self._buffer) |
| 122 | + return ((self._buffer[1] << 8) | (self._buffer[0])) & 0xFFFF |
| 123 | + |
| 124 | + def baseline_data(self, pin): |
| 125 | + """Return baseline data register value for the provided pin (0-11). |
| 126 | + Useful for debugging. |
| 127 | + """ |
| 128 | + if pin < 0 or pin > 11: |
| 129 | + raise ValueError('Pin must be a value 0-11.') |
| 130 | + self._read_register_bytes(MPR121_BASELINE_0 + pin, self._buffer, 1) |
| 131 | + return self._buffer[0] << 2 |
| 132 | + |
| 133 | + def touched(self): |
| 134 | + """Return touch state of all pins as a 12-bit value where each bit |
| 135 | + represents a pin, with a value of 1 being touched and 0 not being touched. |
| 136 | + """ |
| 137 | + self._read_register_bytes(MPR121_TOUCHSTATUS_L, self._buffer) |
| 138 | + return ((self._buffer[1] << 8) | (self._buffer[0])) & 0xFFFF |
| 139 | + |
| 140 | + def is_touched(self, pin): |
| 141 | + """Return True if the specified pin is being touched, otherwise returns |
| 142 | + False. |
| 143 | + """ |
| 144 | + if pin < 0 or pin > 11: |
| 145 | + raise ValueError('Pin must be a value 0-11.') |
| 146 | + t = self.touched() |
| 147 | + return (t & (1 << pin)) > 0 |
0 commit comments