Get unlimited public & private packages + package-based permissions with npm Pro.Get started »

array-gpio

1.3.9 • Public • Published

array-gpio

This is a low-level ARM peripherals control library for microcontroller development and prototyping using a simple modern API.

One of its key features is the use of array for creating multiple GPIO objects providing an easy, flexible and unique way of controlling GPIO peripherals.

For IoT or machine-to-machine applications, please check m2m using array-gpio.

Supports the following ARM peripherals

  • GPIO
  • PWM
  • I2C (master)
  • SPI

This module uses a C/C++ ARM peripherals control library rpi as addon that maps register access in memory using /dev/mem for PWM, I2C, SPI and /dev/gpiomem for GPIO control.

Compatibility

Note: This module will generally work for all Raspberry Pi 40-pin models.

  • Raspberry Pi Models: B+, 2, 3, Zero & Zero W, Compute Module 3, 3B+, 3A+, 4
  • Node.js Versions: 5.x, 6.x, 7.x, 8.x, 9.x, 10.x

GPIO pin numbering is based on the physical pin numbers P01-P40 from the board header.

Installation

$ npm install array-gpio

A Quick Start Guide

Creating an input/output object

Example 1

circuit setup: One momentary switch button connected to pin 11 and one led connected to pin 33.

// r for raspberry pi
const r = require('array-gpio');
 
// set pin 11 as switch input
let sw = r.Input(11);
 
// set pin 33 as led output
let led = r.Output(33);
 
/* monitor switch sw for rising edge 're' detection
  pressing the sw button will turn ON the led */
 
sw.watch('re', () => led.on());
 
/* monitor switch sw for falling edge 'fe' detection
   releasing the sw button will turn OFF the led */
 
sw.watch('fe', () => led.off());
 

Similarly, you can monitor both rising and falling edge detection

const r = require('array-gpio');
 
/* using .in and .out as shorthand
   for .Input and .Output constructor methods */
 
let sw = r.in(11);
let led = r.out(33);
 
/* monitor sw both for rising edge 're' and falling 'fe' detection
   pressing the sw button will turn ON the led
   releasing the sw button will turn OFF the led */
 
sw.watch('both', () => {
  if(sw.isOn){
    led.on();
  }
  else{
    led.off();
  }
});
 
/* or just drop the 1st argument, same as above */
sw.watch(() => {
  if(sw.isOn){
    led.on();
  }
  else{
    led.off();
  }
});
 

Example 2

circuit setup: Two momentary switch buttons connected to pin 11 and 13 and one led connected to pin 33.

const r = require('array-gpio');
 
let sw1 = r.in(11);
let sw2 = r.in(13);
let led = r.out(33);
 
// pressing switch sw1, led will turn ON and stays ON
sw1.watch('re',() => led.on());
 
// pressing switch sw2, led will turn OFF and stays OFF
sw2.watch('re',() => led.off());

Using a shared callback function to monitor all input pins.

Use the main module .watchInput(callback) method to monitor all your inputs. The method's callback argument will be invoked if one of your input pins changes state to true or ON state condition. To capture which pin state has changed, you can test each input using its getter property state for true condition or use the isOn property that will always evaluate to true condition.

Example 3

// r for raspberry pi
const r = require('array-gpio');
 
let sw1 = r.in(11);
let sw2 = r.in(13);
let led = r.out(33);
 
r.watchInput(() => {
  if(sw1.isOn){
    led.on();
  }
  else if(sw2.isOn){
    led.off();
  }
});

This method makes it easy to monitor multiple inputs. It provides a quick way to see all the action/responses for each input true/ON state condition. We only need to track the true or ON state condition of each input pin.

Creating an input/output array objects

If you are comfortable working with arrays, you can generate an input/output array object as shown below.

Example 1

circuit setup: Two momentary switch buttons connected to pin 11 and 13 and two led's connected to pin 33 and 35.

const r = require('array-gpio');
 
/* By providing more than one pin argument to Input/Output
   constructor method, we create an array object. */
 
let sw  = r.in(11,13);
let led = r.out(33,35);
 
/* By default, the elements of returned array object will be
 * indexed consecutively from 0 to n, where (n + 1) is the
 * total number of elements of the array object.
 *
 * sw[0]  - switch button connected to pin 11
 * sw[1]  - switch button connected to pin 13
 * led[0] - led connected to pin 33
 * led[1] - led connected to pin 35
 */
 
r.watchInput(function(){
  if(sw[0].isOn){
    led[1].off();
    led[0].on();
  }
  else if(sw[1].isOn){
    led[0].off();
    led[1].on();
  }
});

