In this example the graphs of fuzzy rules will be added in order to better represent the fuzzy logic controller implementation. In the next figures the part of the GUI is shown, where different actual values are considered.
In this example socket.io library is used.
var http = require("http").createServer(handler); // on req - handvar io = require("socket.io").listen(http); // socket libraryvar fs = require("fs"); // variable for file system for providing htmlvar firmata = require("firmata");console.log("Starting the code");var board = new firmata.Board("/dev/ttyACM0", function(){ console.log("Connecting to Arduino"); board.pinMode(0, board.MODES.ANALOG); // enable analog pin 0 board.pinMode(1, board.MODES.ANALOG); // enable analog pin 1 board.pinMode(2, board.MODES.OUTPUT); // direction of DC motor board.pinMode(3, board.MODES.PWM); // PWM of motor board.pinMode(4, board.MODES.OUTPUT); // direction of DC motor});function handler(req, res) { fs.readFile(__dirname + "/example29.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 varvar actualValue = 0; // actual value varvar Kp = 0.55; // proportional factor of PID controllervar Ki = 0.008; // integral factor of PID controllervar Kd = 0.15; // differential factor of PID controllervar factor = 0.3; // proportional factor that deterimes speed of res.var pwm = 0; // set pwm as global variablevar pwmLimit = 254; // to limit value of the pwm that is sent to the motorvar err = 0; // errorvar errSum = 0; // sum of errors as integralvar dErr = 0; // difference of errorvar lastErr = 0; // to keep the value of previous error to estimate derivativevar controlAlgorithmStartedFlag = 0; // variable for indicating weather the Alg has benn sta.var intervalCtrl; // var for setInterval in global scopehttp.listen(8080); // server will listen on port 8080var sendValueViaSocket = function(){}; // var for sending messagesvar sendStaticMsgViaSocket = function(){}; // for sending static messagesboard.on("ready", function(){ board.analogRead(0, function(value){ desiredValue = value; // continuous read of analog pin 0});board.analogRead(1, function(value){ actualValue = value; // continuous read of analog pin 1});io.sockets.on("connection", function(socket) { socket.emit("messageToClient", "Srv connected, board OK"); socket.emit("staticMsgToClient", "Srv connected, board OK"); setInterval(sendValues, 40, socket); // on 40ms trigerr func. sendValues socket.on("startControlAlgorithm", function(numberOfControlAlgorithm){ startControlAlgorithm(numberOfControlAlgorithm); }); socket.on("stopControlAlgorithm", function(){ stopControlAlgorithm(); }); sendValueViaSocket = function (value) { io.sockets.emit("messageToClient", value); }; sendStaticMsgViaSocket = function(value) { io.sockets.emit("staticMsgToClient", value); }; }); // end of sockets.on connection}); // end of board.on ready////////////////////////////////////////////////fuzzy{var NFuzzyVars = 2;var NFuzzyOutputs = 1;var NFuzzySets = new Array(NFuzzyVars);NFuzzySets[0] = 3;NFuzzySets[1] = 3;var FSvalues = new Array(NFuzzyVars);for (var i=0;i!=NFuzzyVars;i++){ FSvalues[i] = new Array(NFuzzySets[i]); for (var j=0;j!=NFuzzySets[i];j++) { FSvalues[i][j] = new Array(3); }}var NRules = 3;var RBase = new Array(NRules);for (var i=0;i!=NRules;i++){ RBase[i] = new Array(NFuzzyVars);}var ValuesForFuzzy = new Array(NFuzzyVars);ValuesForFuzzy[0] = 0;ValuesForFuzzy[1] = 0;var AlphaCut = new Array(NFuzzySets[0]);var RN = 0;RBase[RN][0] = 0; RBase[RN][1] = 0; RN++;RBase[RN][0] = 1; RBase[RN][1] = 1; RN++;RBase[RN][0] = 2; RBase[RN][1] = 2; RN++;var FSpos1 = 125;var FSpos2 = 25;function resetFSvalues(){ FSvalues[0][0][0] = -FSpos1; FSvalues[0][0][1] = -FSpos1; FSvalues[0][0][2] = 0; FSvalues[0][1][0] = -FSpos1; FSvalues[0][1][1] = 0; FSvalues[0][1][2] = FSpos1; FSvalues[0][2][0] = 0; FSvalues[0][2][1] = FSpos1; FSvalues[0][2][2] = FSpos1; FSvalues[1][0][0] = -FSpos2; FSvalues[1][0][1] = -FSpos2; FSvalues[1][0][2] = 0; FSvalues[1][1][0] = -FSpos2; FSvalues[1][1][1] = 0; FSvalues[1][1][2] = FSpos2; FSvalues[1][2][0] = 0; FSvalues[1][2][1] = FSpos2; FSvalues[1][2][2] = FSpos2;}function getMRFromFSvalues(value,NumOfVar,NumOfSet){ if (NumOfSet == 0) { if (value < FSvalues[NumOfVar][NumOfSet][0]) { return 1; } else if (value > FSvalues[NumOfVar][NumOfSet][2]) { return 0; } else { return (FSvalues[NumOfVar][NumOfSet][2] - value) / (FSvalues[NumOfVar][NumOfSet][2] - FSvalues[NumOfVar][NumOfSet][1]); } } else if (NumOfSet == NFuzzySets[NumOfVar] - 1) { if (value < FSvalues[NumOfVar][NumOfSet][0]) { return 0; } else if (value > FSvalues[NumOfVar][NumOfSet][2]) { return 1; } else if (value < FSvalues[NumOfVar][NumOfSet][1]) { return (value - FSvalues[NumOfVar][NumOfSet][0]) / (FSvalues[NumOfVar][NumOfSet][1] - FSvalues[NumOfVar][NumOfSet][0]); } } else { if (value < FSvalues[NumOfVar][NumOfSet][0]) { return 0; } else if (value > FSvalues[NumOfVar][NumOfSet][2]) { return 0; } else if (value < FSvalues[NumOfVar][NumOfSet][1]) { return (value - FSvalues[NumOfVar][NumOfSet][0]) / (FSvalues[NumOfVar][NumOfSet][1] - FSvalues[NumOfVar][NumOfSet][0]); } else { return (FSvalues[NumOfVar][NumOfSet][2] - value) / (FSvalues[NumOfVar][NumOfSet][2] - FSvalues[NumOfVar][NumOfSet][1]); } }}function getDesiredValuesFuzzy(){ resetFSvalues(); for (var j=0;j!=NFuzzySets[0];j++) { AlphaCut[j] = 0; } for (var i=0;i!=NRules;i++) { var tempMR = 0; var tempMinMR = 1; for (var CurrentVar = NFuzzyOutputs;CurrentVar!=NFuzzyVars;CurrentVar++) { tempMR = getMRFromFSvalues(ValuesForFuzzy[CurrentVar],CurrentVar,RBase[i][CurrentVar]); if (tempMR < tempMinMR) tempMinMR = tempMR; } for (var CurrentVar = 0;CurrentVar!=NFuzzyOutputs;CurrentVar++) { if (tempMinMR > AlphaCut[RBase[i][CurrentVar]]) AlphaCut[RBase[i][CurrentVar]] = tempMinMR; } } for (var CurrentVar = 0;CurrentVar!=NFuzzyOutputs;CurrentVar++) { var FuzzyRange = FSvalues[CurrentVar][NFuzzySets[CurrentVar]-1][2] - FSvalues[CurrentVar][0][0]; console.log(FuzzyRange); var NIntervals = 100; var CoordinateMassSumm = 0; var MassSumm = 0; for (var i=0;i!=NIntervals;i++) { var TempCoordinate = FSvalues[CurrentVar][0][0] + FuzzyRange/NIntervals*i; var TempMass1 = 0; var TempMass2 = 0; for (var j=0;j!=NFuzzySets[CurrentVar];j++) { TempMass2 = getMRFromFSvalues(TempCoordinate,CurrentVar,j); if (TempMass2 > AlphaCut[j]) TempMass2 = AlphaCut[j]; if (TempMass2 > TempMass1) TempMass1 = TempMass2; } MassSumm += TempMass1; CoordinateMassSumm += TempCoordinate * TempMass1; } if (MassSumm != 0) ValuesForFuzzy[CurrentVar] = CoordinateMassSumm / MassSumm; if (ValuesForFuzzy[CurrentVar].isNaN) ValuesForFuzzy[CurrentVar] = 0; }}}////////////////////////////////////////////////unfuzzyfunction controlAlgorithm (parameters) { if (parameters.ctrlAlgNo == 1) { pwm = parameters.pCoeff*(desiredValue-actualValue); if (pwm > pwmLimit) {pwm = pwmLimit}; // to limit pwm values if (pwm < -pwmLimit) {pwm = -pwmLimit}; // to limit pwm values if (pwm > 0) {board.digitalWrite(2,1); board.digitalWrite(4,0);}; // direction if > 0 if (pwm < 0) {board.digitalWrite(2,0); board.digitalWrite(4,1);}; // direction if < 0 board.analogWrite(3, Math.abs(pwm)); } if (parameters.ctrlAlgNo == 2) { err = desiredValue - actualValue; // error as difference between desired and actual val. errSum += err; // sum of errors | like integral dErr = err - lastErr; // difference of error pwm = parameters.Kp1*err+parameters.Ki1*errSum+parameters.Kd1*dErr; // PID expression lastErr = err; // save the value of error for next cycle to estimate the derivative if (pwm > pwmLimit) {pwm = pwmLimit}; // to limit pwm values if (pwm < -pwmLimit) {pwm = -pwmLimit}; // to limit pwm values if (pwm > 0) {board.digitalWrite(2,1); board.digitalWrite(4,0);}; // direction if > 0 if (pwm < 0) {board.digitalWrite(2,0); board.digitalWrite(4,1);}; // direction if < 0 board.analogWrite(3, Math.abs(pwm)); } if (parameters.ctrlAlgNo == 3) { var errLast = err; err = desiredValue - actualValue; // error as difference between desired and actual val. errSum += err; // sum of errors | like integral dErr = err - lastErr; // difference of error if(errLast*err < 0) errSum = 0; if(errSum > 254/parameters.Ki2) errSum = 254/parameters.Ki2; if(errSum < -254/parameters.Ki2) errSum = -254/parameters.Ki2; pwm = parameters.Kp2*err+parameters.Ki2*errSum+parameters.Kd2*dErr; // PID expression console.log(parameters.Kp2 + "|" + parameters.Ki2 + "|" + parameters.Kd2); lastErr = err; // save the value of error for next cycle to estimate the derivative if (pwm > pwmLimit) {pwm = pwmLimit}; // to limit pwm values if (pwm < -pwmLimit) {pwm = -pwmLimit}; // to limit pwm values if (pwm > 0) {board.digitalWrite(2,1); board.digitalWrite(4,0);}; // direction if > 0 if (pwm < 0) {board.digitalWrite(2,0); board.digitalWrite(4,1);}; // direction if < 0 board.analogWrite(3, Math.abs(pwm)); } if (parameters.ctrlAlgNo == 4) { ValuesForFuzzy[1] = desiredValue - actualValue; FSpos1 = parameters.FSpos1; FSpos2 = parameters.FSpos2; console.log(parameters); getDesiredValuesFuzzy(); pwm = ValuesForFuzzy[0]; err = desiredValue - actualValue; // error as difference between desired and actual val. lastErr = err; // save the value of error for next cycle to estimate the derivative if (pwm > pwmLimit) {pwm = pwmLimit}; // to limit pwm values if (pwm < -pwmLimit) {pwm = -pwmLimit}; // to limit pwm values if (pwm > 0) {board.digitalWrite(2,1); board.digitalWrite(4,0);}; // direction if > 0 if (pwm < 0) {board.digitalWrite(2,0); board.digitalWrite(4,1);}; // direction if < 0 board.analogWrite(3, Math.abs(pwm)); }};function startControlAlgorithm (parameters) { if (controlAlgorithmStartedFlag == 0) { controlAlgorithmStartedFlag = 1; intervalCtrl = setInterval(function(){controlAlgorithm(parameters);}, 30); // call the alg. on 30ms console.log("Control algorithm has been started."); sendStaticMsgViaSocket("Control alg " + parameters.ctrlAlgNo + " started | " + json2txt(parameters)); }};function stopControlAlgorithm () { clearInterval(intervalCtrl); // clear the interval of control algorihtm board.analogWrite(3, 0); err = 0; // error as difference between desired and actual val. errSum = 0; // sum of errors | like integral dErr = 0; lastErr = 0; // difference pwm = 0; controlAlgorithmStartedFlag = 0; console.log("Control algorithm has been stopped."); sendStaticMsgViaSocket("Stopped.")};function sendValues (socket) { socket.emit("clientReadValues", { "desiredValue": desiredValue, "actualValue": actualValue, "pwm": pwm, "err": err, "errSum": errSum, "dErr": dErr, "AlphaCut":AlphaCut, "ValuesForFuzzy":ValuesForFuzzy });};function json2txt(obj) // function to print out the json names and values{ var txt = ''; var recurse = function(_obj) { if ('object' != typeof(_obj)) { txt += ' = ' + _obj + '\n'; } else { for (var key in _obj) { if (_obj.hasOwnProperty(key)) { txt += '.' + key; recurse(_obj[key]); } } } }; recurse(obj); return txt;}<!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><canvas id="canvas4" width = "200" height = "100" style="border: 1px dashed #00c3c3;"></canvas><br><canvas id="canvas2" width ="200" height = "100" style="border: 1px dashed #00c3c3;"></canvas> <canvas id="canvas5" width = "200" height = "100" style="border: 1px dashed #00c3c3;"></canvas><br><canvas id="canvas3" width = "200" height = "100" style="border: 1px dashed #00c3c3;"></canvas><canvas id="canvas6" width = "200" height = "100" style="border: 1px dashed #00c3c3;"></canvas><br></div><p></p>pCoeff: <input id="pCoeff" value="0.1" size="5" /><button id="buttonStartControlAlgorithm1" onClick="startControlAlgorithm1();">Start Ctrl Alg1</button><button id="buttonStopControlAlgorithm" onClick="stopControlAlgorithm();">Stop Ctrl Alg</button><p></p>Kp: <input id="Kp1" value="0.15" size = "5" />Ki: <input id="Ki1" value="0.0055" size = "5" />Kd: <input id="Kd1" value="0.25" size = "5" /><button id="buttonStartControlAlgorithm2" onClick="startControlAlgorithm2();">Start Ctrl Alg2</button><button id="buttonStopControlAlgorithm" onClick="stopControlAlgorithm();">Stop Ctrl Alg</button><p></p>Kp: <input id="Kp2" value="0.5" size = "5" />Ki: <input id="Ki2" value="0.008" size = "5" />Kd: <input id="Kd2" value="0.35" size = "5" /><button id="buttonStartControlAlgorithm3" onClick="startControlAlgorithm3();">Start Ctrl Alg3</button><button id="buttonStopControlAlgorithm" onClick="stopControlAlgorithm();">Stop Ctrl Alg</button><p></p>FSpos1: <input id="FSpos1" value="125" size = "5" />FSpos2: <input id="FSpos2" value="25" size = "5" /><button id="buttonStartControlAlgorithm4" onClick="startControlAlgorithm4();">Start Ctrl Alg4</button><button id="buttonStopControlAlgorithm" onClick="stopControlAlgorithm();">Stop Ctrl Alg</button><div id="divForStaticPrint"> </div><p></p><div id="divForPrint"></div><br><script type="text/javascript" src="/socket.io/socket.io.js"></script><script type="text/javascript">var potValue1 = 0; // value of the first potentiometervar potValue2 = 0; // value of the second potentiometervar x1 = new Array(); // array for x1var y1 = new Array(); // array for y1var x2 = new Array(); // array for x2var y2 = new Array(); // array for y2var x3 = new Array(); // array for x3 variablevar y3 = new Array(); // array for y3 variablevar canvas1;var canvas2;var ctx1;var ctx2;var pwm;var FSpos1=document.getElementById("FSpos1").value;var FSpos2=document.getElementById("FSpos2").value;// variable for P partvar x4 = new Array(); // array for x4 variablevar y4 = new Array(); // array for y4 variablevar canvas4;var ctx4;// variable for I partvar x5 = new Array(); // array for x5 variablevar y5 = new Array(); // array for y5 variablevar canvas5;var ctx5; // variable for D partvar x6 = new Array(); // array for x6 variablevar y6 = new Array(); // array for y6 variablevar canvas6;var ctx6;function load() { // function that is started, when we open the page canvas1 = document.getElementById("canvas1"); ctx1 = canvas1.getContext("2d"); canvas2 = document.getElementById("canvas2"); ctx2 = canvas2.getContext("2d"); // initialization for canvas3 canvas3 = document.getElementById("canvas3"); ctx3 = canvas3.getContext("2d"); // initialization for canvas4 canvas4 = document.getElementById("canvas4"); ctx4 = canvas4.getContext("2d"); // initialization for canvas5 canvas5 = document.getElementById("canvas5"); ctx5 = canvas5.getContext("2d"); // initialization for canvas6 canvas6 = document.getElementById("canvas6"); ctx6 = canvas6.getContext("2d"); // initialization of first graph 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 }; // initializaion of second graph for (var i=0; i<200; i++) { x2[i] = i; // x2 values are 0, 1, 2, ... y2[i] = 0; // for y2 values are 0 }; // initialization of xy3 variables for (var i=0; i<200; i++) { x3[i] = i; // x values are 0, 1, 2, ... y3[i] = 0; // for y values are 0 }; // initialize fourth graph arrays for (var i=0; i<200; i++) { x4[i] = i; // for x values are 0, 1, 2, ... y4[i] = 0; // for y values are 0 }; // initialize fifth graph arrays for (var i=0; i<200; i++) { x5[i] = i; // for x values are 0, 1, 2, ... y5[i] = 0; // for y values are 0 }; // initialize sixth graph arrays for (var i=0; i<200; i++) { x6[i] = i; // for x values are 0, 1, 2, ... y6[i] = 0; // for y values are 0 }; };var divForPrint = document.getElementById("divForPrint");// var for printing messagesvar numberOfLinesInLog = 20; // variable for the number of lines in log divvar counterOfLogs = 0; // variable for counting the logsfunction log(msg) { // function to print messages to div with implemented scroll var node=document.createElement("tr"); // we create variable node as tr (table row) var textnode=document.createTextNode(counterOfLogs + " | " + msg); // create elem. with text node.appendChild(textnode); // add to "node", i.e. table row divForPrint.insertBefore(node, divForPrint.childNodes[0]); // insert into variable divForPrint -> document.getElementById("divForPrint"); if (counterOfLogs > numberOfLinesInLog-1) { // if there are more numbers as e.g. 10 divForPrint.removeChild(divForPrint.childNodes[numberOfLinesInLog]); // remove the oldest printout } counterOfLogs = counterOfLogs + 1; // increase the counter of logs}var socket = io.connect("192.168.254.149:8080"); // connect via socketsocket.on("messageToClient", function (msg){ log(msg); // add msg to div});socket.on("staticMsgToClient", function(msg) { // when we recive static message document.getElementById("divForStaticPrint").innerHTML = "Status: " + msg; // we print to div});socket.on("clientReadValues", function(value) { potValue1 = value.desiredValue; potValue2 = value.actualValue; pwm = parseInt((value.pwm).toFixed(0), 10); // Draw graph No1 ***************************************** ctx1.lineWidth = "1"; ctx1.strokeStyle = "#ff0000"; ctx1.clearRect(0, 0, canvas1.width, canvas1.height); // clear the canvas // add legend to graph ctx1.font = "11px Arial"; ctx1.fillText("Desired", 70, 10); ctx1.beginPath(); // beginning of the short line for the legend ctx1.lineTo(50, 6); ctx1.lineTo(65, 6); ctx1.stroke(); ctx1.font = "11px Arial"; ctx1.fillText("Actual", 140, 10); ctx1.strokeStyle = "#00ff00"; ctx1.beginPath(); // beginning of the short line for the legend ctx1.lineTo(120, 6); ctx1.lineTo(135, 6); ctx1.stroke(); // add axis labels ctx1.fillText("<-" + 0 + "|" + 200 + "->", 150, 100-5); // display no. of points on x-axis // min on y-axis label ctx1.fillText(1023,5,11); ctx1.fillText(0,5,100-5); ctx1.strokeStyle = "#ff0000"; 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 No1 *********************************** // Draw graph No2 ***************************************** ctx1.strokeStyle = "#00ff00"; // green line ctx1.beginPath(); // to start drawing new line y2.splice(0, 1); // on the position 0 in the field y2 we erase one value y2[199] = potValue2; // new value is added at the end for (var i=0; i<200; i++) { ctx1.lineTo(x2[i], (100 - (y2[i] / 1023) * 100)); // 0,0 x,y coordinate is in upper left corner }; ctx1.stroke(); // to draw the line // End of draw graph No2 *********************************** // Draw graph No3 on canvas2 ***************************************** ctx2.lineWidth = "1"; ctx2.clearRect(0, 0, canvas2.width, canvas2.height); // clear the canvas // draw centerline at 0 ctx2.strokeStyle = "#add8e6"; ctx2.beginPath(); // draw centerline at 0 ctx2.lineTo(0, 50); // starting point ctx2.lineTo(200, 50); // ending point ctx2.stroke(); // add legend to graph ctx2.font = "11px Arial"; ctx2.fillText("PWM", 70, 10); ctx2.strokeStyle = "#0000ff"; ctx2.beginPath(); // beginning of the short line for the legend ctx2.lineTo(50, 6); ctx2.lineTo(65, 6); ctx2.stroke(); ctx2.strokeStyle = "#0000ff"; ctx2.beginPath(); // to start drawing new line y3.splice(0, 1); // on the position 0 in the field y we erase one value y3[199] = pwm; // new value is added at the end for (var i=0; i<200; i++) { ctx2.lineTo(x3[i], (100 - (255 + y3[i]) / 510 * 100)); // 0,0 x,y coordinate is in upper left corner }; ctx2.stroke(); // to draw the line // add axis labels ctx2.fillText("<-" + 0 + "|" + 200 + "->", 150, 100-5); // display no. of points on x-axis // min on y-axis label ctx2.fillText(255,5,11); ctx2.fillText(-255,5,100-5); // End of draw No3 on canvas2 *********************************** // Draw canvas3 as X **********************************************ctx3.clearRect(0, 0, canvas3.width, canvas3.height); // clear canvas only ONCE! // draw Xctx3.lineWidth = "1";ctx3.strokeStyle = "#add8e6";ctx3.beginPath(); // beginning of the linectx3.lineTo(10, 10); // starting pointctx3.lineTo(190, 90); // ending pointctx3.stroke(); // to put it on the graphctx3.beginPath(); // beginning of the linectx3.lineTo(10, 90); // starting pointctx3.lineTo(190, 10); // ending pointctx3.stroke(); // to put it on the graph// Draw canvas3 END ************************************// Draw canvas4 graph for P part **********************************************ctx4.clearRect(0, 0, canvas4.width, canvas4.height); // clear canvas only ONCE!var newvalue = 0;var range = 35;// draw line at coordinate 0ctx4.lineWidth = "1";ctx4.strokeStyle = "#000000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100, 0); // starting pointctx4.lineTo(100, 100); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#000000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(0, 90); // starting pointctx4.lineTo(200, 90); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#000000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(95, 10); // starting pointctx4.lineTo(105, 10); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100-FSpos2/range*100, 90); // starting pointctx4.lineTo(100, 10); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(FSpos2/range*100+100, 90); // starting pointctx4.lineTo(100, 10); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#00ff00"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100-FSpos2/range*100, 10); // starting pointctx4.lineTo(100, 90); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#00ff00"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100-FSpos2/range*100, 10); // starting pointctx4.lineTo(0, 10); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#0000ff"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(FSpos2/range*100+100, 10); // starting pointctx4.lineTo(100, 90); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#0000ff"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(FSpos2/range*100+100, 10); // starting pointctx4.lineTo(200, 10); // ending pointctx4.stroke(); // to put it on the graphvar errvalue = value.err*range/FSpos2*2;if(errvalue < -FSpos2/range*100/4){ctx4.lineWidth = "1";ctx4.strokeStyle = "#00ff00"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = 80/(FSpos2/range*100)*(errvalue+FSpos2/range*100)+10;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = -80/(FSpos2/range*100)*(errvalue)+10;if(errvalue > 0) newvalue = 90;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graph}else{ ctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = -80/(FSpos2/range*100)*(errvalue)+10;if(errvalue > 0) newvalue = 90;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graph ctx4.lineWidth = "1";ctx4.strokeStyle = "#00ff00"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = 80/(FSpos2/range*100)*(errvalue+FSpos2/range*100)+10;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graph}if(errvalue > FSpos2/range*100/4){ ctx4.lineWidth = "1";ctx4.strokeStyle = "#0000ff"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = -80/(FSpos2/range*100)*(errvalue-FSpos2/range*100)+10;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graph ctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = 80/(FSpos2/range*100)*(errvalue)+10;if(errvalue < 0) newvalue = 90;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graph}else{ctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = 80/(FSpos2/range*100)*(errvalue)+10;if(errvalue < 0) newvalue = 90;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#0000ff"; // light redctx4.beginPath(); // beginning of the linectx4.lineTo(100+errvalue, 90); // starting pointnewvalue = -80/(FSpos2/range*100)*(errvalue-FSpos2/range*100)+10;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graph}ctx4.lineWidth = "1";ctx4.strokeStyle = "#00ff00"; // light redctx4.beginPath(); // beginning of the linenewvalue = 80/(FSpos2/range*100)*(errvalue+FSpos2/range*100)+10;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100, newvalue); // starting pointctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the grapctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linenewvalue = -80/(FSpos2/range*100)*(errvalue)+10;if(errvalue > 0) newvalue = 90;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100, newvalue); // starting pointctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // light redctx4.beginPath(); // beginning of the linenewvalue = 80/(FSpos2/range*100)*(errvalue)+10;if(errvalue < 0) newvalue = 90;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100, newvalue); // starting pointctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graphctx4.lineWidth = "1";ctx4.strokeStyle = "#0000ff"; // light redctx4.beginPath(); // beginning of the linenewvalue = -80/(FSpos2/range*100)*(errvalue-FSpos2/range*100)+10;if(newvalue > 90) newvalue = 90;if(newvalue < 10) newvalue = 10;ctx4.lineTo(100, newvalue); // starting pointctx4.lineTo(100+errvalue, newvalue); // ending pointctx4.stroke(); // to put it on the graphctx4.fillText(-range,5,85);ctx4.fillText(range,180,85);ctx4.fillStyle = "#00ff00";ctx4.fillText(value.AlphaCut[0],5,38);ctx4.fillStyle = "#ff0000";ctx4.fillText(value.AlphaCut[1],5,50);ctx4.fillStyle = "#0000ff";ctx4.fillText(value.AlphaCut[2],5,62);// draw P/*ctx4.lineWidth = "1";ctx4.strokeStyle = "#ff0000"; // set red colorctx4.beginPath(); // to start drawing new liney4.splice(0, 1); // on the position 0 in the field y3 we erase one valuey4[199] = value.err; // new value is added at the endfor (var i=0; i<200; i++) { ctx4.lineTo(x4[i], (100 - (1024 + y4[i]) / 2048 * 100)); // 0,0 x,y coordinate is in upper left corner};ctx4.stroke(); // to draw the line*/ // END of draw canvas4 graph for P part ********************************************** // Draw canvas5 graph for I part **********************************************ctx5.clearRect(0, 0, canvas4.width, canvas4.height); // clear canvas only ONCE!newvalue = 0;range = 254;// draw line at coordinate 0ctx5.lineWidth = "1";ctx5.strokeStyle = "#000000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100, 0); // starting pointctx5.lineTo(100, 100); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#000000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(0, 90); // starting pointctx5.lineTo(200, 90); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#000000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(95, 10); // starting pointctx5.lineTo(105, 10); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#ff0000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100-FSpos1/range*100, 90); // starting pointctx5.lineTo(100, 10); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#ff0000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(FSpos1/range*100+100, 90); // starting pointctx5.lineTo(100, 10); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#00ff00"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100-FSpos1/range*100, 10); // starting pointctx5.lineTo(100, 90); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#00ff00"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100-FSpos1/range*100, 10); // starting pointctx5.lineTo(0, 10); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#0000ff"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(FSpos1/range*100+100, 10); // starting pointctx5.lineTo(100, 90); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#0000ff"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(FSpos1/range*100+100, 10); // starting pointctx5.lineTo(200, 10); // ending pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#000000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100+FSpos1/range*100, 90); // starting pointctx5.lineTo(100+FSpos1/range*100, 10); // starting pointctx5.stroke(); // to put it on the graphctx5.lineWidth = "1";ctx5.strokeStyle = "#000000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100-FSpos1/range*100, 90); // starting pointctx5.lineTo(100-FSpos1/range*100, 10); // starting pointctx5.stroke(); // to put it on the graphctx5.fillText(-range,5,85);ctx5.fillText(range,180,85);var cyclevalue = 0;ctx5.lineWidth = "1";ctx5.strokeStyle = "#00ff00"; // light redfor (var ii=-(100-FSpos1/range*100).toFixed()+2;ii<0;ii++){ ctx5.beginPath(); // beginning of the line ctx5.lineTo(100+ii, 90); // starting point newvalue = 80/(FSpos1/range*100)*(ii+FSpos1/range*100)+10; if(newvalue > 90) newvalue = 90; if(newvalue < 10+80*(1-value.AlphaCut[0])) newvalue = 10+80*(1-value.AlphaCut[0]); ctx5.lineTo(100+ii, newvalue); // ending point ctx5.stroke(); // to put it on the graph }ctx5.lineWidth = "1";ctx5.strokeStyle = "#ff0000"; // light redfor (var ii=-(100-FSpos1/range*100).toFixed()+2;ii<0;ii++){ ctx5.beginPath(); // beginning of the line ctx5.lineTo(100+ii, 90); // starting point newvalue = -80/(FSpos1/range*100)*(ii)+10; if(newvalue > 90) newvalue = 90; if(newvalue < 10+80*(1-value.AlphaCut[1])) newvalue = 10+80*(1-value.AlphaCut[1]); ctx5.lineTo(100+ii, newvalue); // ending point ctx5.stroke(); // to put it on the graph}ctx5.lineWidth = "1";ctx5.strokeStyle = "#ff0000"; // light redfor (var ii=0;ii<FSpos1/range*100;ii++){ ctx5.beginPath(); // beginning of the line ctx5.lineTo(100+ii, 90); // starting point newvalue = 80/(FSpos1/range*100)*(ii)+10; if(newvalue > 90) newvalue = 90; if(newvalue < 10+80*(1-value.AlphaCut[1])) newvalue = 10+80*(1-value.AlphaCut[1]); ctx5.lineTo(100+ii, newvalue); // ending point ctx5.stroke(); // to put it on the graph}ctx5.lineWidth = "1";ctx5.strokeStyle = "#0000ff"; // light redfor (var ii=0;ii<FSpos1/range*100;ii++){ ctx5.beginPath(); // beginning of the line ctx5.lineTo(100+ii, 90); // starting point newvalue = -80/(FSpos1/range*100)*(ii-FSpos1/range*100)+10; if(newvalue > 90) newvalue = 90; if(newvalue < 10+80*(1-value.AlphaCut[2])) newvalue = 10+80*(1-value.AlphaCut[2]); ctx5.lineTo(100+ii, newvalue); // ending point ctx5.stroke(); // to put it on the graph}ctx5.lineWidth = "2";ctx5.strokeStyle = "#000000"; // light redctx5.beginPath(); // beginning of the linectx5.lineTo(100+value.ValuesForFuzzy[0]/range*100, 90); // starting pointctx5.lineTo(100+value.ValuesForFuzzy[0]/range*100, 85); // starting pointctx5.stroke(); // to put it on the graph// END of draw canvas5 graph for i part **********************************************// Draw canvas6 graph for D part **********************************************ctx6.clearRect(0, 0, canvas6.width, canvas6.height); // clear canvas only ONCE! // draw line at coordinate 0ctx6.lineWidth = "1";ctx6.strokeStyle = "#add8e6"; // light greenctx6.beginPath(); // beginning of the linectx6.lineTo(0, 50); // starting pointctx6.lineTo(200, 50); // ending pointctx6.stroke(); // to put it on the graph // put on the legendctx6.font = "11px Arial";ctx6.fillText("dError/dt",70,10);ctx6.strokeStyle = "#00ff00";ctx6.beginPath(); // beginning of legend line drawctx6.lineTo(50, 6);ctx6.lineTo(65, 6);ctx6.stroke(); // end of legend line draw // draw Ictx6.lineWidth = "1";ctx6.strokeStyle = "#0000ff"; // set green colorctx6.beginPath(); // to start drawing new liney6.splice(0, 1); // on the position 0 in the field y3 we erase one valuey6[199] = value.dErr; // new value is added at the endfor (var i=0; i<200; i++) {ctx6.lineTo(x6[i], (100 - (150 + y6[i]) / 300 * 100)); // 0,0 x,y coordinate is in upper left corner};ctx6.stroke(); // to draw the line // add axis labelsctx6.font = "10px Arial";// x-axis labelctx6.fillText("<-"+ 0 + "|" + 200 + "->", 155, 100-5); // display number of points on x-axis// min on y-axis label://ctx6.textBaseline="top"; // to print font 5 px from topctx6.fillText(150,5,11); // values for y axisctx6.fillText(-150,5,100-5); // END of draw canvas6 graph for D part ********************************************** log(value.desiredValue + "|" + value.actualValue + "|" + (value.desiredValue-value.actualValue) + "|" + (value.pwm).toFixed(0));})function startControlAlgorithm1() { stopControlAlgorithm(); // just in case, if it is not started pCoeff = document.getElementById("pCoeff").value; // read the value of coeff from input field socket.emit("startControlAlgorithm", {"ctrlAlgNo": 1, "pCoeff": pCoeff}); // send value of coeff}function startControlAlgorithm2() { stopControlAlgorithm(); // just in case, if it is not started Kp1 = document.getElementById("Kp1").value; // read the value of coeff from input field Ki1 = document.getElementById("Ki1").value; // read the value of coeff from input field Kd1 = document.getElementById("Kd1").value; // read the value of coeff from input field socket.emit("startControlAlgorithm", {"ctrlAlgNo": 2, "Kp1": Kp1, "Ki1": Ki1, "Kd1": Kd1}); // send value of coeff}function startControlAlgorithm3() { stopControlAlgorithm(); // just in case, if it is not started Kp2 = document.getElementById("Kp2").value; // read the value of coeff from input field Ki2 = document.getElementById("Ki2").value; // read the value of coeff from input field Kd2 = document.getElementById("Kd2").value; // read the value of coeff from input field socket.emit("startControlAlgorithm", {"ctrlAlgNo": 3, "Kp2": Kp2, "Ki2": Ki2, "Kd2": Kd2}); // send value of coeff}function startControlAlgorithm4() { stopControlAlgorithm(); // just in case, if it is not started FSpos1 = document.getElementById("FSpos1").value; // read the value of coeff from input field FSpos2 = document.getElementById("FSpos2").value; // read the value of coeff from input field socket.emit("startControlAlgorithm", {"ctrlAlgNo": 4, "FSpos1": FSpos1, "FSpos2": FSpos2}); // send value of coeff}function stopControlAlgorithm() { socket.emit("stopControlAlgorithm");}socket.on("disconnect", function(){ log("Disconnected from the server"); // we print status of disconn. to div}); </script> </body> </html>