Giter Site home page Giter Site logo

fivdi / onoff Goto Github PK

View Code? Open in Web Editor NEW
1.2K 41.0 116.0 937 KB

GPIO access and interrupt detection with Node.js

License: MIT License

JavaScript 97.45% Shell 1.04% TypeScript 1.51%
gpio interrupt raspberry-pi beaglebone beaglebone-black linux javascript nodejs iot

onoff's Introduction

Build Status codecov npm Version Downloads Per Month Mentioned in Awesome Node.js

onoff

GPIO access and interrupt detection with Node.js on Linux boards like the Raspberry Pi or BeagleBone.

onoff supports Node.js versions 10, 12, 14, 15 and 16.

Contents

Installation

npm install onoff

Note that although it's possible to install onoff on non-Linux systems the functionality offered by onoff is only available on Linux systems.

Usage

LEDs and Buttons

Assume that there's an LED connected to GPIO17 and a momentary push button connected to GPIO4.

When the button is pressed the LED should turn on, when it's released the LED should turn off. This can be achieved with the following code:

const Gpio = require('onoff').Gpio;
const led = new Gpio(17, 'out');
const button = new Gpio(4, 'in', 'both');

button.watch((err, value) => led.writeSync(value));

Here two Gpio objects are being created. One called led for the LED connected to GPIO17 which is an output, and one called button for the momentary push button connected to GPIO4 which is an input. In addition to specifying that the button is an input, the constructors optional third argument is used to specify that 'both' rising and falling interrupt edges should be configured for the button GPIO as both button presses and releases should be handled.

After everything has been setup correctly, the buttons watch method is used to specify a callback function to execute every time the button is pressed or released. The value argument passed to the callback function represents the state of the button which will be 1 for pressed and 0 for released. This value is used by the callback to turn the LED on or off using its writeSync method.

When the above program is running it can be terminated with ctrl-c. However, it doesn't free its resources. It also ignores the err argument passed to the callback. Here's a slightly modified variant of the program that handles ctrl-c gracefully and bails out on error. The resources used by the led and button Gpio objects are released by invoking their unexport method.

const Gpio = require('onoff').Gpio;
const led = new Gpio(17, 'out');
const button = new Gpio(4, 'in', 'both');

button.watch((err, value) => {
  if (err) {
    throw err;
  }

  led.writeSync(value);
});

process.on('SIGINT', _ => {
  led.unexport();
  button.unexport();
});

Debouncing Buttons

When working with buttons there will often be button bounce issues which result in the hardware thinking that a button was pressed several times although it was only pressed once. onoff provides a software debouncing solution for resolving bounce issues.

Assume again that there's an LED connected to GPIO17 and a momentary push button connected to GPIO4.

When the button is pressed the LED should toggle its state. This is a typical example of a situation where there will be button bounce issues. The issue can be resolved by using the debounceTimeout option when creating the Gpio object for the button. In the below program the debounceTimeout is set to 10 milliseconds. This delays invoking the watch callback for the button while the button is bouncing. The watch callback will not be invoked until the button stops bouncing and has been in a stable state for 10 milliseconds.

const Gpio = require('onoff').Gpio;
const led = new Gpio(17, 'out');
const button = new Gpio(4, 'in', 'rising', {debounceTimeout: 10});

button.watch((err, value) => {
  if (err) {
    throw err;
  }

  led.writeSync(led.readSync() ^ 1);
});

process.on('SIGINT', _ => {
  led.unexport();
  button.unexport();
});

Blink an LED Using the Synchronous API

Blink an LED connected to GPIO17 for 5 seconds using the synchronous readSync and writeSync methods.

const Gpio = require('../onoff').Gpio; // Gpio class
const led = new Gpio(17, 'out');       // Export GPIO17 as an output

// Toggle the state of the LED connected to GPIO17 every 200ms
const iv = setInterval(_ => led.writeSync(led.readSync() ^ 1), 200);

// Stop blinking the LED after 5 seconds
setTimeout(_ => {
  clearInterval(iv); // Stop blinking
  led.unexport();    // Unexport GPIO and free resources
}, 5000);

Blink an LED Using the Asynchronous API and Completion Callbacks

Blink an LED connected to GPIO17 for 5 seconds using the asynchronous read and write methods and completion callbacks.

const Gpio = require('../onoff').Gpio; // Gpio class
const led = new Gpio(17, 'out');       // Export GPIO17 as an output
let stopBlinking = false;

// Toggle the state of the LED connected to GPIO17 every 200ms
const blinkLed = _ => {
  if (stopBlinking) {
    return led.unexport();
  }

  led.read((err, value) => { // Asynchronous read
    if (err) {
      throw err;
    }

    led.write(value ^ 1, err => { // Asynchronous write
      if (err) {
        throw err;
      }
    });
  });

  setTimeout(blinkLed, 200);
};

blinkLed();

// Stop blinking the LED after 5 seconds
setTimeout(_ => stopBlinking = true, 5000);

Blink an LED Using the Asynchronous API and Promises

Blink an LED connected to GPIO17 for 5 seconds using the asynchronous read and write methods and Promises.

const Gpio = require('../onoff').Gpio; // Gpio class
const led = new Gpio(17, 'out');       // Export GPIO17 as an output
let stopBlinking = false;

// Toggle the state of the LED connected to GPIO17 every 200ms
const blinkLed = _ => {
  if (stopBlinking) {
    return led.unexport();
  }

  led.read()
    .then(value => led.write(value ^ 1))
    .then(_ => setTimeout(blinkLed, 200))
    .catch(err => console.log(err));
};

blinkLed();

// Stop blinking the LED after 5 seconds
setTimeout(_ => stopBlinking = true, 5000);

Check accessibility

Sometimes it may be necessary to determine if the current system supports GPIOs programmatically and mock functionality if it doesn't. Gpio.accessible can be used to achieve this.

const Gpio = require('onoff').Gpio;

const useLed = (led, value) => led.writeSync(value);

let led;

if (Gpio.accessible) {
  led = new Gpio(17, 'out');
  // more real code here
} else {
  led = {
    writeSync: value => {
      console.log('virtual led now uses value: ' + value);
    }
  };
}

useLed(led, 1);

API

Class Gpio

Gpio(gpio, direction [, edge] [, options])
  • gpio - An unsigned integer specifying the GPIO number.
  • direction - A string specifying whether the GPIO should be configured as an input or output. The valid values are: 'in', 'out', 'high', and 'low'. If 'out' is specified the GPIO will be configured as an output and the value of the GPIO will be set to 0. 'high' and 'low' are variants of 'out' that configure the GPIO as an output with an initial level of 1 or 0 respectively.
  • [edge] - An optional string specifying the interrupt generating edge or edges for an input GPIO. The valid values are: 'none', 'rising', 'falling' or 'both'. The default value is 'none' indicating that the GPIO will not generate interrupts. Whether or not interrupts are supported by an input GPIO is GPIO specific. If interrupts are not supported by a GPIO the edge argument should not be specified. The edge argument is ignored for output GPIOs.
  • [options] - An optional options object.

Configures the GPIO based on the passed arguments and returns a new Gpio object that can be used to access the GPIO.

The following options are supported:

  • debounceTimeout - An unsigned integer specifying a millisecond delay. Delays invoking the watch callback for an interrupt generating input GPIO while the input is bouncing. The watch callback will not be invoked until the input stops bouncing and has been in a stable state for debounceTimeout milliseconds. Optional, if unspecified the input GPIO will not be debounced.
  • activeLow - A boolean value specifying whether the values read from or written to the GPIO should be inverted. The interrupt generating edge for the GPIO also follow this this setting. The valid values for activeLow are true and false. Setting activeLow to true inverts. Optional, the default value is false.
  • reconfigureDirection - A boolean value specifying whether the direction for the GPIO should be reconfigured even though the direction is already configured correctly. When an application starts, the direction of a GPIO used by that application may already be configured correctly, for example, from a previous run of the application. Reconfiguring the direction of that GPIO can result in unwanted side effects. For example, if a GPIO is already configured as an output and it is reconfigured as an output by passing 'out' to the constructor, the value of that output will be set to 0. In some applications this is not desirable and the value of the output should not be modified. The reconfigureDirection option can help here. If reconfigureDirection is set to false the direction of a GPIO that is already correctly configured will not be reconfigured. Optional, the default value is true.

GPIOs on Linux are identified by unsigned integers. These are the numbers that should be passed to the onoff Gpio constructor when exporting GPIOs to userspace. For example, pin 11 on the Raspberry Pi expansion header corresponds to GPIO17 in Raspbian Linux. 17 is therefore the number to pass to the onoff Gpio constructor when using pin 11 on the expansion header.

read([callback])
  • [callback] - An optional completion callback that gets two arguments (err, value), where err is reserved for an Error object and value is the number 0 or 1 and represents the state of the GPIO.

Read GPIO value asynchronously. If no completion callback is specified read returns a Promise which resolves to the value of the GPIO on success or rejects with an Error object on failure.

Note that most systems support readback of GPIOs configured as outputs. The read method can therefore be invoked for any GPIO, irrespective of whether it was configured as an input or an output. The Raspberry Pi and BeagleBone are examples of such systems.

readSync()

Read GPIO value synchronously. Returns the number 0 or 1 to represent the state of the GPIO.

Note that most systems support readback of GPIOs configured as outputs. The readSync method can therefore be invoked for any GPIO, irrespective of whether it was configured as an input or an output. The Raspberry Pi and BeagleBone are examples of such systems.

write(value[, callback])
  • value - The number 0 or 1.
  • [callback] - An optional completion callback that gets one argument (err), where err is reserved for an error object.

Write GPIO value asynchronously. If no completion callback is specified write returns a Promise that resolves with no value on success or rejects with an Error object on failure.

Note that on most systems invoking write for a GPIO configured as an input will result in an EPERM error indicating that the operation is not permitted. The Raspberry Pi and BeagleBone are examples of such systems.

writeSync(value)
  • value - The number 0 or 1.

Write GPIO value synchronously.

Note that on most systems invoking writeSync for a GPIO configured as an input will result in an EPERM error indicating that the operation is not permitted. The Raspberry Pi and BeagleBone are examples of such systems.

