Wicked Beernut Home - Halloween Home
Beginner's Guide to Haunting with a Stamp Microcontroller

Acronyms
|
AC |
Alternating Current |
|
BASIC |
Beginner's All-Purpose Symbolic Instruction Code |
|
BS1 |
BASIC Stamp 1 |
|
BS2 |
BASIC Stamp 2 |
|
BS2E |
BASIC Stamp 2E |
|
BS2SX |
BASIC Stamp 2SX |
|
DC |
Direct Current |
|
DOS |
Disk Operating System |
|
DVR |
Digital Voice Recorder |
|
EEPROM |
Electronically Erasable Programmable Read-Only Memory |
|
LED |
Light Emitting Diode |
|
PBASIC |
Parallax BASIC |
|
PIR |
Passive Infrared |
|
RAM |
Random Access Memory |
|
SSR |
Solid State Relay |
The BASIC stamp is a microcontroller developed by Parallax, Inc. which is easily programmed using a simplified, but customized form of the BASIC (beginners all-purpose symbolic instruction code) programming language, called PBASIC. It is called a "stamp" because it is close to the size of an average postage stamp.
There are fundamentally two BASIC stamp microcontrollers: the BS1 (BASIC stamp 1); and the BS2 (BASIC stamp 2). The following table summarizes a few of the differences between the BS1 and the BS2.
|
Feature |
BS1 |
BS2 |
|
Speed (MHz / instructions per second) |
4 MHz / 2,000 |
20 MHz / 4,000 |
|
EEPROM (bytes) |
256 |
2K |
|
Program Length (lines of PBASIC) |
80 - 100 |
500 |
|
RAM Variables (bytes) |
16 |
32 |
|
Inputs / Outputs |
8 |
16 |
|
PC Interface |
Parallel port |
Serial port |
Note that there are actually several flavors of the BS2 including the BS2SX (BASIC Stamp 2SX) and the BS2E (BASIC Stamp 2E). The BS2SX executes at 50 MHz. The BS2E and the BS2SX both have eight 2K program spaces.
The stamp microcontroller has pins that can be programmed to monitor inputs or to control outputs. The most important difference between the BS1 and the BS2 is the number of inputs/outputs. The BS1 has eight inputs/outputs, the BS2 has 16. In most haunt applications, a microcontroller will be dedicated to a single prop and most props can be monitored and controlled using eight or fewer inputs/outputs.
The BS2 is at least twice as fast as the BS1, but the speed of the BS1 is more than adequate for most haunt applications.
EEPROMs provide non-volatile storage for your PBASIC program (your program is retained in memory even when the power is removed). The BS2 has at least eight times as much EEPROM as the BS1, but the BS1's EEPROM is more than adequate for most haunt applications.
The BS2 has a more robust PBASIC instruction set compared to the BS1, but the BS1's PBASIC instruction set is more than adequate for most haunt applications.
The BS2 is much easier to program than the BS1. The BS2 compiler automatically assigns variables to its RAM as where the programmer must manually assign variables to RAM in the case of the BS1. We can live with this shortcoming of the BS1 since the programs that control most haunt applications are relatively simple. Manually assigning variables to RAM in this case is straightforward.
There are two other factors that led me to the BS1 and specifically, the First Step microcontroller by Lynxmotion: cost; and packaging.
The BS2 starts at around $50 and typically requires a separate carrier board, further adding to the cost. The First Step microcontroller is an integrated BS1 and carrier board. All of the BS1 pins (inputs, outputs, power, ground, reset, …) are accessible via header posts. You can plug Hitec and Futaba servo motors directly into the first four output pins of the First Step microcontroller. The First Step microcontroller has a RJ11 connector that conveniently connects the BS1 to the parallel port of your PC for programming and debug.
Lynxmotion sells the First Step microcontroller kit for $40. The First Step is a kit that requires intermediate soldering skills. Lynxmotion will sell assembled kits for $45. I purchased a few assembled kits from Lynxmotion. I also purchased a few unassembled kits from Mondo-Tronics' Robot Store. Mondo-Tronics normally sells the First Step kit (unassembled) for $40, but has sold the unassembled kit for as low as $32. Mondo-Tronics does not sell an assembled version of the kit.
Stamp Documentation
Stamp documentation is available for free on the Parallax, Inc. website. From the Parallax homepage, click on Downloads. From the Downloads page, click on BASIC Stamp Documentation. My only stamp reference is the 354 page "BASIC Stamp Manual, Version 2.0c".
Stamp Software
Stamp software is available for free on the Parallax, Inc. website. From the Parallax homepage, click on Downloads. From the Downloads page, click on BASIC Stamp Software. The "BASIC Stamp I editor for DOS" is used with the First Step microcontroller.
Stamp Interfacing
The First Step microcontroller programming cable can be purchased from Lynxmotion (part number DB25-01, $6.00) or you can make your own from the instructions in the assembly manual included with the First Step microcontroller. You can use a Radio Shack 25-Pin D-sub to modular phone jack adapter (276-1405, $3.99) or a modular/EIA adapter kit (276-1405A, $3.99) and a 6' four-conductor modular line (telephone) cord (279-347, $4.29). The wiring is shown below.

