Notes from Node and SPI


These are my notes from Russell Hay's talk on July 3, 2012 at NodeConf called Node and SPI. You can follow Russell on twitter @russellhay.

What is SPI really? It's a loosely defined specification. There's a lot of things left ambiguous, and lots of variety between implementations (are you triggering on the rising edge or the falling edge of the clock?) It's a 4-wire interface between a master and a slave, and it's full-duplex, so when you're reading you're also writing.

The four signals are:

  • CLK - clock
  • CS - chip select
  • MISO - Slave to master (read)
  • SIMO - Master to slave (write)

If you have multiple devices on the same bus, one will be a master and you may have multiple slaves. You set the chip select to active for a specific device, and then your dataframe is going to that specific device and all the other devices are ignoring it. Basically a tri-state interface.

What can you control with the SPI Bus?

  • I/O Extenders
  • Motor Controllers
  • LED Drivers
  • ADC
  • Sensors of all kinds
  • Voice Record and Playback
  • DSP
  • Touchscreens

I did a search on digikey for SPI, and I think 30,000 individual hits on that search. There's a lot of variety, and being able to communicate on the SPI bus is really important.

Beagleboard XM is a dev board like Emily was saying earlier; it's the more powerful one, because I am lazy and don't like waiting for things to finish compiling. The Saleae Logic Analyzer would have saved me tons of time. It's about $150, relatively cheap for a logic analyzer. AdaFruit LED Pixels are great when you want to make flashy lights. They're RGB LED array, 25 in a strand, individually addressable for individual colors. There's no chip select line, so there's only a two-wire interface for them. As long as you're under 1MHz it works fine.


There are some issues to get the kernel to compile with all the SPI stuff enabled. If you follow the instructions start to finish, it will work (although it didn't for me.) A number of patches are needed to enable beagleboard XM specific kernel drivers. Add "buddy=spidev" to kernel boot flags.

Why did we need this? We wanted an ambient notification of build and test failures that was simple to deploy and a small form factor.

I built a module called node-spi. Opening a connection is really simple, you create the Spi() device and open it. You'll notice that it's spidev3.0; this is an implementation of the beagleboard XM. 3.0 allows you to connect 2 devices at the same time.

Writing is also easy. You create a buffer:
var data = new Buffer(128)
device..write(data, callback());

This is synchronous right now.

I ran into a number of hardware challenges; most logic analyzers are expensive, I didn't have an oscilloscope. The individual components are cheap, but debugging things when they don't work is frustrating and expensive. Sometimes, things just don't work when everything looks like it should! I have a limited EE background, so sometimes reading datasheets is like gibberish to me. Finally, SPI is loosely-defined.

With the Beagleboard specifically, there is a lot of outdated information. Beaglebone vs Beagleboard XM is difficult to differentiate online if people are not precise. I'm planning to scale back to the Beaglebone next time they're in stock.

On the software side, SPI ioctl calls are strictly synchronous in the kernel space, so they don't return until the data transfer is done. I'm working on solutions for that, maybe fixing the SPIdev drivers in the Linux kernel.

Did you enjoy this post? Please spread the word.