watch(callback)
  • callback - A callback that gets two arguments (err, value), where err is reserved for an error object and value is the number 0 or 1 and represents the state of the GPIO. The value can also be used to determine whether the interrupt occurred on a rising or falling edge. A value of 0 implies a falling edge interrupt and a value of 1 implies a rising edge interrupt.

Watch for hardware interrupts on the GPIO. The edge argument that was passed to the constructor determines which hardware interrupts to watch for.

unwatch([callback])
  • [callback] - The callback to remove.

Stop watching for hardware interrupts on the GPIO. If callback is specified, only that particular callback is removed. Otherwise all callbacks are removed.

unwatchAll()

Remove all hardware interrupt watchers for the GPIO.

direction()

Returns the string 'in' or 'out' indicating whether the GPIO is an input or output.

setDirection(direction)
  • direction - A string specifying whether the GPIO should be configured as an input or output. The valid values are 'in', 'out', 'high', and 'low'. If 'out' is specified the GPIO will be configured as an output and the value of the GPIO will be set to 0. 'high' and 'low' are variants of 'out' that configure the GPIO as an output with an initial level of 1 or 0 respectively.

Set GPIO direction.

edge()

Returns the string 'none', 'falling', 'rising', or 'both' indicating the interrupt generating edge or edges for the GPIO. Whether or not interrupts are supported by an input GPIO is GPIO specific. If interrupts are not supported the edge method should not be used. Interrupts are not supported by output GPIOs.

setEdge(edge)
  • edge - A string specifying the interrupt generating edge or edges for an input GPIO. The valid values are: 'none', 'rising', 'falling' or 'both'. Whether or not interrupts are supported by an input GPIO is GPIO specific. If interrupts are not supported the setEdge method should not be used. Interrupts are not supported by output GPIOs.

Set GPIO interrupt generating edge.

activeLow()

Returns true or false indicating whether or not the values read from or written to the GPIO are inverted.

setActiveLow(invert)
  • invert - A boolean value specifying whether the values read from or written to the GPIO should be inverted. The interrupt generating edge for the GPIO also follow this this setting. The valid values for invert are true and false. Setting activeLow to true inverts.

Set GPIO activeLow setting.

unexport()

Reverse the effect of exporting the GPIO to userspace. A Gpio object should not be used after invoking its unexport method.

static accessible

Determine whether or not GPIO access is possible. true if the current process has the permissions required to export GPIOs to userspace. false otherwise. Loosely speaking, if this property is true it should be possible for the current process to create Gpio objects.

It is notable that while this property may be false indicating that the current process does not have the permissions required to export GPIOs to userspace, existing exported GPIOs may still be accessible.

This property is useful for mocking functionality on computers used for development that do not provide access to GPIOs.

This is a static property and should be accessed as Gpio.accessible.

static HIGH / LOW

Constants used when reading or writing a GPIO value. Gpio.HIGH and Gpio.LOW can be used in place of the numeric constants 1 and 0.

How Does onoff Work?

Internally onoff uses sysfs files located at /sys/class/gpio to access GPIOs and the epoll package to detect hardware interrupts. The Linux GPIO sysfs interface for userspace is documented here. It's a relatively simple interface which can be used to ask the Linux kernel to export control of a GPIO to userspace. After control of a GPIO has been exported to userspace, the GPIO can be configured as an input or output. Thereafter, the state of an input can be read, and the state of an output can be written. Some systems will also allow the state of a output to be read. The GPIO sysfs interface can also be used for interrupt detection. onoff can detect several thousand interrupts per second on both the BeagleBone and the Raspberry Pi.

Configuring Pullup and Pulldown Resistors

As mentioned in section How Does onoff Work the sysfs interface is used to access GPIOs. The sysfs interface doesn't offer support for configuring pullup and pulldown resistors on GPIOs.

There are however many platform specific mechanisms for configuring pullup and pulldown resistors that are compatible with onoff. onoff itself doesn't use these mechanisms as one of the goals of onoff is to be platform independent.

Here we'll take a look at two mechanisms available on the Raspberry Pi for configuring pullup and pulldown resistors.

The first point to be aware of is that most GPIOs on a Raspberry Pi have either their pullup or pulldown resistor activated by default. The defaults can be seen in Table 6-31 on pages 102 and 103 of the BCM2835 ARM Peripherals documentation.

Using the gpio Command in /boot/config.txt

On Raspbian 2018-04-18 or later the gpio configuration command can be used in /boot/config.txt to configure pullup and pulldown resistors. Further information is available at New "gpio" config command.

Using Device Tree Overlays

Device tree overlays can also be used to configure pullup and pulldown resistors. The Wiki page Enabling Pullup and Pulldown Resistors on The Raspberry Pi describes this mechanism in more detail.

Benchmarks

Three of the onoff tests are used to monitor performance.

  • performance-async.js - determine max. no. of write ops per seconds
  • performance-sync.js - determine max. no. of writeSync ops per second
  • performance-interrupt.js - determine max. no. of interrupts per second

The results of these tests are shown in the following tables.

