User login

Powered by Drupal, an open source content management system

Theory and Practice of Tangible User Interfaces

Piezo Sequencer

Submitted by criley on Thu, 10/09/2008 - 10:00

Assignment: Input / Output Coincidence Lab Assignment

Collaborators:

I coded a little music sequencer that uses a potentiometer to edit notes in a Processing interface. Notes are represented as large colored 'pixels' which can be edited individually by clicking on them. Twisting the potentiometer changes the note. The Processing interface then creates a string representing the melody which is sent to the Arduino board.

The board itself handles sending the potentiometer value over serial and decodes the strings it receives from Processing, playing the desired notes.

Processing code:

String portname = "COM4";
Serial port;
String buf="";
int cr = 13;  // ASCII return   == 13
int lf = 10;  // ASCII linefeed == 10
char[] melody = {'1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p','1','p'};
//String melody = "1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p1p";
int melody_length=24;
int r=45;
int y=55;
int x=5;
int spacing=5;
boolean waitForLf = false;
int activeRect=0;
void setup() {
  size(1205,155);
  frameRate(10);
  smooth();
  background(40,40,40);
  noStroke();
  port = new Serial(this, portname, 9600);
  for(int i=0;i<melody_length;i++){
    int pot=(int)random(1024);
    //print(pot+", ");
    drawbox(x,y,r,pot);
    x=x+spacing+r;
    fill(255,255,255);
    ellipse(28+(50*i),78,3,3);
  }
}
void draw() {

}

// draw box
void drawbox(int x, int y, int r, int pot) {
  for (int i=0; i<100; i++ ) {
    if(pot>0&&pot<127){
      fill(0,223,240);
      melody[(activeRect*2)+1]='c';
    }else if(pot>128&&pot<255){
      fill(31,191,240);
      melody[(activeRect*2)+1]='d';
    }else if(pot>256&&pot<383){
      fill(63,159,240);
      melody[(activeRect*2)+1]='e';
    }else if(pot>384&&pot<511){
      fill(95,127,240);
      melody[(activeRect*2)+1]='f';
    }else if(pot>512&&pot<639){
      fill(127,95,240);
      melody[(activeRect*2)+1]='g';
    }else if(pot>640&&pot<767){
      fill(159,63,240);
      melody[(activeRect*2)+1]='a';
    }else if(pot>768&&pot<895){
      fill(191,131,240);
      melody[(activeRect*2)+1]='b';
    }else if(pot>896&&pot<1023){
      fill(223,0,240);
      melody[(activeRect*2)+1]='C';
    }
    rect(x,y,r,r);
    fill(0,0,0);
    ellipse(28+(50*activeRect),78,3,3);
  }

}
// called whenever serial data arrives
void serialEvent(Serial p) {
  int c = port.read();
  if(buf=="" && (char)c=='p'){
    waitForLf=false;
  }else{
    waitForLf=true;
  }
  if (c != lf && c != cr && (char)c!='p' && !waitForLf) {
    buf += char(c);
  }
  if (c == lf && !waitForLf) {
    int val = int(buf);
    println("val="+val);
    drawbox(x,y,r,val);
    String mel = String.valueOf(melody);
    port.write(mel);
    buf = "";
    waitForLf=false;
  }
}
void mousePressed(){
  if(mouseY>55&&mouseY<100){
    changeActiveRect(mouseX);
  }
}
void changeActiveRect(int x){
  int oldAct = activeRect;
  println("old: "+oldAct);
  float f = x/51;
  activeRect = (int)f;
  println(activeRect);
  x=(45*activeRect)+5*(activeRect+1);
  ellipseMode(CENTER);
  fill(255,255,255);
  ellipse(28+(50*oldAct),78,3,3);
  fill(0,0,0);
  ellipse(28+(50*activeRect),78,3,3);
}

Arduino code:

int potPin = 0;    // select the input pin for the potentiometer

int val = 0;
char serInString[500];
int cr = 13;  // ASCII return   == 13
int lf = 10;  // ASCII linefeed == 10

int ledPin = 13;
int speakerOut = 7;               
byte names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};  
int tones[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
byte melody[] = "2d2a1f2c2d2a2d2c2f2d2a2c2d2a1f2c2d2a2a2g2p8p8p8p";
int count = 0;
int count2 = 0;
int count3 = 0;
int MAX_COUNT = 24;
int statePin = LOW;

void setup() {
 pinMode(ledPin, OUTPUT); 
 pinMode(speakerOut, OUTPUT);
  beginSerial(9600);
  //Serial.println("ready");
}

void loop() {
  digitalWrite(speakerOut, LOW);
  
  val = analogRead(potPin);    // read value from the sensor
  Serial.print("p");
  Serial.println(val);
  
  //readSerialString(serInString);
  
  //val = val*2;                 // process the value a little
  
  digitalWrite(speakerOut, LOW);     
    for (count = 0; count < MAX_COUNT; count++) {
      statePin = !statePin;
      digitalWrite(ledPin, statePin);
      for (count3 = 0; count3 <= (melody[count*2] - 48) * 30; count3++) {
        for (count2=0;count2<8;count2++) {
          if (names[count2] == melody[count*2 + 1]) {       
            digitalWrite(speakerOut,HIGH);
            delayMicroseconds(tones[count2]);
            digitalWrite(speakerOut, LOW);
            delayMicroseconds(tones[count2]);
          } 
          if (melody[count*2 + 1] == 'p') {
            // make a pause of a certain size
            digitalWrite(speakerOut, 0);
            delayMicroseconds(500);
          }
        }
      }
    }

}
void readSerialString (char *strArray) {
  int i = 0;
  if(!Serial.available()) {
    return;
  }
  while (Serial.available()) {
    char c = Serial.read();
    if(c!=cr && c!=lf){
      strArray[i]=c;
    }else if(i=0 && c=='p'){
      return;
    }else{
      return;
    }
    i++;
  }
}