In this example the analog value from the potentiometer will be read and shown on the graph on client side. In order to observe the results the interactive real time streaming graph will be developed.
First, we should connect the potentiometer to the board. Schematics is shown on the next figure:
The breadboard view is the following (here we should put pot, Arduino and breadboard as shown from left to right for further application). On the breadboard the minus (-) and (+) strips are established in the lower right part of the breadboard. This will be usefull later on.
We should declare new variable for desired value which pot represents on the server side (.js file):
var desiredValue = 0; // desired value var
We should enable analog pin:
console.log("Enabling analog Pin 0");
board.pinMode(0, board.MODES.ANALOG); // analog pin 0
Board analog value is read by the following command:
board.analogRead(0, function(value) {
desiredValue = value; // continuous read of pin A0
});
Definition of the function which sends the data to the last connected client:
wss.sendToLastWs = function sendToLastWs(data) {
if (wss.clients[wss.clients.length-1] !== undefined) { // if websocket exist
if (wss.clients[wss.clients.length-1].readyState === WebSocket.OPEN) { // if it is connected
wss.clients[wss.clients.length-1].send(data); // send to the last connected client - to only one client's websocket
}
}
};
Definition of the function that sends the data to all connected clients
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
};
Within the socket, we set the interval on which the values from the server are sent to the client (setInterval):
wss.on('connection', function (ws, req) { // start of wss code
messageJSON = {"type": "message", "content": "Srv connected, board OK"};
ws.send(JSON.stringify(messageJSON));
setInterval(sendValues, 40); // on 40ms we send message to client
}); // end of sockets.on connection
Function for sending desired value in the json form (we can test sendToLastWs and broadcast function):
function sendValues () {
wss.sendToLastWs(JSON.stringify({"type": "clientReadValues", "desiredValue": desiredValue}));
//wss.broadcast(JSON.stringify({"type": "clientReadValues", "desiredValue": desiredValue}));
};
Code for the first step:
var http = require("http").createServer(handler); // on req - hand
var fs = require("fs"); // variable for file system for providing html
var firmata = require("firmata");
const WebSocket = require('ws'); // for permanent connection between server and client
const wss = new WebSocket.Server({port: 8888}); // websocket port is 8888
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
};
wss.sendToLastWs = function sendToLastWs(data) {
if (wss.clients[wss.clients.length-1] !== undefined) { // if websocket exist
if (wss.clients[wss.clients.length-1].readyState === WebSocket.OPEN) { // if it is connected
wss.clients[wss.clients.length-1].send(data); // send to the last connected client - to only one client's websocket
}
}
};
var messageJSON;
console.log("Starting the code");
var board = new firmata.Board("/dev/ttyACM0", function(){
console.log("Connecting to Arduino");
console.log("Enabling analog Pin 0");
board.pinMode(0, board.MODES.ANALOG); // analog pin 0
});
function handler(req, res) {
fs.readFile(__dirname + "/example10a.html",
function (err, data) {
if (err) {
res.writeHead(500, {"Content-Type": "text/plain"});
return res.end("Error loading html page.");
}
res.writeHead(200);
res.end(data);
})
}
var desiredValue = 0; // desired value var
http.listen(8080); // server will listen on port 8080
board.on("ready", function() {
board.analogRead(0, function(value){
desiredValue = value; // continuous read of analog pin 0
});
wss.on('connection', function (ws, req) { // start of wss code
messageJSON = {"type": "message", "content": "Srv connected, board OK"};
ws.send(JSON.stringify(messageJSON));
//console.log(wss.clients[1]);
setInterval(sendValues, 40); // on 40ms we send message to client
}); // end of sockets.on connection
}); // end of board.on(ready)
function sendValues () {
//wss.sendToLastWs(JSON.stringify({"type": "clientReadValues", "desiredValue": desiredValue}));
wss.broadcast(JSON.stringify({"type": "clientReadValues", "desiredValue": desiredValue}));
};
In .html file we have only added the log of desired value:
ws.onmessage = function(event) {
var msg = JSON.parse(event.data); // string from ws is put to JSON
switch(msg.type) {
case "message":
log(msg.content); // add msg to div
break;
case "clientReadValues":
log(msg.desiredValue); // add msg with value to div
break;
}
};
<!DOCTYPE html>
<meta charset = utf8>
<html>
<head>
<title>Example with pozi</title>
</head>
<body>
<div id="print1"></div>
<br>
<script type="text/javascript">
"use strict"; // in order to use clasess
var divElement = document.getElementById("print1"); // var for div el.
var numberOfLinesBeforeScroll = 10;
var linesPrintCounter = 0;
function log(msg) {
var node=document.createElement("tr"); // we create the variable node as the a table row (tr)
var textnode=document.createTextNode(linesPrintCounter + " | " + msg); // we create element with the text adding the counter
node.appendChild(textnode); // adding text to "node", i.e. table row
divElement.insertBefore(node, divElement.childNodes[0]); // inserting into variable node
if (linesPrintCounter > numberOfLinesBeforeScroll-1) { // if the lines are more than limit -> start with scroll
divElement.removeChild(divElement.childNodes[numberOfLinesBeforeScroll]); // we remove the oldest printout
}
linesPrintCounter++; // increasing the number of printouts
}
let ws = new WebSocket("ws://192.168.254.149:8888"); // create socket - connect to it
var messageJSON;
ws.onmessage = function(event) {
var msg = JSON.parse(event.data); // string from ws is put to JSON
switch(msg.type) {
case "message":
log(msg.content); // add msg to div
break;
case "clientReadValues":
log(msg.desiredValue); // add msg with value to div
break;
}
};
</script>
</body>
</html>
The values from the potentiometer should be seen as in the following figure:
On client side, we declare, that onLoad the function load should be run:
<body onload="load()";>
In html part, we declare the canvas:
<canvas id="canvas1" width = "200" height = "100" style="border: 1px dashed #00c3c3;"></canvas>
Declaration of new variables and function load():
var potValue1 = 0; // value of first potentiometer
var x1 = new Array(); // array for x1 variable
var y1 = new Array(); // array for y1 variable
var canvas1;
var ctx1;
function load() { // function that is started, when we open the page
canvas1 = document.getElementById("canvas1");
ctx1 = canvas1.getContext("2d");
// initialization of graph with points
ctx1.lineWidth = "1";
ctx1.strokeStyle = "#ff0000";
// draw first time series initialization
for (var i=0; i<200; i++) {
x1[i] = i; // for x values are 0, 1, 2, ...
y1[i] = 0; // for y values are 0
};
};
Within WebSocket ws we make the graph:
potValue1 = msg.desiredValue;
// Draw graph *****************************************
ctx1.lineWidth = "1";
ctx1.strokeStyle = "#ff0000";
ctx1.clearRect(0, 0, canvas1.width, canvas1.height); // clear the canvas
ctx1.beginPath(); // to start drawing new line
y1.splice(0, 1); // on the position 0 in the field y1 we erase one value
y1[199] = potValue1; // new value is added at the end
for (var i=0; i<200; i++) {
ctx1.lineTo(x1[i], (100 - (y1[i] / 1023) * 100)); // 0,0 x,y coordinate is in upper left corner
};
ctx1.stroke(); // to draw the line
// End of draw graph***********************************
var http = require("http").createServer(handler); // on req - hand
var fs = require("fs"); // variable for file system for providing html
var firmata = require("firmata");
const WebSocket = require('ws'); // for permanent connection between server and client
const wss = new WebSocket.Server({port: 8888}); // websocket port is 8888
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
};
wss.sendToLastWs = function sendToLastWs(data) {
if (wss.clients[wss.clients.length-1] !== undefined) { // if websocket exist
if (wss.clients[wss.clients.length-1].readyState === WebSocket.OPEN) { // if it is connected
wss.clients[wss.clients.length-1].send(data); // send to the last connected client - to only one client's websocket
}
}
};
var messageJSON;
console.log("Starting the code");
var board = new firmata.Board("/dev/ttyACM0", function(){
console.log("Connecting to Arduino");
console.log("Enabling analog Pin 0");
board.pinMode(0, board.MODES.ANALOG); // analog pin 0
});
function handler(req, res) {
fs.readFile(__dirname + "/example10b.html",
function (err, data) {
if (err) {
res.writeHead(500, {"Content-Type": "text/plain"});
return res.end("Error loading html page.");
}
res.writeHead(200);
res.end(data);
})
}
var desiredValue = 0; // desired value var
http.listen(8080); // server will listen on port 8080
board.on("ready", function() {
board.analogRead(0, function(value){
desiredValue = value; // continuous read of analog pin 0
});
wss.on('connection', function (ws, req) { // start of wss code
messageJSON = {"type": "message", "content": "Srv connected, board OK"};
ws.send(JSON.stringify(messageJSON));
//console.log(wss.clients[1]);
setInterval(sendValues, 40); // on 40ms we send message to client
}); // end of sockets.on connection
}); // end of board.on(ready)
function sendValues () {
//wss.sendToLastWs(JSON.stringify({"type": "clientReadValues", "desiredValue": desiredValue}));
wss.broadcast(JSON.stringify({"type": "clientReadValues", "desiredValue": desiredValue}));
};
<!DOCTYPE html>
<meta charset = utf8>
<html>
<head>
<title>Example with potentiometer</title>
</head>
<body onload="load()";>
<div>
<canvas id="canvas1" width ="200" height = "100" style="border: 1px dashed #00c3c3;"></canvas>
</div>
<div id="print1"></div>
<br>
<script type="text/javascript">
"use strict"; // in order to use clasess
var divElement = document.getElementById("print1"); // var for div el.
var numberOfLinesBeforeScroll = 10;
var linesPrintCounter = 0;
var potValue1 = 0; // value of the first potentiometer
var x1 = new Array(); // array for x1
var y1 = new Array(); // array for y1
var canvas1;
var ctx1;
function log(msg) {
var node=document.createElement("tr"); // we create the variable node as the a table row (tr)
var textnode=document.createTextNode(linesPrintCounter + " | " + msg); // we create element with the text adding the counter
node.appendChild(textnode); // adding text to "node", i.e. table row
divElement.insertBefore(node, divElement.childNodes[0]); // inserting into variable node
if (linesPrintCounter > numberOfLinesBeforeScroll-1) { // if the lines are more than limit -> start with scroll
divElement.removeChild(divElement.childNodes[numberOfLinesBeforeScroll]); // we remove the oldest printout
}
linesPrintCounter++; // increasing the number of printouts
}
let ws = new WebSocket("ws://192.168.254.149:8888"); // create socket - connect to it
var messageJSON;
function load() { // function that is started, when we open the page
canvas1 = document.getElementById("canvas1");
ctx1 = canvas1.getContext("2d");
// initialization of graph with points
ctx1.lineWidth = "1";
ctx1.strokeStyle = "#ff0000";
// draw first time series initialization
for (var i=0; i<200; i++) {
x1[i] = i; // for x values are 0, 1, 2, ...
y1[i] = 0; // for y values are 0
};
};
ws.onmessage = function(event) {
var msg = JSON.parse(event.data); // string from ws is put to JSON
switch(msg.type) {
case "message":
log(msg.content); // add msg to div
break;
case "clientReadValues":
potValue1 = msg.desiredValue;
// Draw graph *****************************************
ctx1.lineWidth = "1";
ctx1.strokeStyle = "#ff0000";
ctx1.clearRect(0, 0, canvas1.width, canvas1.height); // clear the canvas
ctx1.beginPath(); // to start drawing new line
y1.splice(0, 1); // on the position 0 in the field y1 we erase one value
y1[199] = potValue1; // new value is added at the end
for (var i=0; i<200; i++) {
ctx1.lineTo(x1[i], (100 - (y1[i] / 1023) * 100)); // 0,0 x,y coordinate is in upper left corner
};
ctx1.stroke(); // to draw the line
// End of draw graph***********************************
log(msg.desiredValue); // add msg with value to div
break;
}
};
</script>
</body>
</html>
As the result, we should get plotted graph as well as logged value: