
Whats A Microcontroller v3
.0.pdf
Prototyping Your Own Inventions · Page 311
Figure 10-2: Alarm System Prototype Schematic
ACTIVITY #2: BUILD AND TEST EACH CIRCUIT INDIVIDUALLY
Whenever possible, test each subsystem individually before trying to make them work together. If you follow this rule, your projects will go more smoothly, and it’ll save a lot of troubleshooting time. For example, if all the circuits are built but not tested, people have a natural tendency to spend too much time examining code and forget to check each circuit. So, the most important time savings in this procedure is in making sure that there are no circuit mistakes trying to trick you into thinking they are coding errors.
Page 312 · What’s a Microcontroller?
Building and Testing Each Circuit
This activity demonstrates focusing on individual subsystems by building and testing each circuit. Once the pushbutton circuit is built and tested, we’ll build and test the speaker circuit. After repeating this process with the potentiometer and bicolor LED, the circuits will all be “known good” and ready for some application code.
9Find test code in Chapter 3, Activity #2 that you can adapt to testing the Figure 10-2 pushbutton circuit.
9Change the I/O pin references so that it works with the circuit in Figure 10-2.
9Test the code and correct any bugs or wiring errors before continuing.
9Repeat this same process for:
o Piezospeaker circuit from Chapter 8, Activity #1 o Potentiometer circuit from Chapter 5, Activity #3 o Bicolor LED circuit from Chapter 2, Activity #5
9Make sure to save each modified program under a new name, preferably in a separate folder, maybe named “WAM Chapter 10.”
Your Turn – System Test
Now that all the circuits are tested and all the test programs saved on your PC, it’s time to build up a system test that displays debug messages indicating which circuit is being tested as it executes the test code. This is a useful exercise because typical alarm systems have self-test and diagnostic modes that utilize all the features in one routine.
9 Combine elements in your test programs into a single program that it:
oStarts by displaying the color of the bicolor LED in the Debug Terminal as it updates the color...
oThen displays a message that the piezospeaker is making sound while it beeps...
oFinally enters a loop that repeatedly reports the pushbutton drawer sensor and potentiometer hinged door sensor status in the Debug
Terminal.
9 Test for and fix any bugs before continuing.

Prototyping Your Own Inventions · Page 313
ACTIVITY #3: ORGANIZE CODING TASKS INTO SMALL PIECES
Just as each circuit should be built and tested before making them work together, each feature of the code should also be developed and tested individually before incorporating it into the larger application. MicroAlarmProto(Dev-009).bs2 is an example of a program that’s on its way to a proof of concept. Its Debug Terminal user interface is mostly in place, and the alarm system correctly cycles through its various modes or states, including not armed, arming, armed, and triggered.
At this point, the Alarm_Arming subroutine at the end of the program is still under construction. It has code in place that triggers the alarm if the pushbutton is released, which indicates that the drawer has been opened, but it does not yet monitor the hinged door. Potentiometer code needs to be added to the Check_Sensors subroutine that measures its position. If its position is beyond a certain threshold, 15 for example, the state variable should be changed to Triggered. Two additional tasks that remain are to turn the bicolor LED green when the alarm is not armed, and red when it is armed. These remaining tasks are indicated by comments in the code that look like this:
'To-do: bicolor LED green
...
'To-do: bicolor LED red
...
'To-do: Check if Potentiometer is over threshold value. If yes, then, trigger alarm
9Hand-enter MicroAlarmProto(Dev-009).bs2 into the BASIC Stamp Editor (recommended), or download it from www.parallax.com/go/WAM and open it with the BASIC Stamp Editor.
9Examine the program and note how each subroutine is modular, and does a specific job. This is part of organizing coding tasks into small pieces.
9If you do not remember how to use the Debug Terminal’s Transmit and Receive windowpanes, review Figure 9-9 on page 299.
9Load MicroAlarmProto(Dev-009).bs2 into the BASIC Stamp and use the Debug Terminal’s Transmit windowpane to type the character A to arm the alarm, and D to disarm the alarm. The system does a brief countdown before arming the alarm. Make sure to press and hold the pushbutton before the alarm arms.
9While the alarm is armed, release the button. You will have a chance to disarm the alarm after a few seconds of alarm tone.
9Arm the alarm again. This time, type “D” to disarm the alarm before releasing the button.

