Tag Archives: musichackday arduino lilypad hacking hack music london 2009

Musichackday 2009 – my hack: TwinkleStarduino

I had a great weekend at Musichackday in the Guardian offices in Kings Cross. There were some fab hacks going on and excellent people to chat to as well as share ‘n’ compare ideas. I particularly enjoyed sitting in the Arduino room with the tinker.it folk and other hardware hackers such as Mitch Altman, from TV-B-Gone. Mitch had brought his Brain Machine with him and it was very entertaining to watch people drop in and have a go as they were passing by – everyone had something amusing to say about their experience. We also had some great philosophical discussion as we wiled away the afternoon into late evening – so I came away with much to reflect on :-)

About my hack

I’ve been working with computational art for a number of years to create interactive artworks incorporating sound, so I was really excited when I discovered microprocessors for rapid prototyping – because this gave me the opportunity to make something physical. for this project I wanted to created a fine art textiles, interactitive sound artwork.

My original idea was to find a Twitter api, send tweets to an LCD screen and trigger Twinkle to sing – BUT – I bought the wrong LCD screen which runs on 5v, when I needed the basic one that runs on 3.3v – I’m just mulling over ordering the the 3.3v LCD or a 5v Lilypad LiPo battery component so I can complete this idea later.

Soooo… for Musichackday, I took a canvas and cut out shapes in felt for my design. In terms of hardware, I got Twinkle singing through a buzzer via a Lilypad Arduino – which is sending the buzzer note frequencies. To make things a bit more interesting I’ve added an accelerometer which changes the pitch of the note when you move Twinkle about – plus a button so you can toggle between straight and bent pitch Twinkle :-)

In case you haven’t seen it before, Lilypad Arduino is a wearable form of the popular Arduino microprocessor. It’s connected/wired up by conductive thread.

Coding:
I’m using the Arduino compiler on my Mac and the code is written in C, it is then uploaded to the Lilypad via a FTDI Basic Breakout – 3.3V board & USB cable. You could use the Arduino or Processing libraries for code if you wanted to.

Some more info on sound:

The hack uses a LilyPad speaker module to produce simple musical notes.For a chart of the frequencies of different notes see: http://www.phy.mtu.edu/~suits/notefreqs.html

Fiddly?
Yep – sewing is a bit fiddly! All the components are connected by conductive thread – none of these must touch each other or you’ll get a short circuit – which is a challenge in itself :-)

API’s/tools used:

* Sadly no APIs because of my LCD fail – see above
* Lilypad arduino, buzzer, accelerometer, LEDs, conductive thread, felt, canvas.

Here’s the code – enjoy!

/*
* LilyPad tutorial: sound
*
* Uses a LilyPad speaker module to produce simple musical notes
* For a chart of the frequencies of different notes see:
* http://www.phy.mtu.edu/~suits/notefreqs.html
*/

// You can ignore this:
// #include “arduino.h”  // only for testing compiling with g++

#include “WProgram.h”
void setup();
void loop();
void flash_eyes();
int read_accel();
void beep(unsigned char speakerPin, int frequency, long duration);
void play(unsigned char speakerPin, const char *note, long duration);
void play_tune();
int ledPin = 13;        // LED is connected to digital pin 13
int speakerPin = 9;     // speaker connected to digital pin 9
int catseye1 = 5;       // cat’s eye no1
int catseye2 = 12;      // cat’s eye no2
int moveSensor = 3;     // analogue input for accelerometer
int buttonPin = 11;     // button input

// A note in one octave is twice the frequency of the same note in the octave
// below.  We define here the frequencies of the notes in octave 8.  To get
// notes in lower octaves, we just divide by two however many times.

#define NOTE_C8         4186
#define NOTE_CSHARP8    4434
#define NOTE_D8         4698
#define NOTE_DSHARP8    4978
#define NOTE_E8         5274
#define NOTE_F8         5587
#define NOTE_FSHARP8    5919
#define NOTE_G8         6271
#define NOTE_GSHARP8    6644
#define NOTE_A8         7040
#define NOTE_ASHARP8    7458
#define NOTE_B8         7902

// This is an array of note frequencies.  Index the array essentially by note
// letter multiplied by two (A = 0, B = 2, C = 4, etc.).  Add one to index for
// “sharp” note.  Where no sharp note exists, the natural note is just
// duplicated to make this indexing work.  The play() function below does all
// of this for you :)

int octave_notes[14] = {
NOTE_A8, NOTE_ASHARP8,
NOTE_B8, NOTE_B8,
NOTE_C8, NOTE_CSHARP8,
NOTE_D8, NOTE_DSHARP8,
NOTE_E8, NOTE_E8,
NOTE_F8, NOTE_FSHARP8,
NOTE_G8, NOTE_GSHARP8,
};

// This variable tracks the current state of the eye LEDs.
int eyes;

// Arduino runs this bit of code first, then repeatedly calls loop() below.  So
// all initialisation of variables and setting of initial pin modes (input or
// output) can be done here.

void setup() {
pinMode(ledPin, OUTPUT);        // sets the ledPin to be an output
pinMode(speakerPin, OUTPUT);    // sets the speakerPin to be an output
eyes = LOW;                     // initial state of cats eyes is LOW
pinMode(catseye1, OUTPUT);      // sets the cats eye1 to be an output
pinMode(catseye2, OUTPUT);      // sets the cats eye2 to be an output
pinMode(buttonPin, INPUT);      // sets the cats eye2 to be an output
//        Serial.begin(9600);
}

// Arduino will run this over and over again once setup() is done.

void loop()
{
read_accel();
play_tune();    // call the play_tune() function
delay(1000);    // delay for 1 second
}

