Here is another example of a sensor affecting an an HTML element's attrubute on a web page. This time, the shade over a light sensor controls the shade of a drawing canvas.
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.
This Propeller C program responds to GET requests from a browser that have a path of "/light" with a string that represents the decimal value of its light sensor measurement. It's very similar to the ones in Page Requests Info from Propeller [3] and Display Pushbutton States [4], so try those two pages to find out more about the mechanics of the program. The main differences are the name of the id variable (lightId), the name of the path "/light", and the sensor code. The sensor code uses rc_time to set the lightVal variable based on light the phototransistor senses. For more info on that, go back to the Sense Light [1] activity. As usual, wifi_print responds to the GET request, in this case with a decimal text representation of the lightVal variable's value.
#include "simpletools.h" #include "wifi.h" int event, id, handle; int lightId; int lightVal; int main() { wifi_start(31, 30, 115200, WX_ALL_COM); lightId = wifi_listen(HTTP, "/light"); print("getFromPageId = %d\n", lightId); while(1) { wifi_poll(&event, &id, &handle); print("event = %c, id = %d, handle = %d\r", event, id, handle); if(event == 'G') { if(id == lightId) { high(5); pause(1); lightVal = rc_time(5, 1); wifi_print(GET, handle, "%d\n", lightVal); print("Reqply to GET request:%d\n", lightVal); } } pause(500); } }
The JavaScript in this page makes the browser repeatedly send light level GET requests to the Propeller through the wi-Fi module.
The HTML part of the page has:
<body> <canvas id="myCanvas" width="300" height="150" style="border:1px solid gray;"> </canvas> <p id="textLightVal" style="width: 300px; text-align: center"> light = (waiting...)</p> <input type = "text" id = "lightHigh" maxlength = "5" value = "0" onchange = "setMaxMin()" style="width: 145px"> <input type = "text" id = "lightLow" maxlength = "5" value = "4000" onchange = "setMaxMin()" style="width: 145px; text-align: right"> Light range
The var myTimer = setInterval(getFromMcu, 1000) makes the browser execute the getFromMcu function once every second. Variables named lightMax, lightMin, and myRange are declared and initialized, and then the grayScaleCanvas function is called.
<script> var myTimer = setInterval(getFromMcu, 1000); var lightMax = 4000, lightMin = 0, myRange = lightMax - lightMin; grayScaleCanvas("position");
As with previous examples, getFromMcu is called repeatedly, which triggers a call to httpGet, this time with a path of "/light". When the microcontroller responds with a light value, the callback calls the useMcuReply function. This function has been adjusted to update the value displayed by the light = ... paragraph, displaying the number it received. It also calls the grayScaleCanvas function to set the shade of the canvas. For more about now these functions work, read Page Requests Info from Propeller. [3]
function useMcuReply(response) { document.getElementById("textLightVal").innerHTML = "light = " + response; var light = Number(response); grayScaleCanvas(light); } function getFromMcu() { httpGet("/light", useMcuReply); } function httpGet(path, callback) { var req = new XMLHttpRequest(); req.open("GET", path, true); req.onreadystatechange = function() { if (req.readyState == 4) if(req.status == 200) callback(req.responseText); else callback("Waiting..."); } req.send(null); }
The grayScaleCanvas function starts with a number from the Propeller in the lightMin to lightMax range. By default, that's 0 (very bright light) to 4000 (very dark shade). In the end, it has to assign the canvas.style.background property a value of "#000" (black), "#111" (very dark gray), and so on up through hexadecimal "#eee" (very light gray), "#fff" (white). Assuming the default values, it has to map a light sensor value, in the 0...4000 (bright...dark) range to its equivalent position in the hexadecimal f...0 range (decimal 15...0). Some examples: The smallest light sensor values (brightest light) will be close to 0, which map to hexadecimal f (decimal 15). The largest light values close to 4000 would map to 0. If the light sensor value was 3000 in a scale of 0 to 4000, the equivalent value in a scale of f to 0 would be 3, again on a scale of 15...0 or hexadecimal f...0.
function grayScaleCanvas(lightLevel) { var canvas = document.getElementById("myCanvas"); console.log("lightLevel (before) = ", lightLevel); if(lightLevel < lightMin) lightLevel = lightMin; if(lightLevel > lightMax) lightLevel = lightMax; console.log("lightLevel (trimmed) = ", lightLevel); lightLevel -= lightMin; lightLevel = myRange - lightLevel; console.log("lightLevel (after) = ", lightLevel); lightLevel *= 15; lightLevel = lightLevel / myRange; lightLevel = Math.round(lightLevel); console.log("myRange = ", myRange); var colorStr = lightLevel.toString(16); var colorStr = "#" + colorStr + colorStr + colorStr; canvas.style.background = colorStr; console.log(colorStr); }
After the lightLevel variable has been mapped from a scale of 0 to 4000 to its equivalent position in a scale of 15 to 0, var colorstr = lightLevel.toString(16) uses the toString method to convert it to a string that describes the value lightLevel stores in hexadecimal digits. The result could be "0", "1", "2", and so on up through "e", and "f". Then, var colorStr = "#" + colorStr + colorStr + colorStr makes a colorStr result that could be "#000", "#111", "#222", and so on up through "#eee", and "#fff". Last but not least, canvas.style.background = colorstr uses the colorStr to set the canvas' background property to black, a shade of gray, or white that corresponds to the light measurement the Propeller took and relayed.
The setMaxMin function gets called whenever the values in the text inputs are changed by the user. In other words, whenever you type something new into one of those "light range" fields, it triggers an onchange event that causes the setMaxMin function to get called. This function takes the text values from the lightHigh and lightLow fields, and calculates the lightMax, lightMin, and myRange values. The grayScaleCanvas function uses these values to map to the lightLevel value it receives from the Propeller to those "#000", "#111", "#222", ... , "#eee", "#fff" range of values.
function setMaxMin() { lightMin = Number(document.getElementById("lightHigh").value); lightMax = Number(document.getElementById("lightLow").value); console.log(lightMin); console.log(typeof lightMin); myRange = lightMax - lightMin; }
Links
[1] http://learn.parallax.com/tutorials/language/propeller-c/propeller-c-simple-circuits/sense-light
[2] http://192.168.4.1/update-ffs.html
[3] http://learn.parallax.com/tutorials/language/propeller-c/parallax-wx-wi-fi-module-prop-c/page-requests-info-propeller
[4] http://learn.parallax.com/tutorials/language/propeller-c/parallax-wx-wi-fi-module-prop-c/display-pushbutton-states