- Arduino Uno
PCA9685 with 8 servos
Ada Fruit Wave Shield
L298 H-bridge IC
BitVoicer voice recognition library
and a few other supporting hand built circuits...
Regarding the PMDC pins, you can see what I used in the code (assembled in part from test code that I found.) The pins should be open, but they seem to interfere with the servos. Do I need to connect the PMDC's to the PCA?
Code: Select all
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include <BitVoicer11.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 600 // this is the 'maximum' pulse length count (out of 4096)
int led = 6;
BitVoicerSerial bvSerial = BitVoicerSerial(); //Stores true if the Audio Streaming Calibration tool is running
boolean sampleTest = false; //Stores the data type retrieved by getData()
byte dataType = 0; //Sets up the pins and default variables
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 filesystem on the card
FatReader f; // This holds the information for the file we're play
WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time
/*
int mot1ana = ;
int mot1a = 6;
int mot1b=8;
int motrana=;
int motra=; // just changed from pin 11 (used by wave shield)
int motrb=;
*/
int degrees;
int ServoPulse(int degrees)
{
return map(degrees, 0, 180, SERVOMIN, SERVOMAX);
}
uint8_t HEAD = 0;
uint8_t NECK = 1;
uint8_t LST = 2;
uint8_t LSB = 3;
uint8_t RST = 4;
uint8_t RSB = 5;
uint8_t LELB = 6;
uint8_t RELB = 7;
uint8_t LHAND = 8;
uint8_t RHAND = 9;
uint8_t dirLevel; // indent level for file/dir names (for prettyprinting)
dir_t dirBuf; // buffer for directory reads
#define error(msg) error_P(PSTR(msg))
#define DEBOUNCE 5 // button debouncer
// here is where we define the buttons that we'll use. button "1" is the first, button "6" is the 6th, etc
byte buttons[] = {14, 15, 16, 17, 18, 19};
// This handy macro lets us determine how big the array up above is, by checking the size
#define NUMBUTTONS sizeof(buttons)
// we will track if a button is just pressed, just released, or 'pressed' (the current state
volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];
void play(FatReader &dir);
// this handy function will return the number of bytes currently free in RAM, great for debugging!
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;
}
void sdErrorCheck(void)
{
if (!card.errorCode()) return;
putstring("\n\rSD I/O error: ");
Serial.print(card.errorCode(), HEX);
putstring(", ");
Serial.println(card.errorData(), HEX);
while(1);
}
void setup() {
/*
pinMode(mot1ana,OUTPUT);
pinMode(mot1a,OUTPUT);
pinMode(mot1b,OUTPUT);
pinMode (motrana,OUTPUT);
pinMode (motra,OUTPUT);
pinMode (motrb,OUTPUT);
*/
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
pinMode(led, OUTPUT);
bvSerial.setAudioInput(1);
Serial.begin(115200); //Sets up the pinModes
byte i;
putstring_nl("WaveHC with ");
Serial.print(NUMBUTTONS, DEC);
putstring_nl("buttons");
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!
for (i=0; i< NUMBUTTONS; i++) {
pinMode(buttons[i], INPUT);
digitalWrite(buttons[i], HIGH);
}
if (!card.init()) { //play with 8 MHz spi (default faster!)
putstring_nl("Card init. failed!"); // Something went wrong, lets print out why
sdErrorCheck();
while(1); // then 'halt' - do nothing!
}
card.partialBlockRead(true);
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!");
sdErrorCheck(); // Something went wrong, lets print out why
while(1); // then 'halt' - do nothing!
}
putstring("Using partition ");
Serial.print(part, DEC);
putstring(", type is FAT");
Serial.println(vol.fatType(),DEC); // FAT16 or FAT32?
// 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!
}
// Whew! We got past the tough parts.
putstring_nl("Ready!");
TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 |= 1<<TOIE2;
}
SIGNAL(TIMER2_OVF_vect) {
check_switches();
}
void check_switches()
{
static byte previousstate[NUMBUTTONS];
static byte currentstate[NUMBUTTONS];
byte index;
for (index = 0; index < NUMBUTTONS; index++) {
currentstate[index] = digitalRead(buttons[index]); // read the button
if (currentstate[index] == previousstate[index]) {
if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
// just pressed
justpressed[index] = 1;
}
else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
// just released
justreleased[index] = 1;
}
pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed
}
//Serial.println(pressed[index], DEC);
previousstate[index] = currentstate[index]; // keep a running tally of the buttons
}
}
void loop() {
if (sampleTest == true)
{
bvSerial.BANNED(46);
}
if (bvSerial.engineRunning)
{
bvSerial.BANNED(46);
}
}
void serialEvent()
{
dataType = bvSerial.getData();
if (dataType == BV_COMMAND)
sampleTest = bvSerial.cmdData;
if (dataType == BV_STATUS && bvSerial.engineRunning == true)
bvSerial.startStopListening();
if (dataType == BV_STR)
if (bvSerial.strData == "hello"){
playcomplete("hello.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(70));
pwm.setPWM(RSB, 0, ServoPulse(90));
delay(100);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(90));
delay(100);
pwm.setPWM(NECK, 0, ServoPulse(120));
pwm.setPWM(LSB, 0, ServoPulse(180)); // Keep between 90 and 180, so it doesn't hit itself
delay(200);
pwm.setPWM(LHAND, 0, ServoPulse(90));
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(100));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(130));
pwm.setPWM(NECK, 0, ServoPulse(90));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(100));
pwm.setPWM(NECK, 0, ServoPulse(120));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(100));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(RELB, 0, ServoPulse(90));
pwm.setPWM(NECK, 0, ServoPulse(90));
pwm.setPWM(RELB, 0, ServoPulse(0));
pwm.setPWM(LST, 0, ServoPulse(180));
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LHAND, 0, ServoPulse(60));
pwm.setPWM(NECK, 0, ServoPulse(120));
delay(500);
pwm.setPWM(LHAND, 0, ServoPulse(180));
pwm.setPWM(RELB, 0, ServoPulse(50));}
if (bvSerial.strData == "forward"){
/*
//analogWrite(motlana,500); //Forward left
digitalWrite(mot1a,HIGH);
digitalWrite(mot1b,LOW);
delay(200);
digitalWrite(mot1a,LOW);
digitalWrite(mot1b,LOW);
delay(200);
analogWrite(mot1ana,500);
digitalWrite(mot1a,LOW);
digitalWrite(mot1b,HIGH);
delay(200);
digitalWrite(mot1a,LOW);
digitalWrite(mot1b,LOW);
delay(200);
analogWrite(motrana,500); //Forward right
digitalWrite(motra,HIGH);
digitalWrite(motrb,LOW);
delay(200);
digitalWrite(motra,LOW);
digitalWrite(motrb,LOW);
delay(200);
analogWrite(motrana,500);
digitalWrite(motra,LOW);
digitalWrite(motrb,HIGH);
delay(200);
digitalWrite(motra,LOW);
digitalWrite(motrb,LOW);
delay(200);
*/
}
// if (bvSerial.strData == "hi")
// playcomplete("hello.wav");
if (bvSerial.strData == "name"){
playcomplete("name.wav");
pwm.setPWM(HEAD, 0, ServoPulse(90));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(70));
pwm.setPWM(RSB, 0, ServoPulse(90));
delay(100);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(90));
delay(100);
pwm.setPWM(NECK, 0, ServoPulse(120));
pwm.setPWM(LSB, 0, ServoPulse(180)); // Keep between 90 and 180, so it doesn't hit itself
delay(200);
pwm.setPWM(LELB, 0, ServoPulse(100));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(RELB, 0, ServoPulse(90));
pwm.setPWM(NECK, 0, ServoPulse(90));
pwm.setPWM(RELB, 0, ServoPulse(0));
pwm.setPWM(LST, 0, ServoPulse(180));
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LHAND, 0, ServoPulse(60));
pwm.setPWM(NECK, 0, ServoPulse(120));
delay(500);
pwm.setPWM(LHAND, 0, ServoPulse(180));
pwm.setPWM(RELB, 0, ServoPulse(50));
pwm.setPWM(NECK, 0, ServoPulse(90));
pwm.setPWM(RELB, 0, ServoPulse(0));
pwm.setPWM(LST, 0, ServoPulse(180));
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LHAND, 0, ServoPulse(60));
pwm.setPWM(NECK, 0, ServoPulse(120));
delay(500);
pwm.setPWM(LHAND, 0, ServoPulse(180));
pwm.setPWM(RELB, 0, ServoPulse(50));
}
if (bvSerial.strData == "bye"){
playcomplete("bye.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(70));
pwm.setPWM(RSB, 0, ServoPulse(90));
delay(100);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(90));
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(100));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(RELB, 0, ServoPulse(90));
pwm.setPWM(NECK, 0, ServoPulse(90));
pwm.setPWM(RELB, 0, ServoPulse(0));
pwm.setPWM(LST, 0, ServoPulse(180));
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LHAND, 0, ServoPulse(60));
pwm.setPWM(NECK, 0, ServoPulse(120));
delay(500);
pwm.setPWM(LHAND, 0, ServoPulse(180));
pwm.setPWM(RELB, 0, ServoPulse(50));
}
if (bvSerial.strData == "sorry"){
playcomplete("sorry.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
delay(200);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(50));
delay(300);
pwm.setPWM(NECK, 0, ServoPulse(80));
pwm.setPWM(RST, 0, ServoPulse(20));
delay(500);
pwm.setPWM(RST, 0, ServoPulse(00));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(60)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(100));
delay(500);
pwm.setPWM(LST, 0, ServoPulse(70));
delay(500);
}
if (bvSerial.strData == "bored"){
playcomplete("bored.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
delay(200);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(50));
delay(300);
pwm.setPWM(NECK, 0, ServoPulse(80));
pwm.setPWM(RST, 0, ServoPulse(20));
delay(500);
pwm.setPWM(RST, 0, ServoPulse(00));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(60)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(100));
delay(500);
pwm.setPWM(LST, 0, ServoPulse(70));
delay(500);
}
if (bvSerial.strData == "ican"){
playcomplete("ican.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
delay(200);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(50));
delay(300);
pwm.setPWM(NECK, 0, ServoPulse(80));
pwm.setPWM(RST, 0, ServoPulse(20));
delay(500);
pwm.setPWM(RST, 0, ServoPulse(00));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(60)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(100));
delay(500);
pwm.setPWM(LST, 0, ServoPulse(70));
delay(500);
}
if (bvSerial.strData == "no"){
playcomplete("no.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
delay(200);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(50));
delay(300);
pwm.setPWM(NECK, 0, ServoPulse(80));
pwm.setPWM(RST, 0, ServoPulse(20));
delay(500);
pwm.setPWM(RST, 0, ServoPulse(00));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(60)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(100));
delay(500);
pwm.setPWM(LST, 0, ServoPulse(70));
delay(500);
}
if (bvSerial.strData == "yes"){
playcomplete("yes.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
delay(200);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(50));
delay(300);
pwm.setPWM(NECK, 0, ServoPulse(80));
pwm.setPWM(RST, 0, ServoPulse(20));
delay(500);
pwm.setPWM(RST, 0, ServoPulse(00));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(60)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(100));
delay(500);
pwm.setPWM(LST, 0, ServoPulse(70));
delay(500);
}
if (bvSerial.strData == "saw"){
playcomplete("saw.WAV");
pwm.setPWM(HEAD, 0, ServoPulse(90));
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LST, 0, ServoPulse(70));
pwm.setPWM(RSB, 0, ServoPulse(90));
delay(100);
pwm.setPWM(HEAD, 0, ServoPulse(70));
pwm.setPWM(NECK, 0, ServoPulse(90));
delay(100);
pwm.setPWM(NECK, 0, ServoPulse(120));
pwm.setPWM(LSB, 0, ServoPulse(180)); // Keep between 90 and 180, so it doesn't hit itself
delay(200);
pwm.setPWM(LELB, 0, ServoPulse(100));
delay(150);
pwm.setPWM(LELB, 0, ServoPulse(130));
delay(150);
pwm.setPWM(RELB, 0, ServoPulse(90));
pwm.setPWM(NECK, 0, ServoPulse(90));
pwm.setPWM(RELB, 0, ServoPulse(0));
pwm.setPWM(LST, 0, ServoPulse(180));
delay(500);
pwm.setPWM(LSB, 0, ServoPulse(100)); // Keep close to 90, so it doesn't hit itself
pwm.setPWM(LHAND, 0, ServoPulse(60));
pwm.setPWM(NECK, 0, ServoPulse(120));
delay(500);
pwm.setPWM(LHAND, 0, ServoPulse(180));
}
byte i;
}
void playcomplete(char *name) {
playfile(name);
// 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();
}