Description
I developed a pitch matching game, training a good ear, using a piezo speaker and a pot. I was able to (finally!) manage serial signals and to use it with processing. The note is randomly selected and the user adjust a pot to match current tone with the target pitch. the feedback was given with three LEDs telling which sound is target and whether your pitch is lower or higher than the target pitch. On screen, the sequence of circles were drown as the pitch gets similar with color difference by the polarity(lower, higher).
I was planning to use photocells to pick up the note comparison with LED signals and send the signals to processing, but the irregularity of the photocells upon the LED brightness made me to just go with pot signal to display. Overall I truly enjoyed the whole process although it took me a lot of time exposed in annoying sound tone. :)
Components Used
1- Arduino Uno
3- LEDs
6- Resistors
1- Breadboard
1- pot
1- piezo speaker
2- photocell
Code
Arduino Code
int potPin = 5; // select the input pin for the potentiometer
int speakerPin = 7;
int ledPinR = 13;
int ledPinG = 12;
int ledPinB = 2;
int photPin1 = 0;
int photPin2 = 1;
int target;
int tones[8] = {956, 1014, 1136, 1275, 1432, 1519, 1700, 1915};
void setup() {
pinMode(speakerPin, OUTPUT);
pinMode(ledPinR, OUTPUT);
pinMode(ledPinG, OUTPUT);
pinMode(ledPinB, OUTPUT);
// initialize serial communications (for debugging only):
Serial.begin(9600);
}
int randInt = random(8);
void loop() {
digitalWrite(ledPinR, HIGH); // sets the LED on
delay(200); // waits for a second
digitalWrite(ledPinR, LOW); // sets the LED off
target = tones[randInt];
tone(speakerPin, target, 100);
delay(1); // delay in between reads for stability
// Serial.println("target");
//Serial.println(target);
delay(1000);
// read the sensor:
int sensorReading = analogRead(potPin);
// print the sensor reading so you know its range
// map the analog input range (in this case, 400 - 1000 from the photoresistor)
// to the output pitch range (120 - 1500Hz)
// change the minimum and maximum input numbers below
// depending on the range your sensor's giving:
int thisPitch = map(sensorReading, 0, 1023, 900, 2000);
// Serial.println("test");
// Serial.println(thisPitch);
// play the pitch:
tone(speakerPin, thisPitch, 200);
delay(1); // delay in between reads for stability
int diff = target-thisPitch;
Serial.println(diff);
if (abs(diff)<10) {
// Serial.println("matched!");
tone(speakerPin, thisPitch, 800);
digitalWrite(ledPinG, HIGH); // sets the LED on
digitalWrite(ledPinB, HIGH); // sets the LED on
delay(500); // delay in between reads for stability
tone(speakerPin, thisPitch, 300);
delay(300); // delay in between reads for stability
tone(speakerPin, thisPitch, 500);
delay(500); // delay in between reads for stability
digitalWrite(ledPinG, LOW); // sets the LED off
digitalWrite(ledPinB, LOW); // sets the LED off
randInt = random(8);
}
else {
if (diff > 0) {
digitalWrite(ledPinB, HIGH); // sets the LED on
int phot1Reading = analogRead(photPin1);
int phot2Reading = analogRead(photPin2);
// Serial.println("sensor1");
// Serial.println(phot1Reading);
// Serial.println("sensor2");
// Serial.println(phot2Reading);
delay(1000); // delay in between reads for stability
digitalWrite(ledPinB, LOW); // sets the LED off
}
else {
digitalWrite(ledPinG, HIGH); // sets the LED on
int phot1Reading = analogRead(photPin1);
int phot2Reading = analogRead(photPin2);
// Serial.println("sensor1");
// Serial.println(phot1Reading);
// Serial.println("sensor2");
// Serial.println(phot2Reading);
delay(1000); // delay in between reads for stability
digitalWrite(ledPinG, LOW); // sets the LED off
}
}
}
Processing Code
import processing.serial.*;
// Change this to the portname your Arduino board
String portname = "/dev/tty.usbmodem1421"; // or "COM5"
Serial port;//
String buf="";
int cr = 13; // ASCII return == 13
int lf = 10; // ASCII linefeed == 10
PFont f; // STEP 2 Declare PFont variable
void setup() {
frameRate(5);
smooth();
background(40,40,40);
noStroke();
f = createFont("Arial",16,true); // STEP 3 Create Font
port = new Serial(this, portname, 9600);
port.bufferUntil('\n');
size(1000,500);
}
void draw() {
// background(255);
// textFont(f,16); // STEP 4 Specify font to be used
// fill(0); // STEP 5 Specify font color
// text("Hello Strings!",10,100); // STEP 6 Display Text
}
void drawball(int x, int y, int r, int f) {
// for (int j=0; j<100; j= i+5 ) {
// fill(255-i,i, i+100);
// int rv = int(random(1,255));
if (f>0) {
fill(250,100, 255-(f*2));
}
else {
fill (250, 255-(f*2), 100);
}
ellipse(x,y,r,r);
}
//}
int i = 0;
// called whenever serial data arrives
void serialEvent(Serial port) {
// for (int i = 0; i < 10; i = i+1) {
i = i +1;
println(i);
String c = port.readStringUntil(lf);
// if (c != lf && c != cr) {
// buf += char(c);
// }
if (i%3 ==0){
background(40,40,40); // erase screen
}
if (c != null) {
int val = int(trim(c));
println("val="+val);
// float norm_val = (val/1000)*200;
int int_val = val/3;
println("nval="+int_val);
int abs_val = abs(int_val);
int x = (i % 3 + 1) * 200 + 100;//int(random(50,width-100));
int y = 250;//int(random(50,height-100));
println(x);
drawball(x,y,abs_val+70, int_val);
buf = "";
textFont(f,30); // STEP 4 Specify font to be used
if (abs(val) < 10) {
fill(255); // STEP 5 Specify font color
text("matched!", x+50, y+25);
}
else{
fill(255); // STEP 5 Specify font color
text(val,x-50,y);
} // STEP 6 Display Text
}
}
Images
Insert your image links if not attached.
Video
http://www.youtube.com/watch?v=Xzm2zJISBKI