Chapter 3

Building an Animatronic Prop Controller

IN THIS CHAPTER

check Considering control requirements for animatronic props

check Looking at microcontroller products from EFX-TEK

check Examining programming requirements for relay control

check Investigating programming requirements for sound control

check Responding to a motion detector

check A complete program for a scary jack-in-the-box prop

Animatronics refers to the technology used to create automated puppets that move by themselves. The movements are provided by mechanical means such as motors, servos, compressed air, or pneumatics. Animatronic puppets are usually controlled by microprocessors.

My fascination with animatronics started at a very young age, when I first visited Disneyland as a child and was mesmerized by three of the most amazing things I had ever seen: Enchanted Tiki Room, filled with marvelous robotic birds that sang and told jokes; Pirates of the Caribbean, with its swashbuckling pirates; and of course The Haunted Mansion, with its 999 ghosts and room for one more.

The Haunted Mansion was the pièce de résistance. I have been fascinated with all things Halloween ever since and tinkered on and off over the years with building my own animatronic ghosts and goblins.

In this chapter, I show you how to build a microprocessor-based controller system that I’ve used in several of my best Halloween props. I’ve used this exact circuit to create a Frankenstein creature that pops up, a mummy that pops up, and a giant jack-in-the-box, but you can use this circuit to control just about any kind of animatronic creation you can imagine.

Note that Halloween isn’t the only application for animatronics. You can use them in theatrical productions, school fundraisers, or for promotional or marketing purposes. For example, if you own a flower shop, you could create animatronic flowers for your storefront display, or if you own a tuxedo store, you could create an animatronic dancer dressed in your finest tuxedo to draw customers in. The only limit is your imagination.

warning Animatronics should be built and used with care, as they can be dangerous. You must ensure that no one who views your animatronic will be exposed to any danger, such as loose electrical connections or faulty compressed-air fittings. Make sure you place your finished animatronic in a secure area where no one will be able to touch it, and make sure that all electrical and compressed-air fittings are completely secure.

If your animatronic prop uses compressed air, be especially careful! This chapter doesn’t show you how to work with compressed air because that’s a subject for an entire book. If you want to work with compressed air, always use professionally designed and manufactured components such as air cylinders and pop-up mechanisms. Don’t try to build your own compressed air cylinders out of PVC pipe, bicycle pumps, or any other material that isn’t specifically designed to work with compressed air. And beware of inexpensive compressed-air devices available on eBay or other online sites. A good, safe compressed air mechanism should cost you several hundred dollars. If it’s selling online for $49, it’s probably not safe.

Looking at the Requirements of Animatronic Prop Control

Whether it’s used in a haunted house, trade show exhibit, store display, or museum, a typical animatronic prop requires the following elements to achieve the desired effect:

The prop controller I show you how to build in this chapter meets all these needs. It’s based on a BASIC Stamp microprocessor, which provides more than enough computing power to control lights and sound and activate a few pneumatic valves and electric motors.

Instead of building the controller from a BASIC Stamp module from Parallax, the controller shown in this chapter uses components from a company named EFX-TEK, which specializes in microprocessor components for animatronic prop controls. The prop controller uses three products from EFX-TEK: a Prop-1 controller board, which includes a BASIC Stamp microprocessor; an RC-4 relay board that can hold up to four relays for switching 120 VAC circuits; and an images sound board, which can be programmed to play sounds saved on a standard SD memory card.

For more information about these components and how to use them, see the section “Building the Prop Controller ” later in this chapter.

technicalstuff EFX-TEK has recently replaced its RC-4 relay board with a new and improved version called the images . The images is compatible with the images , so you can build the prop controller using either board.

Examining a Typical Animatronic Prop

Figure 3-1 shows a typical animatronic prop that I made a few years ago to use in a Halloween haunted house. The prop is a large jack-in-the-box that benignly plays “Pop Goes the Weasel” while a crank on one side of the prop slowly spins until an unsuspecting visitor approaches it. Then — all in one frightening moment — the music stops, the lid flies open, a large clown head pops up, a bright light comes on to ensure that you can see the clown, and a ghastly voice screams, “Trick or treat!” A moment later, the light goes off, and the clown retracts back into the box. A few seconds after that, the crank starts spinning and the music plays again while the jack-in-the-box waits for another victim.

image

FIGURE 3-1: The jack-in-the-box prop.