Raspberry Pi 4 B, 1.5GHz, Raspberry Pi OS (March 4th 2021, Buster 10.8)

node onoff kernel write / sec writeSync / sec interrupts / sec
v16.0.0 v6.0.3 5.10.17-v7l+ 25124 280417 20240
v15.14.0 v6.0.3 5.10.17-v7l+ 24055 271149 20488
v14.16.1 v6.0.3 5.10.17-v7l+ 21669 254705 19703
v12.22.1 v6.0.3 5.10.17-v7l+ 22618 318417 21122
v10.24.1 v6.0.3 5.10.17-v7l+ 22405 329927 19583

Raspberry Pi 3 B, 1.2GHz, Raspbian Buster 10.1

node onoff kernel write / sec writeSync / sec interrupts / sec
v12.14.0 v5.0.0 4.19.75-v7l+ 21670 207222 18328
v10.18.0 v5.0.0 4.19.75-v7l+ 23661 225758 20741

Raspberry Pi 2 B, 900MHz, Raspbian Buster 10.1

node onoff kernel write / sec writeSync / sec interrupts / sec
v12.14.0 v5.0.0 4.19.75-v7l+ 10769 113107 10373
v10.18.0 v5.0.0 4.19.75-v7l+ 11843 129086 10536

Raspberry Pi 1 B, 700MHz, Raspbian Buster 10.1

node onoff kernel write / sec writeSync / sec interrupts / sec
v12.14.0 v5.0.0 4.19.75+ 2316 26696 2112
v10.18.0 v5.0.0 4.19.75+ 2613 33129 2225

BeagleBone Black, 1GHz, Debian Buster 10.2

node onoff kernel write / sec writeSync / sec interrupts / sec
v12.14.0 v5.0.0 4.19.79-ti-r30 6855 70535 5911
v10.18.0 v5.0.0 4.19.79-ti-r30 7564 79133 5920

BeagleBone, 720MHz, Debian Buster 10.2

node onoff kernel write / sec writeSync / sec interrupts / sec
v12.14.0 v5.0.0 4.19.79-ti-r30 5013 49741 4297
v10.18.0 v5.0.0 4.19.79-ti-r30 5400 57157 4371

Related Packages

Here are a few links to other hardware specific Node.js packages that may be of interest.

  • pigpio - Fast GPIO, PWM, servo control, state change notification and interrupt handling on the Raspberry Pi
  • i2c-bus - I2C serial bus access
  • spi-device - SPI serial bus access
  • mcp-spi-adc - Analog to digital conversion with the MCP3002/4/8, MCP3202/4/8 and MCP3304

Additional Information

onoff was tested on the following platforms:

  • Raspberry Pi 1, 2, 3 and 4
    • Raspbian or Raspberry Pi OS
  • BeagleBone, BeagleBone Black and PocketBeagle
    • Debian

The suitability of onoff for a particular Linux board is highly dependent on how GPIO interfaces are made available on that board. The GPIO interfaces documentation describes GPIO access conventions rather than standards that must be followed so GPIO can vary from platform to platform. For example, onoff relies on sysfs files located at /sys/class/gpio being available. However, these sysfs files for userspace GPIO are optional and may not be available on a particular platform.

onoff's People

Contributors

azazdeaz avatar fivdi avatar jens-duttke avatar johntalton avatar legege avatar manawyrm avatar mildsunrise avatar mwittig avatar pizzaisdavid avatar reconbot avatar saenglert avatar towc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

onoff's Issues

Cannot compile on Raspbian on Raspberry Pi B 2 due to REPLACE_INVALID_UTF8 error (with solution)

This may be worth noting in the documentation since it took me a long time to figure out. The latest Raspbian comes with a faulty Node v0.10.29 which is missing a UTF8 patch. This results in your epoll dependency failing to compile. Note gcc is v4.9.2.

The error shown is:

../node_modules/nan/nan.h:328:47: error: 'REPLACE_INVALID_UTF8' is not a member of 'v8::String'
static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8;

The only solution I found is to upgrade to a newer version, eg:

curl -sL https://deb.nodesource.com/setup_0.12 | sudo -E bash -
sudo apt-get install -y nodejs

This allows onoff to install as expected. It's unfortunate that the out of box Raspbian has this issue but hopefully others won't have to run into this issue too.

Watch does not work.

Running the interrupt-example on a raspi (except with pin 17 and not 18), the callback for the watch-function never fires.
Manually reading the gpio at /sys/class/gpio/gpio17/value the value is changed on buttonpress (from 1 to 0).

The connection is made with a 10Kohm resistor between the gpio-pin and 3.3V and the gpio-pin has a 1Kohm protector resistor in front. The button is connected between gnd and 3.3v.

Running on latest raspbian and node 0.8.23.

Unexporting GPIOs no longer allowed on the BBB with Debian 8.4 2016-05-13

Attempting to unexport a GPIO on the BeagleBone Black when using the Debian 8.4 2016-05-13 image results in errors. Here's an example:

fs.js:613
    return binding.writeBuffer(fd, buffer, offset, length, position);
                   ^
