Introduction: RGB Sound Box


My six year old son is very interested in electronics and especially light bulbs of any kind. This project started when we hooked up an RGB LED to three different buttons - one for each color. From there, it expanded a bit, and became a good way for us to explore a few aspects of simple electronics projects, including prototyping boards, circuit design programs, microcontrollers, and the curiously satisfying use of an Altoids tin for a project enclosure.
 
It was decided to use two RGB LEDS that would light together. The idea is that there is one button for each color - red, green, and blue - and that the buttons can be pressed in any combination to equally mix the colors. That part was simple enough, and the circuit diagram for that is shown in a later step as Figure 1.

The next requirement was to add sound. Specifically, each button is to play a distinct tone, and again, any combination of buttons should play a mix of the tones. This part presented more of a challenge. Using Charles Platt's excellent Make: Electronics book as a source, I experimented with a couple different circuits to provide the oscillating signal for the speaker - one based on a programmable unijuntion transistor, and another using a 555 timer. Since I only wanted to include one such circuit, I found a way in each case to activate the circuit from each of the buttons, but including a different resistor or capacitor in series with each button so each produced a different sound. This worked really well, but there was one shortcoming: with this arrangement, the oscillation circuit was drawing up to 20 mA even when not in use. This was not acceptable because it would result in the unit's batteries being depleted in less than a couple days. I could include an on/off switch, but that would be impractical, because I know that someone would forget to turn it off.

So my next thought was to use a microcontroller. I prototyped the circuit and program on an Arduino Uno R3, but then moved it to an ATtiny85. This worked well, but still drew more than 10 mA continuously. But with some additional programming, the ATtiny85 can run in sleep mode, drawing less than 2 micro amps, and be woken up to produce sound by a button press. Nevertheless, I still included a switch just because I couldn't help myself.

Step 1: Tools and Parts

Tools Needed

  • Breadboard for testing (optional but a good idea)
  • Soldering iron plus solder
  • Wire cutters
  • Drill with 1/4" and 1/2" bits
  • Rotary tool for smoothing edges of holes in the tin
  • Some sort of ISP to program the ATtiny85 (an Arduino board will work)


Parts

  • 1 8-pin DIP socket
  • 1 ATtiny85 microcontroller
  • 2 CR2032 circuit board mount battery holders
  • 2 5mm RGB LEDs (com. anode)
  • 1 Adafruit Perma-Proto Mint Tin Size Breadboard PCB
  • 3 330 Ω Resistors
  • 3 10k Ω Resistors
  • 3 Pushbuttons - I used these from Sparkfun
  • 1 circuit board mount mini slide switch (optional)
  • 1 Speaker - I used a speaker taken out of a musical greeting card, but a piezo buzzer would work as well
  • 1 Altoids-type mint tin
  • 22 gauge solid hookup wire, various colors

Step 2: Prototype

I think it is always a good idea to test out a circuit on a breadboard first, just make sure it works and all your components operate correctly. I have a drawing of the full circuit on a breadboard in Figure 2, along with an actual circuit diagram in Figure 3. Connect up a 6V power source to the +/- rails on the breadboard.

Step 3: Program the Microcontroller

Program the microcontroller. I'm not going to go into detail on how to program an ATtiny85, since that is done quite well in many other places, such as this one. But here is the code I used.

#include <avr/sleep.h>

const int buzzerPin = 3;
const int button1Pin = 1;
const int button2Pin = 2;
const int button3Pin = 4;
int myTone = 0;
unsigned long lastWake;

void setup()
{
  pinMode(buzzerPin, OUTPUT);
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  pinMode(button3Pin, INPUT);
  lastWake = millis();
  digitalWrite (2, HIGH); // enable pull-up
}

void wake ()
{
  // cancel sleep as a precaution
  sleep_disable();
  // must do this as the pin will probably stay low for a while
  detachInterrupt (0);
  lastWake = millis();
}  // end of wake


