Schadenfreude

Assignment: Input / Output Coincidence Lab Assignment

Collaborators:

My idea for this lab was revolved around this great little series of flipbooks called Schadenfreude, defined on the back of the book as:

Noun - Pleasure derived from the misfortune of others

Origin: German, from Schaden 'harm' + Freude 'joy'

Each flipbook illustrates an instance of small embarrassment or misfortune; in the one I selected, while a man is carrying a television on his shoulders with both hands, his pants slowly fall down.

Due to the nature of a flipbook, the reader/viewer must constantly exert pressure on the book in order to flip the pages rapidly enough for the images to "move." I thought it would be a great way to employ the FSR, taping it to the back cover where the fingers push onto the book. I wanted to have the pressure exerted correspond to the Piezo speaker, which is especially appropriate, due to its tinny, almost cruel sound output. I began with the given Theramin code, substituting the photocell for the FSR. This worked, but I had to press the sensor incredibly hard to get a sound out of the Piezo. With some help, I found out that this must be a problem of range, so I looked around at previous classes' codes for help. Ryan Kaufman's "Light Flute" from 2008 was closest to what I was attempting to do, so I amended his code (I am not using a photocell) & ran this:

int fsrPin = 0; // select the input pin for the FSR

int speakerPin = 7;

 

 

int fsrval = 0;

 

void setup() {

pinMode(speakerPin, OUTPUT);

Serial.begin(9600);

Serial.println("ready");

}

 

void loop() {

if (fsrval < 150); // set threshold value on FSR for program to proceed.

Serial.print (fsrval); // read input.

digitalWrite(speakerPin, LOW);

 

 

 

for( int i=0; i<500; i++ ) { // play it for 50 cycles

digitalWrite(speakerPin, HIGH);

digitalWrite(speakerPin, LOW);

}

}

 

This didn't really help! I fiddled for awhile longer, & couldn't figure out how to correctly calibrate the system. So, already handicapped, I thought of what I would like the system to be like even more ideally. It would be great if the sound the Piezo played corresponded in actual melody to the sentiment of the flipbook. I found this code on the Arduino website, & liked it:

/* Play Melody

* -----------

*

* Program to play a simple melody

*

* Tones are created by quickly pulsing a speaker on and off

*   using PWM, to create signature frequencies.

*

* Each note has a frequency, created by varying the period of

*  vibration, measured in microseconds. We'll use pulse-width

*  modulation (PWM) to create that vibration.

 

* We calculate the pulse-width to be half the period; we pulse

*  the speaker HIGH for 'pulse-width' microseconds, then LOW

*  for 'pulse-width' microseconds.

*  This pulsing creates a vibration of the desired frequency.

*

* (cleft) 2005 D. Cuartielles for K3

* Refactoring and comments 2006 clay.shirky@nyu.edu

* See NOTES in comments at end for possible improvements

*/

 

// TONES  ==========================================

// Start by defining the relationship between

//       note, period, &  frequency.

#define  c     3830    // 261 Hz

#define  d     3400    // 294 Hz

#define  e     3038    // 329 Hz

#define  f     2864    // 349 Hz

#define  g     2550    // 392 Hz

#define  a     2272    // 440 Hz

#define  b     2028    // 493 Hz

#define  C     1912    // 523 Hz

// Define a special note, 'R', to represent a rest

#define  R     0

 

// SETUP ============================================

// Set up speaker on a PWM pin (digital 9, 10 or 11)

int speakerOut = 9;

// Do we want debugging on serial out? 1 for yes, 0 for no

int DEBUG = 1;

 

void setup() {

pinMode(speakerOut, OUTPUT);

if (DEBUG) {

Serial.begin(9600); // Set serial out if we want debugging

}

}

 

// MELODY and TIMING  =======================================

//  melody[] is an array of notes, accompanied by beats[],

//  which sets each note's relative length (higher #, longer note)

int melody[] = {  C,  b,  g,  C,  b,   e,  R,  C,  c,  g, a, C };

int beats[]  = { 16, 16, 16,  8,  8,  16, 32, 16, 16, 16, 8, 8 };

int MAX_COUNT = sizeof(melody) / 2; // Melody length, for looping.

 

// Set overall tempo

long tempo = 10000;

// Set length of pause between notes

int pause = 1000;

// Loop variable to increase Rest length

int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES

 

// Initialize core variables

int tone = 0;

int beat = 0;

long duration  = 0;

 

// PLAY TONE  ==============================================

// Pulse the speaker to play a tone for a particular duration

void playTone() {

long elapsed_time = 0;

if (tone > 0) { // if this isn't a Rest beat, while the tone has

//  played less long than 'duration', pulse speaker HIGH and LOW

while (elapsed_time < duration) {

 

digitalWrite(speakerOut,HIGH);

delayMicroseconds(tone / 2);

 

// DOWN

digitalWrite(speakerOut, LOW);

delayMicroseconds(tone / 2);

 

// Keep track of how long we pulsed

elapsed_time += (tone);

}

}

else { // Rest beat; loop times delay

for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count

delayMicroseconds(duration);

}

}

}

 

// LET THE WILD RUMPUS BEGIN =============================

void loop() {

// Set up a counter to pull from melody[] and beats[]

for (int i=0; i<MAX_COUNT; i++) {

tone = melody[i];

beat = beats[i];

 

duration = beat * tempo; // Set up timing

 

playTone();

// A pause between notes...

delayMicroseconds(pause);

 

if (DEBUG) { // If debugging, report loop, tone, beat, and duration

Serial.print(i);

Serial.print(":");

Serial.print(beat);

Serial.print(" ");

Serial.print(tone);

Serial.print(" ");

Serial.println(duration);

}

}

}

 

/*

* NOTES

* The program purports to hold a tone for 'duration' microseconds.

*  Lies lies lies! It holds for at least 'duration' microseconds, _plus_

*  any overhead created by incremeting elapsed_time (could be in excess of

*  3K microseconds) _plus_ overhead of looping and two digitalWrites()

*

* As a result, a tone of 'duration' plays much more slowly than a rest

*  of 'duration.' rest_count creates a loop variable to bring 'rest' beats

*  in line with 'tone' beats of the same length.

*

* rest_count will be affected by chip architecture and speed, as well as

*  overhead from any program mods. Past behavior is no guarantee of future

*  performance. Your mileage may vary. Light fuse and get away.

*

* This could use a number of enhancements:

* ADD code to let the programmer specify how many times the melody should

*     loop before stopping

* ADD another octave

* MOVE tempo, pause, and rest_count to #define statements

* RE-WRITE to include volume, using analogWrite, as with the second program at

*          http://www.arduino.cc/en/Tutorial/PlayMelody

* ADD code to make the tempo settable by pot or other input device

* ADD code to take tempo or volume settable by serial communication

*          (Requires 0005 or higher.)

* ADD code to create a tone offset (higer or lower) through pot etc

* REPLACE random melody with opening bars to 'Smoke on the Water'

*/

I knew that it was beyond my means to attempt to suture the two codes, as I couldn't even get the first one to work too well. BUT! I did splice them together well enough so that Arduino ran it without an error notice (this always feels so triumphant even if it's fruitless in the end).