The assignment of this week did not turn out as expected. I wanted to build a piano with 8 different keys. But I realized after hacking a while that I needed two FSRs. I tried to solve the problem with a photocell. If the hand is on the left of the FSR you have the first 4 notes, and on the right you have the second 4 notes, because then the photocell should be able to sense your hand. This does not work well for two reasons: the photocell is not sensitive enough and the input for the FSR does not work well.
I thus tried to build something else, by connecting two pots I could also control the volume and the pitch to change the sound. So, now I have a failed piano build by a sponge and I can control the volume and pitch. As an extra output I build a prosessing code to show the sound with little bars. Higher volume is more bars, pitch is the color of the bars and the force on the FSR is the height of the bars.
1 Arduino uno
2 Pots
1 Piezo
1 Photocell
1 FSR
1 Sponge
Code
int ledPin = 13;
int speakerPin = 9;
int fsrPin = 0;
int force = 0;
int maxForce = 1000;
int phoPin = 1;
int light = 0;
int threshold = 750;
int pitchPin = 2;
float pitch = 0;
int volPin = 3;
int vol = 0;
int serByte = -1;
int DEBUG = 1;
// note names and their corresponding half-periods
byte names[] ={ 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
char toneNames[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
int ledState = LOW;
int count = 0;
int count2 = 0;
int count3 = 0;
int MAX_COUNT = 24;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("ready");
}
void loop() {
analogWrite(speakerPin, 0);
force = analogRead(fsrPin); // highest possible value is 1024
light = analogRead(phoPin); // Get the value from the photocel
pitch = (float) (analogRead(pitchPin) / 500.00); // Values roughly between 0 and 2
vol = analogRead(volPin) / 2; // Volume is 0 to 512
String myForce = "f" + String(force);
Serial.println(myForce);
String myPitch = "";
if(pitch < 0.7) {
myPitch = "p1";
}
else if(pitch >= 0.7 && pitch < 1.3) {
myPitch = "p2";
}
else if(pitch >= 1.3) {
myPitch = "p3";
}
Serial.println(myPitch);
String myVolume = "v" + String(vol);
Serial.println(myVolume);
if(force > ((maxForce/4)*3) && force < maxForce) {
if(light < threshold) {
serByte = 'C';
}
else {
serByte = 'b';
}
}
else if(force >= (maxForce / 2) && force < ((maxForce/4)*3)) {
if(light < threshold) {
serByte = 'a';
}
else {
serByte = 'g';
}
}
else if(force >= (maxForce/4) && force < (maxForce/2)) {
if(light < threshold) {
serByte = 'f';
}
else {
serByte = 'e';
}
}
else if(force > 5 && force < (maxForce/4)) {
if(light < threshold) {
serByte = 'd';
}
else {
serByte = 'c';
}
}
ledState = !ledState;
digitalWrite(ledPin, ledState);
for (count = 0; count <= 8; count++) { // look for the note
if (names[count] == serByte) {
if(DEBUG == 1) {
Serial.print("Tone: ");
Serial.print(toneNames[count]);
Serial.print(", Force: ");
Serial.print(force);
Serial.print(", Light: ");
Serial.print(light);
Serial.print(", Pitch: ");
Serial.print(pitch);
Serial.print(", Volume: ");
Serial.println(vol);
}
if(pitch < 0.25) {
pitch = 0.25;
}
else if(pitch > 2.00) {
pitch = 2.00;
}
for(int i = 0; i < 50; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin, vol);
delayMicroseconds(tones[count] * pitch);
digitalWrite(speakerPin, 0);
delayMicroseconds(tones[count] * pitch);
}
serByte = -1;
}
}
}
Processing
import processing.serial.*;
// Change this to the portname your Arduino board
Serial port;
String buf = "";
char command;
int previousForce = 0;
int force = 0; // Show a bar that is higher when more force
int pitch = 0; // Change color for different pitch
int volume = 0; // More bars at higher volume
int cr = 13; // ASCII return == 13
int lf = 10; // ASCII linefeed == 10
void setup() {
size(512,512);
frameRate(60);
smooth();
background(40,40,40);
noStroke();
port = new Serial(this, Serial.list()[14], 9600);
}
void draw() {
background(40,40,40);
int mHeight = 0;
int mWidth = 20;
int x = 12;
int y = height - mHeight;
int margin = 5;
if(pitch == 1) {
fill(255, 0, 0);
}
else if(pitch == 2) {
fill(0, 255, 0);
}
else if(pitch == 3) {
fill(0, 0, 255);
}
int numRects = volume / (mWidth + margin);
for(int i = 0; i < numRects; i++) {
if(force > 0) {
mHeight = int(random((force - 20), (force + 20)));
y = height - mHeight;
}
rect(x + (i * (mWidth + margin)), y, mWidth, mHeight, 5, 5, 5, 5);
}
}
// called whenever serial data arrives
void serialEvent(Serial p) {
// Read anything that is send to the port
int c = port.read();
// if it is not 13 or 10 store the data
if (c != lf && c != cr) {
buf += char(c);
}
// If it is 10, analyze the input
if (c == lf) {
// Only continue when the buffer is nog empty
if(buf.length() > 0) {
// The first character could tell what the sender of the
// data is (pot, light or force)
char command = buf.charAt(0);
// If the force is the sender, it is the trigger to shoot
if(command == 'f') {
force = (int(buf.substring(1)) / 3);
}
// the pitch (pot1)
if(command == 'p') {
pitch = int(buf.substring(1));
}
// the volume (pot2)
if(command == 'v') {
volume = int(buf.substring(1));
}
// Clear the buffer
buf = "";
}
}
}
- Login to post comments