Robot Controlled using HTML5/JavaScript and BeagleBone Green

The control of a robot may be painful as you have to develop specific clients for each mobile device. I propose a Web based control

Categories: Intermediate

M
otivation

It is cool to be able to use the mobile devices to control the stuffs that we build. However, it may be complicated to install the application of the mobile device of a friend to let him play with the project.

In a earlier version of this project, the board used was too complicated regarding the deployment of the server part of this project. The choice of
BeagleBone Green
for this project was motivated by the power of it’s processor and the ease of use of the
BoneScript

. Indeed, with this fabulous board, i was able to develop the full-stack application and deploy it in the board in a natural way. 

Objective

I propose here a web based interface that use HTML5 features to get the accelerometer data from all the devices that have one and use this information to remotely control a robot.

This project aims to be a first step towards
an autonomous vehicle that can generate the topography of desert regions to collect topological data for building desertification model and enable predictive modeling to optimize the counter desertification actions.

The autonomous vehicle version will use SeeedStudio sensors in addition to the BeagleBone Green board to collect the topographic data. It will use a solar charger to get the energy in the middle of the desert.

More details are available in the description if the proposed idea
here
.

Demo is better than a description

How the Accelerometer W
orks in Mobile Device


The accelerometer in mobile device use an embedded sensor. The browser get this information and make it available trough the HTML5/JavaScript API.

Figure 1

The Figure One Shows the axes of rotation that can be used. You can get the values using the HTML5 API as illustrated in the code bellow.

if (window.DeviceMotionEvent != undefined) {    window.ondevicemotion = function(e) {

                accelerationX = e.accelerationIncludingGravity.x;

	        accelerationY = e.accelerationIncludingGravity.y;

		accelerationZ = e.accelerationIncludingGravity.z;

		

	}


WebSockets are Cool

One of the main concerns for the web based IoT control is the protocol used for the communication between the GUI and the robot. HTTP is the traditional protocol used in the web browser. However, it has as very heavy communication model compared to the socket. That is because HTTP is a Layer 7 protocol that handles multiple stuffs like headers. The introduction of WebSockets in HTML5 allows the users to instantiate sockets like they can do on a native language. the code bellow shows how we instantiate a WebSocket in this project:

  function loading() {    connection = new WebSocket('ws://10.0.0.38:80');

    connection.onopen = function () {

      connected = true;

    };

    connection.onerror = function (error) {

     //Sorry, but there\'s some problem with your connection or the server is down.

    };

    connection.onclose = function () {

      console.log('You are disconnected to Robot.');

      //alert("You are disconnected to Hellium drone.");

    };

    

    connection.onmessage = function (e) {

   // Log messages from the server

      console.log('Server: ' + e.data);

    };

  };


The WebSocket needs also to be handled on the BeagleBone Green to enable the communication between the board and the web page. To do so, a library is available for nodeJS and well described in the this tutorial. You can handle this kind of connection as illustrated in the code bellow :

var WebSocketServer = require('websocket').server;

var http = require('http');

var b = require('bonescript');

function printJSON(x) { console.log(JSON.stringify(x)); }



var server = http.createServer(function(request, response) {

  // process HTTP request. Since we're writing just WebSockets server

  // we don't have to implement anything.

});

server.listen(1337, function() { });



// create the server

wsServer = new WebSocketServer({

  httpServer: server

});






JSON is your friend

Once the connection is established using the websocket you need a representation for the data that you will exchange between the webpage and your device. JSON is a very good choice for this propose. for this project, the representation used is composed from an object containing two attribute "left" and "right" for the wheels. Each attribute is as object composed from the "pin" that represents the 3 pins used to control a DC motor using a H-Bridge in the board, "dir" the direction of the wheel, and the "value" of the speed.

Bellow a sample JSON object to illustrate how it works:

{

	"right": {

		"pin": [3, 4, 5],

		"dir": true,

		"value": 0

	},

	"left": {

		"pin": [9, 10, 11],

		"dir": false,

		"value": 1023

	}

}


Json is supported naively in
BeagleBone Green
against Arduino where you need to use a library,

this one for example
, to support it. 

WiFi setup

The wireless support is an important part of this project. You need first to configure the BeagleBone Green with a dongle WiFi.

First Connect the 
dongle WiFi as illustrated in the Figure 2. The tip here is to chose a dongle WiFi compatible with Raspbery-Pi, That will ensure that you will not have issues during the setup.

Figure 2

SSH to your board as illustrated in Figure 3. Note that the USB connection enable that. There is no need to an Ethernet connection. As reminder your user is probably "root"

Figure 3

Now execute the command below in order to activate the WiFi and list the available connections.

root@beaglebone:~# apt-get update

root@beaglebone:~# ifconfig wlan0 up

root@beaglebone:~# iwconfig

root@beaglebone:~# iwlist wlan0 scan




Now your WiFi needs to be configured in order to get connected automatically on the boot of your 
BeagleBone Green. To do so, install 
wpasupplicant
that handles the automation of the connection as described below:

root@beaglebone:~# apt-get install wpasupplicant 

root@beaglebone:~# nano /etc/network/interfaces


Find the WiFi connection section on this file and modify it as described below:

...



# WiFi Example

#auto wlan0

allow-hotplug wlan0

iface wlan0 inet dhcp

    wpa-ssid "YOUR-SSID"

    wpa-psk  "YOUR-PASS"



...


Last, turn the WiFi up and do some checks using the command below:

root@beaglebone:~# ifconfig wlan0 up

root@beaglebone:~# ifup wlan0

root@beaglebone:~# ifconfig wlan0


At this stage, you should see the IP address associated with the WiFi connection of your BeagleBone Green.

Congratulation ! Your BeagleBone Green is connected to your WiFi Network.

Hardware setup

The robot is not complicated to build. As i used some kits (see the components part), you need to attach the BeagleBone Green
to the DC to the H-Bridge and DC motors. The schematics attached to this project illustrates the pinout connection. for information, the Figure 4 illustrates the pins used from the BeagleBone Green in this project.


Figure 4

Software setup

The software part of this project is composed from two main parts: A client and a server.

Both are deployed to the BeagleBone Green. The client part is retrieved using the mobile device browser from the nodeJS server on the BeagleBone Green. The Figure 5 illustrates the sequence of the exchange between the and the mobile device.

Figure 5

The server part is executed by running the script called bbg.js . As illustrated below, this script runs a websocket server and update the BeagleBone Green pins using the BoneScript library.

var WebSocketServer = require('websocket').server;

var http = require('http');

var b = require('bonescript');

function printJSON(x) { console.log(JSON.stringify(x)); }



var server = http.createServer(function(request, response) {

  // process HTTP request. Since we're writing just WebSockets server

  // we don't have to implement anything.

});

server.listen(1337, function() { });



// create the server

wsServer = new WebSocketServer({

  httpServer: server

});



function handleElem(e) {



  var pin = e.pin[0];

  var pin1 = e.pin[1];

  var pin2 = e.pin[2];

  var dir = e.dir;

  var value = e.value ;





  b.pinMode(pin, 'out');

  b.pinMode(pin1, 'out');

  b.pinMode(pin2, 'out');



  b.analogWrite(pin, 0.7, value, printJSON);

  b.digitalWrite(pin1, ! dir);

  b.digitalWrite(pin2, dir);

}



// WebSocket server

wsServer.on('request', function(request) {

  var connection = request.accept(null, request.origin);



  // This is the most important callback for us, we'll handle

  // all messages from users here.

  connection.on('message', function(message) {

    try {

      var json = JSON.parse(message.data);



      vhandleElem(json.left);

      handleElem(json.right);



    } catch (e) {

      console.log('This doesn\'t look like a valid JSON: ', message.data);

      return;

    }

    if (message.type === 'utf8') {

      analogWrite('P9_14', value);

      digitalWrite(pin1, ! dir);

      digitalWrite(pin2, dir);



      b.analogWrite('P9_14', 0.7, 2000, printJSON);



    }

  });



  connection.on('close', function(connection) {

    // close user connection

  });

});




The client is a web application. As illustrated in the code below, it send a JSON object to the server containing the pins and the values that will be used to control the robot.



if (window.DeviceMotionEvent != undefined) {

	window.ondevicemotion = function(e) {

    ax = event.accelerationIncludingGravity.x * 5;

    ay = event.accelerationIncludingGravity.y * 5;

    dx = e.accelerationIncludingGravity.x;

    dy = e.accelerationIncludingGravity.y;

    document.getElementById("accelerationX").innerHTML = e.accelerationIncludingGravity.x;

		document.getElementById("accelerationY").innerHTML = e.accelerationIncludingGravity.y;

		document.getElementById("accelerationZ").innerHTML = e.accelerationIncludingGravity.z;



		if ( e.rotationRate ) {

			document.getElementById("rotationAlpha").innerHTML = e.rotationRate.alpha;

			document.getElementById("rotationBeta").innerHTML = e.rotationRate.beta;

			document.getElementById("rotationGamma").innerHTML = e.rotationRate.gamma;

		}

	}



  function loading() {

    connection = new WebSocket('ws://YOUR-BeagleBone-Green-IP:80');

    connection.onopen = function () {

      document.getElementById("sending").innerHTML = 'You are connected to Robot.';

      var ret = {

        left : getJsonRet(0,['P8_13','P8_12','P8_11']),

        right : getJsonRet(1,['P8_19','P8_18','P8_17'])

      };

      document.getElementById("sending").innerHTML = 'Sending : ' + JSON.stringify(ret);

      connection.send(JSON.stringify(ret));

      connected = true;

    };








Replicate and Enjoy!

The github repository contains all the sources and resources needed to replicate this project in a couple of hours if you have the same components as i used in my project. the only line of code that you should modify is the IP of your device. You need to modify the file
html-js-robot/app/


car.html
and use you IP.

You need to clone the project source on your BeagleBone Green:

root@beaglebone:~# git clone https://github.com/charifmahmoudi/html-js-robot

root@beaglebone:~# cd html-js-robot


Run the server part

root@beaglebone:~/html-js-robot# node server/bbg.js


Then run the client part, i recommend to use
Grunt
using the command below

root@beaglebone:~/html-js-robot# grunt serve


It will run a server to allow you to access the HTML page from your
BeagleBone Green
. Then you will see a new page on your browser if your are using the GUI. Copy the URL from this page, close the page, and use this URL in your mobile device browser.

An alternative method is to copy paste the car.html in your mobile device and open it directly.

That’s all folks!!!

Comments are not currently available for this post.