Chapter 10. JavaScript and constrained hardware
This chapter covers
- How JavaScript-capable embedded hardware platforms compare with host-client and single-board-computer (SBC) platforms
- Steps for familiarizing yourself with a new development platform
- Examining two representative embedded JavaScript platforms: Espruino Pico and Kinoma Element
- Developing projects with the Espruino Pico
- Crafting text and shapes with Nokia 5110 LCD displays and the Espruino Graphics library
- Reusing trusty components: using the BMP180 multisensor and HMC5883L compass in new ways on different platforms
- A case-study view of the Kinoma Element
In the first half of this book, electronics fundamentals were demonstrated by using a tethered Arduino Uno—a host-client setup. In the past few chapters, though, you’ve met the Tessel 2, which has the oomph to run Node.js natively within its OpenWrt operating system—that’s a single-board-computer (SBC) setup.
Now we’re going to take a look at a third class of JavaScript-controlled platforms: constrained embedded hardware with native support for JavaScript (or, often, something that’s JavaScript-like). To accomplish this feat with such limited hardware resources, these platforms tend to rely on highly optimized custom JavaScript engines.
These devices are evolving quickly, entering (and exiting) the market more rapidly than can be captured well in print. At this very moment, the Espruino platform—we’ll be looking at the Espruino Pico shortly—seems to be maintaining robust momentum (figure 10.1). The Kinoma Element—also on-deck for our investigations—has been in prerelease for quite some time. Although Kinoma’s embedded runtime has been held up as an early pioneer in supporting most ECMAScript 6 features, the Element product may not end up taking off. It’s hard to say with things moving so quickly.
Obsolescence is pretty much guaranteed for IoT hardware and software information committed to print, which is why this chapter focuses more on tasks and puzzles common across embedded JavaScript platforms. Specific products and platforms come and go, but there are a bunch of common research steps that can help you get up to speed, quickly, on whichever product you choose.
For this chapter, you’ll need the following:
- 1 Espruino Pico
- 1 Kinoma Element
- 1 USB micro cable
- 18 (two strips of 9 each) 0.1″ male breakaway header pins
- 1 USB 2.0 A to USB A female (a.k.a. a USB extension cord) cable
- 1 Adafruit BMP180 I2C multisensor breakout board
- 1 Nokia 5110 84x48 LCD display module
- 1 100 V resistor
- 1 Adafruit HMC5883L magnetometer (compass) breakout board
- 1 full-sized breadboard
- Jumper wires