// ————————————————————————-

// A function to toggle the cat’s eyes on and off.
void flash_eyes()
{
// Invert the desired state of the cat’s eyes:
if (eyes == LOW) {
eyes = HIGH;
} else {
eyes = LOW;
}

// Write the new value to all the LED pins:
digitalWrite(ledPin, eyes);
digitalWrite(catseye1, eyes);
digitalWrite(catseye2, eyes);
}

// ————————————————————————-

// Read accelerometer
int read_accel()
{
static int last_accel = 0;
int in = analogRead(moveSensor);
int diff = last_accel – in;
last_accel = in;
//  Serial.println(diff);
if (diff < -5 || diff > 5) {
return diff;
}
return 0;
}

// To produce a tone, this function toggles the speaker output pin at the
// desired frequency (in Hz).  It calculates how many times to do this to
// produce a note of the desired length (in milliseconds).

void beep(unsigned char speakerPin, int frequency, long duration)
{

int i;
long delayAmount = (long)(1000000/frequency);
long loopTime = (long)((duration*1000)/(delayAmount*2));

int accel_diff = 0;
int button_in = digitalRead(buttonPin);
for (i = 0; i < loopTime; i++) {
if (button_in == HIGH && (i & 31) == 0) {
accel_diff = read_accel();
}
digitalWrite(speakerPin, HIGH);
delayMicroseconds(delayAmount + accel_diff);
digitalWrite(speakerPin, LOW);
delayMicroseconds(delayAmount + accel_diff);
}
}

void play(unsigned char speakerPin, const char *note, long duration)
{
int octave_number = 4;  // default to octave 4
int i = 0;

// Check for valid note letter
if (note[i] >= ‘A’ && note[i] <= ‘G’) {
// Calculate index into octave_notes[]
int note_index = (note[i] – ‘A’) * 2;
i++;
// Check for sharp sign
if (note[i] == ‘#’) {
note_index++;
i++;
}
// Check for an octave number
if (note[i] >= ’0′ && note[i] <= ’8′) {
octave_number = note[i] – ’0′;
i++;
}
// Fetch the note frequency from the octave_notes[] table
int frequency = octave_notes[note_index];

// That will be the frequency for the note in octave 8, so we
// need to divide it by two for each octave lower that we
// actually want.

// The ‘>>’ operator is a useful shorthand that (for integers
// >= 0) basically translates to “divide by two this many
// times”, so we will use that:

frequency = frequency >> (8 – octave_number);

// Actually play the note!
beep(speakerPin, frequency, duration);
}
}

void play_tune()
{
flash_eyes(); play(speakerPin, “C6″, 500);    // twin-
flash_eyes(); play(speakerPin, “C6″, 500);    // -kle
flash_eyes(); play(speakerPin, “G6″, 500);    // twin-
flash_eyes(); play(speakerPin, “G6″, 500);    // -kle
flash_eyes(); play(speakerPin, “A6″, 500);    // lit-
flash_eyes(); play(speakerPin, “A6″, 500);    // -tle
flash_eyes(); play(speakerPin, “G6″, 1000);    // star
flash_eyes(); play(speakerPin, “F6″, 500);    // how
flash_eyes(); play(speakerPin, “F6″, 500);    // i
flash_eyes(); play(speakerPin, “E6″, 500);    // won-
flash_eyes(); play(speakerPin, “E6″, 500);    // -der
flash_eyes(); play(speakerPin, “D6″, 500);    // what
flash_eyes(); play(speakerPin, “D6″, 500);    // you
flash_eyes(); play(speakerPin, “C6″, 1000);    // are

flash_eyes(); play(speakerPin, “G6″, 500);    // up
flash_eyes(); play(speakerPin, “G6″, 500);    // a-
flash_eyes(); play(speakerPin, “F6″, 500);    // -bove
flash_eyes(); play(speakerPin, “F6″, 500);    // the
flash_eyes(); play(speakerPin, “E6″, 500);    // world
flash_eyes(); play(speakerPin, “E6″, 500);    // so
flash_eyes(); play(speakerPin, “D6″, 1000);    // high
flash_eyes(); play(speakerPin, “G6″, 500);    // like
flash_eyes(); play(speakerPin, “G6″, 500);    // a
flash_eyes(); play(speakerPin, “F6″, 500);    // dia-
flash_eyes(); play(speakerPin, “F6″, 500);    // -mond
flash_eyes(); play(speakerPin, “E6″, 500);    // in
flash_eyes(); play(speakerPin, “E6″, 500);    // the
flash_eyes(); play(speakerPin, “D6″, 1000);    // sky

flash_eyes(); play(speakerPin, “C6″, 500);    // twin-
flash_eyes(); play(speakerPin, “C6″, 500);    // -kle
flash_eyes(); play(speakerPin, “G6″, 500);    // twin-
flash_eyes(); play(speakerPin, “G6″, 500);    // -kle
flash_eyes(); play(speakerPin, “A6″, 500);    // lit-
flash_eyes(); play(speakerPin, “A6″, 500);    // -tle
flash_eyes(); play(speakerPin, “G6″, 1000);    // star
flash_eyes(); play(speakerPin, “F6″, 500);    // how
flash_eyes(); play(speakerPin, “F6″, 500);    // i
flash_eyes(); play(speakerPin, “E6″, 500);    // won-
flash_eyes(); play(speakerPin, “E6″, 500);    // -der
flash_eyes(); play(speakerPin, “D6″, 500);    // what
flash_eyes(); play(speakerPin, “D6″, 500);    // you
flash_eyes(); play(speakerPin, “C6″, 1000);    // are

}

int main(void)
{
init();

setup();

for (;;)
loop();

return 0;
}