Creating an array object using the pin number as index so we can reference each input/output object by its pin number.

Example 2

const r = require('array-gpio');
 
let sw  = r.in(11,13, {index: 'pin'});
let led = r.out(33,35, {index: 'pin'});
 
/* Both input/output array objects will be indexed by its pin number.
 *
 * sw[11]  - switch button connected to pin 11
 * sw[13]  - switch button connected to pin 13
 * led[33] - led connected to pin 33
 * led[35] - led connected to pin 35
 */
 
r.watchInput(function(){
  if(sw[11].isOn){
    led[35].off();
    led[33].on();
  }
  else if(sw[13].isOn){
    led[33].off();
    led[35].on();
  }
});

Example 3

circuit setup: Two momentary switch buttons connected to pin 11 and 13 and six led's connected to pin 33, 35, 37, 36, 38 and 40.

const r = require('array-gpio');
 
let sw = r.in(11,13,{index:'pin'});
let led = r.out(33,35,37,36,38,40,{index:'pin'});
 
let LedOn = () => {
  // initial ON time delay in ms
  let t = 0;
  for(let x in led){
    t += 50;
    led[x].on(t);
  }
}
 
let LedOff = () => {
  // initial OFF time delay in ms
  let t = 0;
  for(let x in led){
    t += 50;
    led[x].off(t);
  }
}
 
r.watchInput(() => {
  if(sw[11].isOn){
    LedOn();
  }
  else if(sw[13].isOn){
    LedOff();
  }
});
 

API

Input(pin1, pin2, ... , pinN)

or

in(pin1, pin2, ... , pinN)

input object constructor

Sets a GPIO pin or group of GPIO pins as input object.

Choose your pin based on the physical pin numbering (P01-P40) from the board header.

Returns a regular input object for a single pin argument or an array object if more than one pin argument is provided.

Single Input Object

/* creates a single input object */
var sw1 = r.Input(11);
 
/* check sw1 current logical state */
console.log(sw1.state);
 

Input Array Object

/* creates an array input object */
var input = r.Input(11,13,15,19);
 
/* get the current logical state of each element of input array object */
console.log(input[0].state); // current state of pin 11
console.log(input[1].state); //        "         pin 13
console.log(input[2].state); //        "         pin 15
console.log(input[3].state); //        "         pin 19
 
// or iterate over each element of the input array object
 
for(let x in input){
   console.log(input[x].state);
}
 
// or
 
input.forEach(function(e, index){
   console.log(input[index].state);
});
 
 

By default, the elements of returned array object will be indexed consecutively from 0 to n, where (n + 1) is the total number of elements of the array object.

If you want to use the pin number as index, you can use the following option.

var input = r.Input(11,13,15,19, {index: 'pin'});
 
/* get the current logical state of each element of the input array object */
console.log(input[11].state); // current state of pin 11
console.log(input[13].state); //        "         pin 13
console.log(input[15].state); //        "         pin 15
console.log(input[19].state); //        "         pin 19
 
// similarly, you can iterate over each element of the input array object
 
for(let x in input){
   console.log(input[x].state);
}
 
// or
 
input.forEach(function(e, index){
   console.log(input[index].state);
});
 

You can set as many input pins as you can. You are only limited by how many GPIO pins are available on your Raspberry Pi.

Using an object as pin argument

// object as argument to input constructor
var InputPins = {pin: [11, 13, 15]};
 
var input = r.Input(InputPins);
 
// or
 
// using an object argument with pin as index
var input = r.Input({pin:[11,13,15,19], index:'pin'});
 

Force a single argument input object to behave as array object

If you have an input/output function api where the number of pin argument can change dynamically from a single pin to a multiple pin argument, you can set the array property to true. The returned object will be an array even with only a single argument.

// creates an array input object using a single argument
var sw = r.Input({pin:[11], array:true});
 
// sw[0] is valid since sw is an array
console.log(sw[0].state); // true or false
 
// sw is invalid, sw is no longer a regular object
console.log(sw.state); // error
 
// This behavior is the same when using the index property
 
// creates an array object using a single argument with pin as index
var sw = r.Input({pin:[11], array:true, index:'pin'});
 
// get the sw current logical state
console.log(sw[11].state);  // valid

state

input/output property

Reads the current logical condition of any input/output object at any given point in your application during runtime. It is a getter property only.

Returns true if the object is in high or ON state condition.

Otherwise returns false for low or OFF state condition.

Example 1

const r = require('array-gpio');
 
let sensor  = r.in(11);
 
// returns the current state of sensor object
console.log(sensor.state);

Example 2

const r = require('array-gpio');
 
