Today is Tuesday, May 15th 2012. Just over a year ago, I discovered node-serialport by Chris Williams and went immediately to the closest Microcenter and purchased the Getting Started with Arduino kit.
With my new kit and Chris’s serialport code, I was able to produce a JavaScript program and an Arduino program coupled to produce a simple Light Dependant Resistor demo (Arduino programs are written in the Arduino programming language which is based on C/C++, which is then compiled with avr-gcc and shipped to the microcontroller. The program was simple: print the current value of the LDR to the terminal via interactive REPL. Take a look:
Pretty cool, right? Maybe, but I don’t want to write Processing, C or C++. I want make robots that are driven by JavaScript programs.
About a month later at JSConf 2011 in Porland Oregon, while sitting on the floor in the hallway, Max Ogden and I hacked together a rad demo that allowed him to slide his finger back and forth over a Soft Potentiometer Membrane to control video playback. The sensor was attached to an Arduino board, the board then connected via USB to his laptop, which was running a Node.js program that listened for serialport data events and pushed the sensor data back out to a web browser client via Socket.IO, which was processed into time and handed off to Popcorn.js.
Soft Pot > Arduino > USB > Node Serialport > Socket.IO > Popcorn.js
Once the touch data reached the client on the browser, which was being displayed on my laptop, we used Popcorn.js and the data values to fast-forward and rewind a video of a Monkey Riding a Dog. That code is available here and you can watch the demo here (jump to 22:34).
Neat, isn’t it? Maybe, but I don’t want to write Processing, C or C++. I want make robots that are driven by JavaScript programs.
After returning from JSConf, things got very busy at Bocoup and I simply didn’t have time, nor interest, to spend on my ideas. My kit collected dust for nearly a year, occassionally I would come across interesting JavaScript, Node and Arduino projects, but I was too busy to really spend any time with them.
In December 2011, Duino was released, but I didn’t discover it until March of 2012. This was very exciting, because it was doing all of the things I had hoped to do with JavaScript and Arduino – so I cloned the repo and tried out a few of the demos. Then I started writing code and making pull requests. There was still a problem however – Duino expected me to extend the protocol written in C++ that it shipped with, in order to add new features. I sucked it up and wrote several modules including GPS, Ping, PIR and Sensor.
So this was cool, but I don’t want to write Processing, C or C++. I want make robots that are driven by JavaScript programs.
Then this happened…
@paultag @rwaldron @campedersen wouldnt that basically be this github.com/jgautier/firma… ?
— julian gautier (@Jagautier) March 29, 2012
@rwaldron lol! you do know you have a fork right 😛 github.com/rwldrn/firmata
— julian gautier (@Jagautier) March 29, 2012
And everything changed.
The package Julian had created was a JavaScript implementation of Firmata, which is a protocol for communicating with Arduino microcontrollers from software on a host computer, written in any language. Free of Processing, C and C++ bondage, and using Firmata as the baseline communication channel, I rebooted and started from scratch. First, I endeavored to write a Board
constructor that, while inspired by and conceptually similar to Cam’s duino.Board()
, had finer abstractions for instance management, active serial/USB discovery and by-default REPL sessions built in to every program. This is the foundation of Johnny-Five.
Once I had the initial Board
constructor, I created a slightly modified version of Julian’s servo-sweep.js as a proof of concept for baseline of the framework:
var five = require("../lib/johnny-five.js"),
board;
board = new five.Board();
board.on("ready", function() {
var claw = 9,
arm = 11,
degrees = 10,
incrementer = 10,
last;
this.board.pinMode( claw, 3 );
this.board.pinMode( arm, 3 );
setInterval(function() {
if ( degrees >= 180 || degrees === 0 ) {
incrementer *= -1;
}
degrees += incrementer;
if ( degrees === 180 ) {
if ( !last || last === 90 ) {
last = 180;
} else {
last = 90;
}
this.board.servoWrite( arm, last );
}
this.board.servoWrite( claw, degrees );
}.bind(this), 50);
});
With a stronger Board
constructor, porting all of the modules I had created for Duino into this new framework was mostly a breeze. A few days later, the Servo
module emerged, transforming the code into this:
var five = require("../lib/johnny-five.js"),
board;
board = new five.Board();
board.on("ready", function() {
var claw = new five.Servo( 9 ),
arm = new five.Servo( 10 ),
degrees = 10,
incrementer = 10,
last;
this.loop( 25, function() {
if ( degrees >= 180 || degrees === 0 ) {
incrementer *= -1;
}
degrees += incrementer;
if ( degrees === 180 ) {
if ( !last || last === 90 ) {
last = 180;
} else {
last = 90;
}
arm.move( last );
}
claw.move( degrees );
});
});
Over the next few weeks as I acquired new hardware and sensors, each new piece brought with it a new physical engineering and software engineering challenge. Several times I found myself revisiting a stable module and starting over when a useful abstraction presented itself. One of the most important refactorings that occurred had nothing to do with code. Early on it became clear that I would need to document the hardware that I was building, especially if I was to continue creating sans permanence. Arduino tutorials are often published with colorful illustrations of the microcontroller connected to a breadboard and various gadgets – this is what I wanted and what I found in Fritzing. With Fritzing, I now had the tools to quickly and easily create detailed, visually appealing documentation of the hardware that accompanied each of the example programs that I created.
var five = require("johnny-five"),
board, led;
board = new five.Board();
board.on("ready", function() {
// Create a standard `led` on pin 13
led = new five.Led(13);
// "strobe" the led in 100ms on-off phases
led.strobe(100);
});
Once assembled, the program can be run from the command line as
node led-strobe.js
and should look like this:
Admittedly, this example is less-then-mind-blowing — but it’s just one piece of a larger whole.
My goal for Johnny-Five is to create a framework for programming Arduino Robots with nothing more then JavaScript. I believe that JavaScript, inherently asynchronous and the platform that Node.js has built around this paradigm, is the perfect environment for writing evented, streaming programs for controlling the highly synchronous world of hardware.
As part of Johnny-Five’s development process, I’ve created 28 component-centric mini-programs. I intend to publish these along with breadboard schematics and parts lists, twice each week over the next few months.
…And this is how I’ll make robots that are driven by JavaScript programs.
As the language continues to prove itself worthy of high performance use beyond the browser and its lower level capabilities improve, I don’t think it’s unreasonable to at least open our minds and imagine a future where we control things like home and vehicle automation, assembly lines, meteorological equipment, robotics… etc. with programs written in JavaScript.
References: [0] node-serialport [1] Chris Williams [2] Microcenter [3] Getting Started with Arduino [4] Arduino [5] Arduino LDR Demo [6] Arduino program [7] Arduino programming language [8] C [9] C++ [10] avr-gcc [11] Node REPL [12] JSConf 2011 [13] Max Ogden [14] Soft Potentiometer [15] Soft Potentiometer Membrane [16] Socket.IO [17] Popcorn.js [18] Monkey Riding a Dog [19] Monkey Riding a Dog Demo Code [20] Duino [22] GPS [23] Ping [24] PIR [25] Sensor [26] Firmata JavaScript implementation [27] Firmata [28] Johnny-Five [29] servo-sweep.js [30] Hardware and Sensors [31] Fritzing [32] int64/uint64 value objects prototyped in SpiderMonkey [33] JavaScript Today and Tomorrow: Evolving the Ambient Language of the Ambient Computing Era [34] Controlling Big, Mean, Devices…..With Javascript!