The Muses of Ancient Greece are dead and gone, and I’ve discovered why.
The concept is simple: buttons for tones, distance sensor for modulation.
Schematic:

Code:
// keeping track of button input pins
int buttonPins[] = {A1, A2, A4, A5};
// keeping track of base tones {C, E, G, A}
float baseNotes[] = {262, 330, 392, 440};
//difference between semitones, for use with modulation
pinMode(pinTrigger, OUTPUT);
//setting the buttons to INPUT_PULLUP means i don't have to worry about pull down resistors clogging up my board
pinMode(buttonRed, INPUT_PULLUP);
pinMode(buttonGreen, INPUT_PULLUP);
pinMode(buttonYellow, INPUT_PULLUP);
pinMode(buttonBlue, INPUT_PULLUP);
for (int i = 0; i < 20; i+=2) {
modulation = semitone * fret;
if (digitalRead(buttonRed) == LOW) { //if the first key is pressed
tone(buzzer, 262 + modulation);
else if (digitalRead(buttonGreen) == LOW) { //if the second key is pressed
tone(buzzer, 330 + modulation);
else if (digitalRead(buttonYellow) == LOW) { //if the third key is pressed
tone(buzzer, 392 + modulation);
else if (digitalRead(buttonBlue) == LOW) {
tone(buzzer, 440 + modulation);
noTone(buzzer); //if no key is pressed turn the buzzer off
float echoTime; //variable to store the time it takes for a ping to bounce off an object
float calculatedDistance; //variable to store the distance calculated from the echo time
//send out an ultrasonic pulse that's 10ms long
digitalWrite(pinTrigger, HIGH);
digitalWrite(pinTrigger, LOW);
echoTime = pulseIn(pinEcho, HIGH); //use the pulsein command to see how long it takes for the
//pulse to bounce back to the sensor
calculatedDistance = echoTime / 148.0; //calculate the distance of the object that reflected the pulse (half the bounce time multiplied by the speed of sound)
return calculatedDistance; //send back the distance that was calculated
/* Name: Jan
Project: Rusty Trombone
*/
// keeping track of button input pins
int buttonPins[] = {A1, A2, A4, A5};
int buttonRed = A1;
int buttonGreen = A2;
int buttonYellow = A4;
int buttonBlue = A5;
// distance sensor pins
int pinTrigger = 9;
int pinEcho = 8;
// buzzer pins
int buzzer = 12;
// keeping track of base tones {C, E, G, A}
float baseNotes[] = {262, 330, 392, 440};
//difference between semitones, for use with modulation
float semitone = 15;
float modulation = 0;
float inches;
int fret = 1;
void setup() {
Serial.begin(9600);
//initializing pins
pinMode(buzzer, OUTPUT);
pinMode(pinTrigger, OUTPUT);
pinMode(pinEcho, INPUT);
//setting the buttons to INPUT_PULLUP means i don't have to worry about pull down resistors clogging up my board
pinMode(buttonRed, INPUT_PULLUP);
pinMode(buttonGreen, INPUT_PULLUP);
pinMode(buttonYellow, INPUT_PULLUP);
pinMode(buttonBlue, INPUT_PULLUP);
}
void loop() {
fret = 0;
bool buttonPressed = 0;
inches = getDistance();
for (int i = 0; i < 20; i+=2) {
fret++;
if (inches < i) {
modulation = semitone * fret;
break;
}
}
if (digitalRead(buttonRed) == LOW) { //if the first key is pressed
tone(buzzer, 262 + modulation);
Serial.println(inches);
}
else if (digitalRead(buttonGreen) == LOW) { //if the second key is pressed
tone(buzzer, 330 + modulation);
}
else if (digitalRead(buttonYellow) == LOW) { //if the third key is pressed
tone(buzzer, 392 + modulation);
}
else if (digitalRead(buttonBlue) == LOW) {
tone(buzzer, 440 + modulation);
}
else {
noTone(buzzer); //if no key is pressed turn the buzzer off
}
}
float getDistance()
{
float echoTime; //variable to store the time it takes for a ping to bounce off an object
float calculatedDistance; //variable to store the distance calculated from the echo time
//send out an ultrasonic pulse that's 10ms long
digitalWrite(pinTrigger, HIGH);
delayMicroseconds(1);
digitalWrite(pinTrigger, LOW);
echoTime = pulseIn(pinEcho, HIGH); //use the pulsein command to see how long it takes for the
//pulse to bounce back to the sensor
calculatedDistance = echoTime / 148.0; //calculate the distance of the object that reflected the pulse (half the bounce time multiplied by the speed of sound)
return calculatedDistance; //send back the distance that was calculated
}
/* Name: Jan
Project: Rusty Trombone
*/
// keeping track of button input pins
int buttonPins[] = {A1, A2, A4, A5};
int buttonRed = A1;
int buttonGreen = A2;
int buttonYellow = A4;
int buttonBlue = A5;
// distance sensor pins
int pinTrigger = 9;
int pinEcho = 8;
// buzzer pins
int buzzer = 12;
// keeping track of base tones {C, E, G, A}
float baseNotes[] = {262, 330, 392, 440};
//difference between semitones, for use with modulation
float semitone = 15;
float modulation = 0;
float inches;
int fret = 1;
void setup() {
Serial.begin(9600);
//initializing pins
pinMode(buzzer, OUTPUT);
pinMode(pinTrigger, OUTPUT);
pinMode(pinEcho, INPUT);
//setting the buttons to INPUT_PULLUP means i don't have to worry about pull down resistors clogging up my board
pinMode(buttonRed, INPUT_PULLUP);
pinMode(buttonGreen, INPUT_PULLUP);
pinMode(buttonYellow, INPUT_PULLUP);
pinMode(buttonBlue, INPUT_PULLUP);
}
void loop() {
fret = 0;
bool buttonPressed = 0;
inches = getDistance();
for (int i = 0; i < 20; i+=2) {
fret++;
if (inches < i) {
modulation = semitone * fret;
break;
}
}
if (digitalRead(buttonRed) == LOW) { //if the first key is pressed
tone(buzzer, 262 + modulation);
Serial.println(inches);
}
else if (digitalRead(buttonGreen) == LOW) { //if the second key is pressed
tone(buzzer, 330 + modulation);
}
else if (digitalRead(buttonYellow) == LOW) { //if the third key is pressed
tone(buzzer, 392 + modulation);
}
else if (digitalRead(buttonBlue) == LOW) {
tone(buzzer, 440 + modulation);
}
else {
noTone(buzzer); //if no key is pressed turn the buzzer off
}
}
float getDistance()
{
float echoTime; //variable to store the time it takes for a ping to bounce off an object
float calculatedDistance; //variable to store the distance calculated from the echo time
//send out an ultrasonic pulse that's 10ms long
digitalWrite(pinTrigger, HIGH);
delayMicroseconds(1);
digitalWrite(pinTrigger, LOW);
echoTime = pulseIn(pinEcho, HIGH); //use the pulsein command to see how long it takes for the
//pulse to bounce back to the sensor
calculatedDistance = echoTime / 148.0; //calculate the distance of the object that reflected the pulse (half the bounce time multiplied by the speed of sound)
return calculatedDistance; //send back the distance that was calculated
}
Evidence of My Crimes
Reflections: Code as is requires a lot of fine-tuning for the buzzer not to sound like it’s gently caressing a combine harvester. More specifically, changing the changes in tone from continuous to discrete kept the buzzing down. Tweaking the distance intervals at which the tone goes up or down a semitone keeps it from oscillating too much, as might changing how often the tone sounds. The equation for calculating distance from the sensor also has a lot of room for tuning, but I have not the hubris to claim to be a master of time nor space. Fun project though, had a blast.