Error: EINVAL, invalid argument
    at Error (native)
    at Object.fs.writeSync (fs.js:613:20)
    at Object.fs.writeFileSync (fs.js:1108:21)
    at Gpio.unexport (/root/lcd/node_modules/onoff/onoff.js:302:6)
    at Lcd.close (/root/lcd/node_modules/lcd/lcd.js:219:11)
    at process.<anonymous> (/root/lcd/node_modules/lcd/example/digital-clock-8x1.js:19:7)
    at process.emit (events.js:104:17)
    at Signal.wrap.onsignal (node.js:655:46)

Error: EBUSY: resource busy or locked, write

If my app accidently closed without led4.unexport(); so now I have Error: EBUSY: resource busy or locked, write error for each start. How to avoid it? Raspberry restart does not help.

pi@raspberry-black:~/dev/homesen $ node test-gpio.js
fs.js:706
    return binding.writeBuffer(fd, buffer, offset, length, position);
                   ^

Error: EBUSY: resource busy or locked, write
    at Error (native)
    at Object.fs.writeSync (fs.js:706:20)
    at Object.fs.writeFileSync (fs.js:1234:24)
    at new Gpio (/home/pi/dev/homesen/node_modules/onoff/onoff.js:82:8)
    at Object.<anonymous> (/home/pi/dev/homesen/test-gpio.js:3:12)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
var Gpio = require('onoff').Gpio;
var led4 = new Gpio(4, 'out');
blink(led4, 500);

function blink(led, period) {
    led.write(1, function () {
        setTimeout(function(){
            led.write(0);
        }, period);
    });
}

Receive more than once the same button state

Hi,

I'm using you package to listen to button event and I noticed that sometimes (don't know how to 100% simulate it) I receive more than once the same value.
Below is my code.
When running it and start pressing the button, I get sometimes twice the value 1 (in a row).

button.watch(function(err, value) {
console.log(value);
});

Are you aware of such issue ?

Btw, great package :)

Thanks !

Button debouncing

Hi there,

Nice GPIO library !
Is there any internal mechanism for debouncing the hardware interrupts watch() function? I am having issues with this, and found nothing to get rid of it.

EAGAIN Error

I am getting a resource unavailable error which I think is related to onoff. Have a look at the error message. I have checked all my other modules, and they are not causing the error.

fs.js:476
  var r = binding.read(fd, buffer, offset, length, position);
                  ^
Error: EAGAIN, resource temporarily unavailable
    at Object.fs.readSync (fs.js:476:19)
    at Object.fs.readFileSync (fs.js:310:28)
    at Object.exports.readAIN (/usr/local/lib/node_modules/bonescript/hw_capemgr.js:214:30)
    at Object.f.analogRead (/usr/local/lib/node_modules/bonescript/index.js:229:15)
    at null.<anonymous> (/home/debian/node_modules/thing-client/beagle1.js:648:18)
    at wrapper [as _onTimeout] (timers.js:252:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

Your help will be appreciated.
Thanks
Regards Guy

installing onoff hangs/freeze there

installing onoff on raspberry pi 2 model B, NOOBs v1.4.1 seems to hang at the terminal for very long. Is there any resolve in this? Usually install via 'npm install onoff --save'

EPERM: operation not permitted, write

Hi, I'm just trying the functions out and I'm currently trying to write to pin 4, but getting the above error message. Here's the code, it's pretty basic..

`var Gpio = require('onoff').Gpio,
led = new Gpio(4, 'out');

led.write(1);`

Has anyone come across this before?

Install on darwin

Hi,
I'm using onoff for FirmataPi and have hit a snag. I've been developing on osx, running tests on osx and linux, and have "production" on my raspberry pi. I know onoff can't work on anything but linux but in my tests I'm mocking out onoff as I don't need to test its functionality, just that I'm calling it correctly.

So here's my question, how can I install it on other platforms?

watch 5 inputs at the same time

Hi,

I'm trying to watch 5 inputs at the same time using "persistentWatch : true" and debouncing time 250 and it's not working as it should.

If I watch 4 inputs, everything works fine. I can push the buttons several times, they keep working. But if I use 5 inputs, some things are messed up. I cannot press the same button twice, I have to press another one first before I can press it again.

Is there some kind of limit to the number of inputs that can be watched?
Is there something I can do about it?

Thanks,
Sam

return binding.writebuffer issue

Working onoff I am trying to use a Hall Effect Sensor position (0-off, 1-on) to control a motor. My raspberry pi is giving me the below error. Not sure what to do next.. thank for the help.

fs.js:613
return binding.writeBuffer(fd, buffer, offset, length, position);
^
Error: EBUSY, resource busy or locked
at Error (native)
at Object.fs.writeSync (fs.js:613:20)
at Object.fs.writeFileSync (fs.js:1108:21)
at new Gpio (/node_modules/onoff/onoff.js:82:8)
at Object. (/home/1-28-2016/door.js:3:14)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)

Register pin without altering state

Great library ๐Ÿ‘

Not really an issue, more like a feature request.

When a pin is registered at the start of the script using
var led = new Gpio(14, 'out');

The state of pin 14 is set to LOW (0), regardless of what it was before. If a previous script has set the pin to HIGH and then finishes, or the script restarts for whatever reason, the pin is always reset to LOW.

Is it possible to have the pin registered, but not have the start altered until it is done so manually using write or writeSync?

I appreciate your time.

symbol lookup error

I configured a GPIO ( GPIO 25 to be exact and pulled up)
I watch the pin for state change, the following error occurs when the switch is pressed.

node: symbol lookup error: /home/pi/mytools/gateway/node_modules/onoff/node_modules/epoll/build/Release/epoll.node: undefined symbol: _ZN4node12MakeCallbackEN2v86HandleINS0_6ObjectEEENS1_INS0_8FunctionEEEiPNS1_INS0_5ValueEEE

I tried upgrading wheezy but still did not resolve the issue. Current version I am at :

Linux version 4.1.7+ (dc4@dc4-XPS13-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03) ) #817 PREEMPT Sat Sep 19 15:25:36 BST 2015

onoff version is 1.0.3.

New compilation issue on BeagleBone Black

Can't get onoff to compile on BBB:

node-gyp rebuild

gyp ERR! configure error
gyp ERR! stack Error: Python executable "python" is v2.7.3, which is not supported by gyp.
gyp ERR! stack You can pass the --python switch to point to Python >= v2.5.0 & < 3.0.0.
gyp ERR! stack at failPythonVersion (/usr/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:118:14)
gyp ERR! stack at /usr/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:107:9
gyp ERR! stack at ChildProcess.exithandler (child_process.js:538:7)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:99:17)
gyp ERR! stack at maybeClose (child_process.js:638:16)
gyp ERR! stack at Socket.ChildProcess.spawn.stdin (child_process.js:815:11)
gyp ERR! stack at Socket.EventEmitter.emit (events.js:96:17)
gyp ERR! stack at Socket._destroy.destroyed (net.js:358:10)
gyp ERR! stack at process.startup.processNextTick.process._tickCallback (node.js:245:9)
gyp ERR! System Linux 3.8.13
gyp ERR! command "node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /home/root/downloads/GettingStartedWithNFC/NodeTagToLedPi/node_modules/onoff
gyp ERR! node -v v0.8.22
gyp ERR! node-gyp -v v0.8.5
gyp ERR! not ok
npm ERR! [email protected] install: node-gyp rebuild
npm ERR! sh "-c" "node-gyp rebuild" failed with 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the onoff package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node-gyp rebuild
npm ERR! You can get their info via:
npm ERR! npm owner ls onoff
npm ERR! There is likely additional logging output above.

npm ERR! System Linux 3.8.13
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "install"
npm ERR! cwd /home/root/downloads/GettingStartedWithNFC/NodeTagToLedPi
npm ERR! node -v v0.8.22
npm ERR! npm -v 1.2.14
npm ERR! code ELIFECYCLE
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/root/downloads/GettingStartedWithNFC/NodeTagToLedPi/npm-debug.log
npm ERR! not ok code 0

Thoughts?

The persistentWatch option is no longer required and should be removed

The persistentWatch option was introduced in onoff v0.1.2 as all watches up till then were single shot, they only got called once. By setting the persistentWatch option to true, it was possible to have watchers that always got called. persistentWatch had a default value of false for backward compatibility.

As of onoff v0.2.0, the persistentWatch option is no longer strictly required. Watchers could always be persistent and the single shot effect can be achieved by calling unwatch the first time the watch handler is called. unwatch was added in v0.2.0.

This will be a breaking change for programs that set persistentWatch to false, either explicitly or implicitly as false is the default value.

So, unless someone can come up with a good reason not to, the persistentWatch option will be removed in onoff v0.3.0.

On which computer do you use onoff?

I'd be very interested in knowing on which computers people use onoff.

The Raspberry Pi?
The BeagleBone or BeagleBone Black?
Maybe something else?

If you happen to read this and use onoff, I would be very, very grateful if you posted a comment below saying on which computer you use onoff.

0.11.4+ compatibility

Use nan to isolate the gpiowatcher addon from V8 modifications and make it compatible with node v0.8 through v0.12.

ADC and Pin Muxing

Hi there, first of this is a greata library you have made. I use it a lot!

I have two questions, first of all: I am trying to read from a 2wire temperature sensor (LM75A) using I2c on pins P9_19 and P9_20. I understand that the beaglebone pin functions can be altered depending on what mode it is set to. However, I don't see anywhere in your library where the pin mode can be set.

I have had a little bit of success with the temp readings which leads me to believe that the pin mode is automatically set. I just want to rule this out as a possible cause of my issues with the temp readings.

Secondly, does your library accommodation for analog readings using the AIN pins?

Thanks in advance
Regards
Guy

Restart onoff application -

If I start my ARM machine (note: GPIO 239 is NOT exported yet), start node REPL and enter this code:

const GpioOnOff = require('onoff').Gpio;
const button = new GpioOnOff(239, 'in', 'both');
button.watch(function(err, value) {
  console.log('jo');
  console.log(err, value);
});

everything works as expected. Now if I close the Node REPL and restart Node REPL (note: GPIO 239 is now exported due the first run on onoff) and use the same code as above, the example code does not work anymore. When I cat the GPIO value I can see that the value change if I press the button.