let sw = r.in(11);
let led = r.out(33);
 
sw.watch(function(){
  if(sw.state && led.state === false){
 
  console.log(sw.state); // true
  console.log(led.state); // false
 
  led.on();
 
  console.log(sw.state); // true
  console.log(led.state); // true
  }
});

isOn and isOff

input/output property

Similar to state property but with explicit context.

isOn returns true if the object state is high or true, otherwise it returns false.

isOff returns true if the object state is low or false, otherwise it returns false.

Example

const r = require('array-gpio');
 
let sw1 = r.in(11);
let sw2 = r.in(13);
let led = r.out(33);
 
r.watchInput(() => {
  // turns on led if sw1 is ON and if led is OFF
  if(sw1.isOn && led.isOff){
    return led.on();
  }
  // turns off led if sw2 is ON and if led is ON
  if(sw2.isOn && led.isOn){
    return led.off();
  }
});

watch (edge, callback, [s])

input method

Watches/monitors a particular input object state changes from low condition to high state condition and vice versa.

Input pin state transition from low to high is also called rising edge and falling edge from high to low state transition.

edge

're' or 1 - Enable rising edge (high transition) event detection.

'fe' or 0 - Enable falling edge (low transition) event detection.

'both' - Enable both rising and falling edge event detection.

or

By not providing an edge argument, both rising and falling edge detection will be enabled.

The callback parameter will be executed asynchronously when the input object state changes from low to high condition and vice versa.

The callback function can have optional parameters. The 1st parameter is always an error object which follows the node.js convention. The 2nd parameter state is a boolean value. It will return true for rising edge and false for falling edge input state transition. A 3rd parameter pin is also available. It returns the pin number when the input object changes its state condition.

You can use the callback state and pin parameters to customize your input logic for fine-grained control, switch debouncing, specific logical requirements, etc.

s is an optional input object scan rate (ms). If not provided, scan rate will default to 100 ms, minimum is 1 ms. A lower value will make your input more responsive but contact bounce will increase. A higher value will make it less responsive but with a lower contact bounce.

Example1

const r = require('array-gpio');
 
let sw = r.in(11);
 
function pinEvent(){
  console.log('pin event detected');
}
 
// enable rising edge detection
sw.watch('re', pinEvent);
// or
sw.watch(1, pinEvent);
 
// Enable falling edge detection
sw.watch('fe', pinEvent);
// or
sw.watch(0, pinEvent);
 
// edge argument is not provided,
// both rising and falling edge detection will be enabled
sw.watch(pinEvent);
 
// using a scan rate of 10 ms
sw.watch(pinEvent, 10);

Example 2

const r = require('array-gpio');
 
let sw1 = r.in(11);
let led = r.out(33);
 
// pressing sw1 button will turn ON the led
// the callback state argument will be true
// for rising edge condition
sw1.watch( 're', (err, state) => {
  if(err) return console.log('sw1 err', err);
  led.write(state);
});

unwatch()

input method

Stops monitoring a particular input pin. It will stop executing the callback function for input object state changes.

read([callback])

input/output method

The conventional way of getting the current logical state condition of an input/output object.

Returns 1 if the object state condition is in high state and 0 for low state condition.

The optional callback parameter will be executed asynchronously after the object state condition is returned.

Example

/* r for raspberry */
const r = require('array-gpio');
 
let sw = r.input(11);
let solenoid = r.output(35);
 
let status = sw.read(() => {
  if(status === 1)
    solenoid.on();
  else
    solenoid.off();  
});

watchInput(callback, [s])

main module method

Watches/monitors all input objects for rising and falling edge state transitions.

The callback parameter is shared by all input objects. It will be executed asynchronously when any of the input objects' pin state changes from low to high condition and vice versa.

The callback function can have optional parameters. The 1st parameter is always an error object which follows the node.js convention. The 2nd parameter state is a boolean value. It will return true for rising edge and false for falling edge input state transition. A 3rd pin parameter is also available. It will show the pin number of the input object triggering the state change.

You can use the callback state and pin parameters to customize your input logic for fine-grained control, switch debouncing, specific logical requirements, etc.

s is an optional input object scan rate (ms). If not provided, scan rate will default to 100 ms, minimum is 1 ms. A lower value will make your input more responsive but contact bounce will increase. A higher value will make it less responsive but with a lower contact bounce.

To capture events from a particular pin, you can use the input object's state or isOn property.

This method provides a quick way to see all the action/responses for each input object state changes. In most cases, we just need to provide an action or response when the state changes from low to high condition.

Example 1

const r = require('array-gpio');
 
let sw = r.in(11, 13, 15, {index:'pin'});
let led = r.out(33, 35, {index:'pin'});
 
