Intro + Initial Attempts
This week’s assignment was quite challenging! I tried many things and had to change up details in my idea a lot to get it to work. I was really inspired by the Sound Wall example from Peter Vogel and wanted to incorporate that in the assignment so I can play around with both the photoresistor and the servo motor. Initially, I coded my servo to automatically keep sweeping from left to right, over the photoresistor. I had a small piece of paper taped on my servo arm to cast a shadow over the photoresistor.
The goal was to have a song playing, and then whenever the arm is over the photoresistor, the song switches to a lower octave to simulate a darker sound. The issue I had here is that the code for sweeping the servo arm relied on the delay(), and I think that interfered with triggering the buzzer in a regular manner.
//sweep code from Arduino Reference// for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees // in steps of 1 degree servo.write(pos); // tell servo to go to position in variable 'pos' //delay(40); // waits 40ms for the servo to reach the position } for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees servo.write(pos); // tell servo to go to position in variable 'pos' //delay(40); // waits 40ms for the servo to reach the position }
So, I decided to move the servo arm in an analog matter using the potentiometer and was presented with a second issue. I struggled with having the music playing all the time simultaneously with moving the servo, so I couldn’t have it switch between songs like I had imagined. I’m still a bit confused about how the movement of the servo interferes with the buzzer functions and how to navigate that and want to look into that.
Final Idea
So, I decided to make an “instrument” that plays Happy Birthday when the photoresistor reads a high value of intensity, and then when the knob is turned and the servo arm casts a shadow over the photoresistor the song stops. Then, when the photoresistor detects light again, it starts the song from the beginning.
Here’s my set-up, I used the eraser to elevate my servo!
Here’s a demo:
As you can see, my buzzer is lagging which presented another issue that I’m confused about. The durations of the notes are accurate, and I used the concept of the rate that we covered in class which makes me question if moving a servo and playing the buzzer at the same time causes this.
For the digital input, I used a switch. If the switch is flipped, it moves the servo arm to cover the photoresistor and doesn’t allow the user to move the arm, turning the music off and locking the device.
Overall, brainstorming adding a lot of interacting elements was a lot of fun for me! I would love to find a way to make my initial idea (where the pitches lower in response to shadow) work, though.
Here’s my circuit diagram and code:
#include "pitches.h" #include <Servo.h> Servo servo; //defining photoresistor pin int photoResistor = A1; //potentiometer int potenKnob = A0; //buzzer pin int buzzerLoc = 4; //switch pin int switchPin = 6; //array for birthday song notes int notes[25] = {NOTE_C5, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_F5, NOTE_E5, NOTE_C5, NOTE_C5, NOTE_D5, NOTE_C5, NOTE_G5, NOTE_F5, NOTE_C5, NOTE_C5, NOTE_C6, NOTE_A5, NOTE_F5, NOTE_E5, NOTE_D5, NOTE_AS5, NOTE_AS5, NOTE_A5, NOTE_F5, NOTE_G5, NOTE_F5}; //array for the duration of each note int durations[25] = {8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 2}; //variable to keep track of which note in the song is playing int whichNote = 0; void setup() { servo.attach(2); Serial.begin(9600); pinMode(switchPin, INPUT); } void loop() { //variable to read the switch state int switchState = digitalRead(switchPin); //variable that reads from the photoresistor int prVal = analogRead(photoResistor); //variable to check previous photoresistor value int prevPrVal; //reading the potentiometer location int knobValue = analogRead(potenKnob); //mapping to 180 cause it's being used to move the servo int mappedKnobValue = map(knobValue, 0, 1023, 0, 180); //moving the servo servo.write(mappedKnobValue); //rate at which the music is meant to play, settled 600 after trial and error int rate = 600 / durations[whichNote]; //condition that checks if servo arm is above photoresistor if (prVal >= 800) { //condition that checks if the photoresistor was previously covered, so the song starts over when the arm moves, rather than resuming from the middle if (prevPrVal < 800) { whichNote = 0; //back to beginning } if (millis() % rate == 0) { //condition to move through each note tone(buzzerLoc, notes[whichNote], rate); //plays the note by referring to the note from the array whichNote = (whichNote + 1) % 25; //to loop through the song delay(1); } } //condition that checks digital input from switch, if (switchState == HIGH) { //if the switch is flipped, the instrument is "locked" and no one can play the song by moving the potentiometer knob servo.writeMicroseconds(2100); //writing a value to the servo to move it digitally } prevPrVal = prVal; //setting the current photoresistor reading to the previous variable, to check next time }