I would highly recommend the connector kit (part number CK-01, $23.00) from Lynxmotion. The connector kit includes a crimping tool, 50 female crimp pins, six assorted colors of 24 gauge wire and 3/32" heat shrink tubing. These connectors make it easy to route the signals from the 0.1" spaced, 0.025" square header posts that are on the First Step microcontroller.
-
-
The First Step microcontroller is powered using a nine volt battery or a nine volt AC adapter. Four AA, C or D batteries or a six volt AC adapter provide power to the servo motors (if present).

Stamp Programming
For most haunt applications, the programmer will need to understand,
Memory Organization
Basic Constructs (IF..THEN, FOR..NEXT, GOTO, LOOKUP, BRANCH)
Outputs (OUTPUT, LOW, HIGH, TOGGLE)
Inputs (INPUT)
Time Delays (PAUSE)
Note that the syntax in the following sections is specific to the BS1. All of the programs can easily be converted to the BS2 syntax. Appendix A includes a table that summarizes the BS1 to BS2 conversions corresponding to the subset of the BS1 instruction set utilized as part of this guide.
Memory Organization
Your program will need to store variables (counters, timers, …) in RAM (random access memory). The BS1 has seven words (W0 - W6) of RAM that are available for general-purpose use. These word registers can also be addressed as 14 bytes (B0 - B13). W0 (B0 and B1) are also bit-addressable meaning that the program can directly manipulate individual bits of the word (bytes).
Table 1. BS1 RAM Organization.
|
Word Name |
Byte Names |
Bit Names |
Special Notes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A byte consists of eight bits and is capable of storing values in the range of 0 - 255. A word consists of two bytes (or sixteen bits) and is capable of storing values in the range of 0 - 65,535.
Symbolic names (or simply symbols) can be assigned to the registers. For example,
SYMBOL counter = B0
assigns the symbol counter to the byte register B0.
SYMBOL timer = W1
assigns the symbol timer to the word register W1.
The use of symbols tends to make your program more readable.
The IF..THEN command evaluates the Condition and if the Condition is true (non-zero), goes to the point in the program marked by Address,
IF
Condition THEN Addresswhere,
Condition
is a statement that can be evaluated as true (non-zero) or false (zero).Address
is a label that specifies where to go in the event that Condition is true.FOR..NEXT Command
The FOR..NEXT command creates a repeating loop that executes the program lines between FOR and NEXT, incrementing or decrementing the Counter according to the StepValue until the value of the Counter variable passes the EndValue.
FOR
Counter = StartValue TO EndValue {STEP {-} StepValue}NEXT
{Counter}where,
Counter
is a variable that counts the number of iterations through the FOR..NEXT loop.StartValue
is a variable or constant with a range of 0 - 65,535 that specifies the initial value of the Counter.EndValue
is a variable or constant with a range of 0 - 65,535 that specifies the final value of the Counter.StepValue
is an optional variable or constant with a range of 0 - 65,535 by which the Counter is incremented or decremented with each iteration through the FOR..NEXT loop. If the StartValue is greater than the EndValue, the StepValue is preceded with a minus sign (-).GOTO Command
The GOTO command goes to the point in the program specified by Address,
GOTO Address
where,
Address
is a label that specifies where to go.LOOKUP Command
An array variable (or simply an array) is a group of variables having the same name that can be accessed using an index. The BS1 doesn't support array variables, but the LOOKUP command may be the next best thing. The LOOKUP command stores the Value corresponding to the Index in the Variable,
LOOKUP Index, (Value0, Value1, .., ValueN), Variable
where,
Index
is a variable or constant with a range of 0 - 255 that indicates the Value in the list to be stored in the Variable. An Index of zero stores Value0, an Index of one stores Value1, and so on.Values
are variables or constants with a range of 0 - 65,535.Variable
is a variable that will be set to the Value corresponding to the Index. If the Index exceeds the highest Value number, N, the Variable is left unaffected.BRANCH Command
The BRANCH command jumps to the Address (label) corresponding to the Index,
BRANCH Index, (Address0, Address1, .., AddressN)
where,
Index
is a variable or constant with a range of 0 - 255 that indicates the Address in the list to jump to. An Index of zero jumps to Address0, an Index of one jumps to Address1, and so on.Addresses
are labels that specify where to jump to. If the Index exceeds the highest Address number, N, the BRANCH command does nothing and the program continues with the instruction following the BRANCH command.Outputs
OUTPUT Command
The OUTPUT command sets the specified pin to output mode,
OUTPUT
Pinwhere,
Pin
is a variable or constant with a range of 0 - 7.LOW Command
The LOW command sets the specified pin to output mode and sets the output of the specified pin low (zero volts),
LOW
Pinwhere,
Pin
is a variable or constant with a range of 0 - 7.HIGH Command
The HIGH command sets the specified pin to output mode and sets the output of the specified pin high (five volts),
HIGH Pin
where,
Pin
is a variable or constant with a range of 0 - 7.TOGGLE Command
The TOGGLE command sets the specified pin to output mode and inverts (high-to-low or low-to-high) the state of the specified pin,
TOGGLE Pin
where,
Pin
is a variable or constant with a range of 0 - 7.For example,
SYMBOL PROP1_OUT = 0
assigns the constant value zero to the symbol name PROP1_OUT.
OUTPUT PROP1_OUT
sets pin zero to output mode.
HIGH PROP1_OUT
sets output pin zero high (five volts).
LOW PROP1_OUT
sets output pin zero low (zero volts).
TOGGLE PROP1_OUT
inverts output pin zero low-to-high (five volts).
Inputs
INPUT Command
The INPUT command makes the specified pin an input pin,
INPUT
Pinwhere,
Pin
is a variable or constant with a range of 0 - 7.For example,
SYMBOL PROP1_IN = PIN0
defines an alias PROP1_IN for PIN0.
INPUT 0
sets pin zero to input mode.
START:
IF PROP1_IN = 0 THEN START
test if input pin zero is low (zero volts).
Time Delays
PAUSE Command
The PAUSE command halts the execution of the program for the specified Period,
PAUSE Period
where,
Period
is a variable or constant and is specified in milliseconds with a range of 0 - 65,535.For example,
PAUSE
1000halts the execution of the program for 1,000 milliseconds (or one second). In order to halt the execution of the program for periods greater than 65.535 seconds, the PAUSE command can be nested in a FOR..NEXT loop. The following example halts the execution of the program for five minutes,
SYMBOL minutes = B0
SYMBOL seconds = B1
FOR minutes = 1 TO 5
FOR seconds = 1 TO 60
PAUSE 1000
NEXT seconds
NEXT minutes
Timers
Basic vs. Input-Driven
I define a basic timer as a timer that unconditionally and repeatedly executes a series of steps (two or more) with each successive step toggling (high-to-low and low-to-high) the state of an output. Each step has a unique period that determines how long the output will be held in the current state (high or low).
I define an input-driven timer as a timer that conditionally begins executing a series of steps based on the state of an input.
Dual vs. Multi-Step
I define a dual timer as a timer that involves two steps.
I define a multi-step timer as a timer that involves four or more steps. I restrict the number of steps to be even.
Basic Dual Timer
This program utilizes a BS1 to realize a single basic dual timer. This program unconditionally and repeatedly sets output pin zero high (on) for ten seconds and low (off) for twenty seconds.
PBASIC constant, symbol, variable and alias names are case-insensitive. The convention used here is to assign constants, symbols and aliases using uppercase letters and variables using lower-case letters.
The use of the prefix PROPx_ and propx_ and the symbol PROPx is arbitrary. A more meaningful name can be substituted for PROPx such as,
The basic dual timer is implemented using one constant,
PROPx_OUT
PROPx_OUT is a constant corresponding to the output pin (0, 1, .., 7).
SYMBOL PROPx_OUT = y
where y = 0 - 7.
Input-Driven Dual Timer
This program utilizes a BS1 to realize a single input-driven dual timer. This program conditionally sets output pin one high (on) for ten seconds and low (off) for twenty seconds based on input pin zero being high (on).
The input-driven dual timer is implemented using one alias,
PROPx_IN
and one constant,
PROPx_OUT
PROPx_IN is an alias for the input pin (PIN0, PIN1, .., PIN7) corresponding to PROPx,
SYMBOL PROPx_IN = PINy
where y = 0 - 7.
PROPx_OUT
is described above.Restructured Basic Dual Timer
This program is identical in terms of functionality to the basic dual timer, however we've begun to make some of the infrastructure changes that will be required for a BS1 to service multiple timers. In particular, notice that the code has been organized into a block and that the PAUSE command is outside of this block.
The execution of the program is halted for one second after all of the timer blocks have been executed. Variables are used to keep track of the current step and the amount of time (in seconds) that has elapsed corresponding to the current step.
The restructured basic dual timer is implemented using one constant,
PROPx_OUT
and four variables,
propx_step
propx_timer
time
prop
PROPx_OUT is described above.
propx_step
is a variable that keeps track of the current step. For a dual (two-step) timer, propx_step can be assigned to a bit register (BIT0, BIT1, .., BIT7).SYMBOL propx_step = BITy
where y = 0 - 7. For a multi-step timer, propx_step can be assigned to a byte register (B0, B1, .., B13).
SYMBOL propx_step = By
where y = 0 - 13.
propx_step
will contain the value zero corresponding to the first step, one corresponding to the second step, and so on.propx_timer
is a variable that keeps track of the time (in seconds) that have elapsed corresponding to the current step.SYMBOL propx_timer = By
where y = 0 - 13. propx_timer is represented using a byte register in order to store step times of up to,
255 x 1 sec = 255 sec = ~4 mins
The LOOKUP command is used to access the time value corresponding to each step associated with a particular prop.
LOOKUP propx_step, (m, n), time
where m and n are the time values corresponding to step one (propx_step = 0) and step two (propx_step = 1), respectively. m and n are expressed in terms of seconds.
time
is a variable that is used to store the value corresponding to a particular step associated with a particular prop.SYMBOL time = W5
time is represented using a word register in order to store step times of up to,
65,535 x 1 sec = 65,535 sec = ~1092 mins = ~18 hrs
The size of the register used to store the timer corresponding to a particular prop will determine the maximum step time for that prop.
prop
is a variable that keeps track of the prop currently be serviced.SYMBOL prop = B13
prop contains the value zero corresponding to the first prop, one corresponding to the second prop, and so on.
The timer block jumps to NEXT_PROP upon completion. NEXT_PROP uses the prop variable in conjunction with the BRANCH command in order to determine which PROPx label to jump to next.
TIME_DELAY:
PAUSE 1000
NEXT_PROP:
prop = prop + 1
BRANCH prop, (PROP1, PROP2, .., TIME_DELAY)
prop = 0
GOTO PROP1
After the last prop is serviced, NEXT_PROP jumps to TIME_DELAY, the program pauses one second, the prop variable is incremented by one, the BRANCH command falls through, the prop variable is initialized to zero and we jump to the label corresponding to PROP1.
One of the best ways to understand a program is to create a table that shows the state changes of all the inputs, outputs, delays and variables.
|
Variable |
State |
||||||||||||||||||||||||
|
PROP1_OUT |
1 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
0 |
|
|
|
prop1_step |
0 |
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
1 |
|
|
prop1_timer |
0 |
1 |
|
|
2 |
|
1 |
|
|
|
2 |
|
|
3 |
|
1 |
|
|
|
2 |
|
1 |
|
|
|
|
time |
0 |
|
1 |
|
|
1 |
|
|
|
|
|
2 |
|
|
2 |
|
|
|
|
|
1 |
|
|
|
|
|
prop |
0 |
|
|
1 / 2 / 0 |
|
|
|
|
|
1 / 2 / 0 |
|
|
1 / 2 / 0 |
|
|
|
|
|
1 / 2 / 0 |
|
|
|
|
|
1 / 2 / 0 |
|
PAUSE 1000 |
|
|
|
X |
|
|
|
|
|
X |
|
|
X |
|
|
|
|
|
X |
|
|
|
|
|
X |
Restructured Input-Driven Dual Timer
Again, this program is identical in terms of functionality to the input-driven dual timer, however we've begun to make some of the infrastructure changes that will be required for a BS1 to service multiple timers. In addition to support for multiple timers, these changes will allow a BS1 to support multiple steps per timer.
Note that in the case of the input-driven timer, the execution of the program is halted for 100 milliseconds (as opposed to one second in the case of the basic timer) after all of the timer blocks have been executed. This is to ensure that the timer doesn't miss a change in the state of the input pin.
The restructured input-driven dual timer is implemented using one alias,
PROPx_IN
two constants,
PROPx_OUT
PROPx_MAX_STEPS
and five variables,
propx_step
propx_timer
time
prop
next_step
PROPx_IN, PROPx_OUT, propx_step, time and prop are described above.
propx_timer
is a variable that keeps track of the time (in hundreds of milliseconds) that has elapsed corresponding to a particular step.SYMBOL propx_timer = Wy
where y = 0 - 6. propx_timer is represented using a word register in order to store step times of up to,
65,535 x 100 ms = 6,553,500 ms = ~6,553 sec = ~109 mins = ~2 hrs
The LOOKUP command is used to access the time value corresponding to each step associated with a particular prop.
LOOKUP propx_step, (m, n), time
where m and n are the time values corresponding to step one (propx_step = 0) and step two (propx_step = 1), respectively. m and n are expressed in terms of hundreds of milliseconds. For example,
n
= 200 = 200 x 100 ms = 20,000 ms = 20 secPROPx_MAX_STEPS
is a constant that corresponds to the maximum number of steps associated with a prop.SYMBOL PROPx_MAX_STEPS = n
where n = 0 - 1 for propx_step = BITy (bit register) and n = 0 - 255 for propx_step = By (byte register). PROPx_MAX_STEPS must be consistent with the size of the register (BITy or By) used to represent propx_step. PROPx_MAX_STEPS must be even (two, four, ..). This is a consequence of using the TOGGLE command to alter the state of the output pin. PROPx_MAX_STEPS must correspond to the number of values in the LOOKUP command.
next_step
is a variable that is used to calculate the next step from the current step.SYMBOL next_step = B12
Again, we look at the state changes of all the inputs, outputs, delays and variables in order to better understand the program.
|
Variable |
State |
|||||||||||||||||||||||||
|
PROP1_IN |
0 |
1/0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PROP1_OUT |
0 |
|
1 |
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
prop1_step |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
0 |
|
|
prop1_timer |
0 |
|
|
1 |
|
|
2 |
|
|
.. |
101 |
|
|
|
1 |
|
|
2 |
|
|
.. |
201 |
|
|
|
0 |
|
time |
0 |
|
|
|
100 |
|
|
100 |
|
|
|
100 |
|
|
|
|
|
|
200 |
|
|
|
200 |
|
|
|
|
prop |
0 |
|
|
|
|
1 / 2 / 0 |
|
|
1 / 2 / 0 |
|
|
|
|
|
|
|
1 / 2 / 0 |
|
|
1 / 2 / 0 |
|
|
|
|
|
|
|
next_step |
0 |
|
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
PAUSE 100 |
|
|
|
|
|
X |
|
|
X |
|
|
|
|
|
|
|
X |
|
|
X |
|
|
|
|
|
|
(Note that this section is slightly more advanced and can be skipped if your prop timing doesn't need to be extremely accurate)
The propx_timer variable counts the number of timer "ticks". With the restructured basic timer, our tick was one second (PAUSE 1000). For a step time of 60 seconds, the propx_timer variable counted,
60 ticks x 1 sec = 60 secs
With the restructured input-driven timer, our tick was 100 milliseconds (PAUSE 100). For a step time of 60 seconds, the propx_timer variable counted,
600 ticks x 100 ms = 60,000 ms = 60 secs
This calculation would be accurate if the amount of time that it took to execute the timer program instructions was zero. Of course, we know that this is not the case. The BS1 is capable of executing 2,000 instructions per second.
Let's count the number of instructions (we will assume one instruction per line) that are executed each time the propx_timer variable is incremented. With the restructured basic timer,
With the restructured input-driven timer,
And for the TIME_DELAY branch,
With a timer tick of one second, the time spent executing the timer program instructions is relatively insignificant. However, with a timer tick of 100 milliseconds the time spent executing the timer program instructions can add up.
For an input-driven timer with a step time of 60 seconds, there are seven instructions executed corresponding to each instance of the restructured input-driven timer and five instructions corresponding to the TIME_DELAY branch for a total of 12 instructions,
600 ticks x 12 instructions per tick / 2,000 instructions per sec = 3.6 secs
This means that our step time of 60 seconds will actually be 63.6 seconds, or in other words, skewed by 3.6 seconds.
If the accuracy of your prop timing is critical, we can actually adjust our tick time to compensate for the time spent executing the timer program instructions. For each restructured basic timer we can subtract,
5 instructions / 2,000 instructions per sec = 0.0025 sec = 2.5 ms
from the timer tick. For each restructured input-driven timer, we can subtract,
7 instructions / 2,000 instructions per sec = 0.0035 sec = 3.5 ms
and we can subtract,
5 instructions / 2,000 instructions per sec = 0.0025 sec = 2.5 ms
corresponding to the TIME_DELAY branch.
For a single basic timer, the 100 millisecond tick would be implemented as,
100 - 2.5 - 2.5 = 95
or,
PAUSE 95
For a single input-driven timer, the 100 millisecond tick would be implemented as,
100 - 3.5 - 2.5 = 94
or,
PAUSE 94
For eight basic timers, the 100 millisecond tick would be implemented as,
100 - (2.5 x 8) - 2.5 = 77.5
or,
PAUSE 77
For four input-driven timers, the 100 millisecond tick would be implemented as,
100 - (3.5 x 4) - 2.5 = 83.5
or,
PAUSE 83
For two input-driven timers and two basic timers, the 100 millisecond tick would be implemented as,
100 - (2.5 x 2) - (3.5 x 2) - 2.5 = 85.5
or,
PAUSE 85
Note that all of these values are approximations. For example, the number of instructions that are executed corresponding to an input-driven timer which is idle (3 instructions) is different than the number of instructions that are executed corresponding to an input-driven timer which is active (7 instructions). However, I think that you will find the accuracy is more than adequate for most haunt applications.
One last note. You can minimize the timer skew by increasing the timer tick (even in the case of the input-driven timer). For example, the PIR (passive infrared) movement detector mentioned later in this guide generates an output pulse one second long. There is no need to have a timer tick of 100 milliseconds if you are monitoring an event that is going to last for one second.
A BS1 is capable of functioning as up to eight basic timers, using all eight I/O pins as outputs. This program utilizes a BS1 to realize eight basic dual timers. Note that what we've done is simply take the basic dual timer block and replicate it eight times.
The following table summarizes how the program's constants and variables are mapped to the BS1's memory.
|
Word Name |
Byte Names |
Bit Names |
Special Notes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|
||
|
|
|
|
|
|||
|
|
||
|
|
||
|
|
||
A BS1 is capable of functioning as up to four input-driven timers, using four I/O pins as inputs and four I/O pins as outputs. This program utilizes the BS1 to realize four input-driven dual timers. Again, what we've done is simply take the input-driven dual timer block and replicate it four times.
The following table summarizes how the program's constants and variables are mapped to the BS1's memory.
|
Word Name |
Byte Names |
Bit Names |
Special Notes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
|
|
|
|
||
Basic and Input-Driven, Dual and Multi-Step Timers
The timer building blocks can be combined in different ways. This program utilizes a BS1 to realize one input-driven dual timer, one input-driven four-step timer and two basic dual timers.
The following table summarizes how the program's constants and variables are mapped to the BS1's memory.
|
Word Name |
Byte Names |
Bit Names |
Special Notes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
|
|
|
|
||
Controlling the World with your Stamp Microcontroller
Microcontrollers operate at logic-level voltages (five volts) and current (milliamps). The Real World operates at higher voltages (typically 12 - 240 volts) and current (amps). Paul Bergsman authored Controlling the World with your PC, a book that details how to control Real World devices using the parallel port of a personal computer. The same techniques can be applied to control the world using your stamp microcontroller. A SSR (solid-state relay) is used to bridge the logic-level world of the microcontroller with the Real World.
A SSR is an optically coupled switch. When the BS1's logic-level output voltage is applied to the SSR's input (or control) pins an LED inside the SSR is turned on. An optosensor within the SSR detects the light emitted by the LED and applies power to the output (or load) pins. The stamp microcontroller is optically isolated from the load. This means that the stamp microcontroller won't be subject to spikes, surges and shorts at the SSR's load.
The BS1 can source (generate) a maximum of 20 milliamps per output pin with the total for all of the pins not to exceed 40 milliamps. Most SSRs require five milliamps and therefore can be driven directly from the BS1's output pins.
I have successfully used the Crydom CX240D5, 12 - 280 volt AC, five amp SSR available from Digi-Key (part number CC1063-ND, $9.02).

Note that the CX240D5 is designed to be used with an AC (alternating current) load. The internal load circuitry is different for AC and DC (direct current) SSRs. Make sure to choose a SSR relay that is appropriate for your application.
Detecting Motion
The K76 PIR (passive infrared) movement detector module is an excellent choice for use with a stamp microcontroller. The K76 input power is rated at five to 10 volts DC and as such can be integrated directly with a stamp microcontroller.
Manufacturers Spec sheet, detailed
Essential specs on RE200B sensor
This kit is a fully assembled and tested miniature PIR module with only 3 connections: Power, Ground & Output. Rated for 5 - 10VDC input power. Output is an active high pulse of approximately 0.5 seconds and remains active as long as there is motion. Range up to 3 metres.
I've purchased K76 kits from Circuit Specialists, Inc. for $11.95. Go to their home page and search for "PIR".
Sound
I use a Radio Shack 20-second recording module (part number 276-1323, $9.99) in conjunction with a pair of amplified speakers to generate sounds (laughs, screams, ..). I refer to the Radio Shack 20-second recording module as a DVR (digital voice recorder).

An output pin of the BS1 must be wired to the play button of the DVR. The play button is removed by lifting the two small metal taps on the underside of the circuit board. Removing the play button will reveal a pair of traces on the top of the circuit board.

You can solder a wire to each of the traces. I opted to drill a pair of small holes in the circuit board (as indicated by the dots in the above picture) and solder a header post into each of the holes. You must ensure that the solder forms a good contact between the post and the trace without shorting (soldering together) the two traces. The header posts of the DVR can then be wired to the output pin of the BS1 using a pair of 24 gauge wires with crimp connectors on either end.
I removed the condenser-type speaker/microphone from the DVR by cutting the wires close to the speaker/microphone using a pair of wire cutters. I soldered the wires to a 1/8" phono jack.
I record sounds on the DVR by connecting the 1/8" phono jack of the DVR to the 1/8" headphone jack of my PC using a 1/8" phono plug to 1/8" phono plug cable. You could use other sound sources including a PC sound card, a CD player or a cassette player.
After you are done recording your sound, the amplified speakers plug into the 1/8" phono jack of the DVR. I've experienced good results using amplified speakers costing as little as $3 a pair.
The DVR is wired to an output pin and the corresponding ground pin of the BS1. The BS1 triggers the DVR by setting the output pin low and then high,
SYMBOL DVR = 0
OUTPUT DVR
LOW DVR
HIGH DVR
If the BS1 does not trigger the DVR, try reversing the wires to the output and ground pin.
Prop Programs
Most prop programs will be based on the basic dual timer or the input-driven dual timer. For example, this program controls a Grave Jumper,
At the time the BS1 is powered on or reset, the program,
HIGH READY
PAUSE PROP_READY
LOW READY
START:
IF PIR = 0 THEN START
Upon detecting movement, the program,
HIGH LIFTER
LOW DVR
HIGH DVR
FOR TIMER = 1 TO 40
HIGH FLASHER
PAUSE 50
LOW FLASHER
PAUSE 50
NEXT TIMER
LOW LIFTER
PAUSE CYCLE
GOTO START
From looking at this program, hopefully you can see how it could be used (with only minor modifications) to control a multitude of different props.
Appendix A
The following table summarizes the BS1 to BS2 conversion corresponding to the subset of the BS1 instruction set utilized as part of this guide.
|
BS1 |
BS2 |
|
SYMBOL SymbolValue = BIT0..BIT15 |
SymbolValue VAR BIT |
|
SYMBOL SymbolValue = B0..B13 |
SymbolValue VAR BYTE |
|
SYMBOL SymbolValue = W0..W6 |
SymbolValue VAR WORD |
|
SYMBOL SymbolValue = ConstantValue |
SymbolValue CON ConstantValue |
|
SYMBOL SymbolValue = PIN0..PIN7 |
SYMBOL SymbolValue = IN0..IN7 |
|
LOOKUP Index, (Value0, Value1, .., ValueN), Variable |
LOOKUP Index, [Value0, Value1, .., ValueN], Variable |
|
BRANCH Index, (Address0, Address1, .., AddressN) |
BRANCH Index, [Address0, Address1, .., AddressN] |
For a complete BS1 to BS2 conversion guide refer to,
BASIC Stamp I and Stamp II Conversions