r.watchInput(() => {
  // if sw[11] is ON, led[33] will turn ON
  if(sw[11].isOn){
    led[33].on();
  }
  // if sw[13] is ON, led[35] will turn ON
  else if(sw[13].isOn){
    led[35].on();
  }
  // if sw[15] is ON, both led[33] and led[35] will turn OFF
  else if(sw[15].isOn){
    led[33].off();
    led[35].off();
  }
});

Example 2

const r = require('array-gpio');
 
let sw1 = r.in(11);
 
let led1 = r.out(33);
let led2 = r.out(35);
 
// Using a scan rate of 200 ms and
// a callback with 2 arguments
 
// When you press (rising edge) the sw1 or sw2 buttons, the state value is true
// releasing (falling edge) sw1 or sw2, the state value is false
 
r.watchInput((err, state) => {
  if(err) throw err;
  if(sw1.isOn && state){
    led1.on();
    led2.off();
  }
  else if(sw1.isOff && !state){
    led2.on();
    led1.off();
  }
}, 200);

unwatchInput()

main module method

Stops all input objects pin monitoring for rising and falling edge input state changes.
It will stop executing the shared callback function for any input state changes.

Example

const r = require('array-gpio');
 
let sw1 = r.in(11);
let sw2 = r.in(13);
let sw3 = r.in(15);
 
let led1 = r.out(33);
let led2 = r.out(35);
 
r.watchInput(() => {
  if(sw1.state){
    return led1.on();
  }
  if(sw2.state){
    return led2.on();
  }
  if(sw3.state){
    led1.off();
    led2.off();
  }
});
 
// stops all input pin monitoring after 15 secs
setTimeout(() => r.unwatchInput(), 15000);

Output(pin1, pin2, pin3 ... pinN)

or

out(pin1, pin2, pin3 ... pinN)

output object constructor

Sets a GPIO pin or group of GPIO pins as output object.

Choose your pin based on the physical pin numbering (P01-P40) from the board header.

Returns an output object using a single pin argument or an array object using more than one pin argument.

Single Output Object

/* creates a single output object */
var led = r.Output(11);
 
/* turn ON a single led output */
led.on();
 

Output Array Object

/* creates an array output object */
var output = r.Output(11,13,15,19);
 
/* Turn ON each element of the output array object */
output[0].on();
output[1].on();
output[2].on();
output[3].on();
 
// Iterate over the output array object
 
for(let x in output){
   output[x].on();
}
 
// or
 
output.forEach(function(e, index){
   output[index].on();
});
 
 

Similar to Input(), the elements of returned array object will be indexed consecutively from 0 to n, where (n + 1) is the total number of elements of the array object.

If you want to use the pin number as index, use the following option.

var output = r.Output(33,35,36,37, {index: 'pin'});
 
/* Turn ON each element of the output array object */
output[33].on();
output[35].on();
output[36].on();
output[37].on();
 
// Iterate over the output array object
 
for(let x in output){
   output[x].on();
}
 
// or
 
output.forEach(function(e, index){
   output[index].on();
});
 

Similar to Input(), you can set as many output pins as you can.

Using object as pin argument

const r = require ('array-gpio');
 
// object as argument to input constructor
var OutputPins = {pin:[33,35,37,36,38,40]};
 
var output = r.Output(OutputPins);
 
or
 
// using an object argument with pin as index
var output = r.Output({pin:[33,35,37,36,38,40], index:'pin'});
 

Force a single argument output object to behave as array object

If you have an input/output function api where the number of pin argument can change dynamically from a single pin to a multiple pin argument, you can set the array property to true. The returned object will be an array even with only a single argument.

// creates an array output object using a single argument
var actuator = r.Output({pin:[33], array:true});
 
// actuator[0] is valid since actuator is an array object
console.log(actuator[0].state); // true or false
 
// invalid, actuator is no longer a regular object
console.log(actuator.state); // error
 
// or
 
// creates an array object using a single argument with pin as index
var actuator = r.Output({pin:[33], array:true, index:'pin'});
 
// actuator[0] is valid since actuator is an array object
console.log(actuator[33].state);  // true or false
 
// invalid, actuator is no longer a regular object
console.log(actuator.state); // error

on([t]) and off([t])

output method

Turns ON and OFF an output object instantly.

It has an optional built-in time delay using setTimeout() executed in the the background for convenience.

t is an optional time delay in milliseconds. Output object will turn ON or OFF after the expiration of time delay.

Example

const r = require('array-gpio');
 
let sw = r.Input(11,13);
let actuator = r.Output(33,35);
 