The basic pop-up operation of the jack-in-the-box is accomplished with a compressed air mechanism that can be controlled with an electrically activated valve. When the valve is closed, the mechanism is retracted inside the box. When the valve opens, compressed air flows into an air cylinder that extends the mechanism upward. The clown head is mounted on top of the mechanism. The lid of the jack-in-the-box is positioned such that the clown’s head pushes the lid open when the mechanism extends. Gravity takes care of closing the lid when the mechanism retracts, and the clown goes back into the box.

Note that the point of this chapter is to show you how to build the electronic part of this prop — the prop controller that controls the prop’s action. This chapter doesn’t show you how to build the prop itself. The prop controller is generic enough that it can control just about any prop that includes simple actions such as pneumatic pop-ups, motors, lights, and sound. In fact I’ve used this very same design for half a dozen different Halloween props.

Nevertheless, it’s beneficial to see how the prop controller works in a specific prop, so the following paragraphs describe in general terms how I built the jack-in-the-box prop. This will give you a general idea of how it operates so that you can see how the prop controller works with it.

image

FIGURE 3-2: The lift mechanism.

image

FIGURE 3-3: Schematic diagram for the jack-in-the-box prop.

That’s about it for the jack-in-the-box prop itself. As I’ve already mentioned, the primary focus of this chapter is building the prop controller that provides the brains for this prop. The prop controller can be used for any other type of prop with similar requirements. And, if your prop is more complex than the jack-in-the-box, you can easily expand the prop controller by including additional relay control boards to control more devices.

Building the Prop Controller

Figure 3-4 shows the fully assembled prop controller used to control the jack-in-the-box prop. As you can see, the prop controller is made from three circuit boards, which you can purchase from EFX-TEK ( www.efx-tek.com ). The boards are mounted on an images -inch sheet of Plexiglas, which you can purchase from most hardware stores. Before mounting the components on Plexiglas, spray-paint the back of the Plexiglas black to create a nice, professional-looking board.

image

FIGURE 3-4: The assembled animatronic prop controller.

Here’s a complete list of the parts you’ll need to build the prop controller:

Quantity

Description

1

EFX-TEK Prop-1 controller

1

EFX-TEK PIR sensor (includes a 14-inch extension cable for connecting to the Prop-1)

1

EFX-TEK images audio player

1

EFX-TEK RC-4 relay control board

2

Crydom D2W203F solid-state relays

3

EFX-TEK stand-off kits (each kit includes four images -inch stand-offs and eight 4-40 machine screws)

2

14-inch servo-style extension cables

2

6-inch lengths of 16-gauge stranded wire

1

images -inch sheet of images -inch Plexiglas

1

Can of black spray paint

All these components except the wire, Plexiglas, and the paint can be ordered from EFX-TEK at www.efx-tek.com . The total price for all components should be around $275.

The following paragraphs describe the four main components of the prop controller, which are listed first in the parts list:

warning I can’t say it too many times in this chapter: The prop controller uses line-level voltages that can hurt or even kill you if you aren’t careful. Make sure that the line-level wiring is properly secured and enclosed, and never work on the controller board when the line-level circuits are plugged in.

