Monday, October 26, 2015

Halloween Candy Cauldron V2.0

Last year I was enticed into a Halloween Project.  I was working on my donkey, which involved sound, at the same time many of  the +Adafruit Industries  weekly #ShowandTell and #WearableWednesday projects had a Halloween theme, and of course there's the #electroninchalloween hashtag.

So, I came up with the idea of a candy dish that made Halloween-ey sounds when someone reaches in for candy. It was a big hit with adults, but kids less impressed.  I realized that I had some design flaws.

Here's my appearance on the Adafruit Show and Tell, while I was still working on the SD card reader. It should start just before my section (after you skip the ad), but if not, I start at about minute 18.

First, I did not enclose the circuitry, so aggressive candy grabbers could introduce failure (adults were bigger offenders here).  Second, I wanted to use the +SeeedStudio SD Card Shield, which meant I needed to include an Arduino Uno. That was fine, because the shield sits on top of the Uno and the Adafruit Class D Amp uses 5V. Most SD card readers, particularly MicroSDs, want 3.3V.  I could do this off the Uno, but I needed another approach if I wanted to use a different board with one voltage level or the other.

I had a Adafruit Pro Trinket (5V) around, so I decided to use it.   I need the Pro Trinket as opposed to Trinket, because the smaller (non-Pro) version doesn't have enough pins to support SPI, which I need for the SD card.  I does not have a digital pin #7, which I was using for the Echo Pin on the ultrasonic sensor, so I has to change that to #6. Fortunately, I also had an LC Studios SD Card Reader that accepted 5V or 3.3V. That simplified matters, avoiding a voltage regulator and  logic level converter (which I have, but simpler is better),  The Pro Trinket can be powered from up to 16V, so I'll bring 9V  into it and power a 5V rail from the Trinket.

See issues, below,  I had 2 of the LC Studios boards. One would not work at all.  The other I got to work with the Uno but not with the Trinket. So, I ordered an Adafruit Micro SD Breakout Board. More expensive, but it works--and I am supporting a my favorite supplier.

