Today i will show you how i used my nunchuck.js library to remote control a 3D Cube with a nunchuck controller.
If you don't know how to connect and read data from a nunchuck check this article.

Then you can download nunchuck.js library from NPM:

npm install nunchuck-js

The package provides a server that has to be launched where the nunchuck is wired (usually with a RaspberryPi over i2c), the server tries to connect to the device and once started is reachable on port 8888. To start the server launch these two commands:

cd  node_modules/nunchuck.js/src/nunchuck-remote/
node server.js

Open your browser and point to the server:

http://<ip.of.your.raspi>:8888/cube.html

When the server receives a request to cube.html page, it automatically starts connection with the nunchuck and sends data to the browser over a websocket channel. The video posted below shows a live demo on what you can do with this server:

...a closer look...

Essentially we have two basic components the server and the client. The server uses the nunchuck.js modules to read and decode data from nunchuck and sends them as a JSON string over the websocket. On the other side, the client uses the THREE.js library to render a cube then receives and parse the JSON data to rotate and position the cube.

The server

The core components of the server :

  var nunchuckModules = require('nunchuck-js').nunchuck;
  var NunchuckDevice = nunchuckModules.device;
  var NunchuckDecoder = nunchuckModules.decoder;
  var WebSocketServer = require('websocket').server;

Instatiates the nunchuck device and the websocket server:

var nunchuck = new NunchuckDevice(0x52, 1,[]);
wsServer = new WebSocketServer({
    httpServer: server
});

when the client requests a connection the server instantiates the decoder and sends the datas received from the device:

//connection object previously obtained from accept method
  connection.on('message', function(message) {
          if(message.data!=="start"){return;};

          /*initialize the nunchuck*/
          nunchuck.init();
          console.log("nunchuck initialized....");

          /*starts the decoder and send data*/
          var decoder = new NunchuckDecoder(nunchuck);          
          decoder.start(function(stream){
            var obj = decoder.asObject(stream);        
            connection.sendUTF(JSON.stringify(obj));
          });

    });

The client

The client requests a websocket connection and parses the data:

connection.onmessage = function (message) {
    // try to decode json (I assume that each message from server is json)
    //console.log(message);
    try {
      var json = JSON.parse(message.data);
    } catch (e) {
      console.log('This doesn\'t look like a valid JSON: ', e);
    }
    callback(json);
    // handle incoming message
  };

The callback function simply scales nunchuck values to a more comprehensible THREE.js way, for instance acceleration X value is scaled to a range between -1 and 1 with a 3 digits fixed precision. Then passes the values to the render function:

function(o){
    //parse accelerometer and stick values
    var a = o.accelerometer;
    var s = o.stick;

    var normaX = scale(a.aX,0,255,-1,1);
    var normaY = scale(a.aY,0,255,-1,1);
    var normaZ = scale(a.aZ,0,255,1000,2000);
    var normX = scale(s.x,0,255,-1000,1000);
    var normY = scale(s.y,0,255,-1000,1000);

     //render points
    render(normX,normY,normaX/10,normaY/10,normaZ);
  });

The render function uses the THREE.js objects to do the final work:

function render(x,y,ax,ay,z) {
    cube.rotation.x += ay;
    cube.rotation.y -= ax;
    camera.position.z = z;
    camera.position.x =x*-1;  
    camera.position.y = y*-1; 
    renderer.render(scene, camera);
  };

You can check my repo for the complete and working source code. Hope you like it.

Luigi's Dev Corner


Related articles:


  • submit to reddit
blog comments powered by Disqus