Computing stuff tied to the physical world

Developing in JavaScript for STM32

Last in this little series is another language: JavaScript. There is a mini-implementation of JavaScript called Espruino which can operate in even more cramped environments than Lua (and MicroPython, another language environment for the embedded world).

Espruino runs on boards created via crowdfunding – the latest being the Espruino Pico. This is an absolutely tiny USB-stick like board, with a fairly powerful STM32F401 µC:

Pico angled

But Espruino is also the name of the JavaScript environment itself, which is fully open source and embraces many other µCs, including the STM32F103 on the ARMinARM.

Although JavaScript as a language is a almost half a century more recent than BASIC, the Espruino setup has a very similar feel to it: you type in commands, and it executes them.

It’s very easy to try it out using ARMinARM, by installing it with the setup script:

Fast start:
    10) Upload espruino.bin to ARMinARM board

Now we can connect to the board via a serial connection from the Raspberry Pi:

$ screen /dev/ttyAMA0 9600
 _____                 _ 
|   __|___ ___ ___ _ _|_|___ ___ 
|   __|_ -| . |  _| | | |   | . |
|_____|___|  _|_| |___|_|_|_|___|
 1v73 Copyright 2015 G.Williams


This is a fairly old build, but no matter – the essence is all there. Note that to get that nice welcome screen, you’ll need to press the reset button on the ARMinARM board (next to the single-row header).

As you can see, Espruino knows its (double-precision) maths, just like Lua:


But it also has a Node.js like feel to it:

  "VERSION": "1v73", 
  "BUILD_DATE": "Feb 13 2015", 
  "BUILD_TIME": "13:52:33", 
  "GIT_COMMIT": "dc5b005a93d4eee5ff1f9c97bf328dfbb38fbb59", 
  "CHIP": "STM32F103RET6", 
  "CHIP_FAMILY": "STM32F1", 
  "FLASH": 524288, "RAM": 65536, 
  "SERIAL": "33ffdc05-32503734-25820957", 
  "CONSOLE": "Serial1", 
  "EXPORT": [ 
    "jsvLock,jsvLockAg" ... ",jsvNewWithFlags,", 
    536871036 ]

Quite a bit so, in fact, since it uses the same async callback style to deal with time delays:

>setTimeout(function() { console.log("boom!") }, 1000)

The call returned immediately, and the text was printed 1 second later. This is extremely useful in an interactive context (just as in Node.js), because you can make things work in the background while still keeping access to a responsive command line console.

So let’s make our LED blink, shall we?

>setInterval(function() {
:  digitalWrite(LED, 1 - digitalRead(LED))
:}, 1000)

As you can see, it’s a fairly comforting mix of Arduino’ish calls and a Node.js’ish structure. Note that the “>” and “:” prompts were generated by Espruino, and so was the “=1” result.

That’s it. We get a prompt back, and the LED is happily blinking in the background. To stop it, we can type “clearInterval(1)” (1 being the id returned by setInterval).

Just as with eLua, there’s a lot more to Espruino. Scroll down on the reference page, to see what the software can do (and check out the images at the top for a sample of the boards supported by Espruino). There’s also valuable info on the wiki, and an active forum.

Next, you should have a look at the growing list of modules (full dir list). These modules are implemented in JavaScript, although some require the presence of pre-compiled C library code (see the “Built-in Functionality” on the reference page). They’re even minified.

So, for example, I2C and SPI are built-in as efficient C drivers, but lots of devices attached that way are simply a bit of JavaScript glue code. This is extremely flexible.

It becomes even more interesting in combination with Espruino’s Web IDE – check out the 5-minute video on that page. This is aimed at laptop / desktop use, but could probably be wrangled into connecting to any serial port across the network (using ser2net or similar), including a Raspberry Pi with ARMinARM board. Espruino’s Web IDE offers a surprisingly simple way of writing bits of JavaScript, with access to all online modules using nothing more than a simple “require” call in your code. It’s hard to describe, but very much has the feel of using the Arduino IDE – except that there is virtually no machinery under the hood!

Back to Espruino, as it’s running on the STMF103 µC itself. It’s very JavaScript-like, but there are differences with such a tiny implementation. There are also so some fairly severe limitations, depending on which µC you’re running it on. The two main ones are:

  • Memory – everything needs to fit in RAM, data and code. Espruino does things cleverly, but it can’t do magic – 20 KB of RAM is minimal, 64 KB of RAM is decent.

  • Speed – Espruino is interpreted at the source code level. Very much like some of those old 1970’s and 1980’s BASIC implementations fitting into 2..8 KB. It’s not fast.

Having said that, this does not rule out the use of Espruino for low-power applications, as long as the duty-cycle of being awake is low enough. Spending 1 sec every hour, still means that the setup can spend 99.9% of its time in deep sleep mode, drawing a few microamps.

As with eLua, there is a way to make the µC run Espruino code on power-up: see onInit.

And see this design page, if you want to know more about some trade-offs in Espruino.

One more point is worth noting here: given that Espruino is JavaScript, and that Node.js will run nicely on a Raspberry Pi, this can create a context where everything you develop is written in the same language: JavaScript in the small and in the large ! There can be some advantages to this – data exchange in JSON, for example, becomes trivial.

The same can be said of eLua + Lua, and of MicroPython + Python, of course. Although with JavaScript, this even carries across to the browser and therefore also to the desktop, using a technology such as Electron or Chromium Apps. As to whether it’s important to write everything in (nearly) the same programming language: that’s really up to you.

The main takeaway from all this, is that the traditional “embedded C/C++ programming” approach is starting to see alternatives, at least for the somewhat larger µC’s. They require more resources, but at times that’s irrelevant. Let’s call this option: “BASIC, Reloaded” !