When I unexport the GPIO port manually and restart the Node REPL and run the code above, it works again. So it looks like onoff has some issues when the GPIO pin already is exported.

Possible options to fix this issue:

  • unexportAlways option: if onoff is started with this option, it will try to unexport the GPIO pin first
  • fix the actual issue, might be hard due alot of different systems

Can you reproduce this issue?

installation of epoll dependency seems to fail

when installing the module with npm I get

npm http 404 https://registry.npmjs.org/epoll/-/epoll-0.1.0.tgz
npm ERR! fetch failed https://registry.npmjs.org/epoll/-/epoll-0.1.0.tgz
npm ERR! Error: 404 Not Found

It seems like epoll is not available on npmjs

GPIO initial as HIGH at boot

There is an option to initial them as 1? becuase if they are connected to something all are sync zero at the same time and its annoying..
any suggestion?
thanks

All relays turn on when starting the app

I'm using onoff to control a relay board with LEDs. When I start the app script, all LEDs turn on automatically. Is there a way to prevent onoff from turning all my relays on when initializing them?

I/O errors on first launch

The first time I launch a node application (as sudo) that uses onoff.js, I get this error:

fs.js:540
  return binding.write(fd, buffer, offset, length, position);
                 ^
Error: EIO, i/o error
    at Object.fs.writeSync (fs.js:540:18)
    at Object.fs.writeFileSync (fs.js:987:21)
    at new Gpio (/home/pi/nodeplay/node_modules/onoff/onoff.js:103:10)
    at Object.<anonymous> (/home/pi/nodeplay/process.js:15:16)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)

Subsequent launches are fine, until the next reboot.
Any ideas?

PWM features.

Hi,

Firstly I'm loving On/Off... for me it works the best out of all the others that I tried.

Is there any chance you can add PWM features... I was looking at Webiopi and they use PWM ratio and PWM angle and was wondering if it was something you would be able to add.

Many Thanks

Does not work anymore on Node v4.5.0 (ARM)

The latest onoff version does not work anymore on my arm machine. this is the simple code is use:

const GpioOnOff = require('onoff').Gpio;
const button = new GpioOnOff(239, 'in', 'both');
button.watch(function(err, value) {
  console.log('jo');
  console.log(err, value);
});

-> the button watch function is never triggered.

when reading directly cat /sys/class/gpio/gpio239/value is see that the values are populated correctly.

any hints?

EPERM: operation not permitted, write

Hi, I'm just trying the functions out and I'm currently trying to write to pin 4, but getting the above error message. Here's the code, it's pretty basic..

var Gpio = require('onoff').Gpio,
led = new Gpio(4, 'out');

led.write(1);

Has anyone come across this before?

NOTE: Running Raspbian Jessie and Node.js 6.3.0

unwatch ?

Hi,

Is there a way to "unwatch" the inputs?

The things is, I want to watch 5 buttons and when one is pressed, no others should be able to press there buttons.

Ran into a weird error: EAGAIN

Everything was working fine, until out of the blue I started getting this error which crashed my app:

fs.js:476
  var r = binding.read(fd, buffer, offset, length, position);
                  ^
