Things used in this project

Hardware components:
Phpoc blue per 100x1000 euk22wtv9i
PHPoC Blue
×1
Mikrobus board pfuubo0pro
PHPoC mikroBUS Expansion Board
×1
MikroElektronika MM7150 3D motion sensor
×1
Batery
×1
Handmade Dice Box
×1

Schematics

Components
Things azhkm6dt1g

Code

Main task (task0.php)PHP
This task responds for reading data from MM7150 and send it via websocket to Client.
You can get library for MM7150 here: http://www.phpoc.com/forum/viewtopic.php?f=42&t=223
<?php

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

include_once "/lib/sd_340.php";
include_once "/lib/vd_MM7150_pin_map.php";
include_once "/lib/vn_hid_i2c.php";
include_once "/lib/vd_MM7150.php";

function unsign2sign($val)
{
    if($val&0x8000)
        $val = ($val&0x7fff) - 0x8000;
    
    return $val;
}
// Init user interface

i2c_setup(0, MM7150_ADDR);
uio_setup(0, INT_PIN, "in");
uio_setup(1, WAKEUP_PIN, "out");
uio_out(1, WAKEUP_PIN, HIGH);    
ws_setup(0, "inclinometer", "csv.phpoc");
//List of sensor in use

$sensor_list = array(
                ACCEL_SENSOR_TYPE, 
                GYRO_SENSOR_TYPE, 
                CMP_SENSOR_TYPE, 
                ORI_SENSOR_TYPE, 
                INCL_SENSOR_TYPE);

// Init MM7150. Retrieve HID & report descriptors, and all device features
mm7150_init($sensor_list);

//$sensor_type = ACCEL_SENSOR_TYPE;
//$sensor_type = GYRO_SENSOR_TYPE;
//$sensor_type = CMP_SENSOR_TYPE;
//$sensor_type = ORI_SENSOR_TYPE;
$sensor_type = INCL_SENSOR_TYPE;

mm7150_enable_sensor($sensor_type);

$mult = hid_i2c_get_exponent($sensor_type);

$data = "";    

hid_i2c_request_data($data, $sensor_type);
    
$x_val = unsign2sign(bin2int($data, 0, 2)) * $mult;
$y_val = unsign2sign(bin2int($data, 2, 2)) * $mult;
$z_val = unsign2sign(bin2int($data, 4, 2)) * $mult;
    
while(1)
{    
    /*
    //Polling Driven
    hid_i2c_request_data($data, $sensor_type);
    
    $x_val = unsign2sign(bin2int($data, 0, 2)) * $mult;
    $y_val = unsign2sign(bin2int($data, 2, 2)) * $mult;
    $z_val = unsign2sign(bin2int($data, 4, 2)) * $mult;
    
    echo "pitch: ", $x_val , ",   ";
    echo "roll : ", $y_val , ",   ";
    echo "yaw  : ", $z_val , "\r\n";
    
    */
    
    // Event Driven
    if(uio_in(0, INT_PIN) == INT_ASSERTED)
    {                    
        $data = "";        
        
        $in_sens_type = hid_i2c_read_data($data);
        
        if($in_sens_type == $sensor_type)
        {
            $x_val = unsign2sign(bin2int($data, 0, 2)) * $mult;
            $y_val = unsign2sign(bin2int($data, 2, 2)) * $mult;
            $z_val = unsign2sign(bin2int($data, 4, 2)) * $mult;
            
            echo "pitch: ", $x_val , ",   ";
            echo "roll : ", $y_val , ",   ";
            echo "yaw  : ", $z_val , "\r\n";
            
            if(ws_state(0) == TCP_CONNECTED)
            {
                $wbuf = "[$x_val, $y_val, $z_val]";
                ws_write(0, $wbuf);
            }
        }
    }
    //Client may request data for the first time to get offset.
    if(ws_state(0) == TCP_CONNECTED)
    {
        $rbuf = "";
        $rlen = ws_read_line(0, $rbuf);

        if($rlen)
        {
            $wbuf = "[$x_val, $y_val, $z_val]";
            ws_write(0, $wbuf);
        }
    }
}