Here are the steps to assemble the prop controller:

  1. Paint one side of the Plexiglas with the black spray paint and allow the paint to dry.
  2. Drill the necessary mounting holes in the Plexiglas.

    You’ll need to drill four mounting holes for each of the three boards that will be mounted to the Plexiglas (Prop-1, RC-4, and images ). Use a images -inch drill bit. Figure 3-5 is a rough drilling guide, but note that this diagram isn’t to scale. You’ll need to lay your actual components out on the Plexiglas to determine the exact drilling locations.

  3. Mount the Prop-1 controller on the Plexiglas.

    Use four of the stand-offs and eight of the 4/40 machine screws. Position the Prop-1 controller so that the row of screw terminal connectors is on the left side of the controller as oriented in Figure 3-5 .

  4. Mount the RC-4 board on the Plexiglas.

    Use four of the stand-offs and eight of the 4-40 machine screws. Position the RC-4 board so that the four screw-terminal connectors are at the bottom of the board as oriented in Figure 3-5 .

  5. Mount the images board on the Plexiglas.

    Use four of the stand-offs and eight of the 4-40 machine screws. Position the images board so that the audio output connectors are at the bottom of the board as oriented in Figure 3-5 .

  6. Use the two wires to connect the images and GND terminals on the Prop-1 to the images and GND terminals on the images board.

    These wires are used to provide power for the images board. After test-fitting the wires, cut them to the correct length and strip images inch of insulation off each end. Then insert each end of the wire into the appropriate screw terminal and tighten the screw to ensure a solid connection.

  7. Use one of the extension cables to connect the P7 header on the Prop-1 controller to the SER header on the RC-4.

    This cable enables the Prop-1 controller to send commands to the RC-4 board to cause the RC-4 board to turn its relays on or off.

    Eight three-pin headers are found near the center of the Prop-1 controller board. These headers provide access to the eight I/O ports of the BASIC Stamp microprocessor. The headers are labeled P0 through P7, so you shouldn’t have trouble finding the correct header.

    There are two three-pin headers on the RC-4 board, both labeled SER. These two headers are connected to one another, so it doesn’t matter which one you use as they’re electrically the same.

    The only trick to connecting the extension cable is making sure you get them oriented correctly. The extension cable has three wires: white, red, and black. The cables must be inserted into the header correctly, or the Prop-1 won’t be able to communicate with the RC-4.

    Orienting the cable correctly on the Prop-1 is easy because the three-pin headers are labeled to indicate which pin is white, which is red, and which is black. On the RC-4, the cable should be inserted into the header with the black wire facing the outside edge of the board and the white wire facing the center of the board.

  8. Use the second extension cable to connect the empty SER header on the RC-4 board to one of the SERIAL headers on the images board.

    The purpose of this connection is to enable the Prop-1 controller to communicate with the images audio player to tell it when to play its sounds.

    As oriented in Figure 3-5 , the SERIAL header pins are located near the top-right corner of the images board. The pins on the images headers are labeled W, R, and B, so you should have no trouble orienting the wire colors. As with the RC-4, there are two SERIAL headers on the images ; it doesn’t matter which of them you use.

  9. Use the third extension cable to connect the PIR sensor to the P6 header on the Prop-1 controller.

    The P6 header is right next to the P7 header.

  10. Insert the two Crydom solid-state relays in the K1 and K2 positions on the RC-4 board.

    Note that if your prop needs to control more than two 120 VAC circuits, you can add up to four Crydom relays to the RC-4 board. And you can add additional RC-4 boards if you need to control more than four circuits.

image

FIGURE 3-5: Where to mount the circuit boards and drill the mounting holes for the animatronic prop controller.

Programming the Prop-1 Controller

At the heart of a Prop-1 controller is a Parallax BASIC Stamp microcontroller. As a result, you can program the Prop-1 controller using the same PBASIC programming language you use to program a BASIC Stamp. The techniques for programming in PBASIC are presented in detail in Book 7 . As a result, I won’t review those details here. You’ll need to be familiar with the concepts presented in Book 7 before you attempt to program the Prop-1 controller.

However, realize that the Prop-1 controller uses a simpler form of the BASIC Stamp microprocessor, known as the BASIC Stamp 1. Book 7 covers the more advanced version of the BASIC Stamp, called the BASIC Stamp 2. The BASIC Stamp 1 uses a simpler version of PBASIC than the BASIC Stamp. Here are some of the differences you’ll need to be aware of:

Other than these variations, programming the BASIC Stamp 1 microcontroller is similar to programming its more advanced counterpart.

Sending Commands to the RC-4 or images Modules

I don’t cover the PBASIC command called SEROUT in Book 7 , but you’ll need to be familiar with it to use EFX-TEK’s RC-4 and images modules. The SEROUT command sends data to an external device that’s connected to the Prop-1 controller via one of the I/O pins. It uses a very simple serial communications protocol to accomplish this. Fortunately, you don’t need to worry about the details of how the serial communications protocol works to use the SEROUT command to talk to an RC-4 or images module. But you do need to know how to use the SEROUT command.

The SEROUT command has a simple syntax:

SEROUT pin , mode , (data )

The first parameter of the SEROUT command, pin, is simply the pin number that the data is to be sent to. Since the RC-4 and images modules are connected to PIN7 in the animatronic prop controller, you’ll simply specify PIN7 for this parameter.

The second parameter indicates the communication mode that will be used to send the data. For all EFX-TEK I/O modules, you should specify the built-in constant OT2400 for this parameter.

technicalstuff In case you’re interested, OT2400 means that the transmission speed is 2400 bits per second, and the output polarity is open-drain driven high — which sounds pretty technical to me, so I wouldn’t worry about it. Just use OT2400 for this parameter.

The third parameter, (data), is the one that actually specifies the data to be sent to the external device. You must enclose the data in parentheses, and within the parentheses you can list as many string constants or variables as you want. For example:

SEROUT PIN7, OT2400, ("Hello World!")

This statement sends the string constant “Hello World!” to the device on PIN7.

Here’s an example that accomplishes the same thing but with three string constants instead of one:

SEROUT PIN7, OT2400, ("Hello ", "World", "!")

And here’s an example that uses a variable:

SYMBOL Bam = B0
Bam = "!"
SEROUT PIN7, OT2400, ("Hello, World", Bam)

You might reasonably ask why you would use several string constants or variables instead of just one. The answer to that excellent question will become apparent when you read the following two sections about programming the RC-4 and images modules.

tip It’s a good idea to assign a symbol to the I/O pin to which the RC-4 and images modules are attached, and to the communication mode. For example:

SYMBOL Sio = 7
SEROUT Sio, OT2400, ("Hello, World!")

That way, if you decide to change the I/O pin to which the external device is attached, you have to make only one change to your program — the symbol definition — instead of multiple changes in each SEROUT statement.

Though not as important, it’s also a good idea to use a symbol for the mode parameter, like this:

SYMBOL Sio = 7
SYMBOL Baud = OT2400
SEROUT Sio, Baud, ("Hello, World!")

Why? Because someday you may decide to move your program over to a Prop-2 controller. When you do, you’ll discover that the BASIC Stamp 2 SEROUT command has additional mode settings that enable faster and more reliable serial communications. You’ll be able to change the serial communications mode for all your program’s SEROUT commands simply by changing the SYMBOL statement.

Programming the RC-4 Relay Control Module

The RC-4 relay control module supports up to four high-voltage solid-state relays that can turn line-voltage circuits on and off. EFX-TEK sells the board and relays separately, so you can equip it with just the number of relays your project needs.

A pair of jumper blocks on the RC-4 board lets you give it an address value of 0, 1, 2, or 3. This allows you to daisy-chain up to four RC-4 boards together, allowing you to control up to 16 separate relay circuits. The examples in this section assume that you have removed these two jumpers so that the address of the RC-4 is 0.

To control an RC-4 board from a Prop-1 controller, you use the SEROUT command to send data to the pin that the RC-4 board is connected to. The data that you send must follow this format:

"!RC4", address, command {,data}

The first data item is the string constant “!RC4”. This string constant is a preamble that indicates that the data that follows is intended for an RC-4 relay control card. This allows you to chain several different kinds of EFX-TEK cards together and send commands only to the RC-4.

The second data item is the address of the RC-4 card you want to send the data to. The possible values are 0, 1, 2, or 3.

The third data item is a command, which is a single character that represents one of several commands that the RC-4 can respond to. Depending on the command used, you may also need to provide one or two additional bytes of data after the command. The possible commands are:

Command

What It Does

X

Resets all relays. No additional data is needed.

R

Sets or resets an individual relay to a particular value. Two data bytes are required: one to indicate which relay to set or reset, and a second to indicate whether the relay should be closed (set) or opened (reset).

S

Sets all relays. The S command is followed by a single byte of binary data that indicates which relays should be open and which should be closed.

V

Causes the RC-4 to send its firmware version information back to the prop controller. The version information can be read with a SERIN command.

G

Gets the current status of all relays. Use the SERIN command to read the data from the RC-4 after sending this command.

The three RC-4 commands you’ll use most often are X, to reset all relays; R, to set an individual relay; and S, to set each of the four relays to a particular status (on or off). These commands are described in the following sections.

Turning all relays off

To turn all the relays on an RC-4 module off, use the X command. For example:

SEROUT PIN7, OT2400, ("!RC4", 0, "X")

It’s a good idea to use this command near the beginning of your program to make sure that the program starts with all relays off.

Turning an individual relay on or off

To turn an individual relay on or off, you send an R command to the RC-4. The R command requires that you send five separate data items:

Here’s a SEROUT statement to turn the first relay (number 1) on:

SEROUT PIN7, OT2400, ("!RC4", 0, "R", 1, 1)

And here’s a SEROUT statement to turn the first relay off:

SEROUT PIN7, OT2400, ("!RC4", 0, "R", 1, 0)

Setting all four relays at once

To set the status of all four relays at one time, you can use the S command. This command requires four data items:

The value that controls the relay status is usually written as a percent sign followed by four binary bits representing the status of each relay — 1 for on and 0 for off. The only trick is that the four binary bits are written in reverse order: The first is relay 4, the second is relay 3, the third is relay 2, and the fourth is relay 1.

For example, to turn relay 1 on and the other three relays off, you would use %0001 as the relay status. To turn relays 1 and 3 on and relays 2 and 4 off, you would use %0101 as the status.

Here’s a SEROUT command that sends an S command to turn all four relays on:

SEROUT PIN7, OT2400, ("!RC4", 0, "S", %1111)

And here’s a SEROUT command that turns relays 1 and 3 on and simultaneously turns relays 2 and 4 off:

