Raspberry Pi Pico
MPR121 Touch Sensor
The MPR121 is an integrated circuit that does capacitive touch sensing. The one I am using is an Adafruit board. It costs just over £7 now to buy the latest version and there is a cheaper version that you can use with crocodile clips. You connect to it using I2C.
I used some Play Doh to make my buttons.
Here is a Fritzing diagram using the latest Adafruit board. The unconnected wires on the right of the diagram are what you connect to your electrodes (buttons). You can use anything conductive and experiment with different objects to see how well they work. Play Doh works a treat for touch sensing.
Here is the library I wrote to interact with the MPR121 board. Save it to the Pico as mpr121.py.
from micropython import const from time import sleep_ms ADDRESS = const(0x5a) class MPR121: def __init__(self, i2c): self.i2c = i2c self.reset() def cmd(self, reg, value): self.i2c.writeto_mem(ADDRESS,reg,bytes([value])) def reset(self): self.cmd(0x80, 0x63) sleep_ms(1) self.cmd(0x5e, 0) self.set_thresholds(12,6) rst = [0x01,0x01,0x0e,0,0x01,0x05,0x01,0,0,0,0] for i in range(43, 54): self.cmd(i, rst[i-43]) self.cmd(0x5b, 0) self.cmd(0x5c, 0x10) self.cmd(0x5d, 0x20) self.cmd(0x5e, 0x8f) def touched(self): self.cmd(0,0) lower = self.i2c.readfrom(ADDRESS, 2) return lower[0] + (lower[1]<<8) def set_thresholds(self, touch, release): for i in range(12): self.cmd(0x41 + 2*i, touch) self.cmd(0x42 + 2*i, release)
I tested my connections and code with a simple program, reading values in the shell.
from machine import Pin, I2C from time import sleep from mpr121 import MPR121 i2c=I2C(0,sda=Pin(16), scl=Pin(17)) cap = MPR121(i2c) while True: a =cap.touched() print('{:012b}'.format(a)) sleep(0.02)
Finally, I connected a buzzer to GP15 and made a piano (of sorts).
from machine import Pin, I2C, PWM from time import sleep from mpr121 import MPR121 # define the pin to use for buzzing buzzer = PWM(Pin(15)) # the duty cycle to use when the note is on volume = 2512 # frequency - plays until stopped def note_on(frequency): buzzer.duty_u16(volume) buzzer.freq(frequency) # stop the noise def note_off(): buzzer.duty_u16(0) def bit_length(n): bits = 0 while n >> bits: bits += 1 return bits i2c=I2C(0,sda=Pin(16), scl=Pin(17)) cap = MPR121(i2c) notes = [262,294,330,349,392,440,494,523,587,659,698,784] last = -2 while True: x = cap.touched() # play note from leftmost press only leftmost = bit_length(x&-x) - 1 if leftmost != last: if leftmost==-1: note_off() else: note_on(notes[leftmost]) last = leftmost