Basic Starter Package - Tutorial #2

copyright, Peter H. Anderson, Dept of EE,
Morgan State University, Baltimore, MD, Nov 26, '97

Note.

The Basic Starter Package includes a number of tutorials. The intent is to teach the user how to effectively use the Stamp in the context of various applications.

This section has not been completed. However, what is here may be useful.

Initial Input and Ouput Routines.

Circuit Configuration

Connect the four bit DIP switch as shown in Figure 2. Note that one side of all of the switches tied to ground. The other side of each switch is tied to Stamp terminals 20, 19, 18 and 17. Note that on each of these terminals there is also a 4.7K pullup resistor to +5VDC.

[A single in-line package (SIP) containing nine 4.7K pullup resistors connected to a common point has been supplied in the Basic Starter Kit].

The idea is that when a switch is open, the +5V though the 4.7K pullup resistor is seen by the Stamp as a logic one. When a switch is closed to ground, the Stamp will read a logic zero.

Note that the lead definitions corresponding to terminals 20, 19, 18 and 17 are P15, P14, P13 and P12. For convenience these four switches will be termed S15, S14, S13 and S12.

Also install a pushbutton. This will require that you solder a lead to each of the two terminals on the switch. One side of this pushbutton is connected to ground and the other to terminal 16 of the Stamp. Note the 4.7K pullup resistor to +5. Note that terminal 16 corresponds to function designation P11. Thus, this pushbutton will be refered to as PB11.

In addition, install three additional LEDs, such that you have four LEDs, one each on terminals 8, 7, 6 and 5. These correspond to function designations P3, P2, P1 and P0 and the LEDs will be referred to as LED3, LED2, LED1 and LED0.

Program ARROW_1.BS2.

' Program ARROW_1.BS2.
'
' Causes the LEDs to ripple in one direction.  Operates in a continuous
' loop.
'
' P. H. Anderson, Nov 26, '97

	DIRA=%1111	' make lowest four bits outputs
	DIRC=%0000	' makes bits 8, 9, 10 and 11 inputs
	DIRD=%0000	' make highest four bits inputs
TOP:
	OUTA=%0000	' turn off all LEDs
	PAUSE 50
	OUT0=1		' turn on LED0
	PAUSE 50
	OUT1=1		' turn on LED1
	PAUSE 50
	OUT2=1		' LED2
	PAUSE 50
	OUT3=1		' LED3
	PAUSE 150	' pause a bit longer
	GOTO TOP
Recall in the previous discussion, the directional control word is defined as DIRS. Specific bits may be referenced as DIR3, DIR2, etc. But, in addition, individual nibbles (4-bits) may be refernced. Thus DIRA corresponds to bits 0, 1, 2 and 3. DIRB to bits 4, 5, 6 and 7, etc.

In the example, I used the binary notation using the symbol %. The symbol $ indicates hexadecimal and no symbol defaults to decimal. Thus the following are all the same;

	DIRA=%1111
	DIRA=$F
	DIRA=15
Note that the entire 16 bits could have been set using either of the following;
	DIRS=%0000000000001111
or	DIRS=$000F
Caution.

Avoid setting a pin that is to be used as an input, in the output direction.

For example;

	DIRD=%1111	' this can damage your stamp
The reason is, that if OUT15 is at a logic one, and switch S15 is closed to ground, you will have a dead short on P15. This may well burn out P15.

In fact, I have taught the Basic Stamp to hundreds of students and have lost very few Stamps, but this does happen.

Note that when the Stamp boots up, all pins are defined as inputs. Thus, I encourage my students to only use the DIRS to set outputs. Thus, in the above routine, it would have been sufficient to simply;

	DIRA=%1111	' make lower 4 bits outputs
All of the other bits are configured as inputs by default.

Note that each LED is turned on in sequence with a brief pause between each and a bit longer pause when they are all turned on. Note that OUT1=1 does not affect the state of any other bit.

Program ARROW_2.BS2.

' Program ARROW_2.BS2.
'
' Causes the LEDs to ripple in direction determined by pushbutton PB11
'
' P. H. Anderson, Nov 26, '97

	DIRA=%1111	' make lowest four bits outputs
			' all others are inputs by default
TOP:
	IF (IN11=0) THEN OTHER_WAY
ONE_WAY:		' else
	OUTA=%0000	' turn off all LEDs
	PAUSE 50
	OUT0=1		' turn on LED0
	PAUSE 50
	OUT1=1		' turn on LED1
	PAUSE 50
	OUT2=1		' LED2
	PAUSE 50
	OUT3=1		' LED3
	PAUSE 150	' pause a bit longer
	GOTO TOP

OTHER_WAY:
	OUTA=%0000	' turn off all LEDs
	PAUSE 50
	OUT3=1		' turn on LED3
	PAUSE 50
	OUT2=1		' turn on LED2
	PAUSE 50
	OUT1=1		' LED1
	PAUSE 50
	OUT0=1		' LED0
	PAUSE 150	' pause a bit longer
	GOTO TOP
In this program, IN11 is read and if it is a zero, the program braches to OTHER_WAY, and LED3, LED2, LED1 and LED0 are turned on in sequence. However, if the condition in the parenthesis is false, the branch to OTHER_WAY is not executed and the program continues to the next line, in this case ONE_WAY.

Note that label ONE_WAY is not really required in this instance. However, I usually provide such a label when using an if statement as I am more accustomed to C programmming;

	if (IN11==0)
	{
	   /* if true, do this */
        }
        else
	{
	   /* otherwise, do this */
 	}
That is, if TRUE, do this. Otherwise, do this. I find the PBASIC, if true, GOTO somewhere else to be a bit confusing. Thus, I usually put in a label along with an 'else notation.

It is very important to note that the IF statement includes an implied GOTO.

	IF (IN11=0) THEN {GOTO} OTHER_WAY
It is not a GOSUB. (Recall that you cannot GOTO a subroutine as when the RETURN in the subroutine is executed, the junk on the top of the stack will cause your program to go into "never never land".

Of course, subroutines may be used in a correct manner.

Program ARROW_3.BS2.

' Program ARROW_3.BS2.
'
' Causes the LEDs to ripple in direction determined by pushbutton PB11.
' Same as ARROW_2, except uses subroutines.
'
' P. H. Anderson, Nov 26, '97

	DIRA=%1111	' make lowest four bits outputs
			' all others are inputs by default
TOP:
	IF (IN11=0) THEN OTHER_WAY
ONE_WAY:		' else

	GOSUB UP
	GOTO TOP

OTHER_WAY:
	GOSUB DOWN
	GOTO TOP

UP:
	OUTA=%0000	' turn off all LEDs
	PAUSE 50
	OUT0=1		' turn on LED0
	PAUSE 50
	OUT1=1		' turn on LED1
	PAUSE 50
	OUT2=1		' LED2
	PAUSE 50
	OUT3=1		' LED3
	PAUSE 150	' pause a bit longer
	RETURN

DOWN:
	OUTA=%0000	' turn off all LEDs
	PAUSE 50
	OUT3=1		' turn on LED3
	PAUSE 50
	OUT2=1		' turn on LED2
	PAUSE 50
	OUT1=1		' LED1
	PAUSE 50
	OUT0=1		' LED0
	PAUSE 150	' pause a bit longer
	RETURN
Aside from making the code a bit more readable, one might offer that this approach has no advantage. In fact, it does use a bit more memory (4 bytes) and it takes a bit longer to execute, perhaps 100 usecs.

However, program memory is never a problem until you run out. You pay $49.00 for a Stamp whether you use 64 of the 2048 program words or all of them. Thus, extra bytes are free, until you run out of them. In this application, the extra execution time certainly is not going to cause a problem.

The watch word in today's world of programming is "make it readable". Thus, I suggest this use of subroutines is in fact, better programming.

Program PATT_1.ASM.

In operating a unipolar stepping motor, there are four windings. Winding_0 is operated, and then both Winding_0 and Winding_1, and then Winding_1 alone, etc. Thus;

	%0001		$1
	%0011		$3
	%0010		$2
	%0110		$6
	
	%0100		$4
	%1100		$C
	%1000		$8
	%1001		$9
	
	%0001		$1
	etc
Note that moving down through these patterns will cause the motor to turn in one direction and moving up will cause it to turn the other way.

The amount of delay between outputting these patterns determines the speed of the motor.

Prior to moving on to using the ULN2803 to drive a stepping motor, let's tinker a bit more with the LEDs. Note that a Stamp cannot drive a stepper directly. Damage to the Stamp will result in trying to do so.

' PATT_1.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' One way only.
'
' P. H. Anderson, MSU, 26 Nov, '97

	T CON 200	' 200 msec pause

	DIRA=$F		' low four bits are outputs
	
TOP:
	OUTA=$1
	PAUSE T
	OUTA=$3
	PAUSE T
	OUTA=$2
	PAUSE T
	OUTA=$6
	PAUSE T

	OUTA=$4
	PAUSE T
	OUTA=$C
	PAUSE T
	OUTA=$8
	PAUSE T
	OUTA=$9
	PAUSE T

	GOTO TOP	' keep going
Note that individual bits in the 16-bit word referred to as OUTS, may be referred to as OUT3, OUT2, etc. This was advantageous in the ARROW routines where it was realtively easy to simply set one bit.

However, in this routine, the nibble approach was used. That is, OUTA refers to OUT3, OUT2, OUT1 and OUT0.

Program PATT_2.BS2.

The above will certainly work, but prior to moving to bidirectional control, let's examine another approach.

' PATT_2.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' One way only.  Functionally the same as PATT_1.  Uses LOOKUP.
'
' P. H. Anderson, MSU, 26 Nov, '97

	T CON 200

INDEX	VAR BYTE
PATT	VAR BYTE

	DIRA=$F		' low four bits are outputs
	
TOP:
	FOR INDEX=0 TO 7
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	' keep going
Quite a bit more readable!

Note that the on the first pass through the loop, INDEX is 0. The LOOKUP command then writes the 0th element to variable PATT. PATT is then output. On the next pass, the next element, $3, is copied to PATT and output.

Going the other way is pretty simple.

TOP:
	FOR INDEX=7 TO 0
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	' keep going
Note that the FOR NEXT loop now counts from 7 down to 0. I haven't figured out how the Stamp knows to count down. But, it does.

Program PATT_3.BS2

' PATT_3.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' Bidirectional control using switch S15.  
'
' P. H. Anderson, MSU, 26 Nov, '97

	T CON 200

INDEX	VAR BYTE
PATT	VAR BYTE

	DIRA=$F		' low four bits are outputs
	
TOP:
	IF (IN15=0) THEN ONE_WAY

OTHER_WAY:	'else
	FOR INDEX=7 TO 0
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	' keep going

ONE_WAY:	
	FOR INDEX=0 TO 7
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	' keep going
Note that if switch S15 is in one state, the LEDs "turn" in one direction and if in a zero state, they turn in the other direction.

Program PATT_4.BS2.

A stepping motor may also be run in a full step mode by operating coils two at a time.

	%0011		$3
	%0110		$6
	%1100		$C
	%1001		$9
	
	%0011		$3
	etc
The result is that the motor moves faster then in the half step mode, but the turning action is not as smooth.

Let's assign switch S14 to determine whether the mode is to be half or full step.

Thus, with S15, we have the following;

	S15  	S14	Action

	0 	0	OTHER_WAY_HALF  (OTHER_W_H)
	0	1	OTHER_WAY_FULL  (OTHER_W_F)

	1	0	ONE_WAY_HALF	(ONE_W_H)
	1	1	ONE_WAY_FULL	(ONE_W_F)
' PATT_4.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' Bidirectional control (S15). Half or Full Step mode (S14).
'
' P. H. Anderson, MSU, 27 Nov, '97

	T CON 200

MODE	VAR BYTE
INDEX	VAR BYTE
PATT	VAR BYTE

	DIRA=$F		' low four bits are outputs
	
TOP:
	MODE= (IND >> 2)
	BRANCH MODE, [OTHER_W_H, OTHER_W_F, ONE_W_H, ONE_W_F]

OTHER_W_H:	
	FOR INDEX=7 TO 0
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	

OTHER_W_F:
	FOR INDEX=3 TO 0
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	

ONE_W_H:	
	FOR INDEX=0 TO 7
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	

ONE_W_F:
	FOR INDEX= 0 TO 3
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T
	NEXT
	GOTO TOP	
Note that the D nibble (consisting of IN15, IN14, IN13 and IN12) is read using IND. This is then shifted two places to the right. Thus MODE is
	%0000 00 S15 S14
Depending on the state of S15 and S14, this is 0, 1, 2 or 3.

The BRANCH command is a very welcome alternative to nested IF statements. If MODE is 0, the program branches to the 0th label in the brackets, if 1, to the next label, etc.

As with the IF, note that the BRANCH is a GOTO, not a GOSUB.

Program PATT_5.BS2

Note that in the above the PAUSE is fixed. T has been defined as a constant of 200. Of course, you can change this constant and recompile your program, but there is no way to vary the speed of the motor while the program is running.

Program PATT_5.BS2 is exactly the same as PATT_4, except the the delay between outputting states has been changed to a variable, T_VAR. Note that T_VAR is initialized to 200 and thus the program does the same thing as PATT_4.

' PATT_5.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' Bidirectional control (S15). Half or Full Step mode (S14).
'
' P. H. Anderson, MSU, 27 Nov, '97

	
T_VAR	VAR BYTE
MODE	VAR BYTE
INDEX	VAR BYTE
PATT	VAR BYTE

	DIRA=$F		' low four bits are outputs
	T_VAR=200
	
TOP:
	MODE= (IND >> 2)
	BRANCH MODE, [OTHER_W_H, OTHER_W_F, ONE_W_H, ONE_W_F]

OTHER_W_H:	
	FOR INDEX=7 TO 0
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

OTHER_W_F:
	FOR INDEX=3 TO 0
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

ONE_W_H:	
	FOR INDEX=0 TO 7
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

ONE_W_F:
	FOR INDEX= 0 TO 3
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	
Program PATT_6.BS2.

Let's extend this a bit further by defining switches S13 and S12 to control the speed at which the "motor" turns.

	S13	S12	Delay

	0	0	50
	0	1	75
	1	0	100
	1	1	200
' PATT_6.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' Bidirectional control (S15). Half or Full Step mode (S14).
' Variable speed (S13 and S12).
'
' P. H. Anderson, MSU, 27 Nov, '97


SPEED	VAR BYTE	
T_VAR	VAR BYTE
MODE	VAR BYTE
INDEX	VAR BYTE
PATT	VAR BYTE

	DIRA=$F		' low four bits are outputs
	
	
TOP:
	SPEED=(IND & %0011)
	LOOKUP SPEED, [50, 75, 100, 200], T_VAR
	MODE= (IND >> 2)
	BRANCH MODE, [OTHER_W_H, OTHER_W_F, ONE_W_H, ONE_W_F]

OTHER_W_H:	
	FOR INDEX=7 TO 0
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

OTHER_W_F:
	FOR INDEX=3 TO 0
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

ONE_W_H:	
	FOR INDEX=0 TO 7
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

ONE_W_F:
	FOR INDEX= 0 TO 3
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	
Note that T_VAR is not initialized as it was in Program PATT_5. Rather, nibble D is read. However, this consists of the states of S15, S14, S13 and S12. As only the states of switches S13 and S12 are desired, the nibble is logically anded with %0011. Thus, SPEED is either 0, 1, 2 or 3, depending on the states of S13 and S12. SPEED is then mapped into a value which is copied into T_VAR using the familiar LOOKUP command.

The result is a stepping motor controller where S15 controls the direction, S14 controls whether it is in the full or half step mode and S13 and S12 control the speed.

Program PATT_7.BS2.

This program simply extends PATT_6 such that the motor turns only when the pushbutton PB11 is depressed.

' PATT_7.BS2
'
' Ouputs stepping motor patterns to four LEDs on lowest four bits.
' Bidirectional control (S15). Half or Full Step mode (S14).
' Variable speed (S13 and S12).  Motor turns when PB11 is depressed.
'
' P. H. Anderson, MSU, 27 Nov, '97


SPEED	VAR BYTE	
T_VAR	VAR BYTE
MODE	VAR BYTE
INDEX	VAR BYTE
PATT	VAR BYTE

	DIRA=$F		' low four bits are outputs
	
	
TOP:
	IF (IN11=1) THEN TOP
	SPEED=(IND & %0011)
	LOOKUP SPEED, [50, 75, 100, 200], T_VAR
	MODE= (IND >> 2)
	BRANCH MODE, [OTHER_W_H, OTHER_W_F, ONE_W_H, ONE_W_F]

OTHER_W_H:	
	FOR INDEX=7 TO 0
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

OTHER_W_F:
	FOR INDEX=3 TO 0
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

ONE_W_H:	
	FOR INDEX=0 TO 7
	   LOOKUP INDEX, [$1, $3, $2, $6, $4, $C, $8, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	

ONE_W_F:
	FOR INDEX= 0 TO 3
	   LOOKUP INDEX, [$3, $6, $C, $9], PATT
	   OUTA = PATT
	   PAUSE T_VAR
	NEXT
	GOTO TOP	
Note that IN11 is read, and if at logic one (pushbutton not depressed), the program simply loops.

Summary.

This tutorial has discussed how outputs may be individually set to either a logic one or zero using OUT3, OUT2, etc and how a nibble may be referenced using OUTA.

It has discussed how to read inputs. Note that all inputs may be read as INS. However, individual bits may be read using IN15, IN14, etc and nibbles may be read using IND, INC, etc.

Quantities may be expressed in binary (%), hexadecimal ($) or decimal.

The IF - THEN and BRANCH commands have been presented. Note that both of these are conditional GOTO commands.

The LOOKUP command provides a powerful technique for mapping an index into specific values. In the above examples, this was used to map an index into a stepping motor pattern and to map another index into a time delay value.

The right shift (>>) and logical and (&) operators have been introduced.

Recognize the power of the Stamp. The final result (PATT_7.BS2) is a relatively simple and yet very powerful program. The next tutorial deals with using the ULN2803 to interface the Stamp with a stepper.

Future.

In the future an alternative approach will show how an array may be used (DATA) in place of the LOOKUP.

Tutorial #3 deals with the actual control of the stepper using the ULN2803 supplied with the Basic Starter Package. This tutorial also deals with interfacing in general; optoisolators, medium and power transistor drivers and solid state relays to control AC. This will not appear on the web.

Tutorial #4 will deal with PWM. This will be introduced in the context of dimming an LED and then controlling the speed of the DC motor using the L293D supplied with the Starter Package.

And, then on to using a speaker; playing a tune, using the DTMF command and sending zip tones. That is; beep beep beep pause beep to indicate a temperature is 31 degrees.

Stay tuned. Over the Thanksgiving Break, I am hopeful I can accomplish a great deal. Please forgive grammatical errors and mispells and perhaps an occassional error in the code. Hopefully, I will find them all. Wishfull thinking!

Happy Tinkering!