Web Interfacing With Arduino
Eli Fatsi, Former Development Director
Article Category:
Posted on
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.