Raspberry Pi Pico
Piano HAT

The Piano HAT is a Raspberry Pi accessory made by Pimoroni. It uses two CAP1188 capacitive touch sensors for a total of 16 capacitive touchpads. A full octave of touchpads is laid out as a piano keyboard. There are LEDs which light up as you touch each input. It has to be one of the nicest looking PCBs you have ever seen.

Here is a photograph of it setup with a buzzer. I am using a Waveshare Pico accessory which has a Raspberry Pi style GPIO connector,

Pico Circuit

My connections are GP2 and GP3 to pins 2 and 3 on the pHAT. You also need to connect to the 5V, 3V3 and GND pins of the pHAT. You can see a diagram showing the pHAT pins at Gadgetoid's superb Pinout site,https://pinout.xyz/pinout/piano_hat.

This is the library that you need to save to the Pico as piano.py. The CAP1188 class could be used with another board based on the chip.

class cap1188:
    def __init__(self, ADDR, i2c):
        self.ADDRESS = ADDR
        self.i2c = i2c
        for i in range(8):
            self.i2c.writeto_mem(self.ADDRESS, 0x30 + i, b'\x06')
        self.i2c.writeto_mem(self.ADDRESS, 0x72, b'\xff')
        self.i2c.writeto_mem(self.ADDRESS, 0x1f, b'\x60')
        self.i2c.writeto_mem(self.ADDRESS, 0x20, b'\x38')
        self.i2c.writeto_mem(self.ADDRESS, 0x44, b'\x60')
            
    def read(self):
        self.i2c.writeto_mem(self.ADDRESS, 0, b'\x00')
        data = self.i2c.readfrom_mem(self.ADDRESS, 0x03, 1)
        return data[0]

class piano_hat():
    def __init__(self, i2c):        
        self.a = cap1188(0x28, i2c)
        self.b = cap1188(0x2b, i2c)
    
    def read(self):
        x = self.a.read()
        y = self.b.read()
        if x>0:
            y = 0
        data = list(reversed([x >> i & 1 for i in range(7,-1,-1)]))
        data += list(reversed([y >> i & 1 for i in range(7,-1,-1)]))
        return data

Here was some test code that I used to check my connections and library,

from machine import Pin, I2C
from piano import piano_hat
from time import sleep

i2c = I2C(1,sda=Pin(2), scl = Pin(3))

p = piano_hat(i2c)

while True:
    reading = p.read()
    if sum(reading)>0:
        print(reading)
    sleep(0.1)

Finally, with a buzzer added to the circuit and wrote some code to make a piano that is playable, after a fashion.

from machine import Pin, I2C, PWM
from piano import piano_hat
from time import sleep

# 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)


i2c = I2C(1,sda=Pin(2), scl = Pin(3))

p = piano_hat(i2c)

notes = [523,554,587,622,659,698,740,784,
        831,880,932,988,1047]
last = -1        
while True:
    reading = p.read()
    a = reading[0:13]
    n = -1
    if sum(a)>0:
        n = a.index(1)
        if n!=last:
            note_on(notes[n])
    else:
        note_off()
    last = n