Page 314 · What’s a Microcontroller? |
|
|
||||
' ----- |
[ Title ]----------------------------------------------------------- |
|
|
|
|
|
'What's a Microcontroller - MicroAlarmProto(Dev-009).bs2 |
||||||
'Test cabinet alarm system. |
|
|
|
|||
' {$STAMP BS2} |
|
|
' Target = BASIC Stamp 2 |
|||
' {$PBASIC 2.5} |
|
|
' Language = PBASIC 2.5 |
|||
' ----- |
[ Constants ]------------------------------------------------------- |
|
' Alarm system states |
|||
NotArmed |
CON |
0 |
|
|||
Arming |
CON |
1 |
|
|
|
|
Armed |
|
CON |
3 |
|
|
|
Triggered |
CON |
4 |
|
|
|
|
' ----- |
[ Variables ]------------------------------------------------------- |
|
' Stores second count |
|||
seconds |
VAR |
Word |
|
|||
counter |
VAR |
Byte |
|
' For counting |
||
char |
|
VAR |
Byte |
|
' Stores characters |
|
state |
|
VAR |
Nib |
|
' Stores alarm system state |
|
' ----- |
[ Initialization ]-------------------------------------------------- |
|
' Wait 1 second |
|||
PAUSE 1000 |
|
|
" |
|||
DEBUG "Program running... |
' Display running message |
|||||
state = NotArmed |
|
|
' Initialize alarm state |
|||
' ----- |
[ Main Routine ]---------------------------------------------------- |
|
' Main loop |
|||
DO |
|
|
|
|
||
SELECT state |
|
|
' Evaluate state case by case |
|||
CASE NotArmed |
|
' If state = not armed |
||||
|
' To-do: bicolor LED green |
' |
call Prompt_to_Arm |
|||
|
GOSUB Prompt_to_Arm |
|
||||
CASE Arming |
|
|
' If state = Arming |
|||
|
GOSUB Alarm_Arming |
|
' |
call Alarm_Arming |
||
CASE Armed |
|
|
' If state = Armed |
|||
|
' To-do: bicolor LED red |
' |
Call Check_Sensors |
|||
|
GOSUB Check_Sensors |
|
||||
|
GOSUB Prompt_to_Disarm |
' |
Call Prompt_to_Disarm |
|||
CASE Triggered |
|
' If state = Triggered |
||||
|
GOSUB Alarm_Triggered |
' |
Call Alarm_Triggered |
|||
ENDSELECT |
|
|
' Done evaluating char |
|||
LOOP |
|
|
|
|
' Repeat main loop |
'=====[ Subroutines ]=====================================================
'-----[ Subroutine - Prompt_To_Arm ]--------------------------------------
Prompt_to_Arm: |
' Display message |
||
DEBUG |
CLS, "Type A to arm", CR, ">" |
||
GOSUB |
Get_User_Input |
' |
Call Get_User_Input |
RETURN |
' |
Return from Prompt_to_Arm |

|
|
|
Prototyping Your Own Inventions · Page 315 |
|
|
|
|
' |
-----[ Subroutine - Prompt_to_Disarm ]----------------------------------- |
|
|
|
Prompt_to_Disarm: |
|
' Display message |
|
DEBUG CLS, "Type D to disarm", CR, ">" |
||
|
GOSUB Get_User_Input |
|
' Call Get_User_Input |
|
RETURN |
|
' Return from Prompt_to_Disarm |
' |
-----[ Subroutine - Alarm_Arming ]--------------------------------------- |
|
|
|
Alarm_Arming: |
|
' Warn user to secure cabinet |
|
DEBUG CLS, "Close the cabinet.", |
||
|
CR, "You have" |
|
' Count down seconds left |
|
FOR seconds = 8 TO 0 |
|
|
|
DEBUG CRSRX, 9, DEC seconds, CLREOL, |
' Display time remaining |
|
|
" seconds left... |
" |
' Wait 1 second |
|
PAUSE 1000 |
|
|
|
NEXT |
|
' Repeat count down |
|
state = Armed |
|
' Set state variable to Armed |
|
RETURN |
|
' Return from Alarm_Arming |
' |
-----[ Subroutine - Alarm_Armed ]---------------------------------------- |
|
|
|
Alarm_Armed: |
|
' Armed loop |
|
DO |
|
|
|
GOSUB Prompt_To_disarm |
|
' Check for user input |
|
GOSUB Check_Sensors |
|
' Check sensors |
|
LOOP UNTIL state <> Armed |
|
' Repeat until state not armed |
|
RETURN |
|
' Return from Alarm_Armed |
' |
-----[ Subroutine - Alarm_Triggered ]------------------------------------ |
|
|
|
Alarm_Triggered: |
|
' Alarm triggered loop |
|
DO |
|
|
|
DEBUG CLS, "Alarm triggered!!!" |
' Display warning |
|
|
FOR counter = 1 TO 15 |
|
' Sound 15 alarm tones |
|
FREQOUT 6, 100, 4500 |
|
|
|
PAUSE 100 |
|
|
|
NEXT |
|
' 3 sec. for user to disarm |
|
FOR seconds = 1 TO 6 |
|
|
|
IF state <> triggered THEN EXIT |
|
|
|
GOSUB Prompt_to_Disarm |
|
|
|
NEXT |
|
' Repeat until disarmed |
|
LOOP UNTIL state <> triggered |
||
' |
-----[ Subroutine - Get_User_Input ]------------------------------------- |
|
|
|
Get_User_Input: |
|
' Clear char variable |
|
char = 0 |
|
|
|
SERIN 16, 84, 500, Timeout_Label, [char] |
' Wait 0.5 sec. for key press |
|
|
GOSUB Process_Char |
|
' If key, call Process_Char |
|
Timeout_Label: |
|
' If no key, skip call |
|
RETURN |
|
' Return from Get_User_Input |
' |
-----[ Subroutine - Process_Char ]--------------------------------------- |
|
|
|
Process_Char: |
|
' Evaluate char case by case |
|
SELECT char |
|
|
|
CASE "A", "a" |
|
' If "A" or "a" |

Page 316 · What’s a Microcontroller? |
|
|
|
state = |
Arming |
' |
Change state var to Arming |
CASE "D", |
"d" |
' Else if "D" or "d" |
|
state = |
NotArmed |
' |
Change state var to NotArmed |
CASE ELSE |
|
' else if no "A", "a", "D", "d" |
|
DEBUG "Wrong character, try again" |
' |
Display error message |
|
PAUSE 2000 |
' |
Give user 2 sec. to read |
|
ENDSELECT |
|
' Done with evaluating char |
|
RETURN |
|
' Return from Process_Char |
'-----[ Subroutine - Check_Sensors ]--------------------------------------
Check_Sensors:
'To-do: Check if Potentiometer is over threshold value.
'If yes, then, trigger alarm
IF IN0 = 0 THEN state = Triggered RETURN
'Btn released? Trigger alarm.
'Return from Check_Sensors
New Coding Techniques in the Example Code
Take a look at the second FOR...NEXT loop in the Alarm_Triggered subroutine:
FOR seconds = 1 TO 6
IF state <> triggered THEN EXIT
GOSUB Prompt_to_Disarm
NEXT
If a call to the Prompt_to_Disarm subroutine results in a change in the state variable, the IF...THEN statement uses EXIT to get out of the FOR...NEXT loop before the 6 repetitions are done.
Another new command called SERIN appears in the Get_User_Input subroutine. DEBUG and DEBUGIN are special versions of the more general SEROUT and SERIN commands. To see how this works, try replacing the command DEBUG "Program running..." with
SEROUT 16, 84, ["Program running..."]. Unlike the DEBUG and DEBUGIN commands, SEROUT and SERIN can communicate on any I/O pin, or pin 16 for communication with the DEBUG terminal. They also have special codes you can use to select the baud rate that are described in the SERIN and SEROUT command’s Baud Rate tables in the BASIC Stamp Manual.
Get_User_Input:
char = 0
SERIN 16, 84, 500, Timeout_Label, [char]
GOSUB Process_Char
Timeout_Label:
RETURN

Prototyping Your Own Inventions · Page 317
The Get_User_Input subroutine starts by setting the char variable to 0 to clear any old values char might be storing. Then, it executes the SERIN command, with its optional Timeout value set to 500 ms (half a second), and its optional timeout label set to Timeout_Label, which is two lines below. If the SERIN command does receive a character within 500 ms, it stores the result in the char variable and moves on to the next line, which calls the Process_Char subroutine. If it doesn’t get a character in 500 ms, it instead jumps to Timeout_Label, which causes it to skip over the subroutine call.
Your Turn – Next Steps Toward the Proof of Concept
It’s time to get this program functioning as a proof of concept.
9Save a copy of MicroAlarmProto(Dev-009).bs2 as MicroAlarmProto(Dev010).bs2
9Use segments of your tested code from Activity #2 to complete the three “Todo” items.
9Test your modified code, and when you get it working right, save a copy of the code as MicroAlarmProto(Dev-011).bs2
ACTIVITY #4: DOCUMENT YOUR CODE!
MicroAlarmProto(Dev-011).bs2 is not quite finished because it still needs some documentation and other changes that make the program easier to modify and maintain. For example, in the Alarm_Triggered subroutine, the command FREQOUT 6, 100, 4500 has what some coders call “mystery numbers.” Mystery numbers are values that are used in a way the casual observer might not be able to easily discern. You could rewrite this command as FREQOUT SpeakerPin, BeepTime, AlarmTone. Then, you can add a Pin Directives section above the Constants section, and declare SpeakerPin PIN 6. Also, in the Constants section, declare BeepTime CON 100, and AlarmTone CON 4500.
Not every constant in a given program has to be named. Keep in mind that mystery numbers are values that are used in a way the casual observer might not be able to easily discern. Another example from the Alarm_Triggered subroutine is:
FOR seconds = 1 TO 6 ' 3 sec. for user to disarm.
The numbers 1 and 6 are not mystery numbers because it’s clear that they make the FOR...NEXT loop repeat six times, and the comment to its right indicates that six repetitions lasts for three seconds. Not all supervisors may agree with this interpretation,
Page 318 · What’s a Microcontroller?
and some might heatedly proclaim that the 1 and the 6 really are mystery numbers. If you end up coding at work and your boss is a stickler for naming all constants, it’s probably a good idea to just adhere to whatever coding style is required.
9Go through MicroAlarmProto(Dev-011).bs2 and document mystery numbers by declaring pin directives and constants, and substituting their names for numbers in the program.
9One exception to PIN directives is the SERIN command’s Pin argument, which should be declared as a constant and not a pin. Pin arguments are for I/O pins and range from P0 to P15. The Pin argument 16 causes the SERIN command to listen to the BASIC Stamp module’s SIN pin, which is connected to your board’s programming port.
Another area where MicroAlarmProto(Dev-011).bs2’s documentation is still weak is in the comments that explain each routine and subroutine. Each subroutine should have comments that explain what it does, any variables it depends on to do its job, and any variables that the subroutine uses to store results before its RETURN. Here is an example of good documentation added to the beginning of the Process_Char subroutine.
'-----[ Subroutine - Process_Char ]---------------------------
'Updates the state variable based on the contents of the
'char variable. If char contains "A" or "a", the Armed
'constant gets stored in state. If char contains "D" or "d",
'the NotArmed constant gets stored in state.
'
Process_Char: |
|
'... code omitted here |
' Return from... |
RETURN |
9Update descriptions between the subroutine titles and their labels, and repeat for the main routine as well.
9When you are done, save a copy of your code with the name MicroAlarmProofOfConcept(v1.0).bs2.
Save Copies and Increment Version Numbers after Each Small Change
Make sure to continue saving copies of your code with each small adjustment. This makes it easy to take small steps backward to working code if your change(s) cause bugs. For example, before your next modification, save the file as

Prototyping Your Own Inventions · Page 319
MicroAlarmProofOfConcept(v1.01).bs2, or maybe even v1.01a. When your next feature is fully implemented, chose a reasonable revision step. If it’s a smaller revision, try v1.1; if it’s a big revision, up it to v2.0.
ACTIVITY #5: GIVE YOUR APP AMAZING NEW FUNCTIONALITY
As mentioned earlier, each circuit you have worked with in this text is really an example from a group of components and modules that the BASIC Stamp can interact with in the same way. Figure 10-3 shows some part substitutions you could make to convert your current mini-enclosure security system into one that will protect an object sitting out in the open. This modified system can instead detect motions in the room, and also detect if someone lifts up the object you want to protect:
•Pushbutton: high-low output → replace with PIR Motion Sensor
•Potentiometer: variable resistor → replace with FlexiForce Sensor
The PIR sensor detects changing patterns of passive infrared light in the surrounding area, and sends a high signal to indicate that motion is detected, or a low signal to indicate no motion. The FlexiForce sensor’s resistance varies with force applied to the round dot on the end (such as an object sitting on it), so it can be measured in an RC circuit with the RCTIME command.
Figure 10-3: Sensors to Upgrade our Mini Alarm System
PIR Motion |
FlexiForce Sensor |
Sensor |
|
9Go to www.parallax.com and type “motion detection” into the Search field, then click the Go button.
9Find the PIR Sensor in the search results and go to its product page.
9Download PIR Sensor Documentation (.pdf), and optionally watch the PIR Sensor video clip. The PDF will be in the page’s Downloads section.

Page 320 · What’s a Microcontroller?
9Read the documentation’s explanations, schematic, and PIR_Simple.bs2 example code. Could you substitute this sensor for a pushbutton?
9Go back to your search results (or back to the Parallax home page) and type pressure into the Search field. Then, follow the FlexiForce sensor link.
9Find and un-zip the FlexiForce Documentation and Source Code (.zip).
9In the un-zipped folder, open and read the documentation, schematic, and FlexiForce Simple.bs2 source code. Could you substitute this sensor for a potentiometer?
For a step-by-step example that demonstrates how the enhancements in both this and the next activity can be incorporated into your Micro Alarm application, follow the Stamps in Class “Mini Projects” link at: www.parallax.com/Education.
ACTIVITY #6 : HOW TO JUMP OVER DESIGN HURDLES
Now that you’re just about done with What’s a Microcontroller? one of the most important next steps you can take is finding answers for tasks you don’t already know how to solve with your microcontroller. Here are the general steps:
Step 1: Look for components or circuits that could solve your problem.
Step 2: Read about the component/circuit, and find out how it works. Pay special attention to how the BASIC Stamp would need to interact with the component/circuit.
Step 3: Check to find out if example code is available for the circuit or component. That’ll make it a lot easier to incorporate into your application.
Let’s say that the next step in your project is to display the system’s status without the computer connection. Here’s an example of how you can find and evaluate a component for your application.
9(Step 1) Go to www.parallax.com and try the term “display” in the Search field. From the home page, you may need to click the Go button instead of just pressing Enter. Go to the product pages of the various result items in the search and see if you can find one that’s relatively inexpensive and capable of displaying a couple lines of text.
If you decided the Parallax Serial 2x16 LCD in Figure 10-4 is a good candidate, you’re on the right track. However, just about any of the displays are fair game.