Now I needed an enclosure.  This is a case where a 3D Printer would be really handy so I could design my own (I'm working on that).  Stock enclosures almost always have standoffs in the wrong places, so at best the standoffs are useless and at worst are in the way and have to be cut out, AND they're never exactly the right size.

To recap last year's project, I had:
Ultrasonic Distance Sensor and 3" speaker from a defunct clock radio as peripherals, with an Arduino Uno, SD card shield, and an amp--all loose in the bottom of the cauldron (except the speaker and sensor). The battery was external.

The changes are:
  1. add an enclosure; mine is 5" X 1.75" X 2.5"--bigger than I really need but everything fits, including a half-sized breadboard
  2. change from the Uno to a 5V Pro Trinket
  3. use a MicroSD reader instead of the SD shield
  4. I considered a circuit board or perma-proto), but decided to keep the half-sized breadboard for modularity and simplicity
  5. move the battery into the enclosure and use a switch to power on/off (last year I had the 9V battery outside the cauldron, inside a switched battery holder
  6. as noted below, I used long header pins to connect components to the breadboard
  7. change the pin assignment for the Echo Pin from 7 to 6
I will need to connect 8 wires from the enclosure: 4 to the distance sensor,  2 to the speaker, and 2 from the battery to the switch so I'll need to have holes in the enclosure and devise a way to connect them (short of hardwiring). I have some Radio Shack RCA phono plugs and jacks for the speaker, and holes for the sensor wires and power wires. I will use JST connectors for the power and sensor wires.
Since I'm keeping the breadboard, I can use long header pins in the breadboard, and just plug the JST female ends into them.

Everything else is as in V1.

Issues along the way:

After I got an SD card reader that worked (see above), I had it all working.  Then I must have messed up a connection, because I was getting no sound. I suspected that the HC-SR04 was cooked, so I put on my FTDI board so I could use the serial monitor to see the testing messages I put in the code. Sure enough, it was not registering.  I had 2 more, so I swapped one in. same result.  Swapped the other in--all is well.  I knew I would need more, and my options were 2 for $9 at amazon or $0.88 each off ebay. I ordered 5, If one works I break even with Amazon.  

Next problem:  still no sound. I check every connection and reran everything, so I concluded that the amp was bad too (this happened in another project with the same amp).  I ordered 4 more. As soon as they arrived I soldered the header and terminal block and swapped it in.  No sound. I turned the volume to see if that was the problem,  Just in case, I checked the wiring again. Sure enough, the wire that was supposed to connect A- to GND was misplaced. I moved it and tiedd again. Still no sound. Remembering that I had adjusted the volume, I turned it back. Sure enough, I had turned it down earlier, so now its all good.

New circuit:


Parts

  1. enclosure (mine is 5"L X 1.75"H X 2.5"W)--I don't remember where I got it, but Radio Shack has several that are close, so does Micro Center
  2. half-sized breadboard
  3. Adafruit Pro Trinket (5V)
  4. Adafruit Micro SD Breakout Board
  5. HC-SR04 Ultrasonic sensor (link for example--it can be found for
  6. Adafruit Class D Amp 
  7. 3in 8 Ohm speaker (I took mine from a clock radio)
  8. SPST toggle switch
  9. Sparkfun FTDI Basic Breakpout (for serial debugging)
  10. 9V Battery  (or any power supply > 5V)
  11. snap-on battery cap with leads (for 9V--other options for other power--e.g., a 4XAA enclosure)
  12. female-female jumpers
  13. JST connectors
  14. RCA phono plug and jack
  15. long header pins 

Construction:

  1. Upload the code to the Trinket.  I really didn't have to do this first, but since is was written for the UNO on an earlier version of the IDE, I wanted to make sure.  All good on IDE version 1.6.5...and I had to do it again once I realized that I needed to re-assign the Echo Pin
  2. I used long header pins (long on both sides) in the breadboard, and used JST female ends to connect to them, and soldered the JSTs to the leads to battery/switch, sensor,  and amp. I used female-female jumpers to connect to the SD breakout (also Speaker Pin to the amp). The amp itself is plugged into the breadboard via its header pins
  3. Drill holes in the enclosure (1/8" for the wires to the JST's, 3/8" for the RCA plug--yes I put the plug on the leads to the amp and the jack on the leads to the speaker)
  4. Solder header pins on the Trinket
  5. Solder leads to the RCA jack and plug (only need one of each since there's just one speaker), and the JST connectors
  6. Connect, test, and go

Code

/*2014-10-05
Halloween Candy Dish: Play random sound when kid reaches into bowl
*/
/*2014-10-05 HC_SR04 Distance sensor code added
 Need to modify pins for Halloween (13&12 used by SPI)
 2014-04-26 Downloaded from Instructables
 HC-SR04 Ping distance sensor]
 VCC to arduino 5v GND to arduino GND
 Echo to Arduino pin 13 Trig to Arduino pin 12 (used 8&7 instead)
*/
/* 2015-10-14
 Change to Pro Trinket from Uno to put the circuit in an enclosure
 Echo to 6 (Pro Trinket does not have pin 7)
 see virgilmachine.blogspot.com
*/

/*includes*/
#include    //SPI library
#include     //SD card library
#include //library for playing sound

/*constants*/
#define SD_ChipSelectPin 10
#define trigPin 8
#define echoPin 6 //used to be 7 on Uno--Pro Trinket does not have a pin 7
/*variables*/
int song = 0;   // song number for random function
/*objects*/
TMRpcm speaker;   // create an object for use in this sketch

void setup(){
  randomSeed(analogRead(0));  //initialize random (A0 unconected)
  pinMode(trigPin, OUTPUT);   //pins for distance sensor
  pinMode(echoPin, INPUT);
  speaker.speakerPin = 9; //output to amp
  speaker.loop(0); //2014-10-05 do not play repeatedly
  Serial.begin(9600);
  if (!SD.begin(SD_ChipSelectPin))
     {  // see if the card is present and can be initialized:
     Serial.println("SD not initialized");
      return;   // don't do anything more if not
      }
   else
      {
       Serial.println("SD initialized");
     }  
  speaker.volume(1);
//  speaker.setVolume(7);   //attempt to increase volume
}

void loop() {
  long duration, distance;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
//trigPin must me high for 10 microsecs to do ranging
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
//duration is the time between pings of the sensor  in microseconds as returned on echoPin
  duration = pulseIn(echoPin, HIGH);
//duration is a round-trip, so divide by 2; speed of sound is 29.1 cm/microsec, so distance is in cm
  distance = (duration/2) / 29.1;
    Serial.print(distance);  //debug
    Serial.println(" cm");  //debug
//2014-10-05 If distance is <~5in someone has reached in 12/2.54cm=just under 5in
if (distance < 12)
    {
      song = random(1,10); //get random number from 1 to 9   sounds on SD card are 1.wav, etc.
      Serial.print("song: "); //for debugging
      Serial.println(song); //for debugging
      switch (song) {
        case 1:
          speaker.play("1.wav");
          break;
        case 2:
          speaker.play("2.wav");
          break;
        case 3:
          speaker.play("3.wav");
          break;
        case 4:
          speaker.play("4.wav");
          break;
        case 5:
          speaker.play("5.wav");
          break;
        case 6:
          speaker.play("6.wav");
          break;
        case 7:
          speaker.play("7.wav");
          break;
        case 8:
          speaker.play("8.wav");
          break;
        case 9:
          speaker.play("9.wav");
          break;
      }
        delay(5000);
  }
delay(50);
}