Good Ear

Submitted by kmpark on Wed, 03/06/2013 - 06:00

 

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

 

0
Your rating: None
Drupal theme by Kiwi Themes.