Introducing Raspi-LLIO (Low Level I/O)

In preparation for the upcoming NodeBots Day in San Francisco, I have just published a new library for the Raspberry Pi, called raspi-llio (Low Level Input/Output). This library currently provides access to GPIO, I2C, and PWM capabilities, with SPI and UART capabilities coming soon.

This library provides a Node.js interface to the Wiring Pi C library, and doesn’t do much to provide a higher-level interface that you typically see in JavaScript NodeBots libraries. I wrote the Raspi-IO for such a purpose. My long-term plan is to rework Raspi-IO to be based off of Raspi-LLIO, but for now they are separate.

The Library interfaces with Wiring Pi using node-ffi, a Node.js FFI (Foreign Function Interface) implementation. node-ffi allows me to call straight into an external dynamic library without having to write a C++ Node.js plugin.

As previously mentioned, the API is fairly low level. The API is designed around provided access to the Broadcom SoC’s peripherals, not around making specific use cases easier. As an example, take driving a servo:

var raspi = require('raspi-llio');

var pwm = new raspi.GPIO(1, raspi.GPIO.PWM_OUTPUT);

var value = 20;  
setInterval(function() {  
  if (value == 20) {
    value = 110;
  } else {
    value = 20;
}, 2000);

The magic numbers 20 and 110 are fully left and fully right for a servo, and have to be arrived at somewhat experimentally (servos tend to vary slightly between each other with respect to their maximum and minimum PWM pulse widths). This contrasts sharply with Johnny-Five, which allows you to specify the position in degrees without even having to know that it is generating a PWM signal under the hood.

Why would I want my library to be so explicit? PWM can be used for more than just driving a servo. You can also use a PWM to control the brightness of an LED. When driving an LED, you use the full spectrum of possible duty cycles, from 0% all the way up to 100%. Servos on the other hand vary from about 10% to 20% for full left and full right. As such, it makes the most sense to provide a more raw interface that allows controlling both use cases, given the emphasis on peripherals, not use cases.

I wanted to keep the API low level because a) it allowed me to get the library written faster since Wiring Pi is also this low level and b) it’s not that difficult to get other libraries to “wrap” this library, providing whatever sort of higher-level functionality that library desires.

I mostly wrote this library for myself. My plans for it are to use it to control an I2C sensor for my NodeBots Day project, and to have it form the backbone of Raspi-IO. I hope others can make use of this library, but I realize it may not be well-suited for most NodeBots developers. Either way, it’s been fun to work on and should be very useful in the future.

Update: raspi-llio now supports UART and SPI in theory, although it hasn't been tested against real devices yet.