void loop()
{
  int button1State = digitalRead(button1Pin);
  int button2State = digitalRead(button2Pin);
  int button3State = digitalRead(button3Pin);
 
  if ( (button1State == LOW) && (button2State == LOW) && (button3State == LOW) ) {
    myTone = 100;
  }

  else if ( (button1State == LOW) && (button2State == LOW) ) {
    myTone = 150;
  }
 
  else if ( (button1State == LOW) && (button3State == LOW) ) {
    myTone = 200;
  }
 
  else if ( (button2State == LOW) && (button3State == LOW) ) {
    myTone = 300;
  }
 
  else if (button1State == LOW) {
    myTone = 400;
  }
  else if (button2State == LOW) {
    myTone = 800;
  }
  else if (button3State == LOW) {
    myTone = 2400;
  }
 
  if ( myTone > 0 ) {
    lastWake = millis();
    tone(buzzerPin, myTone, 80);
    delay(40);
  }
  else {
 
  // If there has been no activity for 10 seconds, go to sleep.
  if ( millis() - lastWake > 10000 ) {
    // disable ADC
    ADCSRA = 0;
    set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
    sleep_enable();
    // Do not interrupt before we go to sleep, or the
    // ISR will detach interrupts and we won't wake.
    noInterrupts ();
    // will be called when pin D2 goes low 
    attachInterrupt (0, wake, LOW);
    // turn off brown-out enable in software

    // as the processor executes the next instruction after
    // interrupts are turned on.
    interrupts ();  // one cycle
    sleep_cpu ();   // one cycle
  }
 
  }
  myTone = 0;
   
}


The code produces a steady tone depending on which button, or combination of buttons, is pressed. But it is certainly possible to modify the code however you want. For example, you could code it to do pulsing or alternating tones, or even songs. Note that in the parts list, I include a DIP socket for the ATtiny85, so even after the project is completed, you can pull the chip and re-program it to change the device behavior.

Step 4: Solder It Up

Make a photocopy of the Perma-Proto board before you solder anything onto it. You'll need this to make a template for drilling holes in the mint tin later.

Transfer the circuit to the Perma-Proto board.  Aside from the fact that this board is designed to fit perfectly into mint tin, it is a really nicely made two-sided board with circuit holes plated all the way though. This project takes advantage of this by using the back side to solder on the coin cell holders.

You can use nearly the exact same pin placement in going from breadboard to Perma-Proto board. Here are a few tips and things to pay attention to:
(a) Solder in the 8 pin DIP socket, but don't put in the ATtiny85 chip until you have soldered all the other components to avoid damaging it from the heat of the soldering iron.
(b) Put the speaker and coin cell holder on the back of the board. The positioning is shown in the photo, but you may need to adjust this depending not the exact type of button cell holders you get, and their pin spacing. Just make sure that each battery goes from the +/- rail to an "empty" row on the board that can then be connected to the switch. I connected one battery from row 6 on the + rail to row 12, and the other from row 4 on the - rail to row 11. Then I ran wires from rows 11 and 12 to the switch on the edge. Do this after you've soldered up everything else. The black and red wires that lead to the switch need to run partially underneath the batteries, so put on the wires first, then battery holders.
(c) Place some electrical tape on the back of the circuit board to prevent any short circuits from the speaker casing.
(d) In this step, you can opt to include a switch (pictured) or else omit it. If you omit it, just be sure to connect the two batteries together in series.

Step 5: Prepare the Mint Tin Project Box

Cut out the PCB photocopy and mark center holes for the LEDs and buttons for drilling. You can line these up easily based on the location of the circuit board holes. Use this template to mark holes on the top of the lid.

Be careful drilling - the tin is made of soft, thin metal and bends easily. I warped mine a bit by holding it just a bit too tightly in a drill press vise. To drill through the lid, I placed a block of scrap wood inside the tin, closed it, and drilled from the outside.
Drill a set of small holes in the bottom for the speaker sound in whatever pattern you like.

I also drilled four holes in the bottom corners so I could mount the circuit board to the tin, but I've found that the fit is so perfect (plus the assembly tends to stay in the tin because of the speaker magnet) that screwing it together is unnecessary, so this is optional.

Use a rotary tool with a grinder attachment to smooth any sharp metal edges on your holes, or enlarge holes if your placement was not quite right. This may result in some bare metal, so you may want to paint the box. Or like me, not.

And there it is. Enjoy the lights and noise!