Wicked Beernut Home - Halloween Home

Beginner's Guide to Haunting with a Stamp Microcontroller

E-mail: wbn@wickedbeernut.com

 

Introduction

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

PORT
PINS
DIRS
PIN0 - PIN7
DIR0 - DIR7
I/O pins; bit addressable.
I/O pins directions; bit addressable.
W0
B0
B1
BIT0 - BIT7
BIT8 - BIT15
Bit addressable.
Bit addressable.
W1
B2
B3
 
 
W2
B4
B5
 
 
W3
B6
B7
 
 
W4
B8
B9
 
 
W5
B10
B11
 
 
W6
B12
B13
 
 

 

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.

Basic Constructs

IF..THEN Command

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 Address

where,

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 Pin

where,

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 Pin

where,

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 Pin

where,

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 1000

halts 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.

TB2SX1A.bas

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,

COFFIN_OUT
FOGGER_OUT
POPUP_OUT
..

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).

TI2SX1A.bas

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.

TB2SX1B.bas

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

 

 

 

 

 

 

 

 

 

 

 

 

 

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.

TI2SX1B.bas

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 sec

PROPx_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

 

 

 

 

 

 

 

Timer Skew

(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,

  1. propx_timer = propx_timer + 1
  2. LOOKUP propx_step, (600, 600), time
  3. IF propx_timer <= time THEN NEXT_PROP
  4. prop = prop + 1
  5. BRANCH prop, (PROP1, PROP2, .., TIME_DELAY)

With the restructured input-driven timer,

  1. IF PROPx_IN = 0 AND propx_timer = 0 THEN NEXT_PROP
  2. IF propx_timer > 0 THEN PROPx_RUNNING
  3. propx_timer = propx_timer + 1
  4. LOOKUP propx_step, (600, 600), time
  5. IF propx_timer <= time THEN NEXT_PROP
  6. prop = prop + 1
  7. BRANCH prop, (PROP1, PROP2, .., TIME_DELAY)

And for the TIME_DELAY branch,

  1. PAUSE 100
  2. prop = prop + 1
  3. BRANCH prop, (PROP1, PROP2, .., TIME_DELAY)
  4. Prop = 0
  5. GOTO PROP1

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.

Eight Basic Dual Timers

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.

TB2SX8.bas

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

PORT
PINS
PIN0 - PIN7
PROP1_OUT, PROP2_OUT, PROP3_OUT, PROP4_OUT, PROP5_OUT, PROP6_OUT, PROP7_OUT, PROP8_OUT
DIRS
DIR0 - DIR7
I/O pins directions; bit addressable.
W0
B0
BIT0 - BIT7
prop1_step, prop2_step, prop3_step, prop4_step, prop5_step, prop6_step, prop7_step, prop8_step
B1
prop1_timer
W1
B2
prop2_timer
B3
prop3_timer
W2
B4
prop4_timer
B5
prop5_timer
W3
B6
prop6_timer
B7
prop7_timer
W4
B8
prop8_timer
B9
W5
time
W6
B12
B13
prop

 

Four Input-Driven Dual Timers

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.

TI2SX4.bas

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

PORT
PINS
PIN0 - PIN7
PROP1_IN, PROP2_IN, PROP3_IN, PROP4_IN, PROP1_OUT, PROP2_OUT, PROP3_OUT, PROP4_OUT
DIRS
DIR0 - DIR7
I/O pins directions; bit addressable.
B0
BIT0 - BIT7
prop1_step, prop2_step, prop3_step, prop4_step
B1
W1
prop1_timer
W2
prop2_timer
W3
prop3_timer
W4
prop4_timer
W5
time
W6
B12
next_step
B13
prop

 

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.

TINSX4.bas

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

PORT
PINS
PIN0 - PIN7
PROP1_IN, PROP2_IN, PROP1_OUT, PROP2_OUT, PROP3_ OUT, PROP4_OUT
DIRS
DIR0 - DIR7
I/O pins directions; bit addressable.
W0
B0
BIT0 - BIT7
prop1_step, prop3_step, prop4_step
B1
prop2_step
W1
prop1_timer
W2
prop2_timer
W3
prop3_timer
W4
prop4_timer
W5
time
W6
B12
next_step
B13
prop

 

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

RE200B PIR Sensor

Essential specs on RE200B sensor

Movement IC Specs - page 1

Movement IC Specs - page 2

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,

jumper.bas

At the time the BS1 is powered on or reset, the program,

  1. Flashes a green LED for 30 seconds indicating to the haunter that the microcontroller is in control and that it is safe to connect the compressed air.
  2. HIGH READY

    PAUSE PROP_READY

    LOW READY

  3. Monitors a PIR for movement.
  4. START:

    IF PIR = 0 THEN START

    Upon detecting movement, the program,

  5. Turns a SSR on in order to apply power to a solenoid valve that in turn reverses the flow of compressed air to a double-acting air cylinder that in turn lifts a four-bar linkage.
  6. HIGH LIFTER

  7. Triggers a DVR to emit a load scream through a pair of amplified speakers.
  8. LOW DVR

    HIGH DVR

  9. Flashes a 100 watt light bulb by turning a SSR on and off every 50 milliseconds for four seconds.
  10. FOR TIMER = 1 TO 40

    HIGH FLASHER

    PAUSE 50

    LOW FLASHER

    PAUSE 50

    NEXT TIMER

  11. Turns the SSR off in order to remove power from the solenoid valve that in turn reverses the flow of compressed air to the double-acting air cylinder that returns the four-bar linkage to its resting position.
  12. LOW LIFTER

  13. Waits one minute before beginning to monitor the PIR for movement again.

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

 

Wicked Beernut Home - Halloween Home