SEROUT PIN7, OT2400, ("!RC4", 0, "S", %0101)

The following SEROUT command turns all relays off, which is equivalent to sending an “X” command:

SEROUT PIN7, OT2400, ("!RC4", 0, "S", %0000)

Using symbols to make RC-4 commands more readable

As I mention earlier in this chapter, it’s a good idea to use symbols for the I/O pin and output mode. It’s also a good idea to use symbols for the RC-4 address, for the relay number, and for the relay status (on or off). That can make your program more readable.

For example, here are some typical symbol declarations:

SYMBOL Sio = 7
SYMBOL Baud = OT2400
SYMBOL RC4 = 0
SYMBOL Relay1 = 1
SYMBOL Relay2 = 2
SYMBOL Relay3 = 3
SYMBOL Relay4 = 4
SYMBOL RelayOn = 1
SYMBOL RelayOff = 0

With these symbol declarations in place, you can turn on relay 1 with this statement:

SEROUT Sio, Baud, ("!RC4", RC4, "R", Relay1, RelayOn)

And here’s a statement that turns relay 1 off:

SEROUT Sio, Baud, ("!RC4", RC4, "R", Relay1, RelayOff)

Here’s a SEROUT statement that uses the symbols to send an S command that turns relays 2 and 4 on and relays 1 and 3 off:

SEROUT Sio, Baud, ("!RC4", RC4, "S",%1010)

A sample program for controlling all four RC-4 relays

Listing 3-1 shows a complete PBASIC program that gives the RC-4 card a bit of a workout by performing the following sequence of steps:

  1. Turn off all relays with an X command.
  2. Pause 1 second.
  3. Use a series of S commands to turn on relays 1, 2, 3, and 4 in sequence at 1-second intervals.

    As each relay is turned on, the other three are turned off.

  4. Pause 1 second, and then turn off all relays.
  5. Use a series of R commands to turn on relays 1, 2, 3, and 4 in sequence at 1-second intervals.

    As each relay is turned on, the status of the other relays are left unchanged. As a result, this part of the program first turns on relay 1, then adds relay 2, then adds relay 3, and then adds relay 4. At this point, all four relays are on.

  6. Wait 1 second, and then repeat the entire program.

You can download this program from this book’s companion website.

LISTING 3-1 An RC-4 Control Program

΄ {$STAMP BS1}
΄ {$PBASIC 1.0}

SYMBOL Sio = 7
SYMBOL Baud = OT2400
SYMBOL RC4 = 0
SYMBOL Relay1 = 1
SYMBOL Relay2 = 2
SYMBOL Relay3 = 3
SYMBOL Relay4 = 4
SYMBOL RelayOn = 1
SYMBOL RelayOff = 0


Main:
΄Turn off all relays
SEROUT Sio, Baud, ("!RC4", RC4, "X")
PAUSE 1000

΄Cycle through the relays one at a time
SEROUT Sio, Baud, ("!RC4", RC4, "S", %0001)
PAUSE 1000
SEROUT Sio, Baud, ("!RC4", RC4, "S", %0010)
PAUSE 1000
SEROUT Sio, Baud, ("!RC4", RC4, "S", %0100)
PAUSE 1000
SEROUT Sio, Baud, ("!RC4", RC4, "S", %1000)
PAUSE 1000

΄Turn off all relays
SEROUT Sio, Baud, ("!RC4", RC4, "S", %0000)
PAUSE 1000

΄Turn on relay 1
SEROUT Sio, Baud, ("!RC4", RC4, "R", Relay1, RelayOn)
PAUSE 1000

΄Add relay 2
SEROUT Sio, Baud, ("!RC4", RC4, "R", Relay2, RelayOn)
PAUSE 1000

΄Add relay 3
SEROUT Sio, Baud, ("!RC4", RC4, "R", Relay3, RelayOn)
PAUSE 1000

΄Add relay 4
SEROUT Sio, Baud, ("!RC4", RC4, "R", Relay4, RelayOn)
PAUSE 1000

΄Repeat!
GOTO Main

Programming the images Audio Player Module

The images audio player module is an amazingly versatile way to add sound to your animatronic prop. Like the RC-4, you communicate with the images module using serial communication via the SEROUT statement. Some commands cause the images module to return data, which you can retrieve with the SERIN statement. But for most props, all you have to do is send a few commands using SEROUT, so you can dispense with the SERIN statement.

The images board can play sounds recorded in WAV format stored on a micro-SD card. So before you program your prop, you’ll need to prepare a micro-SD card with the files you want the prop to play. You can simply use your computer to copy the files to the micro-SD card; the only restriction is that the filenames must be no longer than eight characters, and the filename extension must be .wav . (The images card can’t play MP3 files.)

For the jack-in-the-box prop, just two sound files are needed. The file that contains the “Pop Goes the Weasel” song is named weasel.wav . I created this recording myself; you can download it from this book’s companion website.

The other file is a horrific scream that is played when the clown pops up. This file is named scream.wav . It is also available on the companion website.

technicalstuff The images is an extremely versatile card that’s designed to be usable in stand-alone mode — that is, not controlled by a microcontroller. Many of its features are useful primarily in stand-alone mode. For example, you can store files on the micro-SD card with predefined filenames such as SFX nn .wav and AUX nn .wav , where nn is a two-digit number (for example, SFX01.wav or AUX04.wav ). The images can be configured to automatically play these files in random ways in response to direct trigger inputs on the card. The images can also be configured to play an ambient background sound whose filename must be ambient.wav . These are all very useful features, but not relevant to the prop controller presented in this chapter. So although I ignore those features in this section, I suggest you carefully read the images documentation supplied by EFX-TEK to see how these features work.

To control an images module from a Prop-1 controller, you use the SEROUT command to send data to the pin that the images is connected to. The data that you send must follow this format:

"!AP16", address, command {,data}

The string constant “!AP16” is the preamble that indicates that the command is intended for an images module. This allows you to chain different kinds of modules together with the images , making it possible to control all the modules used in a project from a single I/O pin.

The second data item is the address of the images module you want to send the command to. The possible values are 0, 1, 2, or 3. The address is set by a pair of jumpers on the images board. For the examples in this section, I assume the images address is 0.

The third data item is the command. Depending on the command used, you may also need to provide additional data after the command. The possible commands are:

Command

What It Does

X

Resets the images , which stops any sound that may be playing.

L

Sets the output volume.

PW

Plays a named file. Additional data provides the name of the file and the number of times to loop the file. (Specify 0 for the loop value to repeat the file indefinitely.)

G

Gets the current status of the images card. Use the SERIN command to read a single byte that indicates whether the images is currently playing a sound file and, if so, which sound file is being played.

PS

Plays one of the SFX nn .wav files. Additional data provides the SFX number (that is, the nn ) and the number of times the file should be looped. (Specify 0 for the loop value to repeat the file indefinitely.)

P?

Randomly selects one of the SFX nn .wav files to play.

PA

Plays one of the AUX nn .wav files. Additional data provides the SFX number (that is, the nn ) and the number of times the file should be looped. (Specify 0 for the loop value to repeat the file indefinitely.)

S

Changes the playback speed.

V

Gets the images version information. The version information can be read with a SERIN command.

The four images commands you’ll use most are X, to reset the sound player and stop any sound that may be playing; L to set the output volume; PW, to play a specific file; and G, to get the current status of the images so you can find out if it has finished playing a sound file. These commands are described in the following sections.

Note that throughout these sections, I assume that the following symbols have been defined near the top of the program:

SYMBOL Sio = 7
SYMBOL Baud = OT2400
SYMBOL AP16 = 0

Resetting the images

To reset the images , send an X command like this:

SEROUT Sio, Baud, ("!AP16", AP16, "X")

This causes any WAV file that may be playing to immediately stop. Not only is it a good idea to send this command at the beginning of your program to make sure that the images is ready to receive commands, but this command is also the best way to silence the images if you want to stop it before the current file finishes playing.

Changing the volume

If you want, you can change the output volume from your program. This is useful if you want to play a file at less than full volume. It’s also useful if you want the sound output to come from one side of the room or the other.

To change the output volume, use the L command. The syntax of the L command is this:

"!AP16", address , "L", left , right

Where left and right are values between 0 and 100 that indicate the percentage volume for the left and right outputs, respectively.

For example, to set the output volume to 50% for both left and right, use this statement:

SEROUT Sio, Baud, ("!AP16", AP16, "L", 50, 50)

To make the sound come exclusively from the left channel, use this:

SEROUT Sio, Baud, ("!AP16", AP16, "L", 100, 0)

To restore the sound to full volume, use this statement:

SEROUT Sio, Baud, ("!AP16", AP16, "L", 100, 100)

Playing a specific file

To play a specific WAV file, use the PW command. Here’s the syntax:

"!AP16", address , "PW", name, 13, loops

The name parameter is the name of the file, without the .wav extension. The 13 is required because of a quirk in the way the images programming works. Think of it as a good luck charm!

