phpoc_man
Published

Controlling And Monitoring Brushed DC Motor Via Websocket

This example shows how to control speed and position of brushed DC motors via web-socket.

BeginnerShowcase (no instructions)1,065
Controlling And Monitoring Brushed DC Motor Via Websocket

Things used in this project

Hardware components

PHPoC Blue
PHPoC Blue
×1
PHPoC DC Motor Controller (S-type or T-type)
PHPoC DC Motor Controller (S-type or T-type)
×1
DC motor (generic)
Brushed DC motor with encoder
×1
DC Power Jack Connector
DIYables DC Power Jack Connector
×1
12V power adapter
×1

Story

Read more

Code

User Interface (index.php)

PHP
<!DOCTYPE html>
<html>
<head>
<title>PHPoC - DC motor</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<style>
body { text-align: center; font-size: 15pt; font-family: Arial, Helvetica, sans-serif;}
h1 { font-weight: bold; font-size: 25pt; }
h2 { font-weight: bold; font-size: 15pt; }
button { font-weight: bold; font-size: 15pt; }
table { table-layout : fixed; font-size: 25pt;}
th { text-align: right; padding: 8px;}
td { color: blue; padding: 8px;}
</style>
<script>
var canvas_width = 450, canvas_height = 150;
var trans_x = canvas_width/2, trans_y = canvas_height/2;
var slider_width = 350, slider_height = 15;

var pre_slide_val = 0;
var slide_val = 0;
 
var ws;

function init()
{
	var canvas = document.getElementById("remote");
	canvas.width = canvas_width;
	canvas.height = canvas_height;
	
	canvas.addEventListener("touchstart", handle_event);
	canvas.addEventListener("touchmove", handle_event);
	canvas.addEventListener("mousedown", handle_event);
	canvas.addEventListener("mousemove", handle_event);
	
	var ctx = canvas.getContext("2d");
	
	ctx.translate(trans_x, trans_y);
	ctx.lineWidth = 3;
	ctx.strokeStyle = "#737373";
	ctx.font="25px Georgia";
	ctx.textBaseline="hanging"; 
	
	update_view();
}
function connect_onclick()
{
	if(ws == null)
	{
		var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
		ws = new WebSocket("ws://" + ws_host_addr + "/dc_motor", "text.phpoc");
		document.getElementById("ws_state").innerHTML = "CONNECTING";
		ws.onopen = ws_onopen;
		ws.onclose = ws_onclose;
		ws.onmessage = ws_onmessage;
	}
	else
		ws.close();
}
function ws_onopen()
{
	document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
	document.getElementById("bt_connect").innerHTML = "Disconnect";
}
function ws_onclose()
{
	document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>";
	document.getElementById("bt_connect").innerHTML = "Connect";
	ws.onopen = null;
	ws.onclose = null;
	ws.onmessage = null;
	ws = null;
}
function ws_onmessage(e_msg)
{
	e_msg = e_msg || window.event; // MessageEvent
	
	var arr = JSON.parse(e_msg.data);
	var pos = Math.round(arr[0]);
	var speed = Math.round(arr[1]);
	document.getElementById("speed").innerHTML = speed + " pps";
	document.getElementById("position").innerHTML = pos;
}
function update_view()
{
	var canvas = document.getElementById("remote");
	var ctx = canvas.getContext("2d");
 
	ctx.clearRect(-trans_x, -trans_y, canvas_width, canvas_height); 
	
	ctx.fillStyle = "#0080ff";
	ctx.beginPath();
	ctx.lineTo(0, -50);
	ctx.lineTo(0, 30);
	ctx.stroke();
	
	ctx.textAlign="right";
	ctx.fillText("Clockwise", -15, -50);
	ctx.textAlign="left";
	ctx.fillText("Anti-Clockwise", 15, -50);
	
	ctx.fillStyle = "#737373";
	ctx.beginPath();
	ctx.arc(-slider_width / 2, 0, slider_height / 2, 0.5 * Math.PI, 1.5 * Math.PI);
	ctx.lineTo(slider_width / 2, -slider_height / 2);
	ctx.arc(slider_width / 2, 0, slider_height / 2, 1.5 * Math.PI, 0.5 * Math.PI);
	ctx.lineTo(-slider_width / 2, 0 + slider_height / 2);
	ctx.fill();
	
	var temp = (slide_val + 100) * (slider_width + slider_height) / 200 - (slider_width + slider_height) / 2;
	
	ctx.fillStyle = "#0080ff";
	ctx.beginPath();
	ctx.arc(-slider_width / 2, 0, slider_height / 2, 0.5 * Math.PI, 1.5 * Math.PI);
	ctx.lineTo(temp, -slider_height / 2);
	ctx.lineTo(temp, slider_height / 2);
	ctx.lineTo(-slider_width / 2, slider_height / 2);
	ctx.fill();
	
	ctx.beginPath();
	ctx.arc(temp, 0, slider_height*1.5, 0, 2 * Math.PI);
	ctx.fill();
}
function handle_event()
{
	if(ws == null)
		return;
 
	event.preventDefault();
	
	if(event.offsetX)
	{
		x = event.offsetX - trans_x;
		y = event.offsetY - trans_y;
	}
	else if(event.layerX)
	{
		x = event.layerX - trans_x;
		y = event.layerY - trans_y;
	}
	else
	{
		x = (Math.round(event.touches[0].pageX - event.touches[0].target.offsetLeft)) - trans_x;
		y = (Math.round(event.touches[0].pageY - event.touches[0].target.offsetTop)) - trans_y;
	}
	
	if((y > (-slider_height*3)) 
	&& (y < (slider_height*3))
	&& (x < (slider_width / 2)) 
	&& (x > -(slider_width / 2)))
	{
		slide_val = Math.round((slider_width / 2 + x)/ slider_width *200) - 100;
		
		if(Math.abs(slide_val - pre_slide_val) > 3) 
		{
			ws.send(slide_val.toString() + "\r\n");
			pre_slide_val = slide_val;
		}
	}
	
	update_view();
}
window.onload = init;
</script>
</head>

<body>
<center>
<p>
<h1>PHPoC - DC motor</h1>
</p>
<table style="width:450px">
	<tr>
		<th>Speed: </th>
		<td><span id="speed">null</span></td> 
	</tr>
	<tr>
		<th>Position: </th>
		<td><span id="position">null</span></td> 
	</tr>
</table>

<canvas id="remote"></canvas>

<h2>
<p>
WebSocket : <span id="ws_state">null</span>
</p>
<button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button>
</h2>
</center>
</body>
</html>

Main task (task0.php)

PHP
<?php

include "/lib/sd_spc.php";
include "/lib/sn_tcp_ws.php";

ws_setup(0, "dc_motor", "text.phpoc");

spc_reset();
spc_sync_baud(460800);
spc_request_dev(14, "dc1 pwm set period 1000");
spc_request_dev(14, "dc1 enc set pol +");
spc_request_dev(14, "dc1 pwm set decay slow");
spc_request_dev(14, "dc1 lpf set freq 5000");

spc_request_dev(14, "dc1 pwm set width 0");

$rwbuf = "";

while(1)
{
	if(ws_state(0) == TCP_CONNECTED)
	{
		$rlen = ws_read_line(0, $rwbuf);

		if($rlen)
		{
			$pwm = (int)$rwbuf * 10;
			if($pwm > 0)
				spc_request_dev(14, "dc1 pwm set dir +");
			else
				spc_request_dev(14, "dc1 pwm set dir -");
			
			$pwm = abs($pwm);
			spc_request_dev(14, "dc1 pwm set width $pwm");
		}
		
		$pos = spc_request_dev(14, "dc1 enc get pos");
		
		$enc_period = (int)spc_request_dev(14, "dc1 enc get period");

		if(!$enc_period)
			$speed = 1;
		else
			$speed = 1000000 / $enc_period;
		
		$rwbuf = "[$pos, $speed]";
		ws_write(0, $rwbuf);
		
		usleep(10000);
	}
}

Credits

phpoc_man

phpoc_man

62 projects • 406 followers

Comments