PCOMP Week 4

I recently learnt about digital and analogue inputs/outputs in my physical computing class. The servo motor and the speaker was the most interesting parts among them — Actually, analogue things are more interesting to me! — Therefore I made up my mind to use both of them for my assignment this week.

The basic idea of my device is simple. What could be related to both motion and sound(music)? — Dance! 

I wanted to show different types of motion and sound through multiple motors and speakers, though all I had now were just one servo and one mini speaker. So, I designed the circuit to get two distinctive outputs from the same device depending on the value of a potentiometer.

Following is the schematic diagram:

A potentiometer as an input and a servo motor, an 8Ω-speaker and two LEDs as outputs were used for this device.

At first, I imagined the motor rotates slowly according to the calm music and quickly for the fast-bit music. However, I soon realised that controlling the rotating speed of servo is impossible, thus I changed the plan to make the servo rotate in a big or small angle instead.

The hardest part was the music composition. Although the songs weren’t new at all and were somewhat familiar to me, it was really difficult to find out the notes as I didn’t know the titles of the songs that allow me to search them on the internet, and I’m not a musically gifted person at all!

Anyway, here is the first prototype with the false melodies that I managed to compose:

After seeing this worked fine and did a bit of packaging, I added a Playmobil figure for the dancer. However, I chose a wrong one at first:

Because of the gun, he’s holding, it looks rather horrifying and doesn’t seem like dancing. This thrilling-like concept wasn’t what I intended. So I changed the dancer. Moreover, I figured out that the waltz was “Waltz No. 2”, of Dmitri Shostakovich at this point and was able to find its real notes. In the result, she dances with better melody.

The dimming of the yellow LED doesn’t smooth enough. It might have been better if I divided ‘millis’ with a specific frame number and used the remainders for the timer instead of the ‘i’ value.

The full code is like below:


#include
#include "pitches.h"
////////////////////
#define spkPin 9
#define servoPin 3
#define waltzLED 6
#define technoLED 5
////////////////////
int technoMelody[] = {NOTE_GS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4,
NOTE_GS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4,
NOTE_GS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4,
NOTE_GS4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_G4, NOTE_B4, NOTE_AS4, NOTE_A4};
////////////////////
int technoDuration[] = {385, 200, 200, 200, 200, 200, 200,
385, 200, 200, 200, 200, 200, 200,
385, 200, 200, 200, 200, 200, 200,
385, 200, 200, 200, 200, 200, 200, 200};
////////////////////
int waltzMelody[] = {NOTE_G5, NOTE_DS5, NOTE_D5, NOTE_C5,
NOTE_C5, NOTE_D5, NOTE_DS5, NOTE_C5, NOTE_DS5, NOTE_G5, NOTE_GS5, NOTE_G5, NOTE_F5,
NOTE_F5, NOTE_D5, NOTE_C5, NOTE_B4,
NOTE_G4, NOTE_B4, NOTE_D5, NOTE_B4, NOTE_D5, NOTE_F5, NOTE_G5, NOTE_GS5, NOTE_FS5, NOTE_G5};
////////////////////
int waltzDuration[] = {750, 500, 250, 1000,
250, 250, 250, 250, 250, 500, 250, 750, 750,
750, 500, 250, 1000,
250, 250, 250, 250, 250, 250, 250, 250, 750, 750}; // 27 tones
////////////////////
Servo myServo;
////////////////////
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
myServo.attach(servoPin);
pinMode(waltzLED, OUTPUT);
pinMode(technoLED, OUTPUT);
}
////////////////////
void loop() {
// the value of the potentiometer
int potValue = analogRead(A0);
////////////////////
// decide the mode depending on the value of the potentiometer
// 0: off, 1: waltz, 2: techno
int mode = map(potValue, 0, 1000, 0, 2);
////////////////////
int m, dim;
////////////////////
//Serial.println(mode);
Serial.println(potValue);
////////////////////
if(mode == 0) {
digitalWrite(waltzLED, LOW);
digitalWrite(technoLED, LOW);
}
// waltz
else if(mode == 1) {
// turn off the techno light
digitalWrite(technoLED, LOW);
////////////////////
// turn on the music, dance and light for the waltz mode
for(int i=0; i<27; i++) {
// play the waltz mjusic
tone(spkPin, waltzMelody[i], waltzDuration[i]);
delay(waltzDuration[i]+20);
////////////////////
// rotate the servo to the waltz rhythm
if(i%2 == 0) myServo.write(30);
else myServo.write(0);
////////////////////
// waltz LED (yellow)
if(i<3) {
dim = map(i, 0, 2, 0, 255);
} else if(i<11) {
dim = map(i, 3, 10, 255, 0);
} else if(i<18) { dim = map(i, 11, 17, 0, 255); } else if(i>=18) {
dim = map(i, 18, 26, 255, 0);
}
analogWrite(waltzLED, dim);
////////////////////
// check if the mode changed in the middle of the music
// if so, break out of this for loop
potValue = analogRead(A0);
mode = map(potValue, 0, 1000, 0, 2);
if(mode!=1) i=27; //// i=25
}
}
// techno
else if(mode == 2) {
// turn off the waltz light
digitalWrite(waltzLED, LOW);
////////////////////
// turn on the music, dance and light for the techno mode
for(int i=0; i<29; i++) {
// play the techno music
tone(spkPin, technoMelody[i], technoDuration[i]);
if(technoDuration[i] == 385) delay(450);
else delay(230);
////////////////////
// rotate the servo to the techno rythm
if(i%2 == 0) myServo.write(180);
else myServo.write(0);
////////////////////
// techno LED (violet)
if(i%2 == 0) digitalWrite(technoLED, HIGH);
else digitalWrite(technoLED, LOW);
////////////////////
// check if the mode changed in the middle of the music
// if so, break out of this for loop
potValue = analogRead(A0);
mode = map(potValue, 0, 1000, 0, 2);
if(mode!=2) i=29;
}
}
}

The enclosing would have been better, btw. It is still hard to find a proper material and the way for fabrication.

 

EXTRA LAB

I also made a luv-o-meter mentioned here: Get Creative

I used three LEDs in different colours to show the scores of the force applied on the FSR. The yellow one can be turned on with the weakest pressure, the orange can be lighted with the middle pressure, and the red one is the hardest to turn on.

I measured the range of the FSR to find the proper values for each score and the matchings were like below:

As the maximum value of the FSR was below 900, I needed to adjust the third parameters in map() function to be around that number.

The whole working code is shown below:


#define redLED 11
#define orangeLED 10
#define yellowLED 9
int sensorValue = 0;
////////////////////
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(redLED, OUTPUT);
pinMode(orangeLED, OUTPUT);
pinMode(yellowLED, OUTPUT);
}
////////////////////
void loop() {
// put your main code here, to run repeatedly:
// read the analog input
sensorValue = analogRead(A0);
int force = map(sensorValue, 0, 879, 0, 3);
if(force == 0) {
digitalWrite(redLED, LOW);
digitalWrite(orangeLED, LOW);
digitalWrite(yellowLED, LOW);
} else if(force == 1) {
digitalWrite(redLED, LOW);
digitalWrite(orangeLED, LOW);
digitalWrite(yellowLED, HIGH);
} else if(force == 2) {
digitalWrite(redLED, LOW);
digitalWrite(orangeLED, HIGH);
digitalWrite(yellowLED, HIGH);
} else if(force == 3) {
digitalWrite(redLED, HIGH);
digitalWrite(orangeLED, HIGH);
digitalWrite(yellowLED, HIGH);
}
Serial.print("sensor: ");
Serial.print(sensorValue);
Serial.print("\t");
Serial.print("force: ");
Serial.println(force);
}

Based on this idea, I came up with another idea of playing tug-of-war. I’ll try to build it next time. It would be fun! 😀

Leave a Reply

Your email address will not be published. Required fields are marked *