Giter Site home page Giter Site logo

gpio's Introduction

gpio - talk to your Single Board Computer's gpio headers

NPM

Introduction

This plain JavaScript module is generic and only rely on system's sysfs.

Please consider other (more mature) gpio libraries out there which support better your hardware,

For instance, of you're looking for a reliable way to communicate with the Raspberry Pi using JavaScript, check out the wiring-pi JavaScript library. It provides direct bindings to the fully-featured Wiring Pi C library.

But if you want/need a generic lightweight module, this one can be used as fallback.

Support

Following hardware was reported to work (with some limitations or workarounds)

  • ARTIK10 (inputs' pull down resistors are enabled by default)
  • Raspberry Pi (use wiringpi's /usr/bin/gpio to change mode: gpio -g mode 11 up)

Installation

Get node.js for your SBC, If using Debian or deviates (Raspbian for RPi), you can simply run: sudo apt-get install nodejs

otherwise, install from node or compile it

Usage

This library is an npm package, just define "gpio" in your package.json dependencies or

npm install gpio

Note: you must be have proper privileges to access the GPIO headers (or run node as root).

Standard setup

var gpio = require("gpio");

// Calling export with a pin number will export that header and return a gpio header instance
var gpio4 = gpio.export(4, {
   // When you export a pin, the default direction is out. This allows you to set
   // the pin value to either LOW or HIGH (3.3V) from your program.
   direction: gpio.DIRECTION.OUT,

   // set the time interval (ms) between each read when watching for value changes
   // note: this is default to 100, setting value too low will cause high CPU usage
   interval: 200,

   // Due to the asynchronous nature of exporting a header, you may not be able to
   // read or write to the header right away. Place your logic in this ready
   // function to guarantee everything will get fired properly
   ready: function() {
   }
});

Header direction IN

If you plan to set the header voltage externally, use direction in and read value from your program.

var gpio = require("gpio");
var gpio4 = gpio.export(4, {
   direction: gpio.DIRECTION.IN,
   ready: function() {
   }
});

API Methods

// sets pin to high
gpio4.set();
// sets pin to low (can also call gpio4.reset())
gpio4.set(0);
// Since setting a value happens asynchronously, this method also takes a
// callback argument which will get fired after the value is set
gpio4.set(function() {
   console.log(gpio4.value);    // should log 1
});
gpio4.set(0, function() {
   console.log(gpio4.value);    // should log 0
});
// unexport program when done
gpio4.unexport();

EventEmitter

This library uses node's EventEmitter which allows you to watch for value changes and fire a callback.

// bind to the "change" event
gpio4.on("change", function(val) {
   // value will report either 1 or 0 (number) when the value changes
   console.log(val)
});
      
// you can bind multiple events
var processPin4 = function(val) { console.log(val); };
gpio4.on("change", processPin4);
            
// unbind a particular callback from the "change" event
gpio4.removeListener("change", processPin4);
      
// unbind all callbacks from the "change" event
gpio4.removeAllListeners("change");
      
// you can also manually change the direction anytime after instantiation            
gpio4.setDirection(gpio.DIRECTION.OUT);
gpio4.setDirection(gpio.DIRECTION.IN);

Example

Cycle voltage every half a second

var gpio = require("gpio");
var gpio22, gpio4, intervalTimer;

// Flashing lights if LED connected to GPIO22
gpio22 = gpio.export(22, {
   ready: function() {
      intervalTimer = setInterval(function() {
         gpio22.set();
         setTimeout(function() { gpio22.reset(); }, 500);
      }, 1000);
   }
});

// Lets assume a different LED is hooked up to pin 4, the following code 
// will make that LED blink inversely with LED from pin 22 
gpio4 = gpio.export(4, {
   ready: function() {
      // bind to gpio22's change event
      gpio22.on("change", function(val) {
         gpio4.set(1 - val); // set gpio4 to the opposite value
      });
   }
});

// reset the headers and unexport after 10 seconds
setTimeout(function() {
   clearInterval(intervalTimer);          // stops the voltage cycling
   gpio22.removeAllListeners('change');   // unbinds change event
   gpio22.reset();                        // sets header to low
   gpio22.unexport();                     // unexport the header
   
   gpio4.reset();
   gpio4.unexport(function() {
      // unexport takes a callback which gets fired as soon as unexporting is done
      process.exit(); // exits your node program
   });
}, 10000)

References

Demos on Raspberry Pi:

gpio's People

Contributors

bryant1410 avatar cherniavskii avatar daniel-j avatar enotionz avatar j-san avatar jmstriegel avatar rzr avatar timfpark avatar tjkrusinski 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

gpio's Issues

Cant read initial value of pin

Hi,

i encountered with the problem reading initial value of pin inside ready function, here is the code snippet

var gpio11 = gpio.export(17, {
    direction: "in",
    interval: 200,
    ready: function (val) {
        //here, how to read value of pin?
        console.log(val); // "undefined" - always
        console.log(gpio11.value); // "0" - always
        
        gpio11.on("change", function (val) {
            console.log(val); // reads correctly, "1" or "0"
        });
    }
});

violates unix rule of silence

it would be nice if the default console log messages were turned off by default and there was a debug mode you could enable

Enable pullup/pulldown config of input pins

I have been using the pi-gpio module which uses the gpio-admin command under the covers to export pins - rather than manage the files directly.

For a new project, I need to use the inbuilt pullup/pulldown resistors on the pi - this is done via bit-flipping at specific locations in /dev/mem. The gpio-admin command, written in C, exposes this ability which makes it easy to patch into pi-gpio.... and there is an open pull request for it.

However I see that module is no longer actively maintained, so would like to move over to this one.

As this module manages the pins directly, rather than via gpio-admin, it is not such a simple task to add the resistor support. Before I go down the route of getting this to work, I wanted to raise this issue to flag it for anyone else interested in this, or who has perhaps already done it...

Fast Pulse

Hi;

Using a scope to monitor the pin, I seem to be unable to get a pulse faster than 10ms using the following code, but I really need the pulse width to be in microseconds rather than milliseconds, hence the setTimeout value of 0, which I was hoping would last a few clock cycles. Even if I remove the SetTimeout() function, the pulse width is still 10ms.

there is a 1K pullup on gpio.4.

The following code is intended to pull gpio4 low for 500us, then release it and then read whether the connected device has pulled the line low (presence) and log the result to the console, however I am unable to get a pulse width less than 10ms, any ideas why ??

var dq;
function dqinit(cb){
    dq = gpio.export(4, {
       ready: function() {
          dq.set(0);
          setTimeout(function() {
            dq.set();
            dq = gpio.export(4, {
               direction: "in",
               ready: function() {
                    cb(dq.value); 
               }
            });         
          },0);
       }
    }); 
}

dqinit(function(val){
    console.log(val);
});

_write fails when writing number to file

The _write() function fails when the user is exporting a GPIO port:

TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received type number (15)

Adding .toString() to the fs.writeFile() 'str' option seams to do the job just fine.

.set should always callback

I noticed that set doesn't callback if the value passed would not change the pin. This is hard to reason about in client programs and unexpected - my take is that you should always callback, even if its a no-op.

I'm happy to provide a PR if you agree - reassign to me if so.

Message "path.exists is now called `fs.exists`" appears

The message "path.exists is now called fs.exists"appears, but the library still works. So it's just a minor detail.

I think it can be solved simply modifying gpio.js, line 43,

-- if(path.exists(gpiopath + 'gpio'+n)) {
++ if(fs.exists(gpiopath + 'gpio'+n)) {

Just as the message says :D.

Best Regards and thanks for the great library!

Unsupported "high" direction

The sys API supports a "high" direction, which sets the direction to "out" but also sets the initial value to "1".

set does not work without timeout

This code works:

var gpio = require("gpio");

var pin = gpio.export(21, {
  direction: 'out',
  ready: function() {
    if (process.argv.length > 2) {
      console.log('high');
      setTimeout(function() {
        // for some reason without timeout this does not work
        pin.set();
      }, 1000);
    } else {
      console.log('low');
      pin.set(0);
    }
  }
});

but if I remove this setTimeout it goes high and then immediately goes low. I'll try to track this problem down.

Doing it manually just works:

sudo echo 21 > /sys/class/gpio/export
sudo echo 1 > /sys/class/gpio/gpio21/value

gpio.open should accept array of pin options

gpio.open should support an array of config objects in order to export multiple ports and have an elegant callback that ensures all those ports are available to use.

Contract should look something like...

gpio.open([
  { pin: 4, direction: gpio.DIRECTION.IN },
  { pin: 17, direction: gpio.DIRECTION.OUT }
], function(err, gpioPins) {
  if(err) return console.log(err);

  var gpioPin4 = gpioPins[0];
  var gpioPin17 = gpioPins[1];
});

Pin #16

Pin #16 (WiringPi #4) doesn't seem to have any interface for reading/writing, despite being a programmable pin. I'm curious if this is an issue with my configuration or something else. It's not a big deal, I was just wondering what was going on with that :)

Create an NPM package

You should turn this into an NPM package. Or, if it is already, add the info into the README file.

npm install gpio

gpio incorrectly assumes 0 value by default

In set there's comparison of current value with the new one. But current value is not read from hardware but assumed to be 0 by default. Therefore if gpio is high I cannot make it back low.

CPU Usage

Hi;

I was just looking at CPU usage on my RPI and realised that each export appears to consume around 3.5% of the CPU without doing anything, this does seem rather a lot ??

gpio.export(11,{direction:"out",ready:function(){
    // callback or do something
}})

If I export additional pins, the CPU usage will increase proportionally ??

mapping support

This would provide a way to support multiple devices and platforms. Although the primary use case would be to allow the creation of new mapping files (like #37) but should be flexible enough to enable initializing with a custom map. #40 is related to this since a custom test path is essentially a form of mapping.

onChange Event to be triggered if value modified externaly

Hey,
I'm not quite sure if this is actually a "feature request" or a "bug". If I modify the value of the gpio-pin externaly, for example with gpio -g write 3 0 the onChange event is not triggered. If it is done via the nodeJS app it works fine.

Cannot call method 'stop' of undefined

Hey,

I just created a fresh copy of wheezy on a raspberrypi with node v0.10.5 and using your example I'm getting following message:

    /home/pi/gpio/node_modules/gpio/lib/gpio.js:124
    GPIO.prototype.unexport = function(fn) { this.valueWatcher.stop(); _unexport(t
                                                           ^
    TypeError: Cannot call method 'stop' of undefined
        at GPIO.unexport (/home/pi/gpio/node_modules/gpio/lib/gpio.js:124:60)
        at gpio.export.ready (/home/pi/gpio/app.js:29:13)
        at /home/pi/gpio/node_modules/gpio/lib/gpio.js:102:51
        at /home/pi/gpio/node_modules/gpio/lib/gpio.js:53:38
        at /home/pi/gpio/node_modules/gpio/lib/gpio.js:20:33
       at fs.js:944:21
       at Object.oncomplete (fs.js:107:15)

Problem Running simple GPIO OUT Test

I'm trying something like this. A simple example based on yours. but doesn't runs. when i try this, the led gets on about 100ms and then gets off

var gpio = require("gpio");
var gpio23;
gpio23 = gpio.export(23, {
ready: function() {
gpio23.set();
}
});

I solved adding setInterval of 1ms but it should run without this timmer

setInterval(function(){
gpio23.set();
},1);

Thanks for the good job done

Not sure unexport is working cleanly

I'm new to working with the Raspberry Pi, so this could totally be user error.

I've tried your sample code and it appears to work without error. The problem I see is that if after running your code, I try similar sample code from adafruit's tutorial written in python, that code claims that the pin in still in use.

I'm still to new to all this to be able to determine if the issue is with this component, the python one, or just my lack of knowledge. I would be welcome to any ideas on how I can figure out what is going on. Thanks.

Pin direction change

Apologies if I have miss understood your documentation, however, when implementing your library for my project I am having trouble with switching the direction of a pin from out to in after sending a signal to it (working with a proximity sensor).

This is my code:

// Distance change listener

var gpioProximity = gpio.export(18, {
    direction: 'in',
    ready: function() {
        logger.info('GPIO pin 18 set up as proximity sensor');
        distanceReady = true;
        distanceCheck();
        gpioProximity.on("change", function(val){
            logger.info('GPIO pin 18 seen change');
            if (pingSent == true){
                if (val == 1) {
                    endTime = Date.now();
                    logger.info('End ' + endTime);
                    logger.info('Ping received');
                }
            }
        })
   }
});  

// Distance check

function distanceCheck(){

    distanceChecking = setInterval(function(){
        gpioProximity.setDirection("out");
        setTimeout(gpioProximity.set(1),100);
        setTimeout(gpioProximity.reset(),100);
        startTime = Date.now();
        logger.info('Start ' + startTime);
        pingSent = true;
        gpioProximity.setDirection("in");
        setTimeout(pingSent = false, 500);
        // MATH
        // UPDATE DISTANCE
    }, 2000);
}

This is the console log:

info: GPIO pin 18 set up as proximity sensor
info: Start 1386161269665
EPERM write /sys/class/gpio/gpio18/value
info: Start 1386161271662
EPERM write /sys/class/gpio/gpio18/value
info: Start 1386161273660
EPERM write /sys/class/gpio/gpio18/value
info: Start 1386161275661
EPERM write /sys/class/gpio/gpio18/value
info: Start 1386161277660
EPERM write /sys/class/gpio/gpio18/value
info: Start 1386161279660
EPERM write /sys/class/gpio/gpio18/value
info: Start 1386161281660
EPERM write /sys/class/gpio/gpio18/value

For reference, this is the python script I am basing this on:

import time
import RPi.GPIO as GPIO

    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(12, GPIO.OUT)

    GPIO.output(12, 0)
    time.sleep(0.000002)

    GPIO.output(12, 1)
    time.sleep(0.000005)

    GPIO.output(12, 0)
    GPIO.setup(12, GPIO.IN)

    while GPIO.input(12)==0:
            starttime=time.time()

    while GPIO.input(12)==1: 
            endtime=time.time()

    duration=endtime-starttime
    distance=duration*34000/2
    print str(x + 1) + ": " + str(distance)

Perhaps change node installation instructions

Stumbled across this today.

https://github.com/gflarity/node_pi

The instructions you have will not work to compile that latest node v0.8.2... there is an extra flag that must be included specifically

export GYP_DEFINES="armv7=0"

Also the above repository has compiled binaries, and instructions to install them. This is nice if you don't want to spend 2 hours compiling or setting up a toolchain to cross compile

Bug in 0.2.7

Hi.
For some reason the bug provided here dde7be9 is available in the 0.2.7 which was released 3 years ago.
Could you enable git tags for while updating the version?

ENOENT

trying to

gpio.export(4)

and 've got:

ENOENT read /sys/class/gpio/gpio4/value

ADC reads

Hello,
I'm trying to translate the adafruit tutorial python code about adc to node.js relying on your lib. (http://learn.adafruit.com/reading-a-analog-in-and-controlling-audio-volume-with-the-raspberry-pi/script this one works ok)

Here is my translation : https://github.com/xseignard/adcPi/blob/master/src/app.js

But it doesn't work (callback'd adcOut is always 0), and I'm kinda stuck!

Maybe you can see some obvious?

Another question is about pin notation in your lib: is it bcm? or board one? bcm right?

Regards,

Xavier

100% CPU utilization

For even the simplest programs using 'gpio', node uses 100% CPU on my Raspberry PI with Raspbian. For example:

var gpio = require('gpio');

var gpio4 = gpio.export( 4, 
                         { direction: "out", 
                           ready: function() { 
                               gpio4.set();
                               console.log( "4 exported" ) } } );

setInterval( function() { console.log("ping"); }, 5000 );

started with

sudo node test.js

results in 100% CPU usage. Am I doing something wrong? How can I debug this?

error getting generated using GPIO

Just tried using your module GPIO

getting a rather strange error

Error: ENOENT, open '/sys/class/gpio/gpio18/direction' error: Error: ENOENT, open '/sys/class/gpio/gpio18/value'

Ive got the GPIO working with python - would it be blocking node from the GPIO

I have node version 0.6.19 running on raspbian installed using nvm

test code is


var gpio = require("gpio");
var gpio18 = gpio.export(18);
setInterval(function() {
   gpio18.set();
   setTimeout(function() { gpio18.reset(); }, 500);
}, 1000);

any ideas :)
M

Maintenance transfer

Let me quote @EnotionZ from:
#39

"I'm happy to make someone else maintainer if anyone's interested."

I could volunteer for this, and suggest a cooperative maintenance model (for updating npm repo),
but I am new to project ( #41 )
so if anyone has more experience on this module let us know your plans here,
then @EnotionZ will decide how and when a new version could be released by new maintainers.

My 2c.

Store/manage all instances of GPIOPin

Since gpio.open acts like a Factory pattern for a discrete number of pins, there's no reason why we shouldn't store the GPIOPin instances internally. The benefit is that gpio.close will get all the benefit of contextually closing from the instance (port.close) like killing the filewatcher or whatever else we may add in the future.

The other benefit is if a user happens to open a port that has already been opened, then we can return the GPIOPin instance immediately without trying to close and reopen.

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.