I continued my input device from a couple weeks ago (the piano circuit), and extented the Tkinter load sense python file so that you can visually see what note is being played. I never fully fixed the bugs in my circuit, so it doesn't work quite like I'd want it to, but the basic idea is here.
The piano board from a couple weeks ago. The 2 2x2 headers on the right hand side are the 8 sense pins that are used to connect to 8 keys and play notes.
I'd like to eventually mill out my piano, so it looks more professional, but I decided to first make a cardboard version to test things out. I just grabbed some cardboard, cut out 8 pieces of copper tape, put them on the board, and connected the 8 individual wires to the keys with electrical tape.
My C code from a couple weeks ago programs the circuit so that each pin sense it's number (0 to 7), followed by the value that pin is reading. I then made a python file that reads these identifying numbers, then checks the next number to see if it's less than some threshold value -- this means that the pin has been touched.
from Tkinter import * import serial import winsound WINDOW = 300 # window size WIDTH = 2*WINDOW HEIGHT = WINDOW eps = 0.5 # filter time constant filters = [0] * 8 values = [0]*8 sounds = [261,293,329,349,392,440,494,523] def idle(parent,canvas): global eps ser.flush() while True: key = ord(ser.read()) if key < len(values): values[key] = ord(ser.read()) if key == 7: # last value to be read in a sequence break for i in range(8): canvas.delete("text" + str(i)) if values[i] < 100: canvas.create_text(.125*WIDTH*(i+.5),.95*HEIGHT,text=str(values[i]),font=("Helvetica", 24),tags="text" + str(i),fill="#b00000") if i != 4 and i != 6: # 4 and 6 don't seem to be working :( winsound.Beep(sounds[i],75) canvas.create_rectangle(.125*i*WIDTH,.1*HEIGHT,.125*i*WIDTH+.125*WIDTH,.9*HEIGHT, tags='rect' + str(i), fill='#b00000') else: canvas.create_text(.125*WIDTH*(i+.5),.95*HEIGHT,text=str(values[i]),font=("Helvetica", 24),tags="text" + str(i),fill="#0000b0") canvas.create_rectangle(.125*i*WIDTH,.1*HEIGHT,.125*i*WIDTH+.125*WIDTH,.9*HEIGHT, tags='rect' + str(i), fill='#0000b0') parent.after_idle(idle,parent,canvas) port = 'COM5'#sys.argv[1] # # open serial port # ser = serial.Serial(port,9600) ser.setDTR() # # set up GUI # root = Tk() root.title('piano.py (q to exit)') root.bind('q','exit') canvas = Canvas(root, width=WIDTH, height=HEIGHT, background='white') canvas.create_text(.5*WIDTH,.05*HEIGHT,text="circuit piano",font=("Helvetica", 24),tags="title",fill="#0000b0") for i in range(8): #x0, y0, x1, Y1 canvas.create_text(.125*WIDTH*(i+.5),.95*HEIGHT,text=str(i),font=("Helvetica", 24),tags="text" + str(i),fill="#0000b0") canvas.create_rectangle(.125*i*WIDTH,.1*HEIGHT,.125*i*WIDTH+.125*WIDTH,.9*HEIGHT, tags='rect' + str(i), fill='#0000b0') canvas.pack() # # start idle loop # root.after(100,idle,root,canvas) root.mainloop()
The sensing seems to be noisy unfortunately. I think I'll change the C or python code so that it smooths this out, turning a key "on" or "off" based on multiple timesteps instead of one. I also need to double check the connection for keys 4 and 6, as they didn't seem to work consistenly (and are ignored in the code). I ran the python file with an octave of notes (looked up the frequencies online), so it just does a beep for each key pressed. This could easily be changed to play any music file instead, like real piano notes, or bird calls. Really, anything.