The Parallax WX ESP8266 Wi-Fi module opens up a whole new world of interactive Internet and web features to your microcontroller and robotics projects. The breadboard-friendly, 5 and 3.3 V compatible SIP package (32420S) works well with the BASIC Stamp 2 microcontroller.
The following tutorial will introduce you the Parallax WX Wi-Fi Module, and get it ready to work with your BASIC Stamp 2 microcontroller. Then you will create web interfaces for interacting with simple BASIC Stamp controlled pushbutton, LED, and servo circuits. New to HTML and/or Javascript? No problem. We'll take you through fundamentals so that you can learn to create and optimize your own custom webpages. Use the navigation below when you're ready to get started.
This guide assumes you’ve already got some BASIC Stamp + circuit building experience along with PBASIC programming. If not, here are some nice getting started tutorials and a full reference on PBASIC.
Once you have gone through this tutorial, you will be ready to integratre Wi-Fi capabilty into your BASIC Stamp projects to join the Internet of Things. If you have a Boe-Bot Robot, you can interface it with your smart phone.
Always use the latest versions of the module firmware and an up-to-date example code set.
Follow the checkmarks below to obtain the latest files and make note of where you unzip them. We will be updating your firmware a bit later on in these tutorials.
NOTE: Google’s Chrome web browser is recommended for these Module + BS2 tutorial activities. It can be downloaded and installed from https://www.google.com/chrome/browser/.
STOP: Complete each check mark in order below! Do not connect the module until you reach the appropriate step, or you may damage your Wi-Fi Module.
With the Board of Education, you can connect the WX Wi-Fi module to the AppMod Header (marked X1) or to the breadboard.
' {$STAMP BS2} ' {$PBASIC 2.5} END
It is possible to build the same circuit on the Board of Education breadboard. However, this leaves much less room for other breadboard circuits, so you may need to create your own alternative parts placements in later activities.
' {$STAMP BS2} ' {$PBASIC 2.5} END
Now we need our computer to join our module's network:
The page should display "Updating…" for a few seconds, then "Updating done. Rebooting…" When it returns to the original "Please select an .ota file to load…", it means the update was successfully completed.
Click the Settings button, and make the following adjustments:
Now it's time to load a test webpage into your module. Locate the HTML files you downloaded with the firmware in the beginning of this tutorial series, and then follow the steps below:
Next, we'll load some test code into your BS2 that will allow you to interact with this webpage. Do not close it.
First let's load the test program into your BS2.
Now we'll check the connection between your BS2 and the webpage we had you open in the previous page. Make sure you have the page open and visible.
The BASIC Stamp counts upwards at about 4x per second. Every time you click the web page’s Enter button, the BASIC Stamp should send an updated (and higher) value.
In addition to an updated number in the web page, your BASIC Stamp programming software’s Debug Terminal should display that it sent a number each time you click the button:
You might have noticed that your computer cannot access the internet while it is part of the Wi-Fi module’s network. So, it’s better to have your computer and the Wi-Fi module both join another network that is able to access the Internet. After you do this, you’ll still be able to do all the same activities with the Wi-Fi module. The only difference will be instead of 192.168.4.1, you will have to use the IP address that the Wi-Fi network assigns your Wi-Fi module.
You may need to wait for a minute or two for the module to check for and display available networks.
The Wi-Fi module has 3 modes: AP, STA, and STA+AP. AP stands for access point, and that’s when the Wi-Fi module provides its own access point. In this mode, you can make your computer or phone join the Wi-Fi module's network and access its web pages. STA is short for station mode, and that’s when the Wi-Fi module has joined another access point and is a station on its Wi-Fi network. The other access point will assign the Wi-Fi module an IP address. From that point forward, you’ll use the IP address the module was assigned to access its web pages (instead of 192.168.4.1). STA+AP mode allows it to function as both an access point and a station. This mode should only be used for a brief period of time to search access points and join one.
Stay Secure! Once you have made the Wi-Fi module join another access point, you should switch to station mode (STA) immediately after you have noted the station IP address the Wi-Fi module was assigned by the network. This way, you can minimize the likelihood that hackers will try to use the module as a bridge into another network.There may be many networks available; scrolling up and down on the page will help you locate the network you want to join.
After the Wi-Fi module joins another network, it will show you the IP address the network assigned it. Make sure to record the IP address the Wi-Fi access point assigns your Wi-Fi Module. From here on out, you can use that in place of 192.168.4.1.
IMPORTANT: After the Wi-Fi Module has joined a network, you should note the Station IP Address, and then immediately switch to STA mode.
After the Wi-Fi module is in station mode, its Wi-Fi access point will no longer be available. So, make sure to connect your computer to the same Wi-Fi network you just connected the Wi-Fi module to. Then, make sure to always use the IP address the Wi-Fi module was assigned.
This primer introduces just enough HTML to help get you started with creating web pages that can interact with your BASIC Stamp + Wi-Fi Module. To help keep the focus on the code, we’ll only include the parts you’ll need to make the web page communicate with a microcontroller, and leave out any additional features.
The recommended software for these exercises includes the Google Chrome web browser and the text editor provided by your operating system: Windows Notepad, Mac TextEdit, Ubuntu (Linux) gedit. If you have a Chromebook, find the Caret app in the Chrome Web Store and add to Chrome.
Here is HTML code that displays text in a web page.
<html> Hello, this is a web page. </html>
Now that your HTML file has been saved, let’s view it in Chrome.
<html> <h1>Page Heading</h1> <p>Paragraph text.</p> </html>
This is an opening html tag <html>. This is a closing html tag </html>. The content between those two tags can be in hypertext markup language, which is abbreviated html. In html, the <pre><h1>...</h1></pre> opening and closing tags make the browser display text between them as a level 1 heading. For paragraph text, you can use <p>...</p>.
You can do lots of great things with HTML, and here are some tutorials that start simple and cover the topics you’ll need to make your pages awesome:
Like the HTML primer, this one introduces just enough JavaScript to help get you started and familiarize you with another component of webpage design for your module. The w3schools.com site will have lots more examples for you to try.
Html also has features for creating interface elements like buttons and checkboxes. Here is an example that creates a button with the <button>…</button> tags. The button doesn’t actually do anything yet. For that, we’ll need Javascript.
<html> <p>This button doesn't do anything yet.</p> <p>The next program will make it do something.</p> <button>Button</button> </html>
Javascript is code you can embed in an HTML document to make it do things automatically. Here is an example that makes an alert box pop up when you click the button.
Some browsers will give you an option to prevent a site from displaying popup alert windows. For the purpose of these lessons, you need to allow your browser to show popup alerts – at least temporarily.
<html> <p>Click button to see alert popup message.</p> <button onclick = "showAlert()">Alert Popup</button> <script> function showAlert() { alert('This is an alert!'); } </script> </html>
A JavaScript function named showAlert was added between <script>...</script> tags. The code in this function is contained by curly braces { }. Inside this function, there’s one JavaScript method call - alert(‘This is an alert!’);
Changing <button> to <button onclick = “showAlert()”> adds an onclick event to the button tag to make it call the showAlert function when the button is clicked.
You can do even more great things with a combination of JavaScript and HTML. So, here are some JavaScript tutorials that also start simple and cover the topics you’ll need to make your pages and IoT applications awesome:
One common task for Internet of Things (IoT) applications is for a page to send information to a “thing” on the internet. Whether it’s a web-controlled robot, a remote-controlled alarm system, or whatever else you can imagine, the principle is pretty much the same: the JavaScript code has to be able to accept an input, and send information to the Internet thing about the input it received.
Before sending info to the BASIC Stamp through the Wi-Fi module, let’s start with using JavaScript to change text in a web page.
<html> <button onclick = "changeText()">Change Text</button> <p id = "myText">Click button to change this text.</p> <script> function changeText() { document.getElementById("myText").innerHTML = "Hey, look, the text changed!!!"; } </script> </html>
In this example, the paragraph <p> tag was expanded to <p id = “myText”>. With this identifier, the JavaScript can modify this paragraph element using document.getElementById(“myText”).innerHTML = “Hey, look, the text changed!!!”;
In JavaScript, document is an example of an object. Objects have methods, which are actions that can be performed on their data, like getElementById(“myText”), which finds the element with the myText ID. Objects also have properties, and innerHTML is an example of one of the document object’s properties. By setting that innerHTML equal to “Hey, look, the text has changed!!!”, it replaces the existing innerHTML - Click button to change this text.”
We’ve given HTML button and paragraph elements IDs so that JavaScript can access and modify them. In this example, JavaScript uses a text input’s ID to get information, adds some text to it, and then displays that text in the web page.
<html> <p>Type something, then click Enter: </p> <input type = "text" id = "textField"> <button onclick = "changeText()">Enter</button> <p id = "myText">Waiting...</p> <script> function changeText() { var x = document.getElementById("textField").value; document.getElementById("myText").innerHTML = "You typed: " + x; } </script> </html>
This creates the text input and gives it an ID <input type = "text" id = "textField">. The button and paragraph also have IDs: <button onclick = "changeText()">Enter</button> and <p id = "myText">Waiting...</p>.
Inside the changeText function, var x = document.getElementById("textField").value declares a variable named x that receives the value contained in the text input. Next, document.getElementById("myText").innerHTML = "You typed: " + x; adds “You typed: “ to whatever you typed in the text input and puts it in the paragraph with the myText ID.
This application of client server communication through JavaScript is called AJAX, and there’s some great tutorials on it too:
Now that you can use a program to modify and display information to a page, you can also modify and send information to the BASIC Stamp.
This is going to be similar to what you did in the Load a Test Page into the Module section.
Want to use the Enter key as a shortcut to clicking Send? Change this line:
<input type = "text" id = "textField" maxlength = "5">
...to:
<input type = "text" id = "textField" maxlength = "5" onchange = "changeText()">
One way that a web page can transmit information like button clicks and text to a server is through an HTTP POST request. An example of this you might be familiar with is if you type into a search field, and ?search=WhatYouTyped appears after the .html in the web address. In some pages do not show that in response to a search because they’ll send the text invisibly through a part of the HTTP POST called the post body, which is what this example does.
Most of the html and JavaScript works the same way that it did in the section you just finished (06-text-enter-display from the Relay Information with JavaScript section). One of the parts that changed is that now, if you type “Hi!” and click the button, the changeText function:
This is a name-value pair that the BASIC Stamp program is expecting in an HTTP POST request that contains the path “/fptm”. So, the line with httpPost(“/fptm”, msg); passes “/fptm” and the msg variable, which is currently storing “txt=Hi!”. The httpPost function receives that path and parameter, and sends them to the Parallax Wi-Fi module web server as a post request.
The text highlighting in this code example is provided by Notepad++, available from notepad++.org [16].
There are three important pieces of this JavaScript you’ll need for your BS2:
1) Inside your BASIC Stamp Code, you’ll need to set #DEFINE POSTS = 1, which adds the variables and subroutines your program will need to support post requests.
2) The Listen_Setup subroutine will need the address of a string command (CMD) that tells the Wi-Fi module to LISTEN for HTTP requests with the path /fptm, which is short for from page to microcontroller. A carriage return is required to complete a serial command to the Wi-Fi module.
3) The Wi-Fi module can filter out the “txt=” part of the POST request so that your BASIC Stamp just receives “hello”, “bye” and other things you typed.
Path can be /fptm* to allow for different types of information delivered on different paths. Since the string comparisons for this take more code and memory, we’ll examine it more closely later.Your PBASIC code will need to store a listener ID, and 6 characters for a string of up to 5. The PAUSE 1000 prevents certain operating systems from thinking a serial plug and play device is trying to connect. GOSUB Break sends a Break condition to the Wi-Fi Module to tell it to communicate serially with a microcontroller.
The Listen_Setup subroutine takes care of sending the ListenToPg DATA to the Wi-Fi module. Just set eeAddr to ListenToPg, then call the Listen_Setup subroutine. It will place a value in a variable named id. Copy this value to msgId for use at various places in the program. Up to 4 ID values are available, from 1 to 4. If id stores 0, it means that something went wrong, so the program doesn’t continue.
If Listen_Setup contained a valid id, the program continues to the main loop, which repeatedly calls the Poll_Events subroutine and conditionally executes other code depending on the values of op, id, and handle. Since only POSTS are supported in this program, Poll_Events can only return “P” for POST, “N” for nothing, or “E” for ERROR. If op is equal to “P”, it’s a POST request, and if the id variable is equal to the msgId variable (from GOSUB Listen_Setup), then, the program knows it came though on the /fptm path, and it’s time to start processing it.
For a full list of possible responses, see the “Serial Protocol” section of the Parallax Wi-Fi Module API document [17].
To process the post request, set eeAddr to MsgKey (that’s “txt”), and then call GOSUB Post_Request_Start. Next, use a SERIN command to capture the HTTP POST request’s value that corresponds to the “txt” key. Examples of value would be “hello”, “bye”, andy anything else (up to 5 characters) that you type into the page’s field and then click the Enter button. SERIN FromDo, Baud, 250, Timeout, [Wait($FE, “=”), WAIT(“,”), STR textStr\6\CR] waits for up to .25 seconds for a reply that starts with 0xFE’,’. Then, it waits for a comma, and loads up to the next six characters received into textStr, but terminates early if a CR is received.
Below the loop, you will find a collection of constants, variables, and subroutines that allow your code to focus on the basics, like sending a break, setting up a listener, and polling for and processing events.
The information below shows the the transmitter (BS2 or WX) along with a brief description of the message, the actual base-16 hexadecimal values, and the constant names in the PBASIC program. To find out more about each of the serial values and what they mean, check the Parallax Wi-Fi Module Serial API.
Message: BS2: Break condition
Hex: [0][0][0][0][0]
Constants: [0][0][0][0][0]
Message: BS2: Listen for /fptm path ; WX: Success, listener ID 1
Hex: [fe][e7][f7]/fptm[0d] ; [fe]=S,1[0d]
Constants: [CMD][LISTEN][HTTP]/fptm[CR] ; [CMD]=S,1[CR]
Message: BS2: Poll listener IDs ; WX: No requests
Hex: [fe][ec][0d] ; [fe]=N,0,0[0d]
Constants: [CMD][POLL][CR] ; [CMD]=N,0,0[CR]
Message: BS2: Poll listener IDs ; WX: POST request handle 5, ID 1
Hex: [fe][ec][0d] ; [fe]=P,5,1[0d] ; [fe][e6]5,txt[0d]
Constants: [CMD][POLL][CR] ; [CMD]=P,5,1[CR] ; [CMD][ARG]5,txt[CR]
Message: BS2: Ask for txt in name ; WX: Success, txt=Hi!
Hex: [fe]=S,Hi![0d] ; [fe][e5]5,200,2[0d]OK ; [fe]=S,0[0d]
Constants: [CMD]=S,Hi![CR] ; [CMD][REPLY]5,200,2[CR]OK ; [CMD]=S,0[CR]
Message: BS2: Handle 5 200 OK (success)* ; WX: Success reply processed
Hex: [fe][ec][0d] ; [fe]=S,5,0[0d]
Constants: [CMD][POLL][CR] ; [CMD]=S,5,0[CR]
Message: BS2: Poll listener IDs ; WX: Success, handle 5 confirmed
Hex: [fe][ec][0d] ; [fe]=N,0,0[0d]
Constants: [CMD][POLL][CR] ; [CMD]=N,0,0[CR]
Message: BS2: Poll listener IDs ; WX: No requests
Hex: N/A
Constants: N/A
* Reply to handle 5 with the value 200 (success) and 2 characters of text “OK” which can be displayed in the web page’s developer console.
An HTML page that can send “hello” or “bye” to the BASIC Stamp can just as easily control circuits, like indicator lights. For example, with the LEDs connected to P7 and P9 as shown, the web page can send io=pin7state1 to make an LED connected to P7 turn on.
Instead of a text field, this example gets its user input from textboxes. Click the checkbox once, and a checkmark appears and the light turns on. Click it again, and the checkbox disappears and the light turns off. With each click of a checkbox, the message the page sends the BASIC Stamp (like io-pin7,state1) gets displayed in the page too.
Keep in mind: If you followed the instructions in the Join Another Wi-Fi Network section, you’ll have to replace 192.168.4.1 with the Wi-Fi module’s station IP address.
The HTML and JavaScript is very similar to the previous example. Aside from some variable and function name changes, the main differences are in how the checkboxes are handled.
When a given checkbox is clicked, the onclick event calls the ledVals function, passing the button’s id -either 7 or 9. The paragraph with the ledval ID will hold a copy of the text that gets sent to the BASIC Stamp.
The PBASIC program running in the BASIC Stamp will have a listener filtering for HTTP POSTs with a path named “/leds”. It also has code that expects a message like “io=pin7state1” to turn the P7 LED on, “io=pin7state0” to turn it off, and so on. So the ledVals has to assemble a string with that with the io=pin#state# information, and pass that and the “/leds” path to the httpPost function.
When you click one of the checkboxes, html calls ledVals function, passing its checkbox id (either 7 or 9) to the ledVals pinId parameter. Then, var state = document.getElementById(pinId).checked copies the state of that checkbox (true or false) into a variable named state. Next, var nameVal = “io=pin” + pinId “ “state” + Number(state) uses all that information to put together the “io=pin#state#”. After printing the nameVal string to the ledval paragraph with document.getElementById…, the httpPost(“/leds”, nameVal) function call passes the “/leds” path and the nameVal variable to the httpPost function. Remember, the nameVal variable is the one that contains a string that’s something like “io=pin7state1”.
The checked property is boolean, that’s true or false. Number(led) converts it to a 1 or 0. The JavaScript responds to the fact that strings are being added together by automatically converting to “1” or “0” before appending the string.Here’s the httpPost function. It transmits the “/leds” path and the param string, which will contain a string like “io=pin7state1” to the Parallax Wi-Fi module that’s hosting the web page, and the module in turn relays that information to the BASIC Stamp.
The string “io=pin7state1” is considered a post parameter that consists of a name-value pair. The name is “io” and the value is “pin7state1”.
The DATA directive for setting up the HTTP listener is similar to the previous example. Since the web page is sends the posts with the url set to the “/leds” path, the PBASIC DATA directive has “/leds” as part of its ListenerLeds setup string. After sending the break condition, the program sets the HTTP Listener by:
Variables for the actual LED light control are ioPin and state. After initializing them, the main loop repeatedly calls the Poll_Events subroutine. When Poll_Events places “P” in the op variable and a value that matches ledId in the id variable, the program can process the post request. It starts by setting eeAddr to ioKey and then calls the Post_Request_Start subroutine. This tells the Parallax Wi-Fi module to strip the io from the post reply and just send the value part of the name value pair, which will be something like “pin7state1”. Then, a SERIN command that waits for the CMD character, followed by “=”. After that it uses DEC ioPin to throw away the characters in “pin” and just put the 7 or 8 value in the ioPin variable. Then, DEC state throws away the characters in “state” and puts the 1 or 0 following it into the state variable. After that the page needs acknowledgement of the post request, which is completed with a call to the Post_Request_Ack subroutine.
After the ioPin and state variables have been received, they are displayed with a DEBUG command. Then, the if state = 1...endif block turns the light in question on or off. For example, if ioPin is 7 and state is 1, HIGH ioPin becomes HIGH 7. For lots more information on HIGH and LOW turn the lights on/off, see Chapter 2 in What’s a Microcontroller [4].
With just a few small tweaks to the JavaScript and PBASIC, that light control with checkboxes app can be transformed into slider control of servo position.
Keep in mind: If you followed the instructions in the Join Another Wi-Fi Network section, you’ll have to replace 192.168.4.1 with your IP address.
This is the HTML that displays the slider and the angle. When the slider is adjusted, the onchage=”servoPosition(id)” passes the id of the slider to the servoPosition function’s sliderID parameter.
<H2>Servo</H2> Position: 150 <input type="range" id="position" min="30" max="150" value="90" onchange="servoPosition(id)"> 30
The servoAngle var get’s the slider’s value with document.getElementById(sliderId).value. The slider actually counts from 30 to 150, so servoAngle = (150 - servoAngle) + 30 calculates what the angle we really want is. For example, when the slider is ⅓ of the way from left to right, the range type returns 70, but we really want that to be 110. With servoAngle = (150 - servoAngle) + 30 we get 110 = 150 - 70 + 30. After that, nameVal = “angle=” + servoAngle creates the name value pair parameter to send to the httpPost function. For example, with the slider set to ⅓ of the way from left to right, it might send “angle=110”. The PBASIC has a listener set up to monitor HTTP POST requests witht he “/servo” path, so the httpPost call is httpPost(“/servo”, nameVal).
function servoPosition(sliderId) { var servoAngle = document.getElementById(sliderId).value; servoAngle = (150 - servoAngle) + 30; var nameVal = "angle=" + servoAngle; document.getElementById("servoval").innerHTML = nameVal; httpPost("/servo", nameVal); }
As with the previous messages and lights, the information about where the web page wants to position the servo will come through as HTTP POST requests, so the #DEFINE POSTS is set to 1. This incorporates the code below the “Wi-Fi support below” line that handles POST requests.
' Page Controls Servo Host Host.bs2 ' Allows page-controls-servo.html to control servo position through ' a range (slider) control. ' {$STAMP BS2} ' Target = BASIC Stamp 2 ' {$PBASIC 2.5} ' Language = PBASIC 2.5 ' I/O connections & baud rate. ToDI CON 2 ' BS2 P11 -> Wi-Fi DI FromDO CON 4 ' BS2 P10 <- Wi-Fi DO ' Select which features to support. #DEFINE POSTS = 1 ' HTTP POST requests #DEFINE GETS = 0 ' HTTP GET requests #DEFINE WEBSOCKETS = 0 ' WebSockets #DEFINE PATHS = 0 ' Path text comparisons #DEFINE DEBUGS = 0 ' Debug Terminal Info
The setup is also almost the same as the previous two examples, just a different name for the setup string DATA, the ID, and a different path -”/servo”.
' Wi-Fi setup and initialization ListenSErvo DATA CMD, LISTEN, HTTP, ' String to set up listener ID "/servo", CR ServoKey DATA "angle", CR ' I/O message key search string servoId VAR Nib Restart_Point: ' Beginning of program PAUSE 1000 ' Wait for certain OS COM ports DEBUG "Starting...", CR ' Display starting message GOSUB Break ' Break condition to Wi-Fi module eeAddr = ListenServo ' Prepare Listener setup string GOSUB Listen_Setup ' Set up listener servoId = id ' Store ID that was returned IF servoId > 0 THEN ' Check if listener setup success DEBUG "servoIdId = ", DEC servoId, CR, CR ELSE DEBUG "Error setting up listener!" END ENDIF
The Main loop checks if there are any POST requests coming from with the “/servo” path, and if so, it puts the angle information in its servoAngle variable with SERIN FromDO, Baud, msTimeout, Warning,' Get post data prameters [WAIT(CMD, "="), DEC servoAngle]. Of course, this command comes between the required Post_Reqeust_Start and Post_Request_Stop function calls.
' Servo setup and initialization servoPin CON 13 ' Servo constant and variables servoAngle VAR Word servoPulse VAR Word servoAngle = 45 ' Initialize servo angle DO ' Main loop GOSUB Poll_Events ' POLL for recent events IF op = "P" AND id = servoId THEN ' If POST request pending IF(id = servoID) THEN eeAddr = ServoKey ' Set to filter for txt key GOSUB Post_Request_Start ' Initialize POST request SERIN FromDO, Baud, msTimeout, Warning,' Get post data parameters [WAIT(CMD, "="), DEC servoAngle] GOSUB Post_Request_Ack ' Acknowledge POST DEBUG "servoAngle = ", ' Display LED values DEC servoAngle, CR ENDIF ENDIF ' end op = 0 & id = ledId servoPulse = 300 + (servoAngle * 5) PULSOUT servoPin, servoPulse LOOP ' ========[ Your code above ]=============================================== ' ========[ Wi-Fi support below ]===========================================
The position the Parallax Standard Servo holds increases by 1 degree per 10 microseconds of pulse width increase with 1500 being about 90 degrees. Since PULSOUT units are in 2 microsecond units, the 0 to 180 range is PULSOUT pin, 300 to PULSOUT pin, 1200. Try substituting some values into servoPulse = 300 + (servoAngle * 5). For example, servoAngle = 0 should make servoPulse 300. Likewise, servoAngle = 180 should make servoPulse 1200, servoAngle = 90 yields 750, and so on... PULSOUT servoPin, servoPulse sends the corresponding control pulse to the servo connected to servoPin (13).
Up to this point, your page has been sending information to the microcontroller host with HTTP POST requests. There’s also a way for the page to ask the microcontroller for information with HTTP GET requests. Here is an example where each time you click the Update button, the page asks for, gets, and displays a new value from the BASIC Stamp 2.
Reminder: If you followed the instructions in the Join Another Wi-Fi Network section, you’ll have to replace 192.168.4.1 with your IP address.
Since the BASIC Stamp program counts upwards at several times per second, the number should be higher each time you click the button.
Don’t want to have to click the button to see the value updated? The page can do it automatically. Here’s an example that updates every 3 seconds.
Note: it’s probably not a good idea to try to see how fast you can make this go, because it can end up making the application unresponsive. We have websockets (introduced soon) to establish a communication line that’s much more streamlined than HTTP requests.
The HTML has a button with an onclick event to call a function in the JavaScript called getFromMCU. The JavaScript updates the paragraph with the value ID as soon as it gets the reply from the microcontroller.
Using this JavaScript is pretty easy. In getFromMcu, you give it the path, “/tpfm” in this case, which is an abbreviation of “to page from microcontroller. The reply from the BASIC Stamp will appear inside the response parameter of useMcuReply(response) when it’s ready. The “when it’s ready” part depends on network traffic and also how long the BS2 takes to get around to answering. For more info on how this code works, there’s an Advanced Topic after an explanation of the BASIC Stamp 2 code.
Since the page we have here isn’t making any HTTP POST requests, #define POSTS has been set to 0. Conversely, since the page is making HTTP GET requests, #define GETS has been set to 1 to add the GET subroutines to the application. Aside from that, setting up a listener for GET requests is the the same process as setting it up for POST requests. The only difference is that there’s no key string accompanying GET requests.
Inside the main loop, the code is adds 1 to a variable named val ever ¼ second and then checking for a “G” in the op variable after a call to Poll_Events. If the op variable does contain a “G”, it means the Wi-Fi module has received an HTTP GET request from one if its listener IDs. Just like there’s a Post_Request_Start and Post_Request_Ack for handling POST requests, there’s also a Get_Request_Start and Get_Request_Ack for handling GET requests. The difference is that instead of POSTing information to the server (our BASIC Stamp 2), this page is GETting information. Before calling Get_Request_Start it’s important to set charCount to the number of characters the reply to the GET request will contain. Then, between Get_Request_Start and Get_Request_Ack, SEROUT ToDi, Baud, [DEC5 val]. Note that the because charCount was 5, the SEROUT sends DEC5 val.
The true inside req.open(“GET, path, true) means that the request will get processed asynchronously. Asynchronously means that the the httpGet function won’t wait till everything is ready because other things and scripts in a given web page might need attention in the meantime. So, the main thread actually executes everything inside the httpGet function right away and returns. However, after the httpGet function is done, req.onreadystatechange contains a function that gets run each time the readyState property advances through its five states.
According to AJAX - The onreadystatechange Event [19], the readyState property advances through five states: (0) request not yet initialized, (1) server connection established, (2) request received, (3) processing request, (4) request finished and response ready. There’s also a status property that’s 200 for “OK” or 404 for “page not found”.
The important thing to keep in mind is that each time the readyState changes, the function inside onreadystatechange automatically executes, checking if readyState has reached 4 and status is 200. When both of those are true, the response is ready.
When the response IS finally ready, the callback parameter contains useMcuReply. That’s the function the httpGet(“/tpfm”, useMcuReply) passed when it called httpGet, with the understanding that it would “call back” that usMcuReply function at some later time (when readyState is 4 and status is 200). At that point, callback(req.responseText) becomes useMcuReply(req.responseText).
If the BASIC Stamp replied with “42”, that’s what req.responseText will contain, and also what gets passed to the useMcuReply function’s response parameter. Inside useMcuReply, there’s JavaScript that would display “Value: 42” in the paragraph with the value label.
With a way for the page to ask the BASIC Stamp questions, it can ask for sensor states. In this example, the page asks the BASIC Stamp about pushbutton states every 3 seconds and updates the states of radio buttons and text displaying the button states.
If you only have two pushbuttons, you can borrow the stationing mode pushbutton connected to P14 and just temporarily leave P14 disconnected. If you do that, make sure to rebuild the P14 pushbutton after you are done with this activity.
Reminder: If you followed the instructions in the Join Another Wi-Fi Network section, you’ll have to replace 192.168.4.1 with your IP address.
To really speed things up, we’ll use WebSockets, but that’s in a later activity. For the time being, we can speed it up a little without risking data loss due to unpredictable times it takes for HTTP requests to complete.
Note: it’s probably not a good idea to try to see how fast you can make this go, because it can end up making the application unresponsive. We have websockets (introduced soon) to establish a communication line that’s much more streamlined than HTTP requests.
The HTML part of the page is a couple radio buttons. You might have seen radio buttons from online quizzes and questionnaires. You normally click them to select your answer or reply. In this example, the JavaScript will update their selected/not selected states according to whether the BASIC Stamp sends a 1 (pressed) or 0 (not pressed) for a given puhsbutton. As with other elements, the radio buttons have IDs so that the JavaScript can act one when a given button is pressed on the Board of Education.
The var myTimer = setInterval(getFromMcu, 2000) is one way to tell a web page to repeatedly call a function. There’s a lot more to this than meets the eye, but for now, just remember that this line causes the browser to automatically call the getFromMCU function every 2 seconds (2000 ms).
The getFromMcu function, which now gets called every 2 seconds, calls the httpGet function. Remember from the How it Works section in Page Requests Info from BS2 [20] that the BASIC Stamp’s program has code that detects when a GET request comes through with a path of “/tpfm” (to page from microcontroller). Remember also that the GET request will take an unknown amount of time and is designed to take care of that in the background while the main thread moves on, and that its second argument is the function to call when it’s done.
This is the httpGet function, which sends the GET request and then eventually reaches a readyState or 4 and calls the callback function, which in your program is useMcuReply. For more info on how this works, revisit the Page Requests Info from BS2 [20] activity’s Advanced Topic section.
The useMcuReply function is the one that gets called when the httpGet request is done and is really the only function that has changed since Page Requests Info from BS2. The response parameter is going to contain a reply from the BASIC Stamp, which is running Page Displays Buttons Host.bs2. That program replies with a string that contains the characters representing two binary digits. The four different strings that might come through are “11”, “10”, “01”, and “00”. The left digit is 1 if the P3 pushbutton is pressed, or 0 if it’s not. Likewise, the right digit is 1 if the P1 pushbutton is pressed, and 0 if it’s not. Keep in mind that’s what response contains.
The first thing useMcuReply does is change the HTML paragraph with the value ID to something like Value = 01. (That would be if the P1 button is pressed and held down.) The two lines that do that are var = val = document.getElementById(“value”); and val.innerHTML = “Value: “ + response. Assuming the response contained “01” that would cause Value = 01 to be displayed.
Next, a couple of if...else statements set the states of the radio buttons. In the case of “01”, the response.charAt(0) gets the leftmost 0th character from the string. Since that’s a “0”, the code sets the radio button with the P3 ID to false (unchecked or un-selected). The second if condition is true since charAt(1), which is the second character in the string, really is “1”. So it’ set’s the checked property in the radio button object with the P1 ID to true, causing it to appear to be checked or selected.
All the setup in Page Displays Buttons Host.bs2 is the same as it was in Val from Micro Host.bs2 from Page Requests Info from BS2. When an HTTP GET request comes through requesting the resource from the “/tpfm” path, the Poll_Events subroutine stores a value in the id variable that matches getsId. When that happens, the BASIC Stamp sets the program’s charCount variable to 2 since it’s going to send two characters (“11”, “10”, “01”, or “00”). The SEROUT command between the Get_Request_Start and Get_Request_Ack subroutines is what sends those two characters. BIN1 IN3 sends the character representation of the 1/0 stored in the IN3 variable, and BIN1 IN1 does the same for the IN1 variable. For lots more information on how these variables automatically store pushbutton states, see Chapter 3 in What’s a Microcontroller.
Links
[1] http://www.parallax.com/product/28832
[2] https://www.parallax.com/downloads/robotics-boe-bot-text
[3] http://www.parallax.com/product/90005
[4] https://www.parallax.com/downloads/whats-microcontroller-text
[5] https://www.parallax.com/product/27218
[6] https://www.parallax.com/downloads/basic-stamp-manual
[7] http://www.parallax.com/go/PBASICHelp/
[8] https://www.parallax.com/downloads/parallax-wi-fi-module-firmware-and-example-files
[9] http://192.168.4.1/files/numbers-from-micro.html
[10] http://www.w3schools.com/html/default.asp
[11] http://www.tutorialspoint.com/html5/index.htm
[12] http://www.w3schools.com/js/default.asp
[13] http://www.tutorialspoint.com/javascript/javascript_quick_guide.htm
[14] http://www.w3schools.com/ajax/default.asp
[15] http://www.tutorialspoint.com/ajax/index.htm
[16] http://notepad++.org
[17] https://www.parallax.com/downloads/parallax-wi-fi-module-firmware-guide
[18] http://192.168.4.1/update-ffs.html
[19] http://www.w3schools.com/ajax/ajax_xmlhttprequest_onreadystatechange.asp
[20] https://learn.parallax.com/tutorials/language/pbasic/parallax-wx-wi-fi-module-bs2/page-requests-info-bs2