Announcement

Collapse
No announcement yet.

Servo Motor - Controlling Servo Motor via WebSocket with Graphic UI

Collapse
X
Collapse

  • Servo Motor - Controlling Servo Motor via WebSocket with Graphic UI


    Tutorial Video



    Hardware
    • PHPoC Blue (+ USB WLAN) or PHPoC Black (+ Ethernet cable)
    • Micro USB to USB Cable (to upload source code to PHPoC Device)
    • Servo Motor
    • Jumper Cable


    About Servo Motor

    Stardard servo motor is used to control of angular (usually between 0 and 180 degrees). The servo motor used in this example includes three wires:
    • VCC wire.
    • GND wire.
    • Signal wire (receives the PWM control signal from controller).
    How the servo motor works: servo motor can be controlled by generating PWM signal to signal wire of servo motor. The motor sepcification defines cycle time, minimum and maximum duty cycle.
    • If generating PWM signal with minimum duty cycle to signal wire, the servo motor rotate to 0 degree.
    • If generating PWM signal with maximun duty cycle to signal wire, the servo motor rotate to 180 degree.
    • If generating PWM signal with duty cycle between minimum and maximum value to signal wire, the servo motor rotate to position that is proportional to duty cycle.
    How to control servo motor:
    • Harware timer and software timer on PHPoC device can generate PWM signal. Therefore, It just needs connect the HT pin (or selectable IO pin if using software timer) of PHPoC device to the signal wire of servo motor. And then use hardware/software timer to control servo motor.


    Wiring Diagram



    Quick Steps

    Source code of this example is a part of PHPoC Support Packet (PSP). You need to:
    • Download PHPoC Support Package.
    • Upload example\p4s\05.html5_graphics\03.ht_pwm_servo to PHPoC Blue/Black.
    • Configure network parameters (e.g. WiFi SSID, password, IP address ...).
    • Click "Run" button on PHPoC Debugger.
    • Access webpage on PHPoC using Web Browser on your PC or smart phone (See How To).
    If you use PHPoC for the first time, see How To Use PSP.


    Source Code

    Source files includes:
    • init.php: this file is run when PHPoC system is powered or reset. It is used to specify which file is run is system loop.
    • task0.php: this file is run in system loop of PHPoC devices. It acts as WebSocket server and also interacts with servo motor.
    • index.php: this file contains source code of web page.It is only run in response to request from Web Browser. It contains webpage (user interface) and acts WebSocket client.
    • servo_body.png: Image.
    • servo_bracket.png: Image.

    index.php

    [Full Code]
    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; }
    canvas { background-color: #f0f0f0; }
    </style>
    <script>
    var canvas_width = 401, canvas_height = 466;
    var pivot_x = 200, pivot_y = 200;
    var bracket_radius = 160, bracket_angle = 0;
    var bracket_img = new Image();
    var click_state = 0;
    var last_angle = 0;
    var mouse_xyra = {x:0, y:0, r:0.0, a:0.0};
    var ws;

    bracket_img.src = "servo_bracket.png";

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

     servo.width = canvas_width;
     servo.height = canvas_height;
     servo.style.backgroundImage = "url('/servo_body.png')";

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

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

     ctx.translate(pivot_x, pivot_y);

     rotate_bracket(0);

     ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/ht_pwm_servo", "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

     alert("msg : " + e_msg.data);
    }
    function rotate_bracket(angle)
    {
     var servo = document.getElementById("servo");
     var ctx = servo.getContext("2d");

     ctx.clearRect(-pivot_x, -pivot_y, canvas_width, canvas_height);
     ctx.rotate(angle / 180 * Math.PI);

     ctx.drawImage(bracket_img, -pivot_x, -pivot_y);

     ctx.rotate(-angle / 180 * Math.PI);
    }
    function check_range_xyra(event, mouse_xyra)
    {
     var x, y, r, a, rc_x, rc_y, radian;
     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);
      min_r = 60;
      max_r = pivot_x;
      width = 40;
     }
     else
     {
      x = event.offsetX - pivot_x;
      y = pivot_y - event.offsetY;
      min_r = 60;
      max_r = bracket_radius;
      width = 20;
     }

     /* 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;

     radian = bracket_angle / 180 * Math.PI;

     /* rotate coordinate */
     rc_x = x * Math.cos(radian) - y * Math.sin(radian);
     rc_y = x * Math.sin(radian) + y * Math.cos(radian);

     if((r < min_r) || (r > max_r))
      return false;

     if((rc_y < -width) || (rc_y > width))
      return false;

     return true;
    }
    function mouse_down()
    {
     if(event.touches && (event.touches.length > 1))
      click_state = event.touches.length;

     if(click_state > 1)
      return;

     if(check_range_xyra(event, mouse_xyra))
     {
      click_state = 1;
      last_angle = mouse_xyra.a / Math.PI * 180.0;
     }
    }
    function mouse_up()
    {
     click_state = 0;
    }
    function mouse_move()
    {
     var angle;

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

     if(click_state > 1)
      return;

     if(!click_state)
      return;

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

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

     if((Math.abs(angle) > 90) && (angle * last_angle < 0))
     {
      if(last_angle > 0)
       last_angle = -180;
      else
       last_angle = 180;
     }

     bracket_angle += (last_angle - angle);
     last_angle = angle;

     if(bracket_angle > 90)
      bracket_angle = 90;

     if(bracket_angle < -90)
      bracket_angle = -90;

     rotate_bracket(bracket_angle);

     if(ws.readyState == 1)
      ws.send(Math.floor(bracket_angle) + "\r\n");

     debug = document.getElementById("debug");
     debug.innerHTML = Math.floor(bracket_angle);

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

    <body>

    <h2>
    HT / Tower Pro SG92R Micro Servo<br>

    <br>

    <canvas id="servo"></canvas>

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

    </body>
    </html>



    [Explanation]

    Source code of index.php file is composed of HTML, CSS, JavaScript and PHPoC code.

    PHPoC code is interpreted on on PHPoC device.

    PHPoC code may add/update the content of HTML, CSS or JavaScript code. Once PHPoC code is interpreted in PHPoC, the remaining code is client-side code and it is returned to Web Browser. Web Browser receives this code and interpret it to display the webpage.
    • HTML: describes the structure of Web pages
    • CSS: describes how HTML elements are to be displayed
    • JavaScript: This code:
      - Handle click/touch event from user on Webpage,
      - Calculate angle based on click/touch position,
      - Send rotated angle of servo motor to PHPoC device via WebSocket
      - Update Graphic UI: Draw arm horn on canvas with respect to the calculated angle

    init.php

    This file is run when PHPoC system is powered or reset. It is used to specify that task0.php is run is system loop.
    PHP Code:
    <?php

    system
    ("php task0.php");

    ?>



    task0.php

    [Full Code]
    PHP Code:
    <?php

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

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

    define("PWM_PERIOD"20000); // 20000us (20ms)
    define("WIDTH_MIN"600);
    define("WIDTH_MAX"2450);

    ht_pwm_setup(0, (WIDTH_MIN WIDTH_MAX) / 2PWM_PERIOD"us");
    ws_setup(0"ht_pwm_servo""csv.phpoc");

    $rwbuf "";

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

      if(
    $rlen)
      {
       
    $angle = -(int)$rwbuf 90;

       if(
    $angle 0)
        
    $angle 0;

       if(
    $angle 180)
        
    $angle 180;

       
    $width WIDTH_MIN + (int)round((WIDTH_MAX WIDTH_MIN) * $angle 180.0);

       if((
    $width >= WIDTH_MIN) && ($width <= WIDTH_MAX))
        
    ht_pwm_width(0$widthPWM_PERIOD);
      }
     }
    }

    ?>



    [Explanation]

    Source code of this file does:
    • Setup and initialize HT0 timer to generate PWM signal.
    • Setup and initialize WebSocket.
    In infinite loop:
    • Receive data (rotated angle )from Web Browser via WebSocket.
    • Calculate PWM duty cycle based on the received angle
    • Generate PWM signal to control servo motor
    For detail explanation, see How to Control Devices via WebSocket




    See Also

    Other Resources
    Last edited by support; 02-09-2018, 08:45 AM.
      Posting comments is disabled.

    Categories

    Collapse

    Latest Articles

    Collapse

    • Arduino - RS-485 Expansion Board
      by support
      PES-2607 is an easy-to-use RS422/RS485 Expansion Board for Arduino Uno and Mega, which allows Arduino to exchange data with serial device via RS422 or RS485.
      Especially, Arduino does NOT use UART pins to communicate with RS422/RS485 expansion board. Therefore, users can use Arduino UART pins for other purposes.
      Moreover, A single Arduino Uno/Mega can communicate with multiple RS422/RS485 expansion boards (up to 14) without using Arduino UART pins.

      Library and examples for...
      11-13-2018, 02:45 PM
    • Arduino - RS-422 Expansion Board
      by support
      PES-2607 is an easy-to-use RS422/RS485 Expansion Board for Arduino Uno and Mega, which allows Arduino to exchange data with serial device via RS422 or RS485.
      Especially, Arduino does NOT use UART pins to communicate with RS422/RS485 expansion board. Therefore, users can use Arduino UART pins for other purposes.
      Moreover, A single Arduino Uno/Mega can communicate with multiple RS422/RS485 expansion boards (up to 14) without using Arduino UART pins.

      Library and examples for...
      11-13-2018, 02:44 PM
    • Arduino - RS-232 Expansion Board
      by support
      PES-2606 is an easy-to-use RS-232 Expansion Board for Arduino Uno and Mega, which allows Arduino to exchange data with serial device via RS-232.
      Especially, Arduino does NOT use UART pins to communicate with RS-232 expansion board. Therefore, users can use Arduino UART pins for other purposes.
      Moreover, A single Arduino Uno/Mega can communicate with multiple RS-232 expansion boards (up to 14) without using Arduino UART pins.

      Library and example for the RS-232 expansion board...
      11-13-2018, 02:43 PM
    • Arduino - Stepper Motor Controller
      by support
      PES-2605 is an easy-to-use stepper motor controller for Arduino Uno and Mega, which uses micro-stepping method to precisely control stepper motor.
      Library and example for the stepper motor controller are part of of PhpocExpansion library for Arduino. The library reference is available here.

      This tutorial shows how to use the step motor controller with an example of PhpocExpansion library for Arduino.


      Hardware Required...
      11-13-2018, 02:41 PM
    • Arduino - DC Motor Controller
      by support
      PES-2604 is an easy-to-use DC motor controller for Arduino Uno and Mega.
      Library and example for the DC motor controller are part of of PhpocExpansion library for Arduino. The library reference is available here.

      This tutorial shows how to use the DC motor controller with an example of PhpocExpansion library for Arduino.


      Hardware Required...
      11-13-2018, 02:40 PM
    • Arduino - Digital Input Board
      by support
      PES-2602 is an easy-to-use 4-port Input Expansion Board for Arduino Uno and Mega, which allows Arduino to monitor state of DC electric device. In addition, it can monitor NPN, PNP and dry contact(relay).
      Library and example for the 4-port input expansion board are part of of PhpocExpansion library for Arduino. The library reference is available here.

      This tutorial shows how to use 4-port input expansion board with an example of PhpocExpansion library for Arduino.

      ...
      11-13-2018, 02:39 PM
    Working...
    X