The loops parameter indicates how many times the file should be repeated. Normally, you’ll just specify 1 to play the file once. The maximum is 255, but specify 0 if you want the file to keep playing forever — or at least until you reset the images with an X command or use another PW command to play a different file.

Here’s the command to play a file named scream1.wav just once:

SEROUT Sio, Baud, ("!AP16", AP16, "PW", "SCREAM1", 13, 1)

Here’s a command that plays the file weasel.wav indefinitely:

SEROUT Sio, Baud, ("!AP16", AP16, "PW", "WEASEL", 13, 0)

Note that whenever you play a sound file, any other sound file that happens to be playing is immediately stopped. Thus, you don’t have to wait for one sound file to end to play another.

Waiting for a file to finish playing

When you play a sound file, you will often want your program to wait until the sound file finishes playing. You could do that with a PAUSE command if you know exactly how long the sound is. But what if you aren’t sure?

Fortunately, the images includes a G command that gets the current status of the card. To use this command, you must first send the G command to the images with a SEROUT statement. Then, you must retrieve the status result by using a SERIN statement.

The SERIN statement is pretty straightforward: Its syntax looks like this:

SERIN pin, mode, variable

The pin and mode parameters are the same as for the SEROUT statement. The variable parameter is simply the name of a variable you have set aside to receive the status result.

Here’s how you can use the SEROUT and SERIN statements together to get the status of an images :

SYMBOL ap16Status B0
SEROUT Sio, AP16, ("!AP16", AP16, "G")
SERIN Sio, AP16, ap16Status

In this example, the SYMBOL statement equates the name ap16status with the variable B0. Then, the SEROUT statement sends a G command to the images and the SERIN statement retrieves the status data in the variable named ap16Status.

The status data includes a variety of useful information, but in nearly every case the only thing you really want to know is whether the images is currently playing a sound. You can find that out by testing bit 7 of the status byte. The easiest way to do that is to define a symbol using the Basic Stamp’s predefined bit-variables, as in this example:

SYMBOL ap16Status = B0
SYMBOL ap16Playing = BIT7

Then, you can simply test the ap16Playing variable, like this:

IF ap16Playing = 0 THEN SoundDone

This statement will branch to the label SoundDone if the images has finished playing the sound.

Here is a complete snippet of code that plays a sound and then locks itself in a loop until the sound is finished playing:

SEROUT Sio, Baud, ("!AP16", AP16, "PW", "SCREAM", 13, 1)
StillPlaying:
SEROUT Sio, Baud, ("!AP16", AP16, "G")
SERIN Sio, Baud, ap16Status
IF ap16Playing = 0 THEN SoundDone
GOTO StillPlaying
SoundDone:
‘The sound is done!

A sample images program

Listing 3-2 shows a complete PBASIC program that plays sounds on an images card. The program plays the sound weasel.wav for 10 seconds, and then plays the scream.wav sound until that sound ends. Then it repeats. You can download this program from this book’s companion website.

LISTING 3-2 An images Program

΄ {$STAMP BS1}
΄ {$PBASIC 1.0}

SYMBOL Sio = 7
SYMBOL Baud = OT2400

SYMBOL AP16 = 0
SYMBOL ap16Status = B0
SYMBOL ap16Playing = BIT7


΄Reset the card
SEROUT Sio, Baud, ("!AP16", AP16, "X")

Main:

΄Play Pop Goes the Weasel
SEROUT Sio, Baud, ("!AP16", AP16, "PW", "WEASEL", 13, 0)


΄Wait 10 seconds
PAUSE 10000


΄Play the scream
SEROUT Sio, Baud, ("!AP16", AP16, "PW", "SCREAM", 13, 1)

΄Wait for the scream to end
StillScreaming:
SEROUT Sio, Baud, ("!AP16", AP16, "G")
SERIN Sio, Baud, ap16Status
IF ap16Playing = 1 THEN StillScreaming

΄Do it again
GOTO Main

Programming the PIR Motion Detector

The PIR sensor uses infrared light to detect motion. It sends a 1 to the microcontroller when such motion is detected.

At first glance, then, you would think that the PIR sensor is pretty easy to use. Just plug it into one of the Basic Stamp’s I/O pins and wait for that pin to have a value of 1 to trigger your prop. The code would look something like this, assuming that Pir is a symbol assigned to the I/O pin that the PIR is connected to:

WaitForMovement:
IF Pir = 0 THEN WaitForMovement

MovementDetected:
‘Activate your prop now!

Unfortunately, life isn’t that easy where PIR motion detection is concerned. For starters, the PIR won’t be reliable for a while when power is first applied. Thus, any program that uses a PIR to detect motion should start with an immediate 60-second pause. This gives the PIR time to settle down so it can reliably detect motion.

Second, the PIR will often send very brief false triggers when there’s no actual motion present in the room. The usual way to get around this problem is to wait until the PIR’s value is 1 for a quarter of a second before triggering your prop.

You can do this with a tricky bit of code:

SYMBOL Pir = PIN6
SYMBOL waitTimer = B2

PAUSE 60000
Main:
waitTimer = 0

WaitForMotion:
PAUSE 10
waitTimer = waitTimer + Pir * Pir
IF waitTimer < 25 THEN WaitForMotion

'The PIR has detected motion for 0.25 seconds
'so the prop can now be triggered

The cleverness in this bit of code is that the WaitForMotion loop pauses for 10 milliseconds, then adds the value of the PIR input status to the waitTimer variable while at the same time multiplying the result by the status of the PIR input. If the PIR input is 0, multiplying by the input status resets the waitTimer variable to 0 because any number times zero is zero. So this loop won’t exit until the PIR has detected motion consistently for a quarter of a second.

Looking at Complete Jack-in-the-Box Program

Now that you’ve seen the techniques for programming the individual components of the prop controller, put them together to create a program for an actual prop. Listing 3-3 shows the complete program for the jack-in-the-box prop. I made liberal use of comments throughout this program, so you should have no trouble following its basic operation. (The program is available for download at this book’s companion website.)

LISTING 3-3 The Jack-in-the-Box Program

' {$STAMP BS1}
' {$PBASIC 1.0}


' Jack-in-the-Box Program
'
' The following devices are connected to the prop controller for this prop
'
' Pin 6 PIR Sensor
'
' Pin 7 RC-4 Address %00
' AP-16+ Address %00
'
' RC-4 Relay 1 Pneumatic Solenoid Valve to open prop
' Light to illuminate clown
'
' RC-4 Relay 2 Motor to turn crank handle
'
'
' AP-16+ Sound Files
'
' WEASEL.WAV Pop Goes the Weasel to be played while motor is running
' SCREAM.WAV Scream to play when clown pops up


' The action of the prop is as follows:
'
' Turn the crank arm motor and play "Pop Goes the Weasel" until
' motion is detected in the room.
'
' When motion is detected, pop up the clown and play the scream sound.
'
' When the scream sound ends, retract the clown, wait 2 seconds,
' and then resume the crank motor and "Pop Goes the Weasel."
'
' Wait at least 10 seconds before triggering the prop again.



SYMBOL Sio = 7
SYMBOL Baud = OT2400

SYMBOL RC4 = 3
SYMBOL RelayValve = 1
SYMBOL RelayMotor = 2

SYMBOL RelayOn = 1
SYMBOL RelayOff = 0

SYMBOL AP16 = 0
SYMBOL ap16Status = B0
SYMBOL ap16Playing = BIT7

SYMBOL Pir = PIN6
SYMBOL waitTimer = B2



'Reset everything & pause one minute to let the PIR stabilize.
SEROUT Sio, Baud, ("!AP16", AP16, "X")
SEROUT Sio, Baud, ("!RC4", RC4, "X")
PAUSE 50000

Main:

'Play Pop Goes the Weasel in an indefinite loop.
SEROUT Sio, Baud, ("!AP16", AP16, "PW", "WEASEL", 13, 0)

'Start the motor.
SEROUT Sio, Baud, ("!RC4", RC4, "R", RelayMotor, RelayOn)

'Wait 10 seconds for the room to clear.
PAUSE 10000

'Wait for the PIR to trigger for 0.25 seconds.
waitTimer = 0
WaitForMotion:
PAUSE 10
waitTimer = waitTimer + Pir * Pir
IF waitTimer < 25 THEN WaitForMotion

'At this point the trigger has been activated.

'Stop the motor.
SEROUT Sio, Baud, ("!RC4", RC4, "R", RelayMotor, RelayOff)

'Play the scream.
SEROUT Sio, Baud, ("!AP16", AP16, "PW", "SCREAM", 13, 1)

'Pop up the clown.
SEROUT Sio, Baud, ("!RC4", RC4, "R", RelayValve, RelayOn)

'Wait for the scream to end.
StillScreaming:
SEROUT Sio, Baud, ("!AP16", AP16, "G")
SERIN Sio, Baud, ap16Status
IF ap16Playing = 1 THEN StillScreaming

'Retract the clown.
SEROUT Sio, Baud, ("!RC4", RC4, "R", RelayValve, RelayOff)

'Wait 2 seconds.
PAUSE 2000

'Do it again.
GOTO Main