Beaglebone how-to – Click a Breadboard button and change status on a web page using node.js

This article describes how to get the interrupt of a beaglebone GPIO and update via web socket a web page using Node.js.

You can build your button or use the BreadBoard – http://beagleboardtoys.com/wiki/index.php?title=BeagleBone_Breadboard buttons.

Follow the photos of Breadboard

… and Beaglebone.

(from http://elinux.org/BeagleBone)

In this experiment I:

  • setup a pin in INPUT mode (in my example P8_3 – GPIO1_6)
  • setup a pin in OUTPUT mode (P8_15 – GPIO1_15)
  • connect the button S1 in order to interrupt the current between P8_3 and P8_15 when the button is pressed

Here a photo of the cabled board (in the next days I’ll update the post with better images and a video). A 1k resistor is missing in led connection….

Each time you click button S1 the current go down, the led is turned off and pin P8_15 receive a signal.

To send this information to a web page let’s write some line of code in Node.js 🙂

Open Cloud9 on http://beaglebone.local:3000 and add button.js file

var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
var fs = require('fs');
var url = require('url');
var path = require('path');
io.set('log level', 1);

// runs only on beaglebone!
var bb = require('bonescript');
var inputPin = bone.P8_15;
var ledPin = bone.P8_3;

app.listen(2509);

io.sockets.on('connection', function(socket) {
    attachInterrupt(inputPin, CHANGE, function(pin, value) {
        socket.emit('button_event', ((value == HIGH) ? 'white' : 'red') );
        socket.broadcast.emit('button_event', ((value == HIGH) ? 'white' : 'red') );
    });

});

setup = function() {
    pinMode(inputPin, INPUT);

    // turn on the led
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, HIGH);

    attachInterrupt(inputPin, CHANGE, function(pin, value) {
        console.log(pin.key + ' changed to ' + ((value == HIGH) ? 'HIGH' : 'LOW'));
    });

};

function handler(req, res) {
    var uri = url.parse(req.url).pathname;
    var subdir = path.join(process.cwd(), 'button');
    if (uri == '/') {
        loadFile('index.html', subdir, res, "text/html");
    } else {
        if (uri.match(/\.js$/i)) {
            loadFile(uri, subdir, res, "application/javascript");
        } else if (uri.match(/\.css$/i)) {
            loadFile(uri, subdir, res, "text/css");
        } else if (uri.match(/\.htm(.)$/i)) {
            loadFile(uri, subdir, res, "text/html");
        } else if (uri.match(/\.(jpg|png|ico|gif)$/i)) {
            loadFile(uri, subdir, res, "binary");
        } else {
            loadFile(uri, subdir, res, "text/plain");
        }
    }
};

function loadFile(uri, subdir, res, type) {
    var filename = path.join(subdir, uri);
    path.exists(filename, function(exists) {
        if (!exists) {
            res.writeHead(404, {
                "Content-Type": "text/plain"
            });
            res.write("Error 404: '" + uri + "' Not Found\n");
            res.end();
        }else if (type == "binary") {
            fs.readFile(
            filename, "binary", function(err, file) {
                if (err) {
                    res.writeHead(500, {
                        "Content-Type": "text/plain"
                    });
                    res.write(err + "\n");
                    res.end();
                    return;
                }
                res.writeHead(200);
                res.write(file, "binary");
                res.end();
            });
        } else {
            fs.readFile(
            filename, encoding = 'utf8', function(err, file) {
                if (err) {
                    res.writeHead(500, {
                        "Content-Type": "text/plain"
                    });
                    res.write(err + "\n");
                    res.end();
                    return;
                }
                res.writeHead(200, {
                    "Content-Type": type
                });
                res.write("" + file);
                res.end();
            });
        }
    });
};

bb.run();
console.log('Server running at http://beaglebone.local:2509/');

than create a directory named button and add here the index.html

<html>
<head>
    <script src = "/socket.io/socket.io.js" > </script>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
    <script>
		var socket = io.connect();

	    socket.on('button_event', function (data) {
                console.log(data);
                $("body").css("background-color", data);
            });
    </script>
</head>

<body>
	<h1>Press the button, the page will become red!</h1>

</body>
</html>

The “magic” is done by

    attachInterrupt(inputPin, CHANGE, function(pin, value) {
        socket.emit('button_event', ((value == HIGH) ? 'white' : 'red') );
        socket.broadcast.emit('button_event', ((value == HIGH) ? 'white' : 'red') );
    });

This function, exposed by bone library, will alert you each time an I/O changes. The implementation behind is done with a poller, I’m looking for an implementation based on kernel interrupts.

One thought on “Beaglebone how-to – Click a Breadboard button and change status on a web page using node.js

  1. Is it possible for you to post this setup with the wires connected into the GPIO pins on the BBB instead of into cape? I am having trouble replicating this with a BeagleBone Black, breadboard, and button. Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s