Your friends at Viget present Extend, a Code & Technology Blog

Web Interfacing With Arduino

So, you've got what it takes to turn on LEDs and move some motors around using your trusty Arduino. You also have some skills writing web code. Here’s a simple walkthrough of how to combine your great talents and make a nice web interface for your Arduino project!

Communication with the Arduino

Here at Viget we write a fair amount of Ruby code, so this post will focus on interfacing your Arduino with Ruby. Using the serialport gem, communication with your Arduino over the serial port is easy. To enable serial communication from your Arduino, you need a line of setup code:

setup {
    Serial.begin(9600)
}

You can then send out data anywhere in your program:

loop {
    ...
    Serial.println("Hello world!")
    ...
}

Catching this on the Ruby side is straightforward as well. With some set up to specify the port, you’re ready to listen:

require 'serialport'

port_str  = '/dev/tty.usbmodem1411'
baud_rate = 9600
data_bits = 8
stop_bits = 1
parity    = SerialPort::NONE

sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)

while(true) do
  message = sp.gets
  message.chomp!

  puts message
end

This code will read every message coming through the Serial port and print it out (messages come in with a trailing newline character so .chomp! handles that for you). It's worth noting that sp.gets blocks until a message comes in from the Serial port.

Sending messages back to your Arduino from Ruby can be done using sp.write(message), and catching the messages with Serial.read().

Communication with your browser

Now that you’re catching updates from your Arduino in real time, we’ll make use of websockets to instantly update a web page. There’s a great article here explaining this technology and how to easily get yourself set up using Ruby. Here are the basic code snippets.

In your Ruby file:

require 'em-websocket'
require 'json'
require 'serialport'

sp = SerialPort.new('/dev/tty.usbmodem1411', 9600, 8, 1, SerialPort::NONE)

EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 8080) do |ws|
  ws.onopen    { ws.send "hello client" }
  ws.onclose   { puts "WebSocket closed" }

  ws.onmessage do
    ws.send message_from(sp).to_json
  end
end

def message_from(sp)
  message = sp.gets
  message.chop!

  { "event" => message }
end

In your HTML file:

$(document).ready(function() {
    ws = new WebSocket("ws://localhost:8080");

    ws.onopen = function() {
        ws.send("hello server");
    };
    ws.onclose = function() {};

    ws.onmessage = function(evt) {
        console.log(evt.data);
        var message = JSON.parse(evt.data);

        // code to update the page given the incoming message

        // send a dummy message back to initiate
        // the onmessage callback again
        ws.send("next message please!");
    }
});

We now have an instant channel for communication between Arduino-listening Ruby code and JavaScript. With the Ruby file running, we can open up the HTML file in a browser and the communication loop will begin. Ruby will then wait on the Arduino for a message over the serial port, work it into a hash, and ship it over to our JavaScript in JSON. The JavaScript then needs to send a dummy message back so the process can start again.

At this point, your web skills can take over and you can update divs and spans every time something happens on your Arduino. This is an easy way to give a pretty face to our Arduino projects. Bonus points for running your web server on a cheap Raspberry Pi.

Extra credit

Take a look at Dino. This is a sweet little gem that allows you to read from and control your Arduino using only Ruby code -- and it gives you the ability to send commands in real time to the Arduino such as servo.position = 80 or led.on. With Dino, you would not need your Arduino to respond to specific strings coming over the Serial port, but instead could have your Ruby file control the Arduino itself.

 

Think this is a good idea? Found a much better way to interface your Arduino with the web? I’d love to hear your comments below.


Get More From Viget

Subscribe to get our monthly newsletter and occasional special announcements.