Hardware Design with Node & Electron

All the code discussed in this post is available on Github

A few weeks before leaving my last hardware gig, I was asked to give a presentation to the new batch of interns about how we get the job done. Discussing the ethos and pathos of design philosophy isn't very difficult, but as usual in the world of hardware it seemed prudent to provide a practical demonstration. Given that this fell outside the purview of my typical deliverables, and because I had a bit of time to fool around, I decided to play with some new technologies to show what the modern world of software can do for electrical folks in an afternoon — So I tacked together an electron app with a micro-controller, a few power supplies, and an accelerometer to demonstrate some EE basics.

Behold:
tap-tap-tapperoo

Why?

Engineering is mostly about making the best possible product with the resources at hand, like throwing a whisk into a power drill to make mashed potatoes last Thanksgiving:

taters, precious

The software toolchain we use in the world of hardware is dated, because in general we value consistency and reliability over the bleeding edge for our analytical tools. If we are already designing our hardware to be as forward thinking as possible, we don't necessarily want to be spending time learning a new programming language every week — however, in order to combat stagnation, it's good practice to dip our feet back into the pool of available software to see what improvements time has wrought. But what problems does an electrical hardware engineer need to solve with software? Plenty. Here's one.

The Problem

Briefly, a common issue in the world of hardware design is power distribution. There are two classes of power supplies common in consumer electronics, each with their own benefits and detriments; choosing which one to use and when is difficult even for experienced engineers because often times the difference is subtle, subjective, and user-facing. Disturbingly, the discerning factor is sometimes mathematical and therefore requires statistical analysis.

These two most common classes of DC power distribution (“voltage regulators”) are switching supplies such as a buck regulator and linear supplies such as low-dropout regulators (LDOs) — the former are efficient and create lots of electrical noise, the latter are inefficient but very clean. Bucks are more expensive than LDOs, but less are needed because they can handle more power and do so far more efficiently, therefore we need to choose carefully which is appropriate for a given design. As such, I designed a circuit with one of each to demonstrate the differences between them.

Here's the buck regulator:
buck

And here's the LDO:
LDO

Now that we've prototyped the design in a breadboard, let's check the conventional wisdom that, by design, the buck regulator is noisy and the LDO is clean:

scope capture

I know this may look complicated, but it really isn't. The LDO is the bottom signal, and the Buck is the top — These are images captured from an oscilloscope, a piece of equipment designed to measure how voltage or current changes in the time domain. Each horizontal division on the y-axis represents 10 millivolts (mV), or about 1/150th of the voltage of a AA battery. That may not seem like a lot, but the electronics in something like a modern-day cellphone are extremely sensitive and sometimes even a few millivolts can be make or break in a design. Why does the buck look so much 'fuzzier' than the LDO?

It's all part of their operation. Bucks use Pulse Width Modulation (PWM) and a low-pass filter to efficiently provide lots of power, at the cost of additional noise. The SW signal shows the input to the inductive low-pass filter, and the buck signal is zoomed in very closely on the output. Notice how the buck signal looks like a sawtooth, rising while the SW signal is high and falling when it is low:
buck deep dive

So! Yikes, that buck regulator is messy — 30mV of peak-to-peak noise looks pretty stark next to ~5mV of noise on the LDO. Will that electrical fuzz have any effect on the accelerometer? The short answer is “yes”, because barring complete electrical isolation, signals will propagate through a system until they attenuate to such a degree as to be unmeasurable. And these guys are connected by a wire, so the only isolation we’re getting is inside the accelerometer itself. This attenuation within the part is called “Power Supply Rejection Ratio”, or "PSRR", and is a key metric in low-noise systems.

So what about the long answer? In theory, we now know that electrical noise will appear in some form on the signal the accelerometer is measuring, but how much of a real-world effect will this noise have? For that, we need to do some experiments. And to do some experiments, we turn to the spooky world of software.

Modern(-ish) Software Tools for Hardware

At the time of writing, the zeitgeist in the world of Electrical Engineering is to use Python for instrument control and data analysis, thanks to fantastic libraries like PyVISA and Matplotlib. There are a great many advantages to this toolchain for measuring and crunching numbers in large datasets, as well as displaying this data in austere charts and graphs. However, most of the applications written in this tool-chain end up seeming arcane, working exclusively in the command line and outputting accurate, if highly academic, data.

Consider these hydroponics metrics from an old project.

academic data

Not super clear, but it gets the idea across for people who are familiar with the subject. Alas, therein lies the rub. For a business, compelling data is only useful if all of the key decision-making folks understand it, which means the most effective data is also beautiful and accessible. So when presenting our data to a larger audience such as an exec team, we built a the following web view instead.

pretty data

We want to be able to visualize this data easily for people who don't necessarily have similar technical backgrounds to our own. When it comes to making beautiful, cross-platform applications, one of the most well-supported ecosystems is that of Javascript and Electron. This will allow us to write our application like a typical website, easily digestible and highly accessible.

With this goal in mind, we can break up the task into three parts:

  1. Collecting the data
  2. Analyzing the data
  3. Visualizing the data

Collecting the Data

The first step in collecting our data is picking our hardware and designing the circuit. In this case, I used spare parts from past projects, namely:

With some assorted passive components and a USB breakout board for power, these are all we'll need. The Teensy microcontroller will allow us to communicate with our accelerometer over I2C, and we can swap the power supply by moving wires around our breadboard. Thanks to Sparkfun's pre-existing driver code, we should be able to plug this in and see some raw data on the serial port using minicom:

circuit
raw data yay

Great! Now that we have the raw data, we can move on to analysis.

Analyzing the Data

A benefit of using Electron is that we can use Javascript to access the hardware serial ports, something restricted from the browser for security purposes. To set up our project, we can use the Electron quickstart:

# Clone this repository
git clone https://github.com/electron/electron-quick-start

# Go into the repository
cd electron-quick-start

# Install dependencies
npm install

# Run the app
npm start

And to add serial port functionality, we can grab it off of npm inside the application directory:

npm install serialport

After this, all of the code handling the serial port setup can go inside of the main.js file, my implementation of which can be found on the project github.

Now that we have raw accelerometer data within our Javascript application, we can get to the crux of the issue: measuring the noise of the signal. With linear systems (like this one), the type of noise we're likely to see is Additive White Gaussian Noise (AWGN), which is a fancy way of saying that the noise falls on a bell curve. Probably the most important metric of understanding a given bell curve is the standard deviation (σ), which is a way of measuring how a set of data varies from itself. Basically, two standard deviations encompass ~99% of the entire dataset — so if the standard deviation is high, that 99% of data covers a very wide area, but if the standard deviation is low, 99% covers a very small area:
bell curve
See? If the σ is small, this curve could be very tight

So how do we calculate this for our signal?

The data is received in a continuous stream at roughly the speed of the I2C bus, so our sample rate is in the 10's of kHz — this means our data points will pile up fast. If we try and analyze the entire set and re-analyze any time a new point is added, we'll run into bottlenecks on the CPU and indeed on the renderer (one second would yield over 10,000 points, more pixels probably than the horizontal axis of your display). Therefore, we'll analyze the signal in chunks, pushing the data into a queue of limited size (say 100) and running the analysis only there; this has the added benefit of keeping our calculation current, as we are then calculating the standard deviation of the last hundred milliseconds or so.

To calculate the standard deviation of this chunk of data is simple, we can do it ourselves (it really isn't so hard). Or because we're using a programming language with incredible library support, we can use MathJS.

First we install it:

npm install mathjs

Then, we use it:

var math    = require('mathjs');
var sigma_x = math.std(dataset);

Cool! So we're ready for the last step.

Visualizing the Data

Now that we have an electron app that, behind the scenes, collates and analyzes our data, we are ready to display it for the world to see. For this, we need a couple of things:

  • Some HTML and CSS like you'd see on any website
  • Some Javascript to display our data in a chart or graph

For the former, I elected to use HTML5 Boilerplate as it handles most of the things I don't want to touch (404 pages, obvious CSS) and lets me cobble together a very basic index.html + main.css and call it a day.

For the latter, I chose Chart.js because it's very pretty and very concise, isn't it?


After combining the boilerplate and Chart.js, we're good to go!

Conclusion

After all that work, what were the results?

comparison shot

It looks like the dogma is correct, the accelerometer is much noisier when powered by the buck! The standard deviation on each axis is ~1.5-2x higher on the noisier power source, so it looks like the PSRR on this part is not very good.

Does this mean when designing with an accelerometer (or any sensor) we should always use an LDO, no questions asked? No! Depending on the application, this kind of noise can be fine. These units here are in micro-g's, or 1/1000 the force of gravity; if we're measuring acceleration in a car, this noise here is probably acceptable. Finely measuring the motion of a smart phone? Maybe not so much.

Bottom line is, you gotta do the math to know for sure. And thanks to the ever evolving world of software, the tools for doing so are getting better every day.