Robot costume in progress - with Wave Shield!
Moderators: adafruit_support_bill, adafruit

Robot costume in progress - with Wave Shield!

by jerrya on Wed Oct 14, 2009 10:30 pm

My wife and I are making a robot Halloween costume and I just finished the electronics design prototype. I wanted to wait until the costume was finished before revealing it but I'm too excited that I finished my circuit and coding.

Image

http://www.youtube.com/watch?v=IT2OmmcDUek

That's a video of it, and I want to describe it a little. It uses an Adafruit Wave Shield for the sounds, and an antique analog gauge I found at Gateway Electronics here in St. Louis. There's an infrared beam pair from Sparkfun, which will be watching the "candy input slot" on the robot's chest. The gauge displays the count, until too much candy is inserted and it goes crazy. Then after 20 seconds of no more candy, the candy count gets reset, to be ready to do it all over again at the next house.

In the sketch, I used these AlphaBeta libraries: LED, button, TimedAction, and Scheduler. These made coding this sketch very easy. He even updated Scheduler with a clear() for me. Thanks again for that! The hardest part was getting it all to work together. I had been trying to use pin 9 for the gauge, and it crashed the sketch. I did more reading and found out you can't do PWM on 9 with the Wave libraries because of the timer. Pin 6 works fine though.

The beep sound loop I found on my mac, I think it came from iMovie. The speech is recorded synthesis also from my mac, made like this from a terminal:
say -o outputfile.aiff "thing to say"

This makes an aiff file. Then I used iTunes to convert all the sound files to WAV with the right settings for the Wave Shield.

The chaser LEDs are going to surround the Arduino in a shadow box sort of thing, so people can see the controller, and to punch it up so it isn't so boring. ;D

Next I have to install all of this in the costume and solder it all up.

[Cross posted to the Arduino Exhibition forum]
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield!

by adafruit on Thu Oct 15, 2009 11:51 am

that is cool. i like the gauge motion. plz post up a video of the finished costume :)
User avatar
adafruit
 
Posts: 11683
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

Re: Robot costume in progress - with Wave Shield!

by jerrya on Thu Oct 15, 2009 12:01 pm

Thanks! I will post more when there is more to show, for sure.
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield! - completed!

by jerrya on Wed Nov 04, 2009 1:02 am

Here's some photos, and a video of the electronics in action.

http://www.youtube.com/watch?v=S3L5Hl43Y44

Image

Image

Image
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield! - completed!

by Len17 on Wed Nov 04, 2009 1:25 am

Cute! :)
Did the robot's input hopper get filled up?
User avatar
Len17
 
Posts: 393
Joined: Sat Mar 14, 2009 6:20 pm

Re: Robot costume in progress - with Wave Shield!

by jerrya on Wed Nov 04, 2009 8:56 am

Yes, he wore the suit for almost a half hour and then wanted to sit down by a pile of leaves. He tried but there isn't enough room for that, so we took it off. I almost fell over when I felt how heavy it was with candy! He was a real trooper to wear it so long.
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield!

by adafruit on Wed Nov 04, 2009 11:35 am

oh man that is a crazy cool costume. but so much work! hopefully itll get worn next year?
User avatar
adafruit
 
Posts: 11683
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

Re: Robot costume in progress - with Wave Shield!

by jerrya on Wed Nov 04, 2009 12:56 pm

Ha, good one!

Naturally, he already says that next year he wants to be a pirate. Maybe another kid will wear it though.

Thanks for the compliments!
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield!

by johngineer on Wed Nov 04, 2009 5:14 pm

Dude, I am sooo jealous! Well done!
Adafruit Director of Imaging
Member of Technical Staff
Poles up, zeroes down.
User avatar
johngineer
 
Posts: 105
Joined: Fri Aug 14, 2009 5:05 pm
Location: Brooklyn, NY, USA

Re: Robot costume in progress - with Wave Shield!

by jerrya on Thu Nov 05, 2009 10:19 am

I appreciate all the compliments. And thanks, Limor, for the bloggage. That's pretty exciting for us.

There's more info on my blog:
http://jerrya-electronics.blogspot.com/ ... plete.html

