Sunny the RFID lion

http://i155.photobucket.com/albums/s291/ollopat/sunny.jpg
http://i155.photobucket.com/albums/s291/ollopat/DSC04002.jpg
http://i155.photobucket.com/albums/s291/ollopat/DSC04006.jpg

This is a copy of the RFID bear on make. I have however added a few new features in the code like a ram check and a random file player. The random file player adds another dimension to the character. If you would like to make you own it is very easy.

Parts list:
A stuffed animal
Ardunio Uno
6-8 cell AA battery holder
serial parallax RFID reader
Adafruit Wave Shield
8 ohm speaker
RFID tags
1 gig SD memory card

A guide to making one yourself makeprojects.com/Project/Charlie … ear/1411/1
A updated library for the wav shield ladyada.net/make/waveshield/download.html

The code below works with random files named with like “1.wav” “2.wav”… the wav is already part of the file name so when viewing in windows it will be “1” “2”… all the way to 200. Though this value it easily changed in the code. For the back of Sunny I took him to a local seamstress that sewed on Velcro strips that allowed me to throw in all of the electronics. As for power I’m using rechargeable AA’s to run him at the moment which seem to be doing well. If you have any questions please ask below. The code includes the required lines for the RFID and they are tested well the reader I had died on me so I will try and load a new video up with him scanning some tags.

[code]// Sunny mark 4 code

#include <FatReader.h>
#include <SdReader.h>
#include “WaveHC.h”
#include “WaveUtil.h”

SdReader memcard;
FatVolume vol;
FatReader root;
FatReader file;
WaveHC wave;

#define ENABLE 7 // Set the pin number for enabling the RFID reader. The Audio Shield uses pins 2-5.
#define NUMTAGS 22

int val = 0;
char code[10];
int bytesread = 0;
long randNumber;
long randNumber1;
void randWavFile ();
char randWav[5] = {".WAV"};
char randWav1[20];

char knowntags[NUMTAGS][11] = {“3501D5C881”, “35021C5A56”, “35021C7DC1”, “840033972F”, “35021C710E”, “8400339993”, “06008EA09C”, “030096D389”, “030096D371”, “35021C99A2”, “84003399C3”, “35021C8DF6”, “35021C92BA”, “8400339726”, “35021C89FE”, “35021C83D2”, “35021C779F”, “35021C935F”, “8400339764”};
char soundfiles[NUMTAGS][9] = {“3501D5C8”, “35021C5A”, “35021C7D”, “84003397”, “35021C71”, “84003399”, “06008EA0”, “030096D3”, “35021C99”, “35021C8D”, “35021C92”, “35021C89”, “35021C83”, “35021C77”, “35021C93”};
char filename[1][13];

void setup() {
//////// Set up RFID reader to collect tag information /////////////////////
Serial.begin(2400); // RFID reader SOUT pin connected to Serial RX pin at 2400bps
pinMode(ENABLE,OUTPUT); // Set digital pin 7 as OUTPUT to connect it to the RFID /ENABLE pin
digitalWrite(ENABLE, LOW); // Activate the RFID reader

//////// Set the pins to output for driving the Audio Shield
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);

////////// Set up the Audio Shield by initializing the memory card for reading ////////
if (!memcard.init()) {
// If something went wrong sdErrorCheck prints out the error check
putstring_nl(“Card init. failed!”);
cardErrorCheck();
return;
}

//This will optimize the reading of the memory card – remove it if it times out
memcard.partialBlockRead(true);

// Find a FAT formatted partition by looking in teh first five slots. Remember your memory card should be FAT16 or FAT32 formatted
uint8_t partition;
for (partition = 0; partition < 5; partition++) {
if (vol.init(memcard, partition))
break;
}
if (partition == 5)
{
putstring_nl(“No valid FAT partition”);
cardErrorCheck();
while(1); // This is a point of no return. Format your memory card properly and try again.
}

// Open the root directory for reading the files
if (!root.openRoot(vol))
{
putstring_nl(“Can’t open root directory”);
while(1); // Something went wrong here so investigate the file system on your memory card.
}

// If you got this far then the card is ready to read
putstring_nl(“Ready to go”);
playcomplete(“1000.WAV”);
randomSeed(analogRead(0));
}

// If we find an error, check what the error is and show it on the serial terminal
void cardErrorCheck(void)
{
if(!memcard.errorCode()) return;
putstring("\n\rSD I/O error:");
Serial.print(memcard.errorCode());
putstring(", ");
Serial.print(memcard.errorData());
while(1); // Stick here if there is an error
}

void loop() {
// putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad
// Serial.println(freeRam()); // if this is under 150 bytes it may spell trouble!
//Serial.println(randNumber);
//Serial.flush();

randNumber1 = random(500);
randNumber = random(1, 200);
sprintf(randWav1, “%1d.wav”, randNumber);
//Serial.println(randWav1);
delay (50);
//Serial.println(randNumber);
if (randNumber1 == 1)
{
playcomplete(randWav1);
}

if(Serial.available() > 0) { // if data available from reader
if((val = Serial.read()) == 10) { // check for header
bytesread = 0;
while(bytesread<10) { // read 10 digit code
if( Serial.available() > 0) {
val = Serial.read();
if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
break; // stop reading
}
code[bytesread] = val; // add the digit
bytesread++; // ready to read next digit
}
}
if(bytesread == 10) { // if 10 digit read is complete
playsound(code);
Serial.print("TAG code is: "); // possibly a good TAG
Serial.println(code); // print the TAG code
Serial.flush(); // Flush the serial buffer before trying to read a new code
}
bytesread = 0;

}

}

}

