Arduino Rainbow Hack

The following was co-authored and co-hacked with Claire.

Claire and I went to the Arduino Hackday hosted by the Scholars’ Lab on Friday. We had no idea what we were getting into, which made it all the more fun. Jeremy brought in a bunch of Arduino kits of all shapes and sizes, and various people went to work to see what they could make out of them.

First Claire and I got a blinking light to work. From there we decided to skip several chapters to make a little music player using a piezo speaker component. At that point we went off the map, dreaming big and working off the page. We started out working with this schematic, but we wanted to expand things a little.

I apologize in advance for whatever vocabulary gap there might be in the discussion below; it was my first time coding in C.

For one, this set-up only uses a single octave major scale. We opened things up by expanding the range of tones the speaker could play, including both a chromatic scale and adding an extra octave. One difficulty here was in the way that way that accidentals would be read by the board. At first we tried to use standard notation – f sharp would be represented by f#. But the code finds the notes in the melody by reading character by character through an array. So when the computer sees “cc#”, it processes it as two ‘c’s and one nonsense syllable that it can’t process. There is probably a more elegant solution, but we got around this by associating the accidentals with new characters entirely

C#/Db             =>       l

D#/Eb              =>       m

F#/Gb              =>       n

G#/Ab             =>       o

A#/Bb             =>       p

Next, we added an extra octave. To extend the range, we hard coded frequencies for the new notes according to the formula given by the original Arduino code:

timeHigh = period / 2 = 1 / (2 * toneFrequency)

We probably could have done this in a more dynamic way. Or, as Eric and Ronda showed, we could have just downloaded a tone library to do this for us. They were jamming out to the Star Wars theme while we were still trying to get things working.  But eventually, we were able to program in the opening of “Mary Had a Little Lamb,” Mozart’s Lacrimosa, John Coltrane’s “26-2,” and “Somewhere Over the Rainbow.

Here is where things got really ambitious, we came up with the idea to incorporate a RGB LED light that would change colors each time there was a note change in “Somewhere Over the Rainbow.” Rainbow lights for a song about rainbows.

To get the light working we worked off a slightly modified version of this schematic, mashed in with the piezo tutiorial. With some quick help from Eric, we modified the light arrangement so that each generates a random RGB combination. We then synchronized this with the rhythm of the melody.

In terms of the actual circuitry, we just split the digital signal so that it went out to two different parts of the bread board simultaneously and then fed information to both pins. Later we added a volume knob to reduce the maddening noise. You can see attached photos below, though you’ll have to meet us halfway with our diagram of the breadboard.

A later, unsuccessful attempt to key each frequency to a particular color resulted in a light that got brighter or darker depending on the note. I think with a little more time I could fix that by hard coding particular RGB values to particular frequencies, but we were trying to do it dynamically by converting the frequency directly into an intensity value.

Behold our final product!

// Piezo speaker connected to pins
int speakerPin = 6;
// RGB LED leads connected to PWM pins
const int RED_LED_PIN = 9;
const int GREEN_LED_PIN = 10;
const int BLUE_LED_PIN = 11;

// Used to store the current intensity level of the individual LEDs
int redIntensity = 0;
int greenIntensity = 0;
int blueIntensity = 0;

char notes[] = {"cCbgabccaag "}; // a space represents a rest
int length = sizeof(notes); // the number of notes
int beats[] = {4,4,2,1,1,2,4,1,1,1,4,1};
int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
char names[] = { 'c', 'l', 'd', 'm','e', 'f', 'n', 'g', 'o','a', 'p', 'b', 'C', 'L', 'D', 'M', 'E', 'F', 'N', 'G', 'O', 'A', 'P', 'B' };
int tones[] = { 1915, 1805, 1700, 1608, 1519, 1432, 1351, 1275, 1205, 1136, 1073, 1014, 956, 903, 850, 804, 760, 716, 676, 638, 603, 568, 478 };
  
  // play the tone corresponding to the note name
  for (int i = 0; i < sizeof(names); i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}

void setup() {
  pinMode(speakerPin, OUTPUT);
}

void loop() {
  for (int i = 0; i < length; i++) {
    if (notes[i] == ' ') {
      delay(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
      greenIntensity = 255 * rand();
      redIntensity = 255 * rand();
      blueIntensity = 255 * rand();
      analogWrite(GREEN_LED_PIN, greenIntensity);
      analogWrite(RED_LED_PIN, redIntensity);
      analogWrite(BLUE_LED_PIN, blueIntensity);
      delay(beats[i]);
    }
    
    // pause between notes
    delay(tempo / 2); 
  }
}

Arduino Rainbow Circuit MapArduino Breadboard Diagram

Brandon is a 2012-2013 Praxis Fellow and a Ph.D. student in the Department of English. His research focuses on modern and contemporary fiction, especially on Anglophone modernisms and the novel in relation to sound studies and musicology.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Archives