Well the millis function was a bit daunting for me, so I found a way to use the delay function to work for me. I now have a working hacked Big Mouth Billy Bass and I am so excited! There was a statement from the playcomplete function that said "while(wave.isplaying){}" which meant don't do anything while the wave file is playing. That was why I couldn't get the motors and the file to work at the same time. I commented out that line and voila! I also used the "TrueRandom" library which I found online. It requires pin 0 to be free, so I moved my LAT pin on the wave shield to pin 5 and adjusted the library as necessary. It works really well and I never get the same sequence twice.
So all that is left is to finish coding the movements (I will ultimately have around 240 sounds...let's see if the Uno's memory holds up! If not, I will go until it can't hold any more!
Thank you SO MUCH for all of your help! I am posting the code that is working for me in case anyone else wants to try and do their own hacked Big Mouth Billy Bass.
Code: Select all
/*
*This sketch plays a random sound file at the push of a button and syncs up the motors with the sounds.
*/
//include the appropriate libraries
#include "WaveHC.h"
#include "WaveUtil.h"
#include <AFMotor.h>
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include <TrueRandom.h>
//not sure if I need these, but they are in the example sketch...
SdReader card; // This object holds the information for the card
FatVolume vol; // This holds the information for the partition on the card
FatReader root; // This holds the information for the volumes root directory
FatReader f; // This holds the information for the file we're going to play
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
uint8_t dirLevel; // indent level for file/dir names (for prettyprinting)
dir_t dirBuf; // buffer for directory reads
#define DEBOUNCE 100 //button debouncer
//define motors and names
AF_DCMotor mouth(2, MOTOR12_64KHZ);
AF_DCMotor body(3, MOTOR34_64KHZ);
AF_DCMotor tail(4, MOTOR34_64KHZ);
//don't know if I need this...
void play(FatReader &dir);
//setup
void setup()
{
Serial.begin(9600);
mouth.setSpeed(255);
body.setSpeed(255);
tail.setSpeed(255);
BANNED(RELEASE);
body.run(RELEASE);
tail.run(RELEASE);
// Set the output pins for the DAC control. This pins are defined in the library
pinMode(17, OUTPUT);
pinMode(16, OUTPUT);
pinMode(15, OUTPUT);
pinMode(19, OUTPUT);
//enable pull-up resistors on switch pins (analog)
digitalWrite(18, HIGH);
// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
if (!card.init())
{ //play with 8 MHz spi (default faster!)
putstring_nl("Card init. failed!"); // Something went wrong, lets print out why
while(1); // then 'halt' - do nothing!
}
// Now we will look for a FAT partition!
uint8_t part;
for (part = 0; part < 5; part++){ // we have up to 5 slots to look in
if (vol.init(card, part))
break; // we found one, lets bail
}
if (part == 5) { // if we ended up not finding one :(
putstring_nl("No valid FAT partition!");
while(1); // then 'halt' - do nothing!
}
// Try to open the root directory
if (!root.openRoot(vol)) {
putstring_nl("Can't open root dir!"); // Something went wrong,
while(1); // then 'halt' - do nothing!
}
}
//loop
void loop()
{
switch (check_switches()) //see if the button is pressed
{
case 5: //if it is pressed
playSound(); //play a random sound and move motors
break;
}
}
//check switch function coding
byte check_switches()
{
static byte previous[6];
static long time[6];
byte reading;
byte pressed;
byte index;
pressed = 0;
for (byte index = 0; index < 6; ++index) {
reading = digitalRead(14 + index);
if (reading == LOW && previous[index] == HIGH && millis() - time[index] > DEBOUNCE)
{
// switch pressed
time[index] = millis();
pressed = index + 1;
break;
}
previous[index] = reading;
}
// return switch number (1 - 6)
return (pressed);
}
//code for playSound function
void playSound()
{
int Sound = TrueRandom.random(0,41);
//pick a random sound and move the motors to match
switch (Sound)
{
case 1:
body.run(FORWARD); //move the body of the BMBB
playcomplete("1.WAV"); //play the sound
delay(700); //wait for the sound to start
speak(100,100,100,100,100,100,300,200,0,0); //call the speak function which controls the mouth movements...change these values to change the mouth movement
delay(1000); //this keeps the body pointed outward
body.run(RELEASE); //body to resting position
break;
case 2:
body.run(FORWARD);
playcomplete("2.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 3:
body.run(FORWARD);
playcomplete("3.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 4:
body.run(FORWARD);
playcomplete("4.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 5:
body.run(FORWARD);
playcomplete("5.WAV");
delay (200);
speak(300,200,100,0,0,0,0,0,0,0);
tailwag(200,200,200,200,200,200,200,200);
delay(800);
body.run(RELEASE);
break;
case 6:
body.run(FORWARD);
playcomplete("6.WAV");
delay(600);
speak(100,100,100,100,100,100,300,200,0,0);
//overall delay for body
delay(800);
body.run(RELEASE);
break;
case 7:
body.run(FORWARD);
playcomplete("7.WAV");
delay(600);
speak(100,0,100,100,300,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 8:
body.run(FORWARD);
playcomplete("8.WAV");
delay(700);
speak(200,100,100,100,300,200,0,0,0,0);
//overall delay for body
delay(800);
body.run(RELEASE);
break;
case 9:
body.run(FORWARD);
playcomplete("9.WAV");
delay(600);
speak2(100,100,100,100,100,100,100,100,100,100,400,100,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 10:
body.run(FORWARD);
playcomplete("10.WAV");
delay(800);
speak(50,100,100,100,100,100,100,100,200,200);
delay(800);
body.run(RELEASE);
break;
case 11:
body.run(FORWARD);
playcomplete("11.WAV");
delay(700);
speak(100,100,100,100,100,100,200,200,100,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 12:
body.run(FORWARD);
playcomplete("12.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 13:
body.run(FORWARD);
playcomplete("13.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 14:
body.run(FORWARD);
playcomplete("14.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 15:
body.run(FORWARD);
playcomplete("15.WAV");
delay (800);
speak(50,100,1000,100,0,0,0,0,0,0);
body.run(RELEASE);
break;
case 16:
body.run(FORWARD);
playcomplete("16.WAV");
delay(700);
speak(100,100,100,100,100,100,300,200,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 17:
body.run(FORWARD);
playcomplete("17.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 18:
body.run(FORWARD);
playcomplete("18.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 19:
body.run(FORWARD);
playcomplete("19.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 20:
body.run(FORWARD);
playcomplete("20.WAV");
delay (800);
speak(50,100,1000,100,0,0,0,0,0,0);
body.run(RELEASE);
break;
case 21:
body.run(FORWARD);
playcomplete("21.WAV");
delay(700);
speak(100,100,100,100,100,100,300,200,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 22:
body.run(FORWARD);
playcomplete("22.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 23:
body.run(FORWARD);
playcomplete("23.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 24:
body.run(FORWARD);
playcomplete("24.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 25:
body.run(FORWARD);
playcomplete("25.WAV");
delay (800);
speak(50,100,1000,100,0,0,0,0,0,0);
body.run(RELEASE);
break;
case 26:
body.run(FORWARD);
playcomplete("26.WAV");
delay(700);
speak(100,100,100,100,100,100,300,200,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 27:
body.run(FORWARD);
playcomplete("27.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 28:
body.run(FORWARD);
playcomplete("28.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 29:
body.run(FORWARD);
playcomplete("29.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 30:
body.run(FORWARD);
playcomplete("30.WAV");
delay (800);
speak(50,100,1000,100,0,0,0,0,0,0);
body.run(RELEASE);
break;
case 31:
body.run(FORWARD);
playcomplete("31.WAV");
delay(700);
speak(100,100,100,100,100,100,300,200,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 32:
body.run(FORWARD);
playcomplete("32.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 33:
body.run(FORWARD);
playcomplete("33.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 34:
body.run(FORWARD);
playcomplete("14.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 35:
body.run(FORWARD);
playcomplete("35.WAV");
delay (800);
speak(50,100,1000,100,0,0,0,0,0,0);
body.run(RELEASE);
break;
case 36:
body.run(FORWARD);
playcomplete("36.WAV");
delay(700);
speak(100,100,100,100,100,100,300,200,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 37:
body.run(FORWARD);
playcomplete("37.WAV");
delay(700);
speak(600,0,0,0,0,0,0,0,0,0);
tail.run(FORWARD);
//overall delay for body
delay(800);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 38:
body.run(FORWARD);
playcomplete("38.WAV");
delay(600);
speak(200,100,100,100,200,0,0,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
break;
case 39:
body.run(FORWARD);
playcomplete("19.WAV");
delay(700);
speak(100,100,100,100,100,100,300,0,0,0);
//overall delay for body
delay(1000);
body.run(RELEASE);
tail.run(RELEASE);
break;
case 40:
body.run(FORWARD);
playcomplete("40.WAV");
delay (800);
speak(50,100,1000,100,0,0,0,0,0,0);
body.run(RELEASE);
break;
}
}
//code for the speak function...note that there must be 10 values to call the function
void speak(int longDelay, int shortDelay, int longDelay2, int shortDelay2, int longDelay3, int shortDelay3, int longDelay4, int shortDelay4, int longDelay5, int shortDelay5)
{
BANNED(FORWARD);
delay(longDelay);
BANNED(RELEASE);
delay(shortDelay);
BANNED(FORWARD);
delay(longDelay2);
BANNED(RELEASE);
delay(shortDelay2);
BANNED(FORWARD);
delay(longDelay3);
BANNED(RELEASE);
delay(shortDelay3);
BANNED(FORWARD);
delay(longDelay4);
BANNED(RELEASE);
delay(shortDelay4);
BANNED(FORWARD);
delay(longDelay5);
BANNED(RELEASE);
delay(shortDelay5);
}
//in case I have a longer sentence to play...note that there must be 14 values
void speak2(int longDelay, int shortDelay, int longDelay2, int shortDelay2, int longDelay3, int shortDelay3, int longDelay4, int shortDelay4, int longDelay5, int shortDelay5, int longDelay6, int shortDelay6, int longDelay7, int shortDelay7)
{
BANNED(FORWARD);
delay(longDelay);
BANNED(RELEASE);
delay(shortDelay);
BANNED(FORWARD);
delay(longDelay2);
BANNED(RELEASE);
delay(shortDelay2);
BANNED(FORWARD);
delay(longDelay3);
BANNED(RELEASE);
delay(shortDelay3);
BANNED(FORWARD);
delay(longDelay4);
BANNED(RELEASE);
delay(shortDelay4);
BANNED(FORWARD);
delay(longDelay5);
BANNED(RELEASE);
delay(shortDelay5);
BANNED(FORWARD);
delay(longDelay6);
BANNED(RELEASE);
delay(shortDelay6);
BANNED(FORWARD);
delay(longDelay7);
BANNED(RELEASE);
delay(shortDelay7);
}
//a function for wagging the tail...note that there must be 8 values
void tailwag(int longDelay, int shortDelay, int longDelay2, int shortDelay2, int longDelay3, int shortDelay3, int longDelay4, int shortDelay4)
{
tail.run(FORWARD);
delay(longDelay);
tail.run(RELEASE);
delay(shortDelay);
tail.run(FORWARD);
delay(longDelay2);
tail.run(RELEASE);
delay(shortDelay2);
tail.run(FORWARD);
delay(longDelay3);
tail.run(RELEASE);
delay(shortDelay3);
tail.run(FORWARD);
delay(longDelay4);
tail.run(RELEASE);
delay(shortDelay4);
}
// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
// call our helper to find and play this name
playfile(name);
//I commented the following lines out to allow for the wave file to be played while the motor is running
//while (wave.isplaying) {
// do nothing while its playing
//}
// now its done playing
}
void playfile(char *name) {
// see if the wave object is currently doing something
if (wave.isplaying) {// already playing something, so stop it!
wave.stop(); // stop it
}
// look in the root directory and open the file
if (!f.open(root, name)) {
putstring("Couldn't open file "); Serial.print(name); return;
}
// OK read the file and turn it into a wave object
if (!wave.create(f)) {
putstring_nl("Not a valid WAV"); return;
}
// ok time to play! start playback
wave.play();
}