gardner_hjsahwt_00 By Lyza Danger Gardner

This article has been excerpted from JavaScript on Things by Lyza Danger Gardner.

 

 

When I talk with developers who are intrigued by the idea of using their existing web and JavaScript dev skills to build hardware projects, the question that almost invariably pops up is: But, how does that work? Where does the JavaScript execute? How does it control the hardware? How do the pieces work together?

When I talk with developers who are intrigued by the idea of using their existing web and JavaScript dev skills to build hardware projects, the question that almost invariably pops up is: But, how does that work? Where does the JavaScript execute? How does it control the hardware? How do the pieces work together?

 Let’s see if we can answer these questions.

 When combining JavaScript with embedded systems, we still build electronic circuits in the same way that we would for other types of hardware projects. There are still inputs and outputs, wires and components. However, instead of using assembly code or C to control the project’s microcontroller or processor, we use JavaScript.

There are several ways we can do this, i.e. different methods for using JavaScript to provide the logic for hardware projects. These methods are categorized based on where the JavaScript logic executes itself: on a host computer separate from the embedded system; on the embedded system’s microcontroller; or somewhere else entirely.


 Host-Client Method

To get around the constraints of certain microcontrollers, the host-client method allows you to execute JavaScript on a more powerful host computer. As the host runs the code, it exchanges instructions and data with the embedded hardware, which behaves like a client.


gardner_hjsahwt_01

Figure 1 The host-client method of controlling hardware with JavaScript


Many microcontrollers have limitations that impact their ability to run JavaScript. Program memory is constrained, meaning that complex programs either won’t fit or have to be greatly optimized. Many inexpensive microcontrollers are built with 8- or 16-bit architectures running at clock speeds that are low (relative to desktop computers). Most wouldn’t be up to the task of running an operating system, ruling out the ability to run a Node.js or other JavaScript runtime directly on the chip.

Instead, the host-client method involves executing JavaScript logic on a host computer (like your laptop). The host computer does have the brawn necessary to run a full OS. The host machine is able to run Node.js and can make use of the worldwide JavaScript software ecosystem (e.g. npm, the web).

The trick to getting this setup to work is to make the client hardware (e.g. microcontroller) and host system (e.g. your laptop) communicate with each other using a mutually-intelligible “language”, i.e. a common API.


gardner_hjsahwt_02

Figure 2 For host computer and client hardware to communicate in this method, they both need to communicate using a common API.


Let’s imagine that we want to build a little gadget that would automatically turn a fan on when it gets warm. This miniature, independent climate control device could continuously monitor the temperature of the surrounding environment. When it gets too hot, the fan comes on. When it’s nice and cool again, the fan turns off. Let’s also imagine that we already have most of the parts we need (fan, temp sensor, etc.). To configure our automatic fan system gadget to use the aforementioned method, we’d first need to prepare the embedded hardware by uploading special firmware to the microcontroller’s program memory.

Instead of a specific, single-purpose program for controlling the fan, this firmware program makes the microcontroller able to communicate back and forth with other sources that speak the same “language” (i.e. API). That is, it turns the microcontroller-based hardware into a client, all ears and ready to do the bidding of the host computer.


gardner_hjsahwt_03

Figure 3 Specific firmware converts the microcontroller into a client.


The hardware is ready to communicate—the next step is to write software for the fan, using the host computer. For the hardware and software to understand each other, the host computer needs to bark out instructions in a language the microcontroller can comprehend. To make this happen, we can write code using a library or framework that implements the common API.


gardner_hjsahwt_04

Figure 4 The host needs to communicate using the common API, also.


The host is connected to the client hardware, either with a physical, cabled connection (often USB) or wirelessly (WiFi, Bluetooth). Then we start the execution of the fan-controlling JavaScript on the host computer. The host continuously communicates instructions for running the fan to the client. The client can also send messages back to the host—data from a temperature sensor, for example.


gardner_hjsahwt_05

Figure 5 As the host executes the JavaScript logic, instructions and data are continuously exchanged between client and host, using a common API.


Don’t panic, you won’t have to write low-level firmware protocol API software! There are straightforward, open-source options for firmware and Node.js frameworks that implement those firmware protocols—so you can write your host-side JavaScript logic with minimal fuss.

The benefits of the host-client approach are that it’s easy to set up and supported on many platforms. What’s more, it gives you access to the entire Node.js ecosystem, while avoiding the performance and memory constraints of inexpensive microcontrollers. The down side is that the client hardware is helpless without the host—it can only do its thing when the host computer is actively running the software. And while we’ll go wireless eventually, we’ll be starting out with the simplest of host-client options—USB tethering. That means that for a while, your projects will be physically attached to your computer.

Embedded JavaScript

With embedded JavaScript, the JavaScript logic to control the project runs directly on the hardware’s microcontroller. While many microcontrollers aren’t up to running JavaScript natively, some are. As you’d expect with the march of technology, inexpensive microcontrollers are getting more advanced. It has become possible run JavaScript, or an optimized variant of JavaScript, directly on certain embedded processors.

