Assignment 8.1
Post date: Jul 16, 2010 1:37:21 AM
At first I was going to use push buttons for piano keys, but then I realized I only had 5 or so, not to mention pushing them wouldn't exactly be a very light action (musical term), so I decided the best way to emulate a musical keyboard was with the keyboard on my computer. I used the processing commands for determining the key that is currently being pressed and sent that key through serial to the arduino board, where it tested what note the key represented (asdfghjk = cdefgabc starting in octave 5 with the sharps / flats on wetyu) and played that note. To keep things interesting, I connected a potentiometer and used it as a pitch bender (like the ones on those fancy $500+ electronic keyboards). I attached a short sound clip of me demonstrating the keyboard as well as the pitch bend.
There are a few flaws, however. Only one note can be played at a time, however there's not much that I can do about this considering I only have one piezo at the moment. Also the pitch bend will detune the piano slightly while it is bent: this is because the relationship from one note to the next is not perfectly linear, so if every frequency is raised, say 20 Hz, the intervals will no longer be those in any standard western scale. However, I'm sure a formula exists for this relationship, so it could be fixed if necessary.
Code:
ARDUINO:
#include "pitches.h"
#define ASCIIOFFSET 97 //the ascii code of the start of the alphabet (letter 'a')
#define PITCHBEND (analogRead(pot1)/20) //pitch bend = value from pot1 / 20, because 0-1023 is too drastic of a bend
const int piezo1 = 12;
const int pot1 = 5;
// set up an array to convert the ASCII codes of letters a-z (lowercase) into the desired notes
// "home keys" are the c scale (white keys) while the keys in the row above are the sharps and flats (black keys), if applicable
const int keysToNotes[26] = {NOTE_C5, 0, 0, NOTE_E5, NOTE_DS5, NOTE_F5, NOTE_G5,
NOTE_A5, 0, NOTE_B5, NOTE_C6, 0, 0, 0, 0, 0, 0, 0,
NOTE_D5, NOTE_FS5, NOTE_AS5, 0, NOTE_CS5, 0,
NOTE_GS5, 0};
void setup() {
Serial.begin(9600); //begin serial communication at 9600 bps
}
void loop() {
// convert the current serial byte (key pressed) to a musical note, then store the note in an int
int currentNote = keysToNotes[int(Serial.read())-ASCIIOFFSET];
if(currentNote != 0) { //if there is a corresponding note for the current key
tone(piezo1, currentNote - PITCHBEND, 50); //play the tone for 50 ms through piezo1, accounting for pitch bend
}
}
PROCESSING:
import processing.serial.*;
Serial serPort; // Create object from Serial class
void setup()
{
size(200, 200);
// set up serial port
serPort = new Serial(this, Serial.list()[0], 9600);
}
void draw() {
if (keyPressed) {
serPort.write(byte(key)); //write the letter of the key currently being pressed to the serial port
}
}