r.watchInput(() => {
  if(sw[0].isOn && actuator[0].isOff){
    actuator[0].on(200); // turns ON after 200 ms delay
    actuator[1].on();    // turns ON immediately
  }
  else if(sw[1].isOn && actuator[1].isOn){
    actuator[0].off(50); // turns OFF after 50 ms delay
    actuator[1].off();   // turns OFF immediately
  }
});

write(bit [,callback])

output method

This is the conventional way of turning ON and OFF an output object.

bit - control bit number.

1 or true - ON or high state

0 or false - OFF or low state

The optional callback parameter function will be executed asynchronously during the ON/OFF process.

Example

const GPIO = require('array-gpio');
 
const sw = GPIO.input(11,13);
const motor = GPIO.output(33,35);
 
let sw1 = sw[0];
let sw2 = sw[1];
 
let motorA = motor[0];
let motorB = motor[1];
 
GPIO.watchInput((err, state) => {
  if(sw1.read()){
    motorA.write(state, () => motorB.write(!state));
  }
  if(sw2.read()){
    motorB.write(state, () => motorA.write(!state));
  }
});

delayON(t [,callback]) and delayOFF(t [,callback])

or

delayOn(...) and delayOff(...)

output method

Lets you turn ON and OFF an output object with a time delay and an optional callback argument.

t is the required time delay in milliseconds. Output object will turn ON or OFF after the expiration of time delay.

The optional callback argument will be executed asynchronously when time delay expires.

Example

const r = require('array-gpio');
 
const sw = r.in(11,13);
const actuator = r.out(33,35);
 
r.watchInput(() => {
 if(sw[0].state && actuator[0].state === false){
  // actuator[0] will turn ON after 1 sec
  actuator[0].delayON(1000, function(){
    console.log('actuator is ON!');       // prints out after 1 sec
  });
  console.log('turning ON actuator ...'); // prints out immediately
 }
 else if(sw[1].state && actuator[0].state){
  // actuator[0] will turn OFF after 1.5 secs
  actuator[0].delayOFF(1500, function(){
    console.log('actuator is OFF!');       // prints out after 1.5 secs
  });
  console.log('turning OFF actuator ...'); // prints out immediately
 }
});

pulse(pw [,callback])

output method

Generates a single square wave pulse with a duration of pw ms.

pw is the required pulse width or the time duration of the pulse.

The optional callback argument will be executed asynchronously when pw time duration expires.

Example

const r = require('array-gpio');
 
let sw = r.in(11,13);
let actuator = r.out(33,35);
 
r.watchInput(() => {
  // starts a single pulse w/ a duration of 1 sec
  if(sw[0].isOn && actuator[0].isOff){
    actuator[0].pulse(1000);
  }
  // starts a single pulse w/ a duration of 2 secs
  else if(sw[1].isOn && actuator[1].isOff){
    console.log('start of actuator[1] pulse');
    actuator[1].pulse(3000, () => {
      console.log('end of actuator[1] pulse');
    });
  }
});
 

pin

input/output property

Returns the GPIO pin used from your input and output objects.

Example

const r = require('array-gpio');
 
let sw = r.Input(11);
let led = r.Output(33);
 
console.log(sw.pin);  // 11
console.log(led.pin); // 33

close()

input/output method

Closes any input/output object.

Example 1

const r = require('array-gpio');
 
let sw = r.Input(11);
let led = r.Output(33);
 
sw.close();
led.close();

Example 2

const r = require('array-gpio');
 
let input = r.Input(11, 13);
let output = r.Output(33, 35);
 
function appExitProcess(){
  console.log('closing all I/O objects');
  for(let x in input){
    input[x].close();
  }
  for(let x in output){
    output[x].close();
  }
}
 
// using Ctrl-C for app exit
process.on('SIGINT', function (){
  appExitProcess();
  process.exit(0);
});

setR(intR)

input method

Sets or changes input internal resistor using either pull up or pull down.

intR

'pu' or 1 - Enable pull up resistor.

'pd' or 0 - Enable pull down resistor.

If no argument is provided, no internal resistor will be used.

Example

const r = require('array-gpio');
 
let sw = r.Input(11,13,15);
 
// using pull up resistor
sw[0].setR('pu');
// using pull down resistor
sw[1].setR(0);
// no internal resistor
sw[2].setR();

PWM(pin)

PWM object constructor

pin

Use PWM hardware peripherals to generate square-wave pulses for selected physical pin numbers 12, 32, 33 and 35 using its alternate function.

Channel 1 - pins 12 and 32.

Channel 2 - pins 33 and 35.