?>
Web Interface (index.php)PHP
This code responds for receive real-time data from PHPoC via web socket and update state of dice.
I use three js library https://threejs.org/ to draw 3D dice and rotate it
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - geometry - cube</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body { text-align: center;} 
            #myCanvas {
                margin-right: auto;
                margin-left: auto;
                width: 400px; 
                height: 400px; 
                position: relative;
                border: 1px solid #000;
                background-color: #000000;
            }
        </style>
        <script>
            var pitch = 0, roll = 0, yaw = 0;
            var pitch_offset = 0, roll_offset = 0, yaw_offset = 0;            
            var ws = null;
            var first_data = true;
            
            function ws_onopen()
            {
                document.getElementById("ws_state").innerHTML = "OPEN";
                document.getElementById("wc_conn").innerHTML = "Disconnect";
                first_data = true;
                //Send request to get data 
                ws.send("0\r\n"); 
            }
            function ws_onclose()
            {
                document.getElementById("ws_state").innerHTML = "CLOSED";
                document.getElementById("wc_conn").innerHTML = "Connect";
                ws.onopen = null;
                ws.onclose = null;
                ws.onmessage = null;
                ws = null;
            }
            function ws_onmessage(e_msg)
            {
                var arr = JSON.parse(e_msg.data);
                if(first_data)
                {
                    first_data = false;
                    pitch_offset = arr[0];
                    roll_offset  = arr[1];
                    yaw_offset   = arr[2];
                }
                pitch = (arr[0] - pitch_offset) * Math.PI/180;
                roll  = (arr[1] - roll_offset) * Math.PI/180;
                yaw   = (arr[2] - yaw_offset) * Math.PI/180;
                console.log("pitch: "+ arr[0] +", roll: "+ arr[1] +", yaw: "+ arr[2]); 
            }
            function wc_onclick()
            {
                if(ws == null)
                {
                    ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/inclinometer", "csv.phpoc");
                    document.getElementById("ws_state").innerHTML = "CONNECTING";
                    
                    ws.onopen = ws_onopen;
                    ws.onclose = ws_onclose;
                    ws.onmessage = ws_onmessage; 
                }
                else
                    ws.close();
            }
        </script>
    </head>
    <body>
        <canvas id="myCanvas"></canvas>
        <script src="https://threejs.org/build/three.js"></script>

        <script>

            var camera, scene, renderer;
            var mesh;

            init();
            animate();

            function init() {

                camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
                camera.position.y = 40;
                camera.position.z = 60;
                camera.lookAt(new THREE.Vector3( 0, -2, -5 ));

                scene = new THREE.Scene();
                            
                var geometry = new THREE.BoxBufferGeometry(20, 20, 20, 2, 2, 2);
                
                //var material = new THREE.MeshBasicMaterial( { map: texture } );
                var materials = [
                       new THREE.MeshBasicMaterial({
                           map: new THREE.TextureLoader().load('dice_1.jpg')
                       }),
                       new THREE.MeshBasicMaterial({
                           map: new THREE.TextureLoader().load('dice_2.jpg')
                       }),
                       new THREE.MeshBasicMaterial({
                           map: new THREE.TextureLoader().load('dice_3.jpg')
                       }),
                       new THREE.MeshBasicMaterial({
                           map: new THREE.TextureLoader().load('dice_4.jpg')
                       }),
                       new THREE.MeshBasicMaterial({
                           map: new THREE.TextureLoader().load('dice_5.jpg')
                       }),
                       new THREE.MeshBasicMaterial({
                           map: new THREE.TextureLoader().load('dice_6.jpg')
                       })
                    ];

                mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial(materials ));
                mesh.position.y = 10;
                scene.add( mesh );
                
                var grid = new THREE.GridHelper( 50, 20, 0xFFFFFF, 0XFFFFFF);
                //grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
                grid.position.y = 0;
                grid.material.opacity = 0.25;
                grid.material.transparent = true;
                scene.add( grid );

                var canvas = document.getElementById("myCanvas");
                renderer = new THREE.WebGLRenderer({ canvas: canvas });
                
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth/2, window.innerHeight/2 );
                document.body.appendChild( renderer.domElement );


                window.addEventListener( 'resize', onWindowResize, false );

            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth/2, window.innerHeight/2 );

            }

            function animate() {

                requestAnimationFrame( animate );

                mesh.rotation.x = roll;
                mesh.rotation.y = yaw;
                mesh.rotation.z = pitch;

                renderer.render( scene, camera );
            }

        </script>
        <p>WebSocket : <span id="ws_state">null</span><br></p>
        <button id="wc_conn" type="button" onclick="wc_onclick();">Connect</button>
    </body>
</html>

Credits

On uvdqjvxt6b
phpoc_man
3 projects • 81 followers
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaBlog