Two Servos + Wave Shield
Moderators: adafruit_support_bill, adafruit

Two Servos + Wave Shield

by yaroshka on Tue Nov 19, 2013 2:20 am

Hello everyone!

I'm working on my final project for physical computing class. I have an ugly stuffed animal and am trying to convert it into the "Hell Rabbit". When someone enters the room, my rabbit will scream or produce other scary sounds, with the eyes (two red LEDs) blinking and ears sweeping in different directions (using two TowerPro SG90 micro servos). I'm using a PIR motion sensor to activate Wave Shield. So far I was doing great:sensor is triggering the Wave Shield and LEDs are on, while audio is playing. But now I am stuck with the final step - adding two servos. I'm a newbie to the Arduino and don't know how to do it. I've read that the Wave Shield conflicts with standard servo library, so I downloaded another one - ServoTimer2", which uses Timer 2 instead of 1. I tried to put the code for servos in different places in the code (e.g. after 'while.isplaying'), but it does't work properly.

This being said, does anyone knows how to merge servo code with wave shield code (I need two servos, one for each ear). Do I have to use ServoTimer2 library, or there are other ways to do it? I was looking at Pumpking Project and tried to do some copy pasting, but it doesn't work for me, because I hardly know what I'm doing.

Any help will be greatly appreciated!!!!!!!!

Here is the code that I have:

Code: Select all | TOGGLE FULL SIZE
/*
  Motion activated "Hell Bunny"
 
Detects motion using a PIR sensor. When motion is detected plays a random wav file, with two LEDs
on while playing and (TENTATIVELY! two servo motors spinning in opposite directions)

The code is based on Adafruit "Pumpkin Project": http://www.adafruit.com/blog/2008/10/15/freaky-scary-halloween-pumpkin-project/

 */
 
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include "Arduino.h"
 
 
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
 
  // for PIR

  int inputPin = 6;               // choose the input pin (for PIR sensor)
  int pirState = LOW;             // we start, assuming no motion detected
  int val = 0;                    // variable for reading the pin status
  int randNumber;   //random number variable to allow the choosing of which wav will be played
  #define eyeleds 18;                // choose the pin for the LED
  #define DEBOUNCE 5  // button debouncer
 
// 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("nrSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}
 
void setup() {
  byte i;
 
  // set up serial port
  Serial.begin(9600);
  putstring_nl("WaveHC with ");
  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!
 
  // Set the output pins for the DAC control. This pins are defined in the library
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, INPUT);
  pinMode(18, OUTPUT);     // declare sensor as output for eyes
   
 
  //  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
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
 
  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);
 
// 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!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
 
  // Lets tell the user about what we found
  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()
{
 
}
 
void loop(){
  digitalWrite(8,HIGH);
  val = digitalRead(inputPin);  // read input value
  if (val == HIGH) {            // check if the input is HIGH
    if (pirState == LOW) {
      // Oh hey movement!
      Serial.println("Motion detected!");
       // Make scary eyes
            //Turn eyes on
     digitalWrite(18, HIGH);
       Serial.println("playing");
                // Play a sound: 
     randNumber = 0;
     randNumber = random(3);
if (randNumber >= 1)
{
     randNumber = random(3);
     randNumber = randNumber + 1;
     Serial.println(randNumber);
         if (randNumber == 1)
         {
           playcomplete("01.WAV");
         }
       
        else if (randNumber == 2)
        {
            playcomplete("02.WAV");
        }
       
        else if (randNumber == 3)
        {
            playcomplete("03.WAV");
        }
        else if (randNumber == 4)
        {
            playcomplete("04.WAV");
        }
}
       // Go back to sleep
       Serial.println("resetting for next run");
       delay(5000);
 
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
      digitalWrite(18, LOW);
      // we have just turned off
    if (pirState == HIGH){
      // we have just turned of
      Serial.println("Motion ended!");
 
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}
 
// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
    char i;
  uint8_t volume;
  int v2;
  // call our helper to find and play this name
  playfile(name);
  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();
}


Here is what I have so far:

https://www.youtube.com/watch?v=l5Ii_hMstg4

Here is ServoTimer2 Library: http://www.arduino.cc/playground/upload ... Timer2.zip

P.S. I'm using Arduino Uno R3

The picture of Hell Bunny is also attached:)
Attachments
Bunny_15inch.jpg
Hell Bunny
Bunny_15inch.jpg (71.13 KiB) Viewed 434 times
yaroshka
 
Posts: 2
Joined: Tue Nov 19, 2013 1:34 am

Re: Two Servos + Wave Shield

by adafruit_support_bill on Tue Nov 19, 2013 7:35 am

trying to convert it into the "Hell Rabbit"

Any relation to the [url=Caerbannog]Killer Rabbit of Caerbannog[/url]

I tried to put the code for servos in different places in the code (e.g. after 'while.isplaying'), but it does't work properly.

I don't see any servo code in the listing you posted. What code did you put there and what did it do or not do?

The standard servo library conflicts with the timers used by the shield. Your choices are:

* Use ServoTimer2. Support for this library is minimal at best, but some have gotten it to work.
* Bit-bang your own servo timing code.
* Use a Servo Shield or Servo Breakout. These use the I2C bus and have no conflicts with the Wave Shield.
http://www.adafruit.com/products/1411
http://www.adafruit.com/products/815
User avatar
adafruit_support_bill
 
Posts: 31846
Joined: Sat Feb 07, 2009 10:11 am

Re: Two Servos + Wave Shield

by yaroshka on Thu Dec 26, 2013 4:14 am

Hey,

Never mind, I figured it all out. It was working great for couple of hours, but then I lost one servo. But even with this drawback we got an "A" on the project:) Here is the evidence of 2 servos working:

https://www.youtube.com/watch?v=Ab2_rBT101U

And here is our final teaser (thank you so much for the Caerbannog analogy!). You can skip to 1:00 to see it in action:

https://www.youtube.com/watch?v=9Pq_jyKwjg4#t=62
yaroshka
 
Posts: 2
Joined: Tue Nov 19, 2013 1:34 am