Lab submission 5 - Piezo speaker
Description
I made a mini-violin using piezo speaker, potentiometer, and three photocells. The program has two modes of play: manual mode and assisted mode. In the manual mode, the user's fingerings of binary combinations (0 to 7) on the three photocells make different pitches of the sound. In assisted mode, a processing code decides pitches of the sound based on a musical piece. The program has pitch data of parsed MIDI file so that it sequentially output the value according to the user's input.
Video Demo
Components Used
- 3 10k ohm resistors
- 3 photocells
- 1 piezo speaker
- 1 Arduino Uno board
Arduino Code: Mini-violin
int PHOTO_THRESHOLD = 700;
int SPEAKER_CYCLE = 3;
int photoPin1 = 0;
int photoPin2 = 1;
int photoPin3 = 2;
int photoVal1 = 0;
int photoVal2 = 0;
int photoVal3 = 0;
int binaryVal = 0;
int potVal = 0;
int oldPotVal = 0;
int potPin = 4;
boolean wasHigh = true;
boolean started = false;
int speakerPin = 7;
const int tones[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
const int vivaldi[] = {0, 0, 0, 0, 803, 536, 601, 637, 715, 803, 715, 1072, 1072, 601, 637, 715, 803, 851, 601, 601, 637, 637, 715, 637, 601, 536, 477, 425, 803, 715, 637, 601, 536, 477, 851, 803, 715, 637, 601, 536, 955, 851, 803, 715, 637, 803, 851, 1072, 1136, 1072, 715, 1072, 1136, 1072, 637, 1072, 1136, 1072, 568, 715, 803, 715, 536, 1072, 536, 536, 568, 637, 715, 803, 851, 955, 1072, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 955, 851, 1072, 1072, 1072, 715, 803, 851, 955, 1072, 955, 1431, 1431, 803, 851, 955, 1072, 1136, 803, 803, 851, 1072, 601, 637, 715, 803, 851, 601, 601, 637, 637, 955, 851, 803, 715, 637, 601, 851, 803, 715, 637, 601, 536, 803, 715, 637, 601, 536, 477, 851, 851, 803, 715, 851, 955, 1072, 637, 601, 536, 637, 715, 1072, 851, 803, 715, 851, 955, 1072, 637, 601, 536, 637, 715, 1072, 715, 536, 637, 715, 803, 851, 803, 851, 803, 851, 803, 851, 803, 851, 803, 803, 955, 601, 637, 715, 758, 715, 955, 601, 637, 715, 758, 715, 955, 601, 637, 715, 758, 715, 955, 601, 637, 715, 758, 715, 955, 901, 955, 1072, 955, 901, 1431, 901, 955, 1072, 955, 901, 1431, 901, 955, 1072, 955, 901, 1431, 901, 955, 1072, 955, 901, 1431, 1275, 1203, 1275, 1203, 1431, 955, 901, 803, 901, 803, 955, 715, 637, 601, 637, 601, 715, 601, 477, 536, 601, 536, 477, 715, 477, 536, 601, 536, 477, 715, 450, 477, 536, 477, 450, 715, 450, 477, 536, 477, 450, 715, 477, 536, 601, 536, 477, 715, 477, 536, 601, 536, 477, 715, 450, 477, 536, 477, 450, 715, 450, 477, 536, 477, 450, 477, 715, 536, 601, 637, 715, 758, 851, 955, 851, 758, 715, 637, 601, 536, 601, 637, 715, 758, 851, 955, 851, 758, 715, 637, 601, 536, 601, 637, 601, 637, 715, 536, 601, 637, 601, 637, 715, 536, 601, 637, 601, 601, 601, 568, 568, 568, 536, 536, 536, 506, 506, 506, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 536, 536, 536};
const int IDLE = 0, MANUAL = 1, ASSISTED = 2, COLLABORATIVE = 3;
int command;
int count = 0;
void setup() {
pinMode(potPin, INPUT);
pinMode(speakerPin, OUTPUT);
Serial.begin(9600);
command = -100;
}
void loop() {
while(Serial.available() > 0){
command = Serial.read();
if(command==IDLE) {
}
else if(command==MANUAL) {
// read fingering
photoVal1 = analogRead(photoPin1) > PHOTO_THRESHOLD ? 1 : 0;
photoVal2 = analogRead(photoPin2) > PHOTO_THRESHOLD ? 1 : 0;
photoVal3 = analogRead(photoPin3) > PHOTO_THRESHOLD ? 1 : 0;
binaryVal = 4*photoVal1 + 2*photoVal2 + 1*photoVal3;
// make sound if MANUAL mode
for(int i=0;i<SPEAKER_CYCLE;i++) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tones[binaryVal]);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tones[binaryVal]);
}
}
else { // assisted mode
potVal = analogRead(potPin) / 128;
if(!started && potVal<6 && wasHigh) started = true;
if(started && potVal<6 && wasHigh) {
wasHigh = false;
Serial.println('r'); // request new pitch
delay(2);
}
else if(started && potVal>6 && !wasHigh) {
wasHigh = true;
Serial.println('r'); // request new pitch
delay(2);
}
if(started)
for(int i=0;i<SPEAKER_CYCLE;i++) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(vivaldi[command]);
digitalWrite(speakerPin, LOW);
delayMicroseconds(vivaldi[command]);
}
}
}
}
Processing Code: Mini-violin
import processing.serial.*;
String portname = "/dev/tty.usbmodem411";
Serial port;
int state;
final int IDLE = 0, MANUAL = 1, ASSISTED = 2, COLLABORATIVE = 3;
float buttonWidth = 280;
float buttonHeight = 120;
float buttonRound = 5;
int buttonR = 200, buttonG = 255, buttonB = 120;
int bgR = 0x40, bgG = 0x40, bgB = 0x40;
//int tones[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
String[] vivaldi = {"", "", "", "", "D#5", "A#5", "G#5", "G5", "F5", "D#5", "F5", "A#4", "A#4", "G#5", "G5", "F5", "D#5", "D5", "G#5", "G#5", "G5", "G5", "F5", "G5", "G#5", "A#5", "C6", "D6", "D#5", "F5", "G5", "G#5", "A#5", "C6", "D5", "D#5", "F5", "G5", "G#5", "A#5", "C5", "D5", "D#5", "F5", "G5", "D#5", "D5", "A#4", "A4", "A#4", "F5", "A#4", "A4", "A#4", "G5", "A#4", "A4", "A#4", "A5", "F5", "D#5", "F5", "A#5", "A#4", "A#5", "A#5", "A5", "G5", "F5", "D#5", "D5", "C5", "A#4", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "C5", "D5", "A#4", "A#4", "A#4", "F5", "D#5", "D5", "C5", "A#4", "C5", "F4", "F4", "D#5", "D5", "C5", "A#4", "A4", "D#5", "D#5", "D5", "A#4", "G#5", "G5", "F5", "D#5", "D5", "G#5", "G#5", "G5", "G5", "C5", "D5", "D#5", "F5", "G5", "G#5", "D5", "D#5", "F5", "G5", "G#5", "A#5", "D#5", "F5", "G5", "G#5", "A#5", "C6", "D5", "D5", "D#5", "F5", "D5", "C5", "A#4", "G5", "G#5", "A#5", "G5", "F5", "A#4", "D5", "D#5", "F5", "D5", "C5", "A#4", "G5", "G#5", "A#5", "G5", "F5", "A#4", "F5", "A#5", "G5", "F5", "D#5", "D5", "D#5", "D5", "D#5", "D5", "D#5", "D5", "D#5", "D5", "D#5", "D#5", "C5", "G#5", "G5", "F5", "E5", "F5", "C5", "G#5", "G5", "F5", "E5", "F5", "C5", "G#5", "G5", "F5", "E5", "F5", "C5", "G#5", "G5", "F5", "E5", "F5", "C5", "C#5", "C5", "A#4", "C5", "C#5", "F4", "C#5", "C5", "A#4", "C5", "C#5", "F4", "C#5", "C5", "A#4", "C5", "C#5", "F4", "C#5", "C5", "A#4", "C5", "C#5", "F4", "G4", "G#4", "G4", "G#4", "F4", "C5", "C#5", "D#5", "C#5", "D#5", "C5", "F5", "G5", "G#5", "G5", "G#5", "F5", "G#5", "C6", "A#5", "G#5", "A#5", "C6", "F5", "C6", "A#5", "G#5", "A#5", "C6", "F5", "C#6", "C6", "A#5", "C6", "C#6", "F5", "C#6", "C6", "A#5", "C6", "C#6", "F5", "C6", "A#5", "G#5", "A#5", "C6", "F5", "C6", "A#5", "G#5", "A#5", "C6", "F5", "C#6", "C6", "A#5", "C6", "C#6", "F5", "C#6", "C6", "A#5", "C6", "C#6", "C6", "F5", "A#5", "G#5", "G5", "F5", "E5", "D5", "C5", "D5", "E5", "F5", "G5", "G#5", "A#5", "G#5", "G5", "F5", "E5", "D5", "C5", "D5", "E5", "F5", "G5", "G#5", "A#5", "G#5", "G5", "G#5", "G5", "F5", "A#5", "G#5", "G5", "G#5", "G5", "F5", "A#5", "G#5", "G5", "G#5", "G#5", "G#5", "A5", "A5", "A5", "A#5", "A#5", "A#5", "B5", "B5", "B5", "C6", "C6", "C6", "C6", "C6", "C6", "C6", "C6", "C6", "C6", "C6", "C6", "A#5", "A#5", "A#5"};
int index = 4;
int val = 0;
void setup() {
size(displayWidth, displayHeight);
frameRate(30);
smooth();
noStroke();
textSize(40);
// draw three buttons
colorMode(RGB, 255);
// set current state
state = IDLE;
// open serial port
port = new Serial(this, portname, 9600);
}
void draw() {
drawUI();
play();
}
void play() {
switch(state) {
case IDLE:
port.write(IDLE);
break;
case MANUAL:
port.write(MANUAL);
break;
case ASSISTED:
port.write(index);
break;
/*case COLLABORATIVE:
port.write(index);
break;*/
default:
break;
}
}
void drawUI() {
background(bgR, bgG, bgB);
switch(state) {
case IDLE:
bgR = 0x40;
bgG = 0x40;
bgB = 0x40;
break;
case MANUAL:
bgR = 0x50;
bgG = 0x40;
bgB = 0x40;
fill(buttonR, buttonG, buttonB, 180);
rect((displayWidth-buttonWidth*4)/2,
(displayHeight-buttonHeight)/2+buttonHeight*1.1,
buttonWidth,
buttonHeight/5,
buttonRound);
break;
case ASSISTED:
bgR = 0x40;
bgG = 0x50;
bgB = 0x40;
fill(buttonR, buttonG, buttonB, 255);
rect((displayWidth-buttonWidth)/2,
(displayHeight-buttonHeight)/2+buttonHeight*1.1,
buttonWidth,
buttonHeight/5,
buttonRound);
fill(255, 255, 255, 255);
// text("val = " + val, 100, 250);
break;
/*case COLLABORATIVE:
bgR = 0x40;
bgG = 0x40;
bgB = 0x50;
fill(buttonR, buttonG, buttonB, 255);
rect((displayWidth+buttonWidth*2)/2,
(displayHeight-buttonHeight)/2+buttonHeight*1.1,
buttonWidth,
buttonHeight/5,
buttonRound);
break;*/
default:
break;
}
// manual mode button
fill(buttonR, buttonG, buttonB, 180);
rect((displayWidth-buttonWidth*4)/2,
(displayHeight-buttonHeight)/2,
buttonWidth,
buttonHeight,
buttonRound);
fill(bgR, bgG, bgB);
text("manual",
(displayWidth-buttonWidth*4)/2 + 70,
displayHeight/2 + 10);
// assisted mode button
fill(buttonR, buttonG, buttonB, 255);
rect((displayWidth-buttonWidth)/2,
(displayHeight-buttonHeight)/2,
buttonWidth,
buttonHeight,
buttonRound);
fill(bgR, bgG, bgB);
text("assisted",
(displayWidth-buttonWidth)/2 + 60,
displayHeight/2 + 10);
// collaborative mode button
/*fill(buttonR, buttonG, buttonB, 255);
rect((displayWidth+buttonWidth*2)/2,
(displayHeight-buttonHeight)/2,
buttonWidth,
buttonHeight,
buttonRound);
fill(bgR, bgG, bgB);
text("collaborative",
(displayWidth+buttonWidth*2)/2 + 15,
displayHeight/2 + 10);*/
}
void mouseClicked() {
if((displayWidth-buttonWidth*4)/2<mouseX
&& mouseX<(displayWidth-buttonWidth*4)/2+buttonWidth
&& (displayHeight-buttonHeight)/2<mouseY
&& mouseY<(displayHeight-buttonHeight)/2+buttonHeight
) {
state = MANUAL;
}
else if((displayWidth-buttonWidth)/2<mouseX
&& mouseX<(displayWidth-buttonWidth)/2+buttonWidth
&& (displayHeight-buttonHeight)/2<mouseY
&& mouseY<(displayHeight-buttonHeight)/2+buttonHeight
) {
state = ASSISTED;
index = 3;
}
/*else if((displayWidth+buttonWidth*2)/2<mouseX
&& mouseX<(displayWidth+buttonWidth*2)/2+buttonWidth
&& (displayHeight-buttonHeight)/2<mouseY
&& mouseY<(displayHeight-buttonHeight)/2+buttonHeight
) {
state = COLLABORATIVE;
index = 4;
}*/
else {
state = IDLE;
}
}
void serialEvent(Serial p) {
val = port.read();
if(val=='r') {
index++;
}
index = index % vivaldi.length;
}
- Login to post comments
Drupal theme by Kiwi Themes.