Each embedded-JavaScript platform is a combination of hardware and software ingredients working in tandem. On the hardware side, the development boards that are up to the task of running code natively are based on more capable (but still cheap) chips. Most platforms also provide a suite of software tools to complement their hardware. There might also be a corresponding library or framework to use for writing compatible JavaScript code, and a CLI (command-line interface) or other method for preparing the code and uploading it to the microcontroller.

Espruino (http://www.espruino.com) is an example of a JavaScript-based embedded platform. Espruino’s flavor of JavaScript combines optimized core JavaScript with an API of hardware-relevant features. You write code for the Espruino in a Chrome web app IDE and upload it to the board via USB. To adapt our automatic fan for Espruino, we’d need to write the logic using Espruino’s API. Also, Espruino boards’ compactness means they don’t have jumper-wire-compatible I/O pin connections—we’d have to solder our components to the Espruino’s pins.


gardner_hjsahwt_06

Figure 6 The Espruino platform combines small hardware boards with an IDE development environment.


Another example of embedded JavaScript is Tessel, a Node.js-based development platform. Tessel’s (http://tessel.io) hardware offerings aren’t limited to boards, but also include extension modules for various input and output functions. To build a Tessel version of our temperature-triggered fan, we’d use appropriate Tessel hardware modules—the climate module to sense temperature, the relay module to turn our fan on and off. The tessel npm module allows you to write software for the Tessel (in any text editor) and upload it from the command line—wirelessly, if you like, because Tessel 2 has built-in WiFi.


gardner_hjsahwt_07

Figure 7 The Tessel 2 (http://tessel.io) is an open-source platform that combines modular hardware with Node.js-driven software.


Being able to run JavaScript directly on embedded hardware can be power-efficient and self-contained. Projects are independent systems that can run on their own. Unlike the host-client setup, which requires firmware to do translation from JavaScript to machine code, there are (usually) fewer layers of abstraction between your JavaScript and the hardware.

This sounds great, and you might wonder why we wouldn’t use this approach exclusively. There are a few down sides. For one, there are fewer extant hardware options at the moment. Also, each platform has its own platform-specific techniques (software, tools, methodology) which can muddy the waters when learning hardware basics. Most also have certain limitations, either in JavaScript language feature support or in the types of inputs and outputs supported. But it’s an inspiring method with a very bright future.

Other Hardware-JavaScript Combinations

Aside from the host-client method and running embedded javascript, there are a few other ways to combine javascript with hardware projects.

Tiny, single-board computers (sbcs) blend the host and the client into one unit. Cloud-based services make it possible to write javascript code online and deploy it wirelessly to hardware. And emerging, very experimental features in web browsers themselves may offer a portal into the world of hardware for millions of web developers.

RUNNING JAVASCRIPT ON TINY COMPUTERS (SBCS)

Single-board computers (SBCs) like the Raspberry Pi and BeagleBone Black can run full OS environments (typically Linux), and, by extension, Node.js. Instead of an 8- or 16-bit microcontroller, SBCs have higher-performance, general-purpose processors. But many SBCs also have I/O pins and capabilities built right into the same board. Using an SBC to control a hardware project blends aspects of both the host-client method and running embedded JavaScript.

The processor has to continuously run the JavaScript logic for the project to work (as in the host-client model), but the whole package is contained on one board and feels more like an independent, embedded setup. Unlike microcontrollers that run embedded JavaScript logic, though, the processor on an SBC doesn’t run a single-purpose program—it can simultaneously run other processes.


gardner_hjsahwt_08

Figure 8 Several single-board computers (SBCs). Intel Galileo, Gen 2 (top); Raspberry Pi 2 Model B (bottom left); Raspberry Pi Zero (bottom right).


These single-board computers are getting cheap. At this moment, there’s the $5 Raspberry Pi Zero (at least, if you can get your hands on one—they’re notoriously out-of-stock), the $9 C.H.I.P. Even cheaper options are inevitable. There is no longer such a cost differential between low-power microcontroller hardware and legitimate tiny computers with processors that rival tablets and smartphones.

While running JavaScript on single-board computers with GPIO (General-purposeIO) support gives you lots of options on one piece of packaged hardware, it has a few drawbacks. SBCs aren’t as low-power as many microcontroller-based boards—the Raspberry Pi 2 Model B draws 4 watts. While the SBCs we’ll look at do have GPIO support, the pin mappings and usage can be confusing and documentation sketchy or technical, which can be challenging if you’re just learning about hardware hacking. You’ll also need to be ready to face system administration hurdles, as the Linux distributions for SBCs, especially when combined with Node.js, can require some debugging and patience.

For more on using JavaScript to give life to little gadgets and devices, take a look at the FREE first chapter of JavaScript on Things.