If anyone asks for code, I'll post it. And I'm working on posting some in-progress photos I took.
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield!

by adafruit on Thu Nov 05, 2009 3:17 pm

plz post it :)
User avatar
adafruit
 
Posts: 11683
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc

Re: Robot costume in progress - with Wave Shield!

by jerrya on Thu Nov 05, 2009 5:29 pm

I'm not a normally a programmer, so please be gentle. :)

I have to say, I love the libraries I used from AlphaBeta; they made it easy to multi-task the different things that were happening. Check them out if you haven't yet. Links are provided in the comments.

Code: Select all | TOGGLE FULL SIZE
/*
This is a sketch for a robot costume for a little kid.
Jerry Adlersfluegel
10/2009

Using Arduino 17, on an Arduino Diecimila with ATmega328

Costume features:

Chaser LEDs surrounding the Aruino. People will want to know how it all works,
so we want to show off the fact that there's a computer in there. Will be
mounted on the back of the costume, so this will also be a visibility safety
feature.

Candy input slot / Analog gauge. There is an electric eye in the input slot
(with a .75 sec debounce/guard time), and the gauge indicates that candy has been
received, climbing higher with each piece inserted, until the desired amount of
candy has been exceeded, at which point the giver will be rewarded with the
gauge going crazy! (That is, the needle will swing back and forth wildly.) Then,
after an amount of time, the gauge will reset, so the needle is back to 0 at the
next house. This time is enough to get a laugh without showing the giver that it
resets, but not so long that the next house sees the needle still going crazy.

Sound effects via Adafruit Wave Shield. There's an idle loop playing robot
beeps, which gets interrupted by candy input. When the candy count increases,
there is a synthesized speech recording that will be played, a different one for
each quantity. When playback of one of those files completes, the idle loop
starts again.

[Still need to document the circuits.]
*/

// scheduler library http://www.arduino.cc/playground/Code/Scheduler
#include <Scheduler.h>
// LED library http://www.arduino.cc/playground/Code/LED
#include <LED.h>
// Button library http://www.arduino.cc/playground/Code/Button
#include <Button.h>
// library for doing things periodically http://www.arduino.cc/playground/Code/TimedAction
#include <TimedAction.h>
// libraries and includes for wave shield
#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"


// stuff for wave shield
AF_Wave card;
File f;
Wavefile wave;      // only one!

// stuff for the analog gauge
const int GaugePin = 6; // pwm pin for driving analog gauge ** found out you can't use pin 9 for pwm w/wave shield!!
// create an LED object for the gauge, since we're using it like an LED, kinda sorta
LED Gauge = LED(GaugePin); // also, this object removes the need to put anything for it in the setup()
TimedAction GaugeReward = TimedAction(250,CandyOverloadIndication); // to set interval for toggling the gauge

// stuff for the candy input sensor
const int CandyInputPin = 7; // pin for the input of the IR sensor - SEN-00241 from sparkfun
// create a button object for this input.
Button CandyInput = Button(CandyInputPin, PULLDOWN); // again, no setup() required
int CandyCount = 0;
boolean CandyInputBlocked = false; // used to prevent one piece from being overcounted, sort of a debounce
const int CandyGoal = 3; // how much candy to beg for at each house; number of steps on the gauge
boolean CandyIsOverloaded = false; // used in indicating if extra candy was collected
// scheduler object used to reset the candy counter after an amount of time, so it's zeroed at the next house
Scheduler CandyCountResetTime = Scheduler();
Scheduler CandyInputDebounce = Scheduler();

// stuff for the LED chasers
const byte NumberOfChasers = 6;
const byte ChaserInterval = 1000;
LED Chaser[NumberOfChasers] = {
  LED(14), LED(15), LED(16), LED(17), LED(18), LED(19) }; // using the analog inputs as digital outs
byte CurrentChaserLED = 0; // keep track of which chaser LED is current
TimedAction ChaserAction = TimedAction(ChaserInterval, ChaserUpdate); // create protothread for running the chaser

void setup()
{
  Serial.begin(9600);
  // wave shield pins
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);


  if (!card.init_card()) {
    putstring_nl("Card init. failed!");
    return;
  }
  if (!card.open_partition()) {
    putstring_nl("No partition!");
    return;
  }
  if (!card.open_filesys()) {
    putstring_nl("Couldn't open filesys");
    return;
  }
  if (!card.open_rootdir()) {
    putstring_nl("Couldn't open dir");
    return;
  }
  //
  //  putstring_nl("Files found:");
  //  ls();


  // initalize the chaser LEDs. We want all on except the first one
  //
  // turn each Chaser LED
  for(int i=0; i < NumberOfChasers; i++)
  {
    Chaser[i].on();
  }
  // and then flip the first one
  Chaser[CurrentChaserLED].toggle();

  playfile("0IDLE.WAV");

}

void loop()
{
  //  Serial.println(CandyCount);
  ReadSensors();
  UpdateGauge();
  GaugeReward.check();
  ChaserAction.check();
  CandyCountResetTime.update();


  if(!wave.isplaying)
  {
    card.close_file(f);
    playfile("0IDLE.WAV");
  }
}


// Read the values of all sensors, and set variables that reflect their states.
void ReadSensors()
{
  // check if the candy sensor sees candy now, and didn't last time. If so, increment the candy count
  if (CandyInput.isPressed() && CandyInput.stateChanged())
  {
    CandyInputDebounce.update();
    if (!CandyInputBlocked) // during the debounce period, don't do anything with this input
    {
      CandyCount++;
      // also, schedule a time to reset CandyCount to 0, after clearing the schedule queue
      CandyCountResetTime.clear(); // clear the Scheduler queue
      CandyCountResetTime.schedule(ResetCandyCount, 20000); // 20 sec in milliseconds
      CandyInputBlocked = true; // to prevent input from being read
      CandyInputDebounce.schedule(ResetCandyInputDebounce, 750); // schedule a .75 second debounce of candy input
      // and finally, play a sound associated with this qunatity of candy
      switch (CandyCount)
      {
      case 1:
        playfile("1CANDY.WAV");
        break;
      case 2:
        playfile("2YUM.WAV");
        break;
      case 3:
        playfile("3THANKS.WAV");
        break;
      case 4:
        playfile("4OVER.WAV");
        break;
      default:
        break;
      }
    }
  }
}

void playfile(char *name)
{
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
    card.close_file(f);
  }
  f = card.open_file(name);
  if (!f) {
    putstring("Couldn't open file ");
    Serial.print(name);
    return;
  }
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV");
    return;
  }
  // ok time to play!
  wave.play();
}

// set the value the gauge displays
void UpdateGauge()
{
  if (CandyCount <= CandyGoal)
  {
    // set the gauge to the progress towards the candy goal. map() that to the PWM range 0-255
    Gauge.setValue(map(CandyCount, 0, CandyGoal, 0, 255));
    CandyIsOverloaded = false;
  }
  else
  {
    CandyIsOverloaded = true;
  }
}

void CandyOverloadIndication()
{
  if (CandyIsOverloaded)
  {
    Gauge.toggle();
  }
}

// fuction to reset the candy input counter
void ResetCandyCount()
{
  CandyCount = 0;
  CandyIsOverloaded = false;
}

// function to flip the current chaser, increment the current value, then flip the next LED
void ChaserUpdate()
{
  Chaser[CurrentChaserLED].toggle();
  CurrentChaserLED == NumberOfChasers - 1 ? CurrentChaserLED = 0 : CurrentChaserLED++;
  Chaser[CurrentChaserLED].toggle();
}

// function to clear the candy input blocked flag
void ResetCandyInputDebounce()
{
 CandyInputBlocked = false;
}

Last edited by jerrya on Fri Nov 06, 2009 3:20 pm, edited 1 time in total.
jerrya
 
Posts: 17
Joined: Wed Apr 01, 2009 9:49 am

Re: Robot costume in progress - with Wave Shield!

by adafruit on Thu Nov 05, 2009 6:36 pm

you did great. it will be really useful for others. thanks!
User avatar
adafruit
 
Posts: 11683
Joined: Thu Apr 06, 2006 3:21 pm
Location: nyc