void playsound(char codetoplay]) {
for(int i = 0; i<8; i++) { // Make a filename from the first 8 characters of the RFID tag number
filename[0]=codetoplay;
}
filename[0][8]=’.’;
filename[0][9]=‘w’;
filename[0][10]=‘a’;
filename[0][11]=‘v’;
silence(); //shut down anything that is currently playing and close that file
playfile(filename[0]);

}

void playfile(char *name) {
if (!file.open(root, name)) {
putstring_nl(“Couldn’t open file”);
return;
}
if (!wave.create(file)) {
putstring_nl(“Not a valid WAV”);
return;
}
wave.play();
}

void silence() {
if(wave.isplaying) {
wave.stop();
}
}

void playcomplete(char *name) {
playfile(name);
while (wave.isplaying){
}
}

int freeRam(void)
{
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
} [/code]

Below is a link to a small video of sunny in action.
i155.photobucket.com/albums/s291/ollopat/th_MOV04008.jpg**

New update!!

First I wanted to make sunny a little more random then he is with just the randomseed taking off the floating analog so I found a library called “TrueRandom” by Peter Knight. Its far more random then the random on the Arduino though prob not “true” randomness. This helps sunny be a lot less predictable in what .wav files he plays and when.

http://i155.photobucket.com/albums/s291/ollopat/debugingcode.jpg

Second? well for the other thing that I wanted to change was the battery pack it was a 4 cell and 2 cell AA packs tied together and was crap. So I upgraded sunny to a 8 cell pack that accepts good old rechargeable batteries. Sunny overall may way a bit more but I think the increased simplicity and run time are worth it.

http://i155.photobucket.com/albums/s291/ollopat/Batterypack.jpg

As for the last new thing I had a old Spark Fun breakout board for a Mems microphone which allowed me to make sunny respond to different noise levels 5 atm. So if you clap your hands to loud next to his ears he will say “ouch Sunny’s ears hurt now”. I made a video of him responding to noise I created below. As well as the updated code.

i155.photobucket.com/albums/s291/ollopat/th_MOV04017.jpg

[code]// An interactive bear for Charlie – RFID triggered sound responses

#include <FatReader.h>
#include <SdReader.h>
#include <TrueRandom.h>
#include “WaveHC.h”
#include “WaveUtil.h”

SdReader memcard;
FatVolume vol;
FatReader root;
FatReader file;
WaveHC wave;

#define ENABLE 7 // Set the pin number for enabling the RFID reader. The Audio Shield uses pins 2-5.
#define NUMTAGS 22

const int analogPin = 1;
int val = 0;
int val1 = 0;
char code[10];
int bytesread = 0;
long randNumber;
long randNumber1;
void randWavFile ();
char randWav[5] = {".WAV"};
char randWav1[20];

char knowntags[NUMTAGS][11] = {“3501D5C881”, “35021C5A56”, “35021C7DC1”, “840033972F”, “35021C710E”, “8400339993”, “06008EA09C”, “030096D389”, “030096D371”, “35021C99A2”, “84003399C3”, “35021C8DF6”, “35021C92BA”, “8400339726”, “35021C89FE”, “35021C83D2”, “35021C779F”, “35021C935F”, “8400339764”};
char soundfiles[NUMTAGS][9] = {“3501D5C8”, “35021C5A”, “35021C7D”, “84003397”, “35021C71”, “84003399”, “06008EA0”, “030096D3”, “35021C99”, “35021C8D”, “35021C92”, “35021C89”, “35021C83”, “35021C77”, “35021C93”};
char filename[1][13];

void setup() {
//////// Set up RFID reader to collect tag information /////////////////////
Serial.begin(2400); // RFID reader SOUT pin connected to Serial RX pin at 2400bps
pinMode(ENABLE,OUTPUT); // Set digital pin 7 as OUTPUT to connect it to the RFID /ENABLE pin
digitalWrite(ENABLE, LOW); // Activate the RFID reader

//////// Set the pins to output for driving the Audio Shield
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);

////////// Set up the Audio Shield by initializing the memory card for reading ////////
if (!memcard.init()) {
// If something went wrong sdErrorCheck prints out the error check
putstring_nl(“Card init. failed!”);
cardErrorCheck();
return;
}

//This will optimize the reading of the memory card – remove it if it times out
memcard.partialBlockRead(true);

// Find a FAT formatted partition by looking in teh first five slots. Remember your memory card should be FAT16 or FAT32 formatted
uint8_t partition;
for (partition = 0; partition < 5; partition++) {
if (vol.init(memcard, partition))
break;
}
if (partition == 5)
{
putstring_nl(“No valid FAT partition”);
cardErrorCheck();
while(1); // This is a point of no return. Format your memory card properly and try again.
}