Error: EAGAIN, resource temporarily unavailable
    at Object.fs.readSync (fs.js:476:19)
    at Object.fs.readFileSync (fs.js:310:28)
    at Object.exports.readAIN (/usr/local/lib/node_modules/bonescript/hw_capemgr.js:214:30)
    at Object.f.analogRead (/usr/local/lib/node_modules/bonescript/index.js:229:15)
    at null.<anonymous> (/home/debian/node_modules/thing-client/beagle1.js:647:18)
    at wrapper [as _onTimeout] (timers.js:252:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

Any idea how I can get through this?

Regards
Guy

Timing issue when setting direction

The README.md file talks at long about gpio export requiring root access.

On my 2014-01-07-wheezy-raspbian image (Rapberry Pi B), /sys/class/gpio/export is indeed owned by root, but gives access to group gpio as well (and user pi is member of the gpio group).

When I start my node.js application as user pi, the onoff export works, but setting the direction fails with EACCES. When I look at /sys/class/gpio, I see the gpio4 directory matching my pin 4. I can set the direction from the shell, and then set the output. Never been root.

I experimented with a script, and I found that I have to sleep for at least 0.2 second before I can access the direction file. I tried to wait until the direction file was created, with no success: the script still needs to wait after that.

Then I tried parallelism: export all 8 pins, wait and then set all 8 directions. It worked if it waits at least 0.4 second.

Do you have ever noticed such a peculiar thing?

Always returning 1 as new value during toggling

Someone can explain why it returns always 'off' in stato? It can't toogle.

var Gpio = require("onoff").Gpio;
led = new Gpio(17, 'out');

   led.read(function (err, value) { // Asynchronous read.
        if (err) throw err;

        led.write(value ^ 1, function (err) { // Asynchronous write.
          if (err) throw err;
          var stato = (value == 1) ? "on": "off"; 
          console.log('Pin new value: '+stato);
        });
  });

For example, when i turn on the pin with a write method, everything seems to work fine, but when i try to read the pin status, the pin turn OFF and the value printed on the console is 0/off.

The weird thing is that it happens even with the rpi-gpio.js library: JamesBarwell/rpi-gpio.js#24

No persistent watch

There is no option to persistently watch and initiate a callback each time it is pressed as it is currently a one-shot watch.

watching/polling not working anymore

I have no idea what's going on, it worked perfectly before.
I can read a GPIO but watching doesn't work and no error is thrown.
I can see via gpio utility that the value of the GPIO changed but onoff won't execute my watch callback.

Any idea?

Arch Linux

3.12.28-1-ARCH

Update for libuv after work callbacks

The signature for lubuv "after work" callbacks in Node.js v0.8.0 is:

typedef void (uv_after_work_cb)(uv_work_t req);

in v0.10.0 it's:

typedef void (uv_after_work_cb)(uv_work_t req, int status);

Update onoff to take this into account and ensure that it functions with both v0.8.0 and v0.10.0.

Install seems to freeze

Hi there, firstly well done on this submission. I'm working on a project and this is going to help a lot.

I am using a Beaglebone Black running the latest Debian Wheezy.

The install seems to freeze halfway through, and I'm wandering if this is normal and it just takes really long to install. Or what might be causing it to freeze..

Here is the output:

debian@debian-armhf:~$ sudo npm install onoff
npm http GET https://registry.npmjs.org/onoff
npm http 200 https://registry.npmjs.org/onoff
npm http GET https://registry.npmjs.org/onoff/-/onoff-0.3.1.tgz
npm http 200 https://registry.npmjs.org/onoff/-/onoff-0.3.1.tgz
npm http GET https://registry.npmjs.org/epoll
npm http 200 https://registry.npmjs.org/epoll
npm http GET https://registry.npmjs.org/epoll/-/epoll-0.1.3.tgz
npm http 200 https://registry.npmjs.org/epoll/-/epoll-0.1.3.tgz
npm http GET https://registry.npmjs.org/nan
npm http 200 https://registry.npmjs.org/nan
npm http GET https://registry.npmjs.org/nan/-/nan-0.8.0.tgz
npm http 200 https://registry.npmjs.org/nan/-/nan-0.8.0.tgz

> [email protected] install /home/debian/node_modules/onoff/node_modules/epoll
> node-gyp rebuild

gyp WARN EACCES user "root" does not have permission to access the dev dir "/root/.node-gyp/0.10.22"
gyp WARN EACCES attempting to reinstall using temporary dev dir "/home/debian/node_modules/onoff/node_modules/epoll/.node-gyp"
gyp http GET http://nodejs.org/dist/v0.10.22/node-v0.10.22.tar.gz
gyp http 200 http://nodejs.org/dist/v0.10.22/node-v0.10.22.tar.gz

Your input will be greatly appreciated.
Thanks in advancef

permission denied

I'm getting

Error: EACCES, permission denied '/sys/class/gpio/export'

when I try your first example on my raspberry pi

Reverse

A lot of times the io is connected to relays the reverse the output. E.G. Gpio goes low, relay closes. It would be nice to have a "reverse" parameter in the constuctor.

gpio-admin support

I'd love to see this module support gpio-admin for exporting and unexporting pins instead of needing to be root.

An example of another node gpio module that does this: https://github.com/rakeshpai/pi-gpio (however that module doesn't seem to support interrupts like this one does)

Question about read right

I'm using RPi 2 with onoff. On my machine I cannot read gpio no matter I export the pin using gpio-admin or not. However as soon as I use python to read the same pin, node.js can get the value even if I unexport the pin with gpio-admin. How can this happen?

The code I'm using:

var gpio = require('onoff').Gpio,
    http = require('http'),
    button = new gpio(18, 'in', 'both');

function exit() {
  process.stdout.write('\n');
  button.unexport();
  process.exit();
}
process.on('SIGINT', exit);

button.watch(function(err, state) {
  if (err) {
    throw err;
  }

  process.stdout.write(button.readSync() + '');
});

http.createServer(function(req, res) {
  res.end(button.readSync() + '');
  process.stdout.write(button.readSync() + '');
}).listen(8080);
import RPi.GPIO as GPIO
import time

print('Setup GPIO pin 18')
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

print('Setup LED')
f = open('/sys/class/leds/led1/trigger', 'r+')
f.write('gpio\n')
f.close()

print('Ready')

while True:
    input_state = GPIO.input(18)
    if input_state == False:
        f = open('/sys/class/leds/led1/brightness', 'r+')
        if f.read() == '1\n':
            f.write('0\n')
        else:
            f.write('1\n')
        f.close()
        print('Button Pressed')
        time.sleep(0.2)

Debounce

I am having an issue with a nosy input.

The interrupts are firing very fast but reading the same value (I think because of the noise).

For example I have an input the is low but the watch listeners are firing always reading 0.

I have tried setting debounceTimeout but this only delays the interrupt and cause them to occur less often.

Can the code be changed to add a readSync after the timeout and fire the watch listeners if the value changed.

Also don't know if the help but it is on a bealge bone black.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.