The Espruino Pico has less memory and less computational power than the Tessel 2. There’s no WiFi and no USB peripheral support, so why use it? Because it shines at other things: it’s cheaper, it’s tiny, it’s reliable, and it’s power-efficient—hallmarks of low-power embedded platforms.
Espruino describes both the hardware family itself and the firmware runtime interpreter that comes preflashed on Espruino devices. Espruino-the-interpreter supports most JavaScript features, but not all of them. You can’t get away with omitting semicolons, for example, and regular expressions aren’t supported.
It’s important to differentiate JavaScript and JavaScript-esque from Node.js: this isn’t Node.js, so you can’t use Johnny-Five or any npm modules.
Instead, Espruino provides its own JavaScript API for interacting with the hardware I/O (www.espruino.com/Reference#software). You’ve got enough experience under your belt now that aspects of the API likely ring familiar—there’s an analogRead function, for example, that takes a pin number as an argument. There are also Espruino-specific modules that encapsulate the behavior of specific electronic components, as you’ll see.
Before examining the Pico in more depth, you’ll get it set up and take a Hello World LED-blinking script for a spin.
The Pico needs to be soldered onto header strips (figure 10.2). Your Pico may have come with header strips, but if not you’ll need two strips of nine pins each.
Figure 10.2. The Pico has 18 pins (two rows of 9 each) at a 0.1-inch pitch—breadboard-compatible. They’ll need to be soldered onto header pins. One end of the Pico board is shaped so that it can be plugged directly into a USB port.

The Pico plugs right into a USB port. Some versions of the Pico have an additional USB micro connection, but you may well be stuck with just the USB A connection. This can be convenient, because you can plug your Pico right into your computer, but if you want to use the Pico on a breadboard—which is necessary when you want to try out any of the I/O pins—it gets a little tricky. The Pico is designed to connect to a USB A female connector. You can use the kind of cable marketed as a USB extension cable to get the USB A to USB A female connections the Pico needs (figure 10.3).
Figure 10.3. You can use a USB extension cable to connect your Pico to your computer, allowing the Pico to be placed on a breadboard. The Pico’s USB end slots into a USB A female connection.

Things are evolving quickly enough in the Espruino family that including exhaustive setup instructions here would be foolish. Instead, head to https://espruino.com to get started.
These are the basic steps, after plugging your Pico into USB:
- Get the Pico ready for your platform:
- Mac users likely don’t need to do anything else.
- Windows users will probably need a driver.
- Linux users may need to adjust permissions.
- Install the Espruino IDE Chrome app (and the Chrome browser if you don’t have it installed).
- Launch the Chrome app, and connect to and update the Pico’s firmware.
For the purposes of experimenting with the Pico, you’ll be using Espruino’s web-based IDE (Chrome app)—that means you’ll connect to, communicate with, and deploy code to the Pico from within the Chrome app.
On the left side of the app’s interface, you’ll see a terminal-like console area. Once you’re connected to a Pico, you can type expressions here directly, sort of like a Node.js interpreter or the Johnny-Five REPL. On the right side is an area where you can compose scripts.
Let’s try it out with the requisite blinking of an LED. For this experiment, you’ll be using one of the Pico’s onboard LEDs, so you can plug the Pico into your USB port directly or stick it on a breadboard with a USB extension cable: the choice is yours.
An assortment of variables are available at a global level in Espruino scripts, pertaining to platform features and pins. This includes the variables LED1 and LED2 for the Pico’s built-in red and green LEDs, respectively (figure 10.5).
Figure 10.5. This experiment will cause the Pico’s onboard LEDs—one red, one green—to blink alternately. Access to the LEDs is provided via the global variables LED1 and LED2.

Fire up the Espruino IDE Chrome app and connect to the Pico. Enter the code shown in the following listing into the code-composition area of the screen (the right side) and click the Send to Espruino icon in the center (figure 10.6).
- 1 LED1 (the red onboard LED) and LED2 (green) are available in Pico scripts.
- 2 Uses setTimeout to make the function call itself every 500 ms
- 3 Kicks off the toggling
This example uses Espruino’s digitalWrite function to alternately set LEDs HIGH and LOW. Once you deploy the code to the Pico, you should see the Pico’s red and green LEDs blinking, one at a time. You’ll also see some output on the left side of the IDE window.
Now that you’ve gotten hands-on, let’s back up a bit. How do you know that the Pico has two built-in LEDs (red and green), and how do you know that there are variables LED1 and LED2? By now, conventions like digitalWrite being a name for a function that writes logic levels to digital outputs probably seems sensible. But it may still seem somewhat magical or random. Where does one start?
There are a series of sleuthing steps you can apply when facing a new platform to get you scooting along in short order. You’ll tackle these to learn about the Pico specifically now, but you can reuse them to evaluate different embedded platforms in the future:
- Discover the platform’s core features
- Find a pinout or hardware diagram
- Learn about the configuration and development workflow
- Find examples and simple tutorials and get hands-on
- Use the reference API documentation
Let’s look at each of these.
Before you even get your hands on a new dev board or platform, you’ll probably want an overall sense of what it can do.
Often the key details are summarized on the manufacturer’s or supplier’s web site. In the Pico’s case, a list of features the Pico’s web page gives us the scoop: it’s a 3.3 V device, petite in form factor (33 mm x 15 mm), it’s powered by a STM32F401CDU6 microcontroller (no, my cat didn’t just walk on my keyboard; ST—the manufacturer—has naming conventions that are unromantic, but quite precise), and it uses an ARM Cortex M4 processor (www.espruino.com/Pico).
Also in the key features list are bullet points about power consumption (figure 10.7). Even if the specific numbers cited here don’t hit home, you can see that they’re making noise about being power efficient.
There are 22 GPIO pins on the device, including 3 I2C interfaces and 3 (hardware) SPI interfaces—not shabby for something so small. If you click through to the microcontroller’s datasheet (http://mng.bz/i7r8), you can see that you have the STM32F401D/E family to thank for that (there’s a section about communication interfaces on the front page).
A couple of other features jump out. One is a nice nod to the ubiquity of 5 V logic—”All GPIO is 5 volt tolerant (Arduino compatible)”—a kindness to those of us who have to swap between the two a lot. Output will always be 3.3 V, but 5 V input won’t give the Pico heartburn.
Another detail worth noting: although 18 pins (two rows of 9) are at a breadboard-standard 0.1″ pin pitch, 8 pins on one short end are only 0.05″ apart (figure 10.8). You won’t be using those pins in your explorations, as they don’t slot easily into a breadboard, but there are physical shims you can get to make it possible.
Figure 10.8. Eight of the Pico’s I/O pins are at a 0.05 inch pitch: too narrow to slot into breadboards.

Granted, this particular list of features doesn’t mention that this a JavaScript-powered device, which is kind of key, but you can certainly glean that from Espruino’s home page (www.espruino.com).
ARM Cortex M MCUs and embedded JavaScript
Both the Espruino Pico and the Kinoma Element are based on microcontrollers from the ARM Cortex M family. Just as ATmega MCUs are found on all sorts of Arduino-compatible, host-client-class boards (like the Arduino Uno and its brethren), ARM Cortex M MCUs are very popular for the class of embedded platforms that include the Element and the Pico. ARM’s site claims that 10s of billions of devices have been produced using products from the Cortex M family.
The 32-bit microcontrollers in the Cortex M family outclass 8-bit ATmegas while still operating at low power (most are predictably not quite as cheap). Embedded JavaScript (or JavaScript-like) runtimes need more processing power than an 8-bit ATmega can provide.
As you continue to experiment with new platforms, chances are you’ll continue to encounter Cortex M variants.
Another thing that’s handy to understand is the platform’s financial and licensing model. Is the hardware or software (or both) open source, or are they proprietary? This can be relevant if you’re considering using a platform commercially, extending hardware or software, or otherwise making contributions to a platform. (Espruino platforms are fully open source.)
Maybe it’s because I have a love for maps, but finding and analyzing a board’s pinout diagram is usually when things really click home. These diagrams show you which pins can do what: communication interfaces, PWM, power pins, and so on.
From the Pico’s diagram (figure 10.9), we can note a few things (see it in a larger size with more detail on Espruino’s Pico documentation page: www.espruino.com/Pico). For one, pin numbers aren’t sequential; they jump around a bit, and you’ll find both A and B pins on both of the two sides you’ll be using. You can also see that there’s PWM support on nearly every GPIO pin. Finally, you can see which pins have hardware support for I2C and SPI, and which can support ADC (analog-to-digital conversion).
A combination of sensible overall pin layout (hardware design) and high-quality pinout diagrams can make for a better development experience.
How is code written? Deployed? How is the device managed, configured, and updated? Is it supported for your operating system? Is the configuration process overwhelming and tedious? That could be a sign of an ongoing headache.
In the Pico’s case, we’ve taken the recommended route of using the Chrome app IDE. This can be convenient—code authoring, device management, and deployment are in one place—but if you’re the kind of person who has an attachment to your own editor or IDE for writing JavaScript, it might drive you nuts.
Get a sense of the high-level software constructs: are there plugins or other modularized components? Is there a general hardware-oriented API? Espruino has both of these.
Stepping through some Hello World examples is next, and you’ve already done that with the Pico. When experimenting with a new platform, figure out how to accomplish some common tasks, such as blinking LEDs, reading data from an analog sensor, working with displays, and controlling I2C devices. Ideally, you’ll get hands-on at this step, getting a sense for how it really feels to interact with the platform during development.
Once you’ve got your head around the big picture, and seen (and tried) a few applied examples, hitting up reference documentation can help fill in the details.
If you glance at Espruino’s API documentation (10.10), you’ll see familiar JavaScript classes—String, Math, Boolean, JSON—along with Espruino-specific classes relevant to hardware stuff: I2C, SPI, WLAN. The Globals section lists hardware functions like digitalWrite() available to Espruino scripts, and also some standard JavaScript global goodies like setTimeout() and eval().
There’s also a page that lists available modules for Espruino and how to use them (www.espruino.com/Modules). More on that as we explore the Pico more fully.
As you learn more about a platform and gain experience with it, you’ll find yourself moving from a learning phase, where you’re seeking out prebaked examples, concepts, and tutorials, to a reference phase, where you’re searching for details on how to accomplish specific tasks.
Figure 10.10. Espruino’s API documentation at www.espruino.com/Reference

Next, you’ll take the Pico for a spin and try out a few experiments. First, you’ll revisit the BMP180 weather multisensor, but you’ll be combining it with a Nokia 5110 LCD display component to build a nice-looking, self-contained mini weather station.
What you’ll need

- 1 Espruino Pico
- 1 full-size breadboard
- 1 USB extension cable
- 1 BMP180 breakout board
- Jumper wires
Because you’re using the Web IDE, working with Espruino modules is as easy as using a require() statement in the Espruino code with the name of the module you’re after. These modules provide encapsulated support for different types of components. And, huzzah, there’s an existing module for your trusty BMP180 temperature and pressure multisensor. The module’s called BMP085 because it’s also compatible with the similar BMP085 sensor. Once the module is imported, you can use the API it provides to interact with the BMP180 sensor. Let’s see what that looks like.
This experiment will log the current temperature (in Celsius) and pressure (in pascals) as obtained from the I2C BMP180 sensor.
The code required to log readings from a BMP180 isn’t too dense, as you’ll see in listing 10.2. It makes use of the exposed I2C1 global to configure an I2C interface that it then passes to the connect method of the BMP085 module.
As you’ve seen, Johnny-Five provides several constructs for performing continuous, periodic actions like sensor reads—board.loop, for example. But you’re not using Johnny-Five here. Instead, you’ll follow Espruino convention, which makes use of setInterval for repeated I/O.
- 1 Sets up the Pico’s first I2C interface (I2C1), using pins B6 for SCL and B7 for SDA
- 2 Requires the BMP085 module and invokes its connect function, using the I2C1 interface
- 3 The getPressure method of the instantiated bmp object is async; registers a callback...
- 4 Performs sensor reads every second (1000 ms)
How do you know that pins B6 and B7 support I2C SCL and SDA respectively? From the pinout (figure 10.11).
To construct this, you’ll want to put the Pico on a full-size breadboard and use a USB extension cable. Construct the circuit shown in figure 10.11.
The setup may seem a bit cockamamie at the moment. “Why stick the BMP180 sensor so far away from the Pico?” you may reasonably be wondering. There’s a method to this madness: the resulting gap will allow for the expansion of this circuit to accommodate the Nokia 5110 LCD component in upcoming experiments.
Full-size breadboard connections
If this is your first time using a full-size breadboard, note that it really is effectively two half-size breadboards joined end-to-end, in terms of electrical connections. A gotcha with full-size breadboards is that the power rails have a break in their connections halfway down the board (figure 10.12).
Figure 10.12. Don’t forget! The power rails on a full-size breadboard have a break midway down the board.

Enter the code from listing 10.2 into the right side of the IDE, and click the Send to Espruino up-arrow icon to execute the code on the Pico. The logged pressure and temperature will appear on the console/terminal (left) side of the IDE window (figure 10.13).
Figure 10.13. Once the BMP180 script is uploaded to the Pico, you should see output logging to the left side of the screen once per second.

What you’ll need

- 1 Espruino Pico
- 1 Nokia 5110 48x84 LCD breakout board
- 1 full-size breadboard
- 1 100 V resistor
- Jumper wires
The Nokia 5110 48x84 pixel display (figure 10.14) was originally used in the popular Nokia 51xx family of phones, which date from the late 1990s (great phones, by the way—they were known for their durability, excellent battery life, and ease of use). Nokia 5110 LCD units can be found online for as little as $6, but they’re easier to find at around $10 each. They’re great little components: 48x84 pixels isn’t infinite real estate, but it’s a lot more than the 16x2 we’ve seen so far. There’s room to draw, animate, and do fun things.
Figure 10.14. The Nokia 5110 LCD has 48x84 pixel resolution and an SPI interface provided by its Phillips Semiconductor PCD8544 driver. The display is shown here the right side up.

The display is controlled by a Philips Semiconductor driver named, in that non-memorable way that such components often have, the PCD8544. The PCD8544 provides an SPI interface to the display, and (yay!) there’s an Espruino module for this controller.
You’ll start by creating a visual countdown timer using the Nokia 5110 on its own, and then you’ll combine it with the BMP180 to make a little weather station.
Nokia 5110/PCD8544 pinouts
Different PCD8544/Nokia 5110 modules have different pinouts! Check your board’s pin labeling before trying to follow the wiring diagram in figure 10.15. The connections should be silkscreened on the board.
The layout used in the wiring diagram is based on the 5110 variant available on SparkFun’s product page (http://mng.bz/IId1), with connections as shown in the following figure. It’s worth noting that the SparkFun module’s pinout is different from the one assumed in the “Pico LCD Display Hello World” tutorial on Espruino’s site (http://mng.bz/604s), but the layout documented by SparkFun seems to be more common.

The wiring diagram in this chapter is based on the SparkFun version of the Nokia 5110 and assumes a pinout as shown here. Check your 5110’s pinouts and adjust the connections in the circuit if they differ.
See table 10.1 for the specifics of which LCD modules pins connect to what on the Pico.
Leave the BMP180 connected from the previous experiment—you’ll use it again in a minute—and connect the Nokia 5110 to a free section of the full-sized breadboard as shown in figure 10.15 (and summarized in table 10.1).
Table 10.1. Nokia 5110 LCD connections
LCD pin function |
Connect to Pico pin |
Wire color in diagram |
|
---|---|---|---|
VCC or Vin | 3.3 V source power | 3.3 V | Red |
GND | Ground | GND | Black |
CE or SCE | SPI chip select | B14 | Blue |
RST | Reset | B15 | White |
DC or D/C | Data/command | B13 | Orange |
MOSI or DN | SPI master out, slave in | B10 | Green |
SCK or SCLK | SPI clock | B1 | Yellow |
LED | 3.3 V source for LED backlight | 3.3 V, through 100 V resistor | Red |
Wiring diagrams and aesthetics
If you study figure 10.15, you’ll notice a few details that are a nod toward clarity and aesthetics, both in the diagram itself and the resulting circuit.
For example, note the power connections (red wires). The BMP180 and Nokia 5110’s backlight LED are now sharing one of the positive power connections. The LCD’s backlight LED power is connected through a 100 V resistor—it’s an LED, so this resistor value of 100 V is a good one for a 3.3 V circuit.
Keep in mind that the full-size breadboard’s power rails have a break in their connections midway along the long side of the breadboard (a full-size breadboard really is equivalent to two half-size boards stuck together). Hence the short extra ground wire in this diagram: it connects the ground power to the other half of the board’s ground rail, bridging the connectivity gap.
When you work with circuit diagrams, you’ll often see affordances made to keep the circuit “tidy” in appearance, like that split ground connection. Yet another example in figure 10.15 is the orange wire for the Nokia 5110’s D/C (data/command mode); the connection is split into two segments so that it doesn’t have to overlap other components or wires visually. Other connections are bridged across the breadboard’s central notch before using separate wires to complete the connections.
There are many ways to achieve the same resulting circuit. Each of the multiwire connections could be made with a single wire, if you’re looking to save on time or wires needed.

To get acquainted with the Nokia 5110 and Espruino’s Graphics capabilities, this experiment creates a 10-second timer that shows its progress using an animated progress bar on the LCD (figure 10.16). You can, of course, adjust the timer’s duration in the code. The timer is started by pressing the Pico’s itty-bitty built-in button.
Figure 10.16. The timer’s display. The filled-in rectangle is “animated” and grows to the right as time elapses.

To write a program for the timer, you’ll use the Espruino PCD8544 module. The code first sets up some variables and creates an initialization function to set up the timer (10.3), as shown in the next listing.
- 1 Determines how many “ticks” (frames) long the timer lasts
- 2 Keeps track of whether the timer is currently running
- 3 Configures an SPI interface for the LCD
- 4 Uses the PCD8544 Espruino module to instantiate an object representing the LCD
- 5 Invokes the onInit() function to get things going
Next, you need to find a way for a user to activate the timer. You can use the Pico’s onboard push button as a trigger to start the timer by making use of some Espruino global goodies: the setWatch(function, pin, options) function and the virtual BTN pin.
The setWatch() function provides interrupt-like behavior, allowing you to register a callback that’s invoked when the watched pin’s value changes. In listing 10.4, setWatch() is used to watch BTN continuously. Before starting the timer, the code makes sure there isn’t another timer already running, and then it resets the timer’s progress and kicks things off.
Interrupt-like behavior?
The setWatch function provides interrupt-like behavior. The technicality is explained in Espruino’s API documentation on setWatch (http://mng.bz/EE71): “Internally, an interrupt writes the time of the pin’s state change into a queue, and the function supplied to setWatch is executed only from the main message loop.”
- 1 Invokes the draw function every frameDuration (200 ms)
- 2 The second argument to setWatch specifies the pin to watch—the Pico’s onboard button.
- 3 The third argument is options, here specifying that the watching should continue indefinitely (repeat: true).
The timer runs by repeatedly invoking a function named draw at a calculated interval. But what is the draw function? You’ll need to write it! Your draw function’s tasks will include incrementing the timer’s progress and rendering its proportional progress onto the LCD screen.
The object returned by the PCD8544 module’s connect method—assigned in your code to the variable lcd—provides a few LCD-specific methods like flip(), which takes the current contents of a buffer and displays them on the screen, and setContrast()—that method does what it sounds like it would do. In addition, the object inherits from Espruino’s Graphics library (www.espruino.com/Graphics), giving you tools to render text strings as well as draw lines and shapes.
The draw function in listing 10.5 uses the drawRect(x1, y1, x2, y2) method to draw the outline of a box representing the total timer duration. Then fillRect(x1, y1, x2, y2) is used to draw a filled-in progress bar at a width representative of the time elapsed so far. The only real math the draw function needs to do is determine how wide that filled rectangle should be—how many of the LCD’s available 84 horizontal pixels represent the proportion of time that has elapsed. That’s calculated and assigned to the rightEdge variable. To summarize: an empty rectangle—the progress bar’s outline—is drawn, vertically centered on the screen, and then a filled rectangle of the calculated width is drawn inside of it.
- 1 If the timer is done, turns it off and stops
- 2 Calculates the x-axis position of the right side of the filled progress rectangle
- 3 Uses drawRect(x1, y1, x2, y2) to draw an empty box vertically centered, eight px high
- 4 Uses fillRect(x1, y1, x2, y2) to draw a filled box representing progress so far
- 5 Draws everything to the LCD screen
Paste the timer code into the right side of the Espruino IDE, connect to the Pico, and upload the code. Press the Pico’s button to start the timer.
You can make adjustments to the code if you’d like. You could change the timer’s duration, or you could make the LCD display a message when the timer is complete, for example.
You’re getting to be rather an expert at building mini weather gadgets, and here’s another one to add to the arsenal. By combining your old friend the BMP180 sensor with the Nokia 5110 display, you can cobble together an independent, nicely formatted, low-power weather device (figure 10.17).
If you followed along through the previous two experiments, you already have the circuit you need: the BMP180 and the Nokia 5110 connected to the Pico on a full-sized breadboard (figure 10.18). You’ll rely on some more features of the Espruino Graphics library to allow you to draw vector fonts and more shapes to format the display of the data, and you’ll deploy the resulting code to the Pico’s flash memory so that the Pico will independently run the program any time it’s provided with power.
As with the timer, you’ll start by setting up some variables and an initialization function, shown in listing 10.6. Pressure readings on the BMP180 are considerably more accurate if you adjust them for your local altitude (in meters). The getSeaLevel method, available on objects returned by the BMP085 module’s connect() function, gives you a handy way to perform that altitude correction. Note that the getPressure method is used here to read both pressure and temperature at the same time. Make sure to adjust the value of the altitude variable in the next listing to your local altitude (in meters).
- 1 Once the LCD is set up, then kick off the setInterval.
- 2 Invokes draw with the current temperature and the pressure adjusted for altitude
- 3 Don’t forget to invoke the onInit function!
As with the timer, you need to write the draw function. The code in listing 10.7 makes use of more shape-drawing methods from the Graphics library: drawLine(x1, y1, x2, y2) and drawCircle(x, y, radius) (figure 10.18). It also avails itself of some methods for deriving dimensions: getWidth() and getHeight(), for example, which return the display’s usable area, in pixels, for the x and y axes, respectively. Finally, stringWidth(str) calculates the pixel width of the given string, using the current font settings.
Let’s talk fonts. There’s a tiny bitmap font available whose characters are 4 x 6 pixels in size. To use the bitmap font, you use the setFontBitmap() method to make that font active. In this example, however, you’ll use a vector font. The vector font can be used at various sizes—it scales. The setFontVector(size) method will set the active font to a scaled vector font with a height of size pixels.
There are a lot of numbers in the following draw function. It’s a bit finicky-looking, but everything here is unsophisticated pixel arithmetic to position elements of text and shapes. Note that the string “mb” in the drawing function (the abbreviation for millibars) is “hand-kerned,” because I found that drawing the string in one go at that font size ran the letters together illegibly.
Put all of the code for the weather gadget into the code side of the Espruino IDE, and use the Send to Espruino icon to run the code on the Pico. It’ll show the temperature and pressure until it’s unplugged from the USB port of your computer.
But you can do a little better! On the left side of the IDE, type the command save() and press Enter. This will flash the code to the Pico. Now, anytime the Pico has power, it will resume running this code. Try it out by plugging the Pico into a USB power source, like a phone charger.
Power efficiency and the LCD’s backlight
To make the weather gadget more power-efficient, you might consider disconnecting the LCD’s LED backlight connection from power. You won’t be able to read the LCD in a dark room, but it’ll draw less power.
To rinse and repeat the process of platform exploration, we’ll take a brief look at another embedded-JavaScript platform: the Kinoma Element.
The Element is a small, JavaScript-powered IoT platform with 16 programmable pins (figure 10.19). Like the Espruino Pico, it’s inexpensive—an Element will set you back about $20 or maybe a little more. Also like the Pico, it lacks the bells and whistles of its more beefy (and costly) brethren—you won’t find onboard USB, Ethernet, SDCard, or other peripheral goodies—but it has the basic bits needed for IoT products in an efficient little package. Also, it has built-in WiFi support.
Chipmaker Marvell produces the Element (http://mng.bz/w1lR), which features its Marvell MW302 System-on-a-Chip (SoC), which in turn uses a 200 MHz ARM Cortex M4. The board, enclosure, JavaScript runtime, and framework software are open source.
To run JavaScript natively with only 512 KB RAM, the Element uses a technology called XIP (execute in place). The Element runs FreeRTOS, a streamlined and minimal open source operating system. The board’s operating voltage is 3.3 V.
The Element comes packaged in an enclosure, which makes it look less like a board and more like a finished device (the enclosure design is open source too). Instead of having dedicated power pins, you configure any of the Element’s 16 pins (8 on each side of the board) as 3.3 V or ground as needed.
Kinoma uses its own (Apache-licensed) JavaScript engine, XS6, which, with minor exceptions, claims ES6 compatibility. Note that the Element’s IDE software is available for Mac and Windows (beta), but it doesn’t have Linux support.
The Element’s pin layout is rather straightforward (figure 10.20). It’s a simpler device than the Pico in terms of I/O feature support; for example, there are two I2C interfaces but no support for SPI. On the flip side, it’s less complex to figure out which pins do what, and the numbering is easy to follow.
The Element is a tidy, self-contained package that won’t require any soldering or prep. Jumper wires can plug right into it directly.
The configuration and workflow is similar to the Pico in that there’s an IDE for configuring, authoring, and deploying. If you have an Element on hand, you can head over to the quick-start guide for details (http://mng.bz/84cS), but these are the general steps:
- Download and install the Kinoma Code IDE.
- Get the Element set up on your WiFi network.
- Apply the firmware update.
Code projects for the Element, developed in the Kinoma Code IDE (figure 10.21), can be deployed over USB or WiFi b/g/n. Setup involves getting the Element on your local WiFi network. It will be assigned its own IP address.
Application projects for the Element have some structure to them. For example, each must contain a project.json file, which defines an entry point—the script that will get executed on the device. The entry point defaults to main.js.
As with Espruino, Kinoma provides some global objects to help you interact with hardware, and there is the notion of modules for the encapsulation of component behavior. Kinoma modules for controlling hardware components are known as Blinking-Light Libraries (BLLs) and they involve interacting with the hardware through a (built-in) Pins module. You can use CommonJS style require statements to pull other JS files into your projects and any built-in or custom BLL modules (but remember, this isn’t Node.js: you can’t use npm modules).
Kinoma’s site has some code examples for the Element: http://mng.bz/1BaB. Looking at the blinking-LED example code (http://mng.bz/5t61), it’s immediately evident that the structure of Kinoma projects is more formal than that of some other platforms (figure 10.22). Blinking an LED involves a project.json file to define the project, a main.js (entry point) to initialize the board and configure the pin for the LED, and an led.js BLL module that provides the logical support for blinking via a toggle method. (The .project file and the XML file in the project appear to be for Kinoma-site-specific build and metadata support.)
Figure 10.22. The source for a blinking-LED Kinoma example project. The structure of a Kinoma project is more involved than that of an Espruino project.

You’ll also need to bring your own LED and resistor to the party, as there’s no evident onboard LED you can use. The code inside of this project’s main.js file assumes you’re using pins 9 and 10 (ground), but there’s no wiring diagram provided.
You’ll learn more about what the code in a Kinoma main.js script looks like in just a bit.
Kinoma modules provide the API for hardware interaction. The most immediately relevant module is Pins, which provides basic I/O support for the kinds of things you’d expect: digital and analog input and output; pulse-width modulation (PWM); serial (I2C, for example). You can find a programmer’s guide on the Kinoma site (http://mng.bz/w1lR).
What you’ll need

- 1 Kinoma Element
- 1 USB A to USB micro cable
- 1 breadboard
- 1 HMC5883L magnetometer breakout board
- Jumper wires
The Element, with its onboard WiFi and web utility libraries, lends itself to acting as a web server a little more obviously than the Pico.
In this experiment, you’ll take a look at the high-level process of creating a project with the Element, crafting a custom BLL to support the HMC5883L I2C magnetometer (compass). you’ll use Kinoma’s available WebSocket module to run a WebSocket server on the Element that can emit changes when the compass heading changes. Finally, you’ll construct an HTML document that will connect to the Element’s WebSocket server and update as the compass heading changes (figure 10.23).
Figure 10.23. Detail of browser display, showing compass heading. The compass heading will update, live, without requiring a browser reload. In this case, the current heading was 190.62 degrees—a little bit west of south.

The HMC5883L module will be connected to a breadboard. By rotating the breadboard, you can change the magnetometer’s orientation and see the updated heading within the browser—in real time.
WebSocket browser support
You’ve met the WebSocket protocol before. In chapter 8, you used socket.IO in the Tessel 2 weather station application to show live-updating temperature and pressure. Socket.IO uses WebSockets for browsers that have WebSockets support, and it falls back to other methods for browsers that don’t support WebSockets.
In this example, you’ll use WebSockets proper: the application won’t work in brows-ers that don’t support WebSockets. A lack of WebSockets support is exceedingly rare in browsers these days, so it’s unlikely you’ll run into problems.
Place the HMC5883L on a breadboard and connect it to the Element as shown in figure 10.24. The SDA and SCL pins on the breakout board connect to the Element’s pins 13 and 14, which, as shown in the pinout in figure 10.20, have support for I2C. Any pin on the Element can be configured as power or ground; pins 11 and 12 are used here because of their proximity to the I2C pins.
The Element live-compass project consists of four files (figure 10.25):
- A package.json file with Kinoma project metadata
- A main.js file serving as the app’s main module (entry point)
- An HMC5883L.js file, which is the custom Kinoma BLL module for the compass
- An index.html file, which is the client-side code—you view it in a web browser
Figure 10.25. The structure for the Element live-compass project. The main.js file provides application logic and a WebSocket server, relying on support from the BLL in HMC5883L.js to interact with the magnetometer. The project.json file defines the project, using Kinoma conventions. Index.html is run in a web browser on your computer and shows live-updating compass headings.

- 1 ID strings should be in “dotted domain name style” according to the documentation.
- 2 The app’s entry point will be main.js.
Kinoma project application modules—main.js in this case—have a general structure. They need to export a default function that implements some event handlers, such as onLaunch() and onQuit(). The launch handler configures the board’s pins and kicks things off.
The module’s basic structure is as follows.
- 1 This is the built-in Pins module, upon which much in Kinoma apps depends.
- 2 Kinoma has a built-in websocket module; you’ll need to use the WebSocketServer from it.
- 3 This is a convenience function for formatting compass headers (not used yet).
- 4 onLaunch() will be invoked automatically on launch.
- 5 Pins.configure takes a callback function, invoked when it’s complete.
Once the custom HMC5883L module is ready, you’ll come back and fill in the blanks in main.js.
A BLL, or blinking-light library, encapsulates Kinoma-compatible component behavior in a module. A BLL module needs to do certain things. According to the Kinoma documentation, a BLL must export at minimum a pins object defining the type of pins it uses, a configure function, and a close function.
The following listing shows an excerpt from the completed HMC5883L BLL module.
- 1 writeByteDataSMB() is provided by the Kinoma I2C API; it reads from a specific register address.
- 2 readBlockDataSMB(), again from the API, is used to get six bytes from the READ register as an array.
- 3 HMC5883L data consists of two bytes for each of the three axes.
- 4 int16() is a utility function to make a 16-bit integer from two bytes (implementation not shown).
- 5 toHeading() uses math to derive a heading from the data (implementation not shown).
Credits for the HMC5883L Kinoma BLL module
I cobbled together this BLL myself as an exploration into how BLL modules and I2C work on the Element, but the code draws heavily from pre-existing work. It’s effectively a port of the Johnny-Five support logic for the sensor (http://mng.bz/TxHV), written by Johnny-Five inventor Rick Waldron. The Johnny-Five code in turn relies on an earlier implementation for Arduino (http://mng.bz/nB4V), which in turn relies on the datasheet for the device (http://mng.bz/j67k).
This kind of complex pedigree is par for the course in open source software, but as a reminder, always check your licenses and make sure you honor them. Also, give shout-outs to the inspiration for your work.
Listing 10.10 only shows a portion of the completed BLL. The complete version of the 5883L BLL can be found in the book’s code repository. You’ll need it if you want to build this experiment: place it in the same directory as the other project files.
With the BLL sewn up, the bits in main.js that rely on on the BLL can be filled in. As shown in the following listing, the onLaunch handler sets up the compass sensor on the Element by passing a settings object to Pins.configure().
- 1 The custom BLL module, by filename, no extension
- 2 Callback function
You also pass a callback function as a second argument to Pins.configure().
Within that callback, you first need to get a WebSocket server going, as shown in the next listing. This code uses the API of the built-in Kinoma WebSocketServer (WebSocketServer was required in listing 10.9).
- 1 ES6 feature support, so Set can be used
- 2 Starts a WebSocket server on the Element’s port 80
- 3 Holds the last compass heading reading
The code in listing 10.12 emits an initial compass reading when a client connects, but how are compass readings obtained in the first place, and how does the client receive updates when the readings change? The last bits of code for main.js, shown in the following listing, take care of those things.
- 1 Reads every 500
- 2 If the new result (the heading, in degrees) differs from the last result by some threshold amount...
- 3 ...it has meaningfully changed. Send the new value to each of the connected clients.
Functions as paths in BLLs
Functions in BLLs are referenced externally by path:
Here, /compass/read is a “path” to the read function in the BLL module. The line of code here repeatedly invokes read every 500 ms, and a callback function receives the result of the latest read operation. See it in play in listing 10.13.
Finally, you’ll need an HTML page to serve as a WebSocket client and to show the compass headings in real time. This page can be viewed in a browser.
- 1 Styling for the heading display
- 2 On load, connects to the WebSocket server
- 3 Important! You need to change this to your own Element’s IP address.
- 4 When new data comes in, updates the HTML in the #direction element to display the new heading
Code is deployed to the Element via the Kinoma Code IDE. Note that the index.html file isn’t served from the Element in this example. Instead, you open that file in a browser once the Element is running the compass application. See the Element quick-start guide (http://mng.bz/84cS) for step-by-step instructions about how to connect to and deploy code to your Element from the Kinoma Code IDE, if you haven’t done so already.
Once the code is deployed and running, you can open up the index.html file in a browser and rotate the breadboard with the attached compass to see the display update in real time.
- Embedded JavaScript platforms use optimized hardware and firmware to execute subsets of JavaScript natively. Both Kinoma and Espruino maintain their own, open source JavaScript engines (KinomaJS and Espruino JavaScript, respectively) to make this possible.
- Embedded JS platforms tend to have more sophisticated processors—often 32-bit—but still have significant constraints on memory and program space.
- Espruino’s open source family of products includes the Pico, a diminutively sized development board. Espruino projects can make use of Espruino-specific modules to work with different kinds of components.
- The Kinoma Element is another open source JavaScript-powered device. Creating projects for the Element involves the use of component modules called BLLs (blinking-light libraries).
- Although there are many platform options out there, you can speed your learning process with new platforms by following certain steps: learning about core details, finding hardware and pinout information, understanding the workflow, trying out examples, and seeking out API documentation.