// Open the root directory for reading the files
if (!root.openRoot(vol))
{
putstring_nl(“Can’t open root directory”);
while(1); // Something went wrong here so investigate the file system on your memory card.
}

// If you got this far then the card is ready to read
putstring_nl(“Ready to go”);
playcomplete(“1000.WAV”);
randomSeed(TrueRandom.random());
}

// If we find an error, check what the error is and show it on the serial terminal
void cardErrorCheck(void)
{
if(!memcard.errorCode()) return;
putstring("\n\rSD I/O error:");
Serial.print(memcard.errorCode());
putstring(", ");
Serial.print(memcard.errorData());
while(1); // Stick here if there is an error
}

void loop() {
//putstring("Free RAM: "); // This can help with debugging, running out of RAM is bad
//Serial.println(freeRam()); // if this is under 150 bytes it may spell trouble!
//Serial.println(randNumber);
//Serial.flush();
int mn = 1024; // mn only decreases
int mx = 0; // mx only increases

// Perform 10000 reads. Update mn and mx for each one.
for (int i = 0; i < 3000; ++i) {
int val1 = analogRead(analogPin);
mn = min(mn, val1);
mx = max(mx, val1);
}
//Serial.print(“m=”);
// Serial.print(mn);
// Serial.print(" M=");
// Serial.print(mx);
//Serial.print(" D=");
// Serial.print(mx-mn);
// Serial.println();

if (mx > 678)
{
playcomplete (“NOISE1.WAV”);
}
if ((mx >= 637) && (mx <=677))
{
playcomplete (“NOISE2.WAV”);
}
if ((mx >= 596) && (mx <= 636))
{
playcomplete (“NOISE3.WAV”);
}
if ((mx >= 555) && (mx <= 595))
{
playcomplete (“NOISE4.WAV”);
}
if ((mx >= 527) && (mx <= 554))
{
playcomplete (“NOISE5.WAV”);
}
randNumber1 = random(80);
randNumber = random(1, 150);
sprintf(randWav1, “%1d.wav”, randNumber);
//Serial.println(randWav1);
delay (50);
//Serial.println(randNumber1);
if (randNumber1 == 1)
{
playcomplete(randWav1);
}

if(Serial.available() > 0) { // if data available from reader
if((val = Serial.read()) == 10) { // check for header
bytesread = 0;
while(bytesread<10) { // read 10 digit code
if( Serial.available() > 0) {
val = Serial.read();
if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
break; // stop reading
}
code[bytesread] = val; // add the digit
bytesread++; // ready to read next digit
}
}
if(bytesread == 10) { // if 10 digit read is complete
playsound(code);
Serial.print("TAG code is: "); // possibly a good TAG
Serial.println(code); // print the TAG code
Serial.flush(); // Flush the serial buffer before trying to read a new code
}
bytesread = 0;

}

}

}
void playsound(char codetoplay]) {
for(int i = 0; i<8; i++) { // Make a filename from the first 8 characters of the RFID tag number
filename[0]=codetoplay;
}
filename[0][8]=’.’;
filename[0][9]=‘w’;
filename[0][10]=‘a’;
filename[0][11]=‘v’;
silence(); //shut down anything that is currently playing and close that file
playfile(filename[0]);

}

void playfile(char *name) {
if (!file.open(root, name)) {
putstring_nl(“Couldn’t open file”);
return;
}
if (!wave.create(file)) {
putstring_nl(“Not a valid WAV”);
return;
}
wave.play();
}

void silence() {
if(wave.isplaying) {
wave.stop();
}
}

void playcomplete(char *name) {
playfile(name);
while (wave.isplaying){
}
}

int freeRam(void)
{
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
} [/code]

Enjoy!**

Slight problem with the code, I got the new RFID reader back and it works great but with the current code the reader does not play a file all the way though it can be interrupted by other RFIDs, I knew this in the beginning and did not see it as a problem but after adding the sound sensor to him that changed. What happened in the code is that after a tag was read it would start playing a file though sunny would hear him self talking and it cut the RFID tag wav short. Here is where in the code you can fix this. Notice I change the last line to playcomplete which will throw sunny in a loop so he wont overhear his self and try and interrupt the current file.

[code]}
void playsound(char codetoplay]) {
for(int i = 0; i<8; i++) { // Make a filename from the first 8 characters of the RFID tag number
filename[0]=codetoplay;
}
filename[0][8]=’.’;
filename[0][9]=‘w’;
filename[0][10]=‘a’;
filename[0][11]=‘v’;
silence(); //shut down anything that is currently playing and close that file
playcomplete(filename[0]);

}[/code]

Below is a picture of everything in sunny except the batteries, speaker and mic breakout.

http://i155.photobucket.com/albums/s291/ollopat/RFID.jpg*

Final video of sunny reading some RFID tags.

i155.photobucket.com/albums/s291/ollopat/th_MOV04020.jpg

DoCDoC*