You can only control 2 peripherals independently, one from channel 1 and one from channel 2. If both peripherals are from the same channel, you can control both channels using only the control values (setRange and setData) from one of the peripherals.

Check the available pins based on your Raspberry pi models.

Requires root access to run your application.

setClockFreq(div)

div The divisor value to calculate the desired clock frequency from a fixed oscillator of 19.2 MHz.

(0 to 4095)

freq = 19200000/div

setRange(range)

Sets the period T of the pulse.

setData(data)

Sets the pw (pulse width) of the pulse.

stop()

Stop the pulse generation of the system 19.2 MHz clock oscillator.

You can restart the pulse generation anytime using the pulse() or setData() function.

close()

Stop and disable PWM. Returns back the pin used for GPIO use.

Example 1

/* Connect an led to pin 12. */
 
/* r for raspberry pi */
const r = require('array-gpio');
 
/* start PWM using pin 12 */
var pwm = r.PWM(12);
 
/* set clock frequency using a div value of 1920 */
pwm.setClockFreq(1920); // sets clock freq to 10kHz or 0.1 ms time resolution for T and pw
 
/* set period (T) of the pulse */
pwm.setRange(1000); // 1000 x 0.1 ms = 100 ms (actual period T)
 
/*
 * set pw (pulse width) of the pulse and start the pulse generation for 2 seconds
 *
 * The led attached to pin 12 should blink for 2 seconds
 */
pwm.setData(100); // 100 x 0.1 ms = 10 ms (actual pw)
 
/* stop PWM and return pin 12 to GPIO input mode */
setTimeout(function(){
 
  pwm.stop();
  pwm.close();
 
}, 2000);
 
 

PWM(pin, freq, T, pw)

PWM object constructor

A quick way to start PWM with predefined clock frequencies.

pin

Choose from channel 1 pins (12, 32) or channel 2 pins (33, 35).

freq (kHz)

Choose from 3 predefined clock oscillator frequency that will provide different time resolutions for your T (period) and pw (pulse width).

10 kHz -> 0.1 ms

100 kHz -> 0.01 ms

1000 kHz -> 0.001 ms or 1 uS (microsecond)

T (ms) is the initial cycle period T of the pulse.

pw (ms) is the initial pulse width of the pulse.

The ratio of pw over T is the pulse duty cycle (pw/T) x 100%.

pulse([pw])

Start the pulse generation or create a new pulse using the pw argument provided. If pw is not provided, it will use the initial pw from the PWM constructor and start the pulse generation.

pw (ms) is the pulse width that will be used to generate a new pulse.

You can change the period T using setRange() and pw using setData() or pulse() function at anytime in your application. However, T is usually fixed while changes in pw controls the behaviour of your motor device.

Example 2

/* Using a generic micro servo motor (~4.8 to 6.0 V)
 *
 * T period = 20 ms
 *
 * pw (pulse width) needed for various servo positions
 *
 * pw = 1.0 ms - pos 1, home position
 * pw = 1.5 ms - pos 2, rotates 40  degrees cw (clockwise) from pos 1
 * pw = 2.0 ms - pos 3, rotates 80  degress cw from pos 1
 * pw = 2.5 ms - pos 4, rotates 120 degress cw from pos 1
 *
 */
 
const r = require('array-gpio');
 
var pin  = 33;    /* channel 2, alt-function 0 */
var freq = 10;    /* 10 kHz provides 0.1 ms time resolution */
var T    = 200;   /* 200 x 0.1 ms = 20 ms */
var pw   = 10;    /* 10  x 0.1 ms = 1.0 ms, home position */
 
/* start PWM and initialize with above details */
var pwm = r.PWM(pin, freq, T, pw);
 
/* create four push buttons sw[0], sw[1], sw[2] and sw[4] */
const sw = r.Input(11,13,15,19);
 
r.watchInput(() => {
  /* Press sw[0] button to rotate the servo motor to pos 1 or home position */
  if(sw[0].isOn){
    pwm.pulse(10);    // 1.0 ms pw
  }
  /* Press sw[1] button to rotate to pos 2 */
  else if(sw[1].isOn){
    pwm.pulse(15);    // 1.5 ms pw
  }
  /* Press sw[2] button to rotate to pos 3 */
  else if(sw[2].isOn){
    pwm.pulse(20);    // 2.0 ms pw
  }
  /* Press sw[3] button to rotate to pos 4 */
  else if(sw[3].isOn){
    pwm.pulse(25);    // 2.5 ms pw
  }
});
 
const appExitProcess = () => {
 console.log('closing all sw and pwm objects');
  for(let x in sw){
    sw[x].close();
  }
  pwm.close();
  process.exit(0);
}
 
process.on('SIGINT', () => {
  console.log('\napp terminated using Ctrl-C');
  appExitProcess();
});
 

I2C()

Start I2C operations. Set pins 03 (SDA) and 05 (SCL) to alternate function 0 (ALT0) for I2C single master serial data transfer operations.

Requires root access.

begin()

Enable or restart I2C interface at anytime in your application. However, it is not necessary when using the I2C() constructor.

end()

End I2C operations. I2C pins 03 (SDA) and 05 (SCL) are returned to GPIO input mode.

setTransferSpeed(baud)

Sets the I2C clock frequency by converting the baud argument to the equivalent I2C clock divider value.

setClockFreq(div)

Sets the I2C clock speed based on the div divisor value. Check values below.

div = 2500 => 10us  => 100 kHz
div = 626  => 2.504us  => 399.3610 kHz
div = 150  => 60ns  => 1.666 MHz (default at reset)
div = 148  => 59ns  => 1.689 MHz

selectSlave(addr)

Sets the I2C slave address.

addr The I2C slave address.

write(wbuf, len)

Write a number of bytes to the currently selected I2C slave.

wbuf Buffer of bytes to write/send.

len Number of bytes to write/send.

read(rbuf, len)

Read a number of bytes from the currently selected I2C slave.

rbuf Buffer of bytes to read/receive.

len Number of bytes to read/receive.

Example

/* Using MCP9808 Temperature Sensor */
 
const r = require('array-gpio');
 
var i2c = r.I2C();
 
/* set data transfer speed to 400 kHz */
i2c.setTransferSpeed(400000);
 
/* MCP9808 device address */
let slave = 0x18;
 
/* access MCP9808 device */
i2c.selectSlave(slave);
 
/* setup write and read data buffer */
const wbuf = Buffer.alloc(16); // write buffer
const rbuf = Buffer.alloc(16); // read buffer
 
/* accessing the internal 16-bit manufacturer ID register within MCP9808 */
wbuf[0] = 0x06; // address of manufacturer ID register
i2c.write(wbuf, 1);
 
/*
 * read content of 16-bit manufacturer ID register (should be 0x54 as per datasheet)
 * reads upper byte (rbuf[0]) and lower byte (rbuf[1]), ID value is on the lower byte
 */
i2c.read(rbuf, 2);
 
console.log('MCP9808 ID: ', rbuf[1].toString(16));  // convert ID to hex value
 
/* Based on MCP9808 datasheet, compute the temperature data as follows */
function getTemp(){
 
  /* variable for temperature data */
  let Temp;
 
  let UpperByte = rbuf[0];
  let LowerByte = rbuf[1];
 
  UpperByte = UpperByte & 0x1F; // Clear flag bits
 
  // Temp < 0�C
  if ((UpperByte & 0x10) == 0x10){
    UpperByte = UpperByte & 0x0F; // Clear SIGN
    Temp = 256 - ((UpperByte * 16) + (LowerByte / 16));
 
  // Temp > 0�C
  }else {
    Temp = ((UpperByte * 16) + (LowerByte / 16));
  }
 
  /* Print out temperature data */
  console.log('Temp: ', Temp);
 
}
 
/* get temperature readings every 2 seconds */
setInterval( function(){
 
  /*
   * accessing the internal 16-bit configuration register within MCP9808
   * You can skip accessing this register using default settings
   */
  wbuf[0] = 0x01; // address of configuration register
  /* change content of configuration register */
  wbuf[1] = 0x02; // register upper byte, THYST set with +1.5 C
  wbuf[2] = 0x00; // register lower byte (power up defaults)
  i2c.write(wbuf, 3);
 
  /* accessing the internal 16-bit ambient temp register within MCP9808 */
  wbuf[0] = 0x05; // address of ambient temperature register
  i2c.write(wbuf, 1);
 
  /* read content of ambient temp register */
  i2c.read(rbuf, 2); // reads UpperByte and LowerByte
 
  /* get temperature data and print out the results */
  getTemp();
 
}, 2000);
 
process.on('SIGINT', function (){
  console.log('\napp terminated using Ctrl-C');
  i2c.end();
  process.exit(0);
});
 

SPI()

Switches RPi SPI0 pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (CE0) and 26 (CE1) to alternate function ALT0 for SPI interface use.

Requires root access.

setClockFreq(div)

Sets SPI clock frequency using a divisor value.

Specifies the divisor used to generate the SPI clock frequency. Figures below show the div and clock frequency generated. Clock is based on nominal core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3.

div The SPI divisor to generate the SPI clock frequency.

SPI div  2048  = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3
SPI div  1024  = 244.140625kHz on Rpi2, 390.625kHz on RPI3
SPI div  512   = 488.28125kHz on Rpi2, 781.25kHz on RPI3
SPI div  256   = 976.5625kHz on Rpi2, 1.5625MHz on RPI3
SPI div  128   = 1.953125MHz on Rpi2, 3.125MHz on RPI3 (default)
SPI div  64    = 3.90625MHz on Rpi2, 6.250MHz on RPI3
SPI div  32    = 7.8125MHz on Rpi2, 12.5MHz on RPI3
SPI div  16    = 15.625MHz on Rpi2, 25MHz on RPI3
SPI div  8     = 31.25MHz on Rpi2, 50MHz on RPI3

chipSelect(cs)

cs = 0,  Chip Select 0
cs = 1,  Chip Select 1
cs = 2,  Chip Select 2
cs = 3,  No Chip Select

cs Sets the chip select pin(s). When a data transfer is made, the selected pin(s) will be asserted or held in active state (usually active low) during the transfer.

setCSPolarity(cs, active)

cs The chip select pin you want to change the active state.

active Change the active state of the pin either active low 0 or high 1.

setDataMode(mode)

Sets the SPI data mode. Sets the clock polariy and phase.

mode = 0,  CPOL = 0, CPHA = 0
mode = 1,  CPOL = 0, CPHA = 1
mode = 2,  CPOL = 1, CPHA = 0
mode = 3,  CPOL = 1, CPHA = 1

mode Choose one of SPI mode above.

transfer(wbuf, rbuf, len)

Transfers any number of bytes to and from the currently selected SPI slave. Selected CS pins (as previously set by chipSelect) will be held in active state during the transfer.

The data read from the slave is placed into rbuf (rbuf must be at least len bytes long). Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherals manual.

wbuf Buffer of bytes to write/send.

rbuf Buffer of bytes to read/receive.

len Number of bytes to send/receive.

write(wbuf, len)

Write a number of bytes to the currently selected SPI slave.

Asserts the currently selected CS pins (as previously set by chipSelect) during the transfer.

wbuf Buffer of bytes to write/send to slave.

len Number of bytes to write/send to slave.

read(rbuf, len)

Read a number of bytes from the currently selected SPI slave.

rbuf Buffer of bytes to read/receive from slave.

len Number of bytes to read/receive from slave.

begin()

Enable or restart SPI interface at anytime in your application. However, it is not necessary when using the SPI() constructor.

end()

End SPI operations. SPI0 pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (CE0) and 26 (CE1) are returned to GPIO input mode.

Example

/* Using MCP3008 10-bit A/D Converter Chip */
 
/*
 * VDD and Vref are connected to Raspberry Pi 3.3 V
 * Channel 0 (pin 1) will be used for analog input voltage using single-ended mode
 * Since Vref is set to 3.3 V, max. analog input voltage
 * should not be greater than 3.3 V
 *
 * Read the MCP3008 datasheet on how to configure the chip for more details
 */
 
const r = require('array-gpio');
 
var spi = r.SPI();
 
spi.setDataMode(0);
spi.setClockFreq(128);
spi.setCSPolarity(0, 0);
spi.chipSelect(0);
 
/* setup write and read data buffer */
const wbuf = Buffer.alloc(16); // write buffer
const rbuf = Buffer.alloc(16); // read buffer
 
/* configure the chip to use CH0 in single-ended mode */
wbuf[0] = 0x01; // start bit
wbuf[1] = 0x80; // using channel 0, single ended
wbuf[2] = 0x00; // don't care data byte as per datasheet
spi.write(wbuf, 3); // write 3 bytes to slave
 
/* alternative way to write and read to a slave at the same time */
//spi.transfer(wbuf, rbuf, 3); // 3 bytes will be sent to slave and 3 bytes to read
 
spi.read(rbuf, 3); // read 3 bytes from slave
/* read A/D conversion result */
/* the 1st byte received through rbuf[0] will be discarded as per datasheet */
var data1 = rbuf[1] << 8;  // 2nd byte, using only 2 bits data
var data2 = rbuf[2];    // 3rd byte, 8 bits data
var value = data1 + data2; // combine both data to create a 10-bit digital output code
 
console.log("* A/D digital output code: ", value);
 
/* compute the output voltage */
var vout = (value * 3.3)/1024;
 
console.log("* A/D voltage output: ", vout);
 
spi.end();

Install

npm i array-gpio

DownloadsWeekly Downloads

1

Version

1.3.9

License

MIT

Unpacked Size

179 kB

Total Files

25

Last publish

Collaborators

  • avatar