Demonstration




Things Used In This Project
  • PHPoC Blue
  • PHPoC Step Motor Controller II
  • Stepper motor SE-SM243
  • Jumper wires


Wiring Diagram

1. Stack Step motor controller II to PHPoC

2. Connecting to a bipolar stepper motor according to this instruction http://www.phpoc.com/support/manual/....php?id=layout


Source Codes

Main Task:
<task0.php>
PHP Code:
<?php

if(_SERVER("REQUEST_METHOD"))
    exit; 
// avoid php execution via http request

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

define("STEPPER_SID"14);
define("SPEED_LOW_LIMIT"32);
define("SPEED_HIGH_LIMIT"100000);

function 
step_loop()
{
    
$last_tick st_free_get_count(0);
    
$rwbuf "";

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

        if(
$rlen)
        {
            
$dur_ms st_free_get_count(0) - $last_tick;

            
$last_tick st_free_get_count(0);

            
$angle = -(float)$rwbuf;
            
$pos = (int)(200.0 32.0 $angle 360.0);

            
$step $pos - (int)spc_request_dev(STEPPER_SID"get pos");

            if(
$step)
            {
                
$speed = (int)abs((float)$step / (float)$dur_ms 1000.0);
                
$speed $speed 10;

                if(
$speed SPEED_LOW_LIMIT)
                    
$speed SPEED_LOW_LIMIT;
                else
                if(
$speed SPEED_HIGH_LIMIT)
                    
$speed SPEED_HIGH_LIMIT;

                
spc_request_dev(STEPPER_SID"goto $pos $speed 1000k");
                
//echo "$step / $dur_ms  $speed\r\n";
            
}
        }

        
usleep(1000);
    }
}

function 
ws_loop()
{
    
spc_request_dev(STEPPER_SID"reset");

    
ws_setup(0"spc_stepper_rotate""csv.phpoc");
    
st_free_setup(0"ms");

    while(
1)
    {
        if(
ws_state(0) == TCP_CONNECTED)
        {
            
$pos = (int)spc_request_dev(STEPPER_SID"get pos");
            
$angle = -(float)$pos / (200.0 32.0) * 360.0;

            
ws_write(0, (string)$angle "\r\n");

            
step_loop();
        }
    }
}

spc_reset();
spc_sync_baud(460800);

spc_request_dev(STEPPER_SID"set vref drive 15");
spc_request_dev(STEPPER_SID"set mode 32");

ws_loop();

?>




User Interface

<index.php>
PHP Code:
<!DOCTYPE html>
<html>
<head>
<title>PHPoC / <?echo system("uname -i")?></title>
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<style>
body { text-align: center; background-color: whiite;}
canvas { background-color: white; }
</style>
<script>
var MIN_TOUCH_RADIUS = 20;
var MAX_TOUCH_RADIUS = 200;
var CANVAS_WIDTH = 402, CANVAS_HEIGHT = 402;
var PIVOT_X = 201, PIVOT_Y = 201;
var plate_angle = 0;
var plate_img = new Image();
var click_state = 0;
var last_angle_pos = 0;
var mouse_xyra = {x:0, y:0, r:0.0, a:0.0};
var ws;

plate_img.src = "step_plate.png";

function init()
{
    var stepper = document.getElementById("stepper");

    stepper.width = CANVAS_WIDTH;
    stepper.height = CANVAS_HEIGHT;

    stepper.addEventListener("touchstart", mouse_down);
    stepper.addEventListener("touchend", mouse_up);
    stepper.addEventListener("touchmove", mouse_move);
    stepper.addEventListener("mousedown", mouse_down);
    stepper.addEventListener("mouseup", mouse_up);
    stepper.addEventListener("mousemove", mouse_move);

    var ctx = stepper.getContext("2d");

    ctx.translate(PIVOT_X, PIVOT_Y);

    rotate_plate(0);

    ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/spc_stepper_rotate", "csv.phpoc");
    document.getElementById("ws_state").innerHTML = "CONNECTING";

    ws.onopen  = function(){ document.getElementById("ws_state").innerHTML = "OPEN" };
    ws.onclose = function(){ document.getElementById("ws_state").innerHTML = "CLOSED"};
    ws.onerror = function(){ alert("websocket error " + this.url) };

    ws.onmessage = ws_onmessage;
}
function ws_onmessage(e_msg)
{
    e_msg = e_msg || window.event; // MessageEvent

    plate_angle = Number(e_msg.data);

    rotate_plate(plate_angle);
    //alert("msg : " + e_msg.data);
}
function rotate_plate(angle)
{
    var stepper = document.getElementById("stepper");
    var ctx = stepper.getContext("2d");

    ctx.clearRect(-PIVOT_X, -PIVOT_Y, CANVAS_WIDTH, CANVAS_HEIGHT);
    ctx.rotate(-angle / 180 * Math.PI);

    ctx.drawImage(plate_img, -PIVOT_X, -PIVOT_Y);

    ctx.rotate(angle / 180 * Math.PI);

    debug = document.getElementById("debug");
    debug.innerHTML = plate_angle.toFixed(1);
}
function check_update_xyra(event, mouse_xyra)
{
    var x, y, r, a;
    var min_r, max_r, width;

    if(event.touches)
    {
        var touches = event.touches;

        x = (touches[0].pageX - touches[0].target.offsetLeft) - PIVOT_X;
        y = PIVOT_Y - (touches[0].pageY - touches[0].target.offsetTop);
    }
    else
    {
        x = event.offsetX - PIVOT_X;
        y = PIVOT_Y - event.offsetY;
    }

    /* cartesian to polar coordinate conversion */
    r = Math.sqrt(x * x + y * y);
    a = Math.atan2(y, x);

    mouse_xyra.x = x;
    mouse_xyra.y = y;
    mouse_xyra.r = r;
    mouse_xyra.a = a;

    if((r >= MIN_TOUCH_RADIUS) && (r <= MAX_TOUCH_RADIUS))
        return true;
    else
        return false;
}
function mouse_down()
{
    if(event.touches && (event.touches.length > 1))
        click_state = event.touches.length;

    if(click_state > 1)
        return;

    if(check_update_xyra(event, mouse_xyra))
    {
        click_state = 1;
        last_angle_pos = mouse_xyra.a / Math.PI * 180.0;
    }
}
function mouse_up()
{
    click_state = 0;
}
function mouse_move()
{
    var angle_pos, angle_offset;

    if(event.touches && (event.touches.length > 1))
        click_state = event.touches.length;

    if(click_state > 1)
        return;

    if(!click_state)
        return;

    if(!check_update_xyra(event, mouse_xyra))
    {
        click_state = 0;
        return;
    }

    angle_pos = mouse_xyra.a / Math.PI * 180.0;

    if(angle_pos < 0.0)
        angle_pos = angle_pos + 360.0;

    angle_offset = angle_pos - last_angle_pos;
    last_angle_pos = angle_pos;

    if(angle_offset > 180.0)
        angle_offset = -360.0 + angle_offset;
    else
    if(angle_offset < -180.0)
        angle_offset = 360 + angle_offset;

    plate_angle += angle_offset;

    rotate_plate(plate_angle);

    if(ws.readyState == 1)
        ws.send(plate_angle.toFixed(4) + "\r\n");

    event.preventDefault();
}
window.onload = init;
</script>
</head>

<body>

<h2>
Smart Expansion / Stepper Rotate<br>
<br>

<canvas id="stepper"></canvas>

<p>
WebSocket : <span id="ws_state">null</span><br>
Angle : <span id="debug">0</span>
</p>
</h2>

</body>
</html>