Level: Beginner
Hours to Complete: 1 - 1.5
Skills Required: PBASIC programming, circuit-building, reading schematics
Have you've ever wanted to thrill your family and friends with both your skill in electronics and in magic? If so, then the Magic BS2 Board is exactly what you need. Ask it a question, give it a little shake, and watch the answer appear magically before your eyes!
Disclaimer: Parallax Inc. takes no responsibility or liability for unwanted, untrue, or potentially slanderous answers. This project is intended strictly for entertainment purposes.
If you are new to the BASIC Stamp microcontroller or to programming, it would be a good idea to review the following before beginning:
(1) HomeWork Board with BASIC Stamp 2 (#555-28188)
····The BASIC Stamp 2 Board of Education is also suitable for this activity.
(1) 4-Directional Tilt Sensor (#28036)
(1) Parallax Serial LCD (#27977, #27976, or #27979)
(1) Servo/LCD Extension Cable (#805-00002)
(1) 3-pin header (#451-00303)
Optional Mounting Bracket Parts
(2) L-Shaped Mounting Brackets (#720-00011)
(6) 4-40 zinc plated nuts (#700-00003)
(4) 1/4" 4-40 pan-head screws (#700-00028)
(2) 1/2" 4-40 pan-head screws
(2) 1/4" round nylon spacers #4
Source Code for Magic BS2 Board [3]
Figure 1 below shows the schematic for the Magic BS2 board, and Figure 2 displays the optional mounting bracket assembly for the LCD display.
Figure 1 – Magic BS2 Board Schematic
Figure 2 – Optional Mounting Bracket Assembly
Not sure how to wire circuits from schematics? No problem! Parallax offers another video tutorial on exactly that topic: How to Wire Circuits from Schematics [4].
Once your circuit is wired, it’s a good idea to test that everything is working properly before developing code. The program below (also included in the source code download zip) displays a message on the Serial LCD and displays the states of the 4-Directional Tilt Sensor using the Debug Terminal.
Code:
' MagicBS2Board_Test.bs2 ' Tests the functionality of the board ' {$STAMP BS2} ' {$PBASIC 2.5} LCDpin PIN 13 ' Declare LCD pin DEBUG CLS ' Clear the Debug Terminal SEROUT LCDpin, 84, [22, 12] ' Initialize the LCD PAUSE 5 SEROUT LCDpin, 84, ["Testing..."] ' Display test message DO DEBUG BIN1 IN0, " ", BIN1 IN1, CR ' Display tilt states PAUSE 300 ' at human speeds LOOP
Another thing to check when running this code is to monitor how the 4-Directional Tilt Sensor responds when being shaken. We will need to determine what pattern emerges (if any) so that we can track when the board is moving and when it’s not, inside the code.
Figure 3 is a snippet of the tilt sensor’s states when being shaken. Notice that the state on at least one pin changes almost every time a reading is taken. But you should also notice that sometimes, the state remains the same. This will be key information as we put together our final program code!
Figure 3 – Debug Terminal Output of Tilt Sensor’s States
As we prepare the final code for the Magic BS2 Board, there are several important factors we will need to keep in mind: how we will create "random" answers, how to determine when the board is being shaken, and what kind of responses we want the board to display.
We certainly want to be sure that the people asking questions don’t get the same response repeated time and time again. So we’ll need to devise a way to randomize the results.
If you recall from A Bi-Color LED Memory Game [5], we used the RANDOM command to generate a random pattern of red & green LED flashes. We can use the same theory from that application for our Magic BS2 board.
First, we’ll need to declare a variable that will be randomized. In this case, we’ll make it a word-sized variable in order to maximize the amount of random numbers generated.
generateMessage VAR Word
Placing the following code at the beginning of our program will keep randomizing the generateMessage variable until the 4-Directional Tilt sensor detects movement. This code will execute very quickly, so it will be very difficult for the user to get the same number twice.
DO old0 = IN0: old1 = IN1 RANDOM generateMessage LOOP UNTIL (old0 <> IN0 OR old1 <> IN1)
By looking at the pattern of the tilt sensor’s states in Figure 3 (shown on previous page), we can apply a general rule that as the states of pin 0 or 1 are fluctuating, the board is being shaken. Once the states remain the same for several cycles, we can assume that the board is still and the user is ready for their answer.
For this, we will need to compare the previous state of both pins with their current state, and when the states begin to repeat, we know the user has stopped shaking the board.
But what if the states repeat a couple times even while the board is being shaken, as seen in Figure 3? To make sure we don’t display an answer while the user is shaking the board, we’ll need to keep track of how many times the sensor’s state has repeated. We’ll give it a generous margin and say that if the sensor’s state repeats 10 times, the user has probably finished shaking the board.
The final thing that needs to be determined is what responses the user will get when done shaking the board. In order to determine what response will be displayed, we’ll look at a nibble (or the last four bits) of the random number generated. To do this, we’ll declare another variable:
displayMessage VAR generateMessage.NIB0
This will give us a possibility of 16 different responses – so we’ll need to think of some! Regular Magic 8-Balls have 20 possible responses with 10 being positive, 5 negative and 5 unclear. To try and keep the proportions somewhat equal, our Magic BS2 Board will have 8 positive responses, 4 negative and 4 undecided. These responses can be chosen by using SELECT…CASE statements, as depicted in the pseudo-code below.
SELECT displayMessage ··CASE 0 ····SEROUT LCDpin, 84, [128, "Message 1"] ··CASE 1 ····SEROUT LCDpin, 84, [128, "Message 2"] ··... ··CASE ELSE ····SEROUT LCDpin, 84, [128, “Message 16”]
Now for the following Magic BS2 Board code, I used Parallax and electronics themed responses (for the fun of it). Feel free to change the responses to anything you desire!
Running the MagicBS2Board.bs2 code below magically turns your BASIC Stamp 2 into an amazing fortune-telling machine. Impress all your friends and family with your microcontroller’s ability to predict the future!
Keep in mind when using the Magic BS2 Board that if you’d like to ask it a second question, you’ll need to press the reset button on your board.
' -----[ Title ]-------------------------------------------------------------- ' MagicBS2Board.bs2 ' Ask a question & get a response from the wise Magic BS2 Board! ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ I/O Definitions ]---------------------------------------------------- LCDpin PIN 13 ' Serial LCD pin ' -----[ Variables ]---------------------------------------------------------- old0 VAR Bit ' Variable space for previous old1 VAR Bit ' tilt states counter VAR Nib ' Counter variable generateMessage VAR Word ' Variable space for randomizing displayMessage VAR generateMessage.NIB0 ' and displaying answers ' -----[ Initialization ]----------------------------------------------------- SEROUT LCDpin, 84, [22, 12] ' Initialize the LCD PAUSE 500 ' Wait for battery connection SEROUT LCDpin, 84, [128, "ASK A QUESTION &", ' Prompt user response 148, "SHAKE FOR ANSWER"] DO old0 = IN0: old1 = IN1 ' Loop until board is RANDOM generateMessage ' shaken & randomize answer LOOP UNTIL (old0 <> IN0 OR old1 <> IN1) SEROUT LCDpin, 84, [12] ' Clear the LCD ' -----[ Main Routine ]------------------------------------------------------- DO old0 = IN0: old1 = IN1 ' Save tilt states to variables PAUSE 100 ' Pause for human speeds IF old0 <> IN0 OR old1 <> IN1 THEN ' Compare to current state & RANDOM generateMessage ' if different, board is shaking counter = 0 ' Reset counter to 0 ELSE ' If they repeat, track with counter = counter + 1 ' counter variable IF counter > 10 THEN ' If it's been the same for 10 GOSUB Display_Answer ' cycles, display the answer ENDIF ENDIF LOOP ' Loop until shaking stops ' -----[ Subroutine - Display_Answer ]---------------------------------------- ' Displays answers based on value in displayMessage & ends the program Display_Answer: SELECT displayMessage CASE 0 SEROUT LCDpin, 84, [128, " PBASICALLY YES"] CASE 1 SEROUT LCDpin, 84, [128, " THE BOE-BOTS", 148, " SAY YES"] CASE 2 SEROUT LCDpin, 84, [128, " RESPONSE FRIED", 148, " ASK LATER"] CASE 3 SEROUT LCDpin, 84, [128, " DEBUGGING...", 148, " TRY AGAIN"] CASE 4 SEROUT LCDpin, 84, [128, " THE SCRIBBLERS", 148, " SAY NO "] CASE 5 SEROUT LCDpin, 84, [128, " PROPELLERY NOT"] CASE 6 SEROUT LCDpin, 84, [128, " REPLY STATIC-Y", 148, " ASK AGAIN"] CASE 7 SEROUT LCDpin, 84, [128, " CURRENTLY NO"] CASE 8 SEROUT LCDpin, 84, [128, " AMMETERS POINT", 148, " TO YES"] CASE 9 SEROUT LCDpin, 84, [128, "AS THE STINGRAYS", 148, " SEE IT - YES"] CASE 10 SEROUT LCDpin, 84, [128, " VOLTAGE SPIKE", 148, " CAN'T SAY NOW"] CASE 11 SEROUT LCDpin, 84, [128, " AS I SPIN IT", 148, " ...YES"] CASE 12 SEROUT LCDpin, 84, [128, " YOU WILL MEET", 148, " NO RESISTANCE"] CASE 13 SEROUT LCDpin, 84, [128, "DON'T CNT ON IT"] CASE 14 SEROUT LCDpin, 84, [128, "THE POLARITY IS", 148, " POSITIVE"] CASE ELSE SEROUT LCDpin, 84, [128, " IN-VARIABLE-Y", 148, " YES"] ENDSELECT END ' End the program
As mentioned above, if you want to ask the Magic BS2 Board a second question, you have to press the reset button on the board. This is sort of inconvenient when wanting to ask many questions in a row. Is there a way that you can modify the program so that the reset button doesn't have to be pushed? (Hint: Yes, there is!)
Here are some important things to ponder if attempting to improve the code:
If you get stuck, go back and run MagicBS2Board_Test.bs2 and monitor how the board responds in different situations. The key to solving these kinds of problems is to pick up on any patterns that emerge which can easily be replicated in code.
Give it a try!
Links
[1] http://www.parallax.com/go/PBASICHelp/
[2] http://www.parallax.com/downloads/tilt-sensor-documentation
[3] https://learn.parallax.com/sites/default/files/Files/Docs/Projects/Magic-BS2/MagicBS2Board.zip
[4] http://www.youtube.com/watch?v=vJUX9cvyYjU
[5] https://learn.parallax.com/project/led-memory-game