Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 89 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
pi-gpio
=======

pi-gpio is a simple node.js based library to help access the GPIO of the Raspberry Pi (Debian Wheezy). It's modelled loosely around the built-in ``fs`` module.
It works with:
* original Raspberry Pi (A and B)
* model B revision 2 boards
* Raspberry Pi Model A+
* Raspberry Pi Model B+
pi-gpio is a simple node.js based library to help access the GPIO of the Raspberry Pi (Debian Wheezy). It's modelled loosely around the built-in ``fs`` module. Works with the original Raspberry Pi (A and B), the model B revision 2 boards, and the Raspberry Pi Model B+.

After the [installation](#installation), reading and writing is as easy as this:
```javascript
var gpio = require("pi-gpio");

gpio.open(16, "output", function(err) { // Open pin 16 for output
gpio.write(16, 1, function() { // Set pin 16 high (1)
gpio.close(16); // Close pin 16
});
gpio.write(16, 1, function() {
console.log("Physical pin no. 16 set to high.");
});

gpio.read(11, function(err, value) {
if (!err) {
console.log("Pin 11 is reading " + (value === 1 ? "high" : "low"));
}
});
```
See the [usage reference](#usage) below for more information.

## How you can help

Expand Down Expand Up @@ -216,7 +217,7 @@ This library simplifies all of this (hopefully), by abstracting away the Broadco
</td>
</tr>
<tr>
<td colspan="4">Model A+ and Model B+ additional pins</td>
<td colspan="4">Model B+ pins</td>
</tr>
<tr>
<td>
Expand Down Expand Up @@ -318,25 +319,21 @@ This library simplifies all of this (hopefully), by abstracting away the Broadco
</tr>
</table>

That gives you several GPIO pins to play with: pins 7, 11, 12, 13, 15, 16, 18 and 22 (with A+ and B+ giving 29, 31, 32, 33, 35, 37, 38 and 40). You should provide these physical pin numbers to this library, and not bother with what they are called internally. Easy-peasy.
That gives you several GPIO pins to play with: pins 7, 11, 12, 13, 15, 16, 18 and 22 (with the B+ giving 29, 31, 32, 33, 35, 37, 38 and 40). You should provide these physical pin numbers to this library, and not bother with what they are called internally. Easy-peasy.

## Installation

If you haven't already, get node and npm on the Pi. The simplest way is:

sudo apt-get install nodejs npm

The Raspberry Pi's GPIO pins require you to be root to access them. That's totally unsafe for several reasons. To get around this problem, you should use the excellent [gpio-admin](https://github.com/quick2wire/quick2wire-gpio-admin).
The Raspberry Pi's GPIO pins require you to be root to access them. That's totally unsafe for several reasons. To get around this problem, you should use the excellent [Wiring Pi GPIO utility](http://wiringpi.com/the-gpio-utility/).

Do the following on your raspberry pi:
Install Wiring Pi (which includes the tool) [as described on their website](http://wiringpi.com/download-and-install/):

git clone git://github.com/quick2wire/quick2wire-gpio-admin.git
cd quick2wire-gpio-admin
make
sudo make install
sudo adduser $USER gpio

After this, you will need to logout and log back in. [Details](http://quick2wire.com/2012/05/safe-controlled-access-to-gpio-on-the-raspberry-pi/), if you are interested.
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

Next, ``cd`` to your project directory and use npm to install pi-gpio in your project.

Expand All @@ -346,62 +343,95 @@ That's it!

## Usage

### .open(pinNumber, [options], [callback])
### .read(pinNumber, [callback], [exportMode])

Aliased to ``.export``
Reads the current value of the pin.

Makes ``pinNumber`` available for use.
* `pinNumber`: As usual.
* `callback`: Will receive a possible error object as the first argument, and the value of the pin as the second argument. The value will be either `0` or `1` (numeric).
* `exportMode` (optional): May be omitted, `'off'`, or `'force'`.
If omitted, the pin will be exported as input before reading unless its last known state is input.
If `'off'`, the pin will be neither exported nor its direction adjusted; leaving those tasks to you. (This matches the old pre-`v0.1.0` behaviour.)
If `'force'`, the pin will be exported as input, even if that's its last known state.

* ``pinNumber``: The pin number to make available. Remember, ``pinNumber`` is the physical pin number on the Pi.
* ``options``: (Optional) Should be a string, such as ``input`` or ``input pullup``. You can specify whether the pin direction should be `input` or `output` (or `in` or `out`). You can additionally set the internal pullup / pulldown resistor by sepcifying `pullup` or `pulldown` (or `up` or `down`). If options isn't provided, it defaults to `output`. If a direction (`input` or `output`) is not specified (eg. only `up`), then the direction defaults to `output`.
* ``callback``: (Optional) Will be called when the pin is available for use. May receive an error as the first argument if something went wrong.
Example:
```javascript
gpio.read(16, function(err, value) {
if(err) throw err;
console.log(value); // The current state of the pin
});
```

### .close(pinNumber, [callback])
### .write(pinNumber, value, [callback], [exportMode])

Aliased to ``.unexport``
Writes `value` to `pinNumber`.

Closes ``pinNumber``.
* `pinNumber`: As usual.
* `value`: Must be either `0` or `1`, or equivalently `false` or `true`.
* `callback` (optional): Will be called when the value is set. Again, might receive an error.
* `exportMode` (optional): May be omitted, `'off'`, or `'force'`.
If omitted, the pin will be exported as output before writing unless its last known state is output.
If `'off'`, the pin will be neither exported nor its direction adjusted; leaving those tasks to you. (This matches the old pre-`v0.1.0` behaviour.)
If `'force'`, the pin will be exported as output, even if that's its last known state.

* ``pinNumber``: The pin number to close. Again, ``pinNumber`` is the physical pin number on the Pi.
* ``callback``: (Optional) Will be called when the pin is closed. Again, may receive an error as the first argument.
Example:
```js
gpio.write(16, 1, function(err) {
if(err) throw err;
console.log("Pin 16 set to HIGH.");
});
```

### .setDirection(pinNumber, direction, [callback])
### .export(pinNumber, [options], [callback])

Changes the direction from ``input`` to ``output`` or vice-versa.
Aliased to `.open`

* ``pinNumber``: As usual.
* ``direction``: Either ``input`` or ``in`` or ``output`` or ``out``.
* ``callback``: Will be called when direction change is complete. May receive an error as usual.
Uses the [GPIO utility](http://wiringpi.com/the-gpio-utility/) to *export* the pin via the `/sys/class/gpio` interface. By default, `.write` and `.read` will automatically export the pin as output/input respectively (see their `exportMode` parameter), so you should not *need* to call this – but it doesn't hurt, if you want to be explicit.
Note: Starting with `v0.1.0`, exporting a pin that's already exported does no harm.

### .getDirection(pinNumber, [callback])
* `pinNumber`: The pin number to make available. Remember, `pinNumber` is the physical pin number on the Pi.
* `options` (optional): Must be a string of options separated by a space, such as `input` or `input pullup`.
You can specify whether the pin direction should be `input` (equivalently `in`) or `output` (`out`).
You can additionally set the internal pullup / pulldown resistor by sepcifying `pullup` (`up`), `pulldown` (`down`), or `tri` (neither pullup not pulldown).
If no direction is given, it defaults to `output`.
If no resistor setting is given, it will not be changed.
* `callback` (optional): Will be called when the pin is available for use. May receive an error as the first argument if something went wrong.

Gets the direction of the pin. Acts like a getter for the method above.
Example:
```js
// export as input, engage internal pullup
gpio.export(16, 'in pullup', function(err) {
// and read value
if (!err) gpio.read(16, function(err, value) {
if (!err) console.log(value);
});
});
```
### .unexport(pinNumber, [callback])

* ``pinNumber``: As usual
* ``callback``: Will be called when the direction is received. The first argument could be an error. The second argument will either be ``in`` or ``out``.
Aliased to `.close`

### .read(pinNumber, [callback])
*Unexports* pin, that is, removes it from the `/sys/class/gpio` interface.
You may unexport the pins you exported if you want to leave your Pi exactly like you found it, but if you just leave them open, there's no harm in that either.

Reads the current value of the pin. Most useful if the pin is in the ``input`` direction.
* `pinNumber`: The pin number to close. Again, `pinNumber` is the physical pin number on the Pi.
* `callback` (optional): Will be called when the pin is closed. Again, may receive an error as the first argument.

* ``pinNumber``: As usual.
* ``callback``: Will receive a possible error object as the first argument, and the value of the pin as the second argument. The value will be either ``0`` or ``1`` (numeric).
### .setDirection(pinNumber, direction, [callback])

Example:
```javascript
gpio.read(16, function(err, value) {
if(err) throw err;
console.log(value); // The current state of the pin
});
```
Changes the direction from `input` to `output` or vice-versa.
Note: By default, `read` and `write` will automatically change the direction to `input`/`output` respectively.

### .write(pinNumber, value, [callback])
* `pinNumber`: As usual.
* `direction`: Either `input` (or `in`) or `output` (`out`).
* `callback`: Will be called when direction change is complete. May receive an error as usual.

Writes ``value`` to ``pinNumber``. Will obviously fail if the pin is not in the ``output`` direction.
### .getDirection(pinNumber, [callback])

Gets the direction of the pin. Acts like a getter for the method above.

* ``pinNumber``: As usual.
* ``value``: Should be either a numeric ``0`` or ``1``. Any value that isn't ``0`` or ``1`` will be coerced to be boolean, and then converted to 0 (false) or 1 (true). Just stick to sending a numeric 0 or 1, will you? ;)
* ``callback``: Will be called when the value is set. Again, might receive an error.
* `pinNumber`: As usual.
* `callback`: Will be called when the direction is received. The first argument could be an error. The second argument will either be `'in'` or `'out'`.

## Misc

Expand All @@ -417,10 +447,10 @@ Writes ``value`` to ``pinNumber``. Will obviously fail if the pin is not in the

(The MIT License)

Copyright (c) 2012 Rakesh Pai <rakeshpai@gmail.com>
Copyright (c) 2012–2014 Rakesh Pai <rakeshpai@gmail.com> and contributors.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13 changes: 13 additions & 0 deletions examples/blink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var gpio = require("../pi-gpio");

// using relative import here for demo purposes
// in your own projects, you should `npm install pi-gpio` and use:
// var gpio = require("pi-gpio");

var value = 1;

setInterval(function() {
gpio.write(16, value, function() {
value = (value === 1 ? 0 : 1);
});
}, 1000);
16 changes: 16 additions & 0 deletions examples/simple-rw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
var gpio = require("../pi-gpio");

// using relative import here for demo purposes
// in your own projects, you should `npm install pi-gpio` and use:
// var gpio = require("pi-gpio");

gpio.write(16, 1, function() {
console.log("Physical pin no. 16 set to high.");
});

// note that by default, the internal pullup/down resistors are off
gpio.read(11, function(err, value) {
if (!err) {
console.log("Pin 11 is reading" + (value === 1 ? "high" : "low"));
}
});
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"author": "Rakesh Pai <rakeshpai@gmail.com>",
"name": "pi-gpio",
"description": "A simple node.js-based GPIO helper for the Raspberry Pi",
"version": "0.0.7",
"version": "0.1.0",
"repository": {
"type": "git",
"url": "git@github.com:rakeshpai/pi-gpio.git"
Expand All @@ -18,7 +18,9 @@
"gpio",
"simple"
],
"dependencies": {},
"dependencies": {
"pi-gpioutil": "^0.0.2"
},
"devDependencies": {
"mocha": "1.x",
"should": "1.x"
Expand Down
54 changes: 54 additions & 0 deletions paramParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
function parseOptions(string) {
var options = { 'direction': 'out' };
string.split(' ').filter(function noEmpties(t) {
return t;
}).forEach(function(option) {
switch (option.toLowerCase()) {
case 'in':
case 'input':
options.direction = 'in';
break;
case 'out':
case 'output':
options.direction = 'out';
break;
case 'up':
case 'pullup':
options.pull = 'up';
break;
case 'down':
case 'pulldown':
options.pull = 'down';
break;
case 'tri':
options.pull = 'tri';
break;
default:
throw new Error("Illegal option token!");
break;
}
});
return options;
}

function parseValue(value) {
switch (value) {
case true:
case 1:
case '1':
return '1';
break;
case false:
case 0:
case '0':
return '0';
break;
default:
throw new Error('Illegal on/off value');
break;
}
}

exports.parseOptions = parseOptions;
exports.parseValue = parseValue;
exports.parseDirection = function(dir) { return parseOptions(dir).direction; };
Loading