node-linux-gpio
Access GPIO on Linux from nodejs using /sys filesystem
Installation
npm install linux-gpio
Usage
Permissions
Note that a process writing to /sys filesystem should run with super user privileges
Basic setup
Classical blinker example
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_OUT}, function(err, pin) {
if (err) {
console.error(err);
} else {
pin.set(function(err) {
if (err) {
console.error(err);
} else {
var count = 20;
var interval = setInterval(function() {
pin.toggle(function(err) {
count--;
if (err || !count) {
clearInterval(interval);
gpio.close();
}
});
}, 1000);
}
});
}
});
Note that for simplicity, further examples do not include error checking. You should always check for errors.
Promises and callbacks
Most functions are asynchronous, returning immediately and delivering result later via callbacks. Two approaches are possible: using node-style callbacks and using promises.
Code examples here use node-style callbacks:
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_OUT}, function(err, pin) {
if (err) {
console.error(err);
} else {
console.log("Exported pin %d", pin.pin);
}
gpio.close();
});
To use promises, omit the last callback argument – and a promise will be returned. By default, bluebird is used for promises. See below for information about using other promise implementations
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_OUT})
.then(function(pin) {
console.log("Exported pin %d", pin.pin);
})
.catch(function(err) {
console.error(err);
})
.finally(function() {
gpio.close();
});
Exporting GPIO pin
Before using a GPIO pin, it must be first exported by writing pin number to /sys/class/gpio/export
.
This creates /sys/class/gpioXXX/
directory with some files inside used to control the pin.
Use gpio.export()
function:
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_OUT}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
gpio.close();
});
Specifying options
Second argument to export()
is an object used to specify options such as pin I/O direction, interrupt mode and invert mode.
All keys are optional. If a key is not specified, corresponding option is not changed
{
"direction": gpio.DIR_OUT, // gpio.DIR_OUT, gpio.DIR_IN
"invert": false, // true/false
"edge": gpio.EDGE_RISING // gpio.EDGE_NONE, gpio.EDGE_RISING, gpio.EDGE_FALLING, gpio.EDGE_BOTH
}
See below for details about each option
Stopping event loop
After you are done with GPIO, call close()
to stop event loop used for interrupt handling. Otherwise, your program will not exit when you expect it to do so
Changing pin direction
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.direction(gpio.DIR_OUT, function(err) {
console.log("Pin %d configured as output", pin.pin);
pin.direction(gpio.DIR_IN, function(err) {
console.log("Pin %d configured as input", pin.pin);
gpio.close();
});
});
});
Use gpio.DIR_OUT
for output, gpio.DIR_IN
for input
I/O direction can also be specified using direction
option for gpio.export()
call.
Reading pin direction
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.direction(function(err, dir) {
console.log("Pin %d configured as %s", pin.pin, dir);
gpio.close();
});
});
Changing pin invert mode
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.invert(true, function(err) {
console.log("Pin %d is in inverted mode", pin.pin);
pin.invert(false, function(err) {
console.log("Pin %d is in non-inverted mode", pin.pin);
gpio.close();
});
});
});
Inverted mode can also be specified using invert
option for gpio.export()
call.
Reading pin invert mode
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.invert(function(err, inv) {
console.log("Pin %d inverted mode:", pin.pin, inv);
gpio.close();
});
});
Reading pin state
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.value(function(err, state) {
console.log("Pin %d state:", pin.pin, state);
gpio.close();
});
});
Changing pin state
Set to high
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.set(function(err) {
console.log("Pin %d set to high", pin.pin);
gpio.close();
});
});
or
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.set(1, function(err) {
console.log("Pin %d set to high", pin.pin);
gpio.close();
});
});
Set to low
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.reset(function(err) {
console.log("Pin %d set to low", pin.pin);
gpio.close();
});
});
or
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.set(0, function(err) {
console.log("Pin %d set to low", pin.pin);
gpio.close();
});
});
Toggling pin state
var gpio = require('linux-gpio');
gpio.export(266, {}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.toggle(function(err, prev) {
console.log("Pin %d toggled, previous state was %d", pin.pin, prev);
gpio.close();
});
});
Interrupts
Setting interrupt mode
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_IN}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.edge(gpio.EDGE_BOTH, function(err) {
console.log("Pin %d interrupt mode set to \"both\"", pin.pin);
gpio.close();
});
});
Use one of gpio.EDGE_NONE
, gpio.EDGE_RISING
, gpio.EDGE_FALLING
and gpio.EDGE_BOTH
. gpio.EDGE_NONE
disables interrupt.
Interrupt mode can also be specified using edge
option for gpio.export()
call.
Interrupt mode can be only specified for pins configured as inputs. Not all GPIO pins can generate interrupts, even if configured as input. Refer to yor system's documentation to find out which pins are interrupt-enabled.
Reading interrupt mode
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_IN}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.edge(function(err, edge) {
console.log("Pin %d interrupt mode is \"%s\"", pin.pin, edge);
gpio.close();
});
});
Reacting to interrupts
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_IN}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.edge(gpio.EDGE_BOTH, function(err) {
console.log("Pin %d interrupt mode set to \"both\"", pin.pin);
pin.on('interrupt', function() {
console.log('interrupt');
});
setTimeout(gpio.close, 5000);
});
});
Unexporting a pin
Unexporting a pin removes corresponding directory from /sys filesystem, and removes event handlers.
var gpio = require('linux-gpio');
gpio.export(266, {direction: gpio.DIR_IN}, function(err, pin) {
console.log("Exported pin %d", pin.pin);
pin.unexport(function(err) {
console.log("Pin %d unexported", pin.pin);
gpio.close();
});
});
Using other promise libraries
If you prefer other promise library to bluebird, you have to configure node-linux-gpio first.
Simpliest form (using Q as example):
var gpio = require('linux-gpio');
var Q = require('q');
gpio.usePromise(Q.Promise);
Just pass promise constructor or function returning a new promise to usePromise
.
Promises are expected to support then
, catch
, and finally
methods. If your (hypotetical) promise library uses other method names, do the following:
var gpio = require('linux-gpio');
var Q = require('q');
/* Q supports legacy fail() and fin() methods */
gpio.usePromise({
func: Q.Promise,
then: 'then',
'catch': 'fail',
'finally' : 'fin'
});
and then you can do
gpio.export(266, {direction: gpio.DIR_OUT})
.then(function(pin) {
console.log("Exported pin %d", pin.pin);
})
.fail(function(err) {
console.error(err);
})
.fin(function() {
gpio.close();
});