Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to Wiring Pi GPIO utility #27

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
135 changes: 85 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@ 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. 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 @@ -321,17 +327,13 @@ 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 @@ -341,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 @@ -412,7 +447,7 @@ Writes ``value`` to ``pinNumber``. Will obviously fail if the pin is not in the

(The MIT License)

Copyright (c) 2012 Rakesh Pai <[email protected]>
Copyright (c) 2012–2014 Rakesh Pai <[email protected]> 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:

Expand Down
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 <[email protected]>",
"name": "pi-gpio",
"description": "A simple node.js-based GPIO helper for the Raspberry Pi",
"version": "0.0.6",
"version": "0.1.0",
"repository": {
"type": "git",
"url": "[email protected]: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