Arduino Action Figure


Introduction

This project details how to make an interactive action figure stand using two Arduino Pro Mini's. The end product plays WAV sound files stored in an SD card and lights up LED's when a button on the side is pressed. Two Arduino's are synchronized to a button press event using I2C communication.

Parts

The below is a list of the basic parts that are necessary for this project.

  1. Arduino Pro Mini x2
  2. Plastic enclosure
  3. 8 ohm speaker
  4. 10k potentiometer
  5. LM386 amplifier
  6. Adafruit NeoPixel ring
  7. SD card breakout
  8. 250uF capacitor
  9. 0.05uF capacitor
  10. 10 ohm resistor
  11. 5V power supply

Playing WAV files

In terms of the circuitry this is the hard part of the project. The main reason is that a LM386 Audio amplifier must be used in order to play the sound at a clear audible level. With some testing, I found that the gain through the amplifier only needs to be about 20, which means that very few parts need to be used.

The schematic below is the one I used. As you can see the 3 pins are left floating and there are only 5 components necessary to achieve a gain of 20.

The next step is to play a WAV file from the SD Card. Fortunately I found a tutorial on this on Instructables which is linked here. The author of the tutorial has many more components than are necessary for this tutorial, however he/she goes through the necessary steps to format the WAV files to be played by the Arduino. The basic steps are shown below.

  1. Format the SD Card to FAT (other FAT formats are okay)
  2. Convert your WAV file to 16000Hz Mono at 8 bits per sample (using Wav Sample Rate Converter)
  3. Upload the files to the SD card

In the tutorial on Instructables, these were the settings used.

At this point we need to hook up an SD card to the Arduino. Depending on which Arduino you have, the pinouts might be slightly different. Below is an example of the SD breakout I used.

For your convenience I've listed the pinouts for a few different and popular Arduinos, I used 2 Arduino Pro Mini's because they are cheap, but other pinouts might be useful for testing if you don't have one on hand.

SPI Pin Arduino Uno Arduino Mega Arduino Pro Mini
MOSI 11 51 11
MISO 12 50 12
SCK 13 52 13
CS 4 53 10

The last thing to do is to upload the code to test whether the WAV files can be played. You must install the TMRpcm library for the Arduino, which can be found here. Now all that is left is to upload this code for the setup() portion of your Arduino code. Note that the Wire.h is included in the code, this will be discussed later when SPI is involved, however it should not affect the operation of the setup. 

Change the tmrpcm.play("START16.WAV") to the desired file name of a file that is in the root directory of the SD card. At this point when the code is uploaded, the music should start playing.

#include<SPI.h>
#include <SD.h>                      // need to include the SD library
#define SD_ChipSelectPin 10  //using digital pin 4 on arduino nano 328
#include <TMRpcm.h>           //  also need to include this library...
#include <Wire.h>

TMRpcm tmrpcm;   // create an object for use in this sketch
 
void setup(){
  Wire.begin(5);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  tmrpcm.speakerPin = 9; //11 on Mega, 9 Son Uno, Nano, etc
 
  if (!SD.begin(SD_ChipSelectPin)) {  // see if the card is present and can be initialized:
  return;   // don't do anything more if not
  }
  Serial.print("SD detected"); 
  tmrpcm.volume(3);
  tmrpcm.play("START16.wav");
  while (tmrpcm.isPlaying())
  {
  }
}

Lighting Effects

The lighting effects are made relatively easily thanks to Adafruit's libraries. The NeoPixel library can be found in the link here. Each of the NeoPIxel products has Power, Ground, Data In, and Data Out solder pads. At this point you should solder wires to the power, ground and data in pins.

Within the Neopixel library there are example sketches that you can upload to the Arduino. The only things that you really need to change are the "NUMPIXEL" definition and "PIN" definition at the beginning of the code. The PIN is simply the pin on the Arduino that the Data In wire is connected to, while the NUMPIXEL is the number of pixels on the ring.

Note that the data out port doesn't need a wire connected in this case, since this output is used to cascade multiple products. The key function that you will need to know how to use is the "setPixelColor" and "Color" function. An example code is shown below.

Suppose that "pixels" is a Adafruit_NeoPixel object.

void setup() {
  pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.
    pixels.show(); // This sends the updated pixel color to the hardware.
    delay(100); // Delay for a period of time (in milliseconds).

  }
}

The "pixel.Color(x,y,z)" function basically  changes the RGB values specified into a 32-bit unsigned integer which can be interpreted by the "setPixelColor" function.  The first argument in the setPixelColor function is simply the index of the LED. Note that you must use the "show" function to display all the lights on the NeoPixel product.

At this point, you can design your own patterns using delays and loops.

I2C Communication

The first question that one might have is why I2C and two Arduino's is even necessary. The problem lies with in the fact that the Arduino cannot inherently multi-task since it only has a single processor. This would mean that you would have to write code to split the CPU time between playing music and displaying the LED lights. Certainly this is possible (otherwise single core PC's would be next to useless for most people) however, it is a lot of extra work and is beyond the scope of this tutorial.

Thus, the approach in this case is to have one Master Arduino which displays the LED lights and one Slave Arduino which plays the music. The master would send a command to the slave to play the music so that both playing music and LED display can happen simultaneously.

Connecting devices to I2C is easy since all that's needed is to connect the SDA and SCL of both Arduino's together. For the Arduino Pro Mini that means we just connect A4 on the Master to A4 on the Slave, and A5 on the Master to A5 on the Slave.

Below is the code that you would need to add on the Master to send data to the Slave (which has address 1). 

=== MASTER CODE ===
#include <Wire.h>

void setup() {
  Wire.begin();
}

void loop()
{
  Wire.beginTransmission(1);    // address of the 
  Wire.write('P'); // Write 1 byte to signal slave to play music
  Wire.endTransmission();
  
  // Code to generate LED effects here
  
}

Below is the code that you would need to add on the Slave to receive data and then play the music. When data is received from the Master, the code in the "receiveEvent" function is run, at that point the data is read and then checked if it is a 'P'. At this point you can insert the code to play the music.

=== SLAVE CODE ===
#include <Wire.h>
 
void setup(){
  Wire.begin(1);
  Wire.onReceive(receiveEvent);
   Serial.begin(9600);
}
 
void loop(){  
}

void receiveEvent(int howMany)
{
  while(Wire.available())
  {
    char c = Wire.read();
    
    if(c == 'P')
    {
      Serial.println("Received P");
      // Code to play music here
    }
  }
}

At this point you should able to send commands from the Master to the Slave to play music. All that's needed to be done is to edit tweak the sound code and the LED light code to get the effects that you desire!