Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Playing With Arduino, IoT, Crossbar, and WebSockets

DZone's Guide to

Playing With Arduino, IoT, Crossbar, and WebSockets

Learn how to display in a webpage one value from your Arduino board; for example, one piece of analog data using a potentiometer.

· IoT Zone
Free Resource

Discover why Bluetooth mesh is the next evolution of IoT solutions. Download the mesh overview.

Yes! Finally, I’ve got an Arduino board. It’s time to hack a little bit. Today, I want to try a few different things. I want to display in a webpage one value from my Arduino board; for example, one piece of analog data using a potentiometer. Let’s start.

We are going to use one potentiometer. A potentiometer is a resistor with a rotating contact that forms an adjustable voltage divider. It has three pins. If we connect one pin to 5V power source of our Arduino, another one to the ground, and another to one A0 (analog input 0), we can read different values depending on the position of the potentiometer’s rotating contact.

arduino_analog

Arduino has 10-bit analog resolution. That means 1,024 possible values, from 0 to 1,023. So when our potentiometer gives us five volts, we’ll obtain 1,024, and when our it gives us 0V, we’ll read 0. Here, we can see a simple Arduino program to read this analog input and send data via serial port:

int mem;
 
void setup() {
  Serial.begin(9600);
}
 
void loop() {
  int value = analogRead(A0);
  if (value != mem) {
    Serial.println(value);
  }
  mem = value;
 
  delay(100);
}

This program is simple loop with a delay of 100 milliseconds that reads A0 and if the value is different than previously read (to avoid sending the same value when nobody is touching the potentiometer), we send the value via the serial port (with 9,600 bauds)

We can test our program using the serial monitor of our Arduino IDE our using another serial monitor.

Now, we’re going to create one script to read this serial port data. We’re going to use Python. I’ll use my laptop, and my serial port is /dev/tty.usbmodem14231.

import serial
 
arduino = serial.Serial('/dev/tty.usbmodem14231', 9600)
 
while 1:
  print arduino.readline().strip()

Basically, we’ve got our backend running. Now, we can create a simple frontend.

...
<div id='display'></div>
...

We’ll need WebSockets. I normally use socket.io but today, I’ll use Crossbar.io. Since I heard about it in a Ronny’s talk at the deSymfony Conference, I've wanted to use it.

I’ll change a little bit of our backend to emit one event:

import serial
from os import environ
from twisted.internet.defer import inlineCallbacks
from twisted.internet.task import LoopingCall
from autobahn.twisted.wamp import ApplicationSession, ApplicationRunner
 
arduino = serial.Serial('/dev/tty.usbmodem14231', 9600)
 
class SeriaReader(ApplicationSession):
    @inlineCallbacks
    def onJoin(self, details):
        def publish():
            return self.publish(u'iot.serial.reader', arduino.readline().strip())
 
        yield LoopingCall(publish).start(0.1)
 
if __name__ == '__main__':
    runner = ApplicationRunner(environ.get("GONZALO_ROUTER", u"ws://127.0.0.1:8080/ws"), u"iot")
    runner.run(SeriaReader)

Now I only need to create a crossbar.io server. I will use a node to do it:

var autobahn = require('autobahn'),
    connection = new autobahn.Connection({
            url: 'ws://0.0.0.0:8080/ws',
            realm: 'iot'
        }
    );
 
connection.open();

Now, we only need to connect our frontend to the WebSocket server:

$(function () {
    var connection = new autobahn.Connection({
        url: "ws://192.168.1.104:8080/ws",
        realm: "iot"
    });
 
    connection.onopen = function (session) {
        session.subscribe('iot.serial.reader', function (args) {
            $('#display').html(args[0]);
        });
    };
 
    connection.open();
});

It works — but thre’s a problem. The first time we connect with our browser, we won’t see the display value until we change the position of the potentiometer. That’s because the iot.serial.reader event is only emitted when potentiometer changes. No change means no new value. To solve this problem, we only need to change a little bit of our crossbar.io server. We’ll “memorize” the last value and we’ll expose one method iot.serial.get to ask about this value:

var autobahn = require('autobahn'),
    connection = new autobahn.Connection({
            url: 'ws://0.0.0.0:8080/ws',
            realm: 'iot'
        }
    ),
    mem;
 
connection.onopen = function (session) {
    session.register('iot.serial.get', function () {
        return mem;
    });
 
    session.subscribe('iot.serial.reader', function javascript:void(0)(args) {
        mem = args[0];
    });
};
 
connection.open();

And now, in the frontend, we ask for iot.serial.get when we connect to the socket:

$(function () {
    var connection = new autobahn.Connection({
        url: "ws://192.168.1.104:8080/ws",
        realm: "iot"
    });
 
    connection.onopen = function (session) {
        session.subscribe('iot.serial.reader', function (args) {
            $('#display').html(args[0]);
        }).then(function () {
                session.call('iot.serial.get').then(
                    function (result) {
                        $('#display').htmlresult);
                    }
                );
            }
        );
    };
    connection.open();
});

And that's all! The source code is available at my GitHub account. You also can see a demo of the working prototype in the below video:

Take a deep dive into Bluetooth mesh. Read the tech overview and discover new IoT innovations.

Topics:
arduino ,iot ,crossbar ,websockets ,tutorial

Published at DZone with permission of Gonzalo Ayuso, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}