Basic Starter Package - Tutorial #1: Note
Basic Starter Package - Tutorial #1: Note
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.
Some may find this first tutorial rather trivial. However, what is trivial to an
experienced user may well be quite useful to a newcomer. The tutorials become
increasingly advanced.
At this point you have assembled the power supply, made the necessary connections
from the serial port cable to the Stamp and have assembled and tested the logic probe.
Lets forge ahead and write some simple programs to flash a a single LED. In doing so, I
hope to get across many of the PBASIC commands in a simple context which is
understandable.
Please refer to Figure #1. Note that this consists of the addition of a single LED from P0
(Terminal 5) on the Stamp to ground. Note that the LEDs supplied with the Basic
Starter package have an integrated 330 Ohm resistor to limit the LED current to
nominally 10 mA.
The idea is to force a logic one on an ouput for a period of time, thus turning the LED
on. And then, output a zero for a period of time, causing the LED to turn off.
Program LED_1.BS2
' LED_1.BS2
'
' Flashes an LED on Output 0 on and off
'
' Peter H. Anderson, MSU, 25 November, '97
'
TOP:
GOTO TOP
Note that an "'" indicates that all that follows on the line is a comment. Although not
required, good programmers spend a bit of effort briefly describing the overall operation
of the program and include annotations within the code to give the reader a clear idea of
what the statements are doing.
The word TOP is a label, in this case, a place in the program. Labels can be virtually
anything other than specific key words.
Each of the 16 I/O pins on the Basic Stamp may be configured as an input or as an
output. The Stamp reserves a 16-bit variable DIRS with the state of each bit being used
to confgure that pin as either as an input or an output.
Specific bits, may be selectively configured using the DIRp nomenclature. That is,
DIR0 or DIR7 or DIR15. A one configures the bit as an output. Thus;
In this case;
The PAUSE command is pretty obvious. Note that the time is in milliseconds. The
maximum value is 2^16-1 or 65,535. Thus, using the PAUSE, the largest delay one
could achieve is nominally 60.5 seconds.
The GOTO redirects the program flow to the designated label. Thus, in this case, the
program simply loops, continually flashing the LED.
Program LED_2.BS2
' LED_2.BS2
'
' Flashes an LED on Output 0 on and off. Simply another
implementation of
' LED_1.BS2.
'
' Peter H. Anderson, MSU, 25 November, '97
'
DIR0=OUT
TOP:
GOTO TOP
Note that a number of changes have been made. However, the program does the same
thing.
The concept of constants has been introduced using the keyword CON. These are
nothing more than constants which are substituted into your code.
DIR0=1
forced pin 0 to be an output. However, I always tend to forget whether it is a zero or a
one and thus I use a standard set of constants that I cut and paste from one program to
another. Thus;
OUT CON 1
simply means, to substitute a "1" where the word OUT appears in the program.
Note that the DIR0=1 has been pulled out of the loop, and is now executed only one
time when the program begins. Once the direction of a bit has been defined, there is no
need to continually do so as was done in the first program.
The commands HIGH and LOW followed by the pin number are simply alternative
representations of the OUT command;
DIR0=OUT
TOP:
FOR TIMES = 1 TO 50
HIGH LED ' turn on the LED
PAUSE DELAY_TIME ' pause for 500 msecs
DEBUG "Done!"
DONE:
GOTO DONE
In this program, the variable TIMES has been declared as a byte (8 bits). Note that a
byte may accommodate the numbers 0 through 255 and in this application where the
highest value is 50, a byte is sufficient. If I desired to flash the LED a 1000 times, the
variable would have been declared as a "word" which is two bytes. A word can
accommodate values from 0 to 65,535.
Note that an additional constant has been defined; LED. Rather than burdening one's
mind with the fact that the LED is on pin 0, this simple idea of a constant permits you to
make that connection just once and then refer to the pin as simply "LED". As we only
are using one lead at this point, the advantage may not be obvious, but it will when we
begin to use many of the 16 inputs and outputs.
Program LED_3 introduces the use of the FOR - NEXT command. In this context, the
commands between the FOR and the NEXT are executed with TIMES equal to 1, and
then with TIMES equal to 2, etc until TIMES is equal to 50. TIMES is then incremented
to 51, which is beyond the upper bound (50) and the program thus breaks from the FOR
loop.
Note that on each pass through the loop, the LED is flashed and, in addition the value of
TIMES is displayed on the terminal using the DEBUG command.
The DEBUG command allows you to print values and text to the terminal. Future
programs will treat this in much greater detail. For the moment;
Program LED_4.BS2.
' LED_4.BS2
'
' Flashes an LED on Output 0 on and off 50 times. Uses a subroutine
'
' Peter H. Anderson, MSU, 25 November, '97
'
DIR0=OUT
TOP:
FOR TIMES = 1 TO 50
GOSUB FLASH
NEXT
DEBUG "Done!"
DONE:
GOTO DONE
The RETURN statement then causes the program to return to the statement after the
GOSUB.
In calling (GOSUB) a subroutine, the return address is pushed on to a stack. When the
RETURN is executed this return address is pulled from the top of the stack. Fortunately,
this is all hidden from the Stamp user, but the general mechanics are important in
appreciating the following limitations.
DIR0=OUT
TOP:
FOR TIMES = 1 TO 50
GOSUB FLASH
NEXT
DEBUG "Done!"
DONE:
GOTO DONE
Note that this program is wrong. The LED will indeed flash the 50 times. However, on
exiting the FOR - NEXT loop, the program will enter the subroutine. Note that there has
been no call (GOSUB). The LED will again flash (for the 51st time). However, on
executing the RETURN, the top of the stack does not contain a valid return address and
your program will go to off to "never never land".
Finally, you must RETURN from a subroutine. Consider the following very incorrect
routine.
DIR0=OUT
TOP:
FOR TIMES = 1 TO 50
GOSUB FLASH
AGAIN:
NEXT
DEBUG "Done!"
DONE:
GOTO DONE
In ths incorrect routine, the FLASH routine is called with a GOSUB and the return
address is pushed on to the top of the stack. However, at the conclusion of the FLASH
routine, I have erroneously used a GOTO. Thus, the return address is not pulled off the
top of the stack. The routine is again called, but there is no corresponding pull in the
subroutine. Thus, the stack is growing and growing and eventually, your program will
stop working.
In summary, when using subroutines, be certain that the only way the program enters
the subroutine is with a GOSUB. No GOTOs and no "walk-ins" as illustrated in routine
LED_4B. Be certain to use a RETURN to go back to the calling program.
Note that in program LED_4, the DEBUG ?TIMES was included in the subroutine to
make a point. All variables in PBASIC are global. That is, the variables are known to all
subroutines.
Program LED_5.BS2.
Consider rolling a die. This generates a random number in the range of 1 to 6. Roll a
second die, generating a second number. Sum them and wink the LED that number of
times. This might be used as a rather expensive and inferior replacement for rolling dice
as in playing Monopoly, Parchesi and other less redeeming games of chance. I say all of
this with tongue in cheek, but the routine helps to make a number of points.
' LED_5.BS2
'
' Flashes an LED on Output 0 on and off the number of times "rolled"
by
' two dice.
'
' Peter H. Anderson, MSU, 25 November, '97
'
DIR0=OUT
TOP:
DEBUG "Done!"
DONE:
GOTO DONE
RETURN
The RANDOM command generates a number in the range of 0 - 65,535 and places the
result in variable R. Note that R has been declared as a word to accommodate this.
The "//" is the mod operator. Somewhere back in junior high, you probably had such
exercises as 12323 divided by 6 = 2053 with a remainder of 5. The mod operation is
simply the remainder. Thus R // 6 generates a number in the range of 0 to 5. Adding one
gives a random number in the range of 1 to 6.
This operation is performed twice to provide values for DIE_1 and DIE_2. The results
are summed (DICE) and subroutine WINK is called which in turn calls subroutine
FLASH, DICE times.
There is a flaw in this program in that it will always produce the same "random"
numbers. The command RANDOM takes the arguement, in this case variable R and
operates on it so as to produce a pseudo random number. In this program, the initial
value of R is 0 and thus the RANDOM command will always produce the same random
R, and thus DIE_1 will always be the same. This value of R is then used to calculate
another value of R, but it will also always be the same and thus DIE_2 will always be
the same. None too practical, but I like the program as it shows the use of the
RANDOM function, the mod operator, nested subroutines and the use of a variable in a
FOR-NEXT loop.
Summary.
All of this has used only one LED which is none too interesting.
However, I am hopeful you have an appreciation for the direction control DIRS, and
controlling the direction of a specific bit (DIR0). You know how to define a constant
using CON, how to declare a variable using VAR and the difference between a byte and
a word. You should know what a label is. All outputs are referred to as OUTS, but a
specific bit may be referenced as OUT0. The commands GOTO, FOR-NEXT, HIGH,
LOW, TOGGLE and PAUSE have been treated. The commands GOSUB and RETURN
have been discussed and hopefully you appreciate the mechanics of subroutines.