Skip to content

Commit

Permalink
update version of i2c dependency in package.json, added feature for p…
Browse files Browse the repository at this point in the history
…ullup

resistors on gpio
  • Loading branch information
askanhesse committed Sep 26, 2018
1 parent 24217ed commit 0be64b9
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 61 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ build/Release
# Deployed apps should consider commenting this line out:
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules

# Intellij
.idea/
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ node-mcp23017

Node.js library for the I2C I/O Expander MCP23017 on a Raspberry Pi

It currently only supports reading from and writing to the chip
It currently supports reading, writing and changing the pull-up resistor of the GPIOs.

The module tries to mimic the Arduino-Syntax

Expand Down Expand Up @@ -79,6 +79,7 @@ var mcp = new MCP23017({
for (var i = 0; i < 16; i++) {
mcp.pinMode(i, mcp.OUTPUT);
//mcp.pinMode(i, mcp.INPUT); //if you want them to be inputs
//mcp.pinMode(i, mcp.INPUT_PULLUP); //if you want them to be pullup inputs
}

mcp.digitalWrite(0, mcp.HIGH); //set GPIO A Pin 0 to state HIGH
Expand Down Expand Up @@ -140,7 +141,6 @@ setInterval(blink, 100); //blink all LED's with a delay of 100ms
## TODO
- implement built-in pullup resistors
- implement interrupt handling
## Acknowledgement
Expand Down
7 changes: 3 additions & 4 deletions examples/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"name": "mcp23017-blink-example",
"version": "1.0.0",
"description": "blinks 16 leds",
"main": "blink.js",
"name": "mcp23017-examples",
"version": "1.1.0",
"description": "different examples for showing functionality of library.",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down
38 changes: 38 additions & 0 deletions examples/pull_down.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
var MCP23017 = require('node-mcp23017');

var mcp = new MCP23017({
address: 0x20, //all address pins pulled low
device: '/dev/i2c-1', // Model B
debug: false
});

mcp.pinMode(0, mcp.INPUT_PULLUP);
mcp.pinMode(1, mcp.INPUT_PULLUP);
mcp.pinMode(2, mcp.INPUT_PULLUP);
mcp.pinMode(3, mcp.INPUT_PULLUP);
mcp.pinMode(4, mcp.INPUT_PULLUP);
mcp.pinMode(5, mcp.INPUT_PULLUP);
mcp.pinMode(6, mcp.INPUT_PULLUP);
mcp.pinMode(7, mcp.INPUT_PULLUP);
mcp.pinMode(8, mcp.INPUT_PULLUP);
mcp.pinMode(9, mcp.INPUT_PULLUP);
mcp.pinMode(10, mcp.INPUT_PULLUP);
mcp.pinMode(11, mcp.INPUT_PULLUP);
mcp.pinMode(12, mcp.INPUT_PULLUP);
mcp.pinMode(13, mcp.INPUT_PULLUP);
mcp.pinMode(14, mcp.INPUT_PULLUP);
mcp.pinMode(15, mcp.INPUT); // this one should float from time to time

setInterval(function(){

var test = function(i){
return function(err, value){
if(value == false){
console.log("Pull down on pin " + i, value);
}
}
}

for (var i = 8; i < 16; i++) {
mcp.digitalRead(i, test(i));
}
139 changes: 86 additions & 53 deletions lib/mcp23017.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
var DIRECTION_GPIOA = 0x00,
DIRECTION_GPIOB = 0x01,
FROM_GPIOA = 0x12,
FROM_GPIOB = 0x13,
TO_GPIOA = 0x14,
TO_GPIOB = 0x15,
var REGISTER_GPIOA = 0x00,
REGISTER_GPIOB = 0x01,
REGISTER_GPIOA_PULLUP = 0x0C;
REGISTER_GPIOB_PULLUP = 0x0D;
READ_GPIOA_ADDR = 0x12,
READ_GPIOB_ADDR = 0x13,
WRITE_GPIOA_ADDR = 0x14,
WRITE_GPIOB_ADDR = 0x15,
Wire = require('i2c');

var MCP23017 = (function() {
MCP23017.prototype.HIGH = 1;
MCP23017.prototype.LOW = 0;
MCP23017.prototype.INPUT_PULLUP = 2;
MCP23017.prototype.INPUT = 1;
MCP23017.prototype.OUTPUT = 0;

MCP23017.prototype.address = 0x20; //if the mcp has all adress lines pulled low

MCP23017.prototype.oldADir = 0xff; //initial state of GPIO A
MCP23017.prototype.oldBDir = 0xff; //initial state of GPIO A
MCP23017.prototype.dirAState = 0xff; //initial state of GPIO A bank
MCP23017.prototype.dirBState = 0xff; //initial state of GPIO B bank

MCP23017.prototype.oldGpioA = 0x0; //initial state of GPIO A
MCP23017.prototype.oldGpioB = 0x0; //initial state of GPIO B
MCP23017.prototype.dirAPullUpState = 0x0; //initial state of GPIO A pull up resistor state
MCP23017.prototype.dirBPullUpState = 0x0; //initial state of GPIO B pull up resistor state

MCP23017.prototype.gpioAState = 0x0; //initial state of GPIOS A
MCP23017.prototype.gpioBState = 0x0; //initial state of GPIOS B

function MCP23017 (config) {
this.address = config.address;
Expand All @@ -34,8 +40,8 @@ var MCP23017 = (function() {

//inits both registers as an input
MCP23017.prototype.reset = function () {
this.oldBDir = 0xff;
this.oldADir = 0xff;
this.dirBState = 0xff;
this.dirAState = 0xff;
this._initGpioA();
this._initGpioB();
};
Expand All @@ -44,7 +50,7 @@ var MCP23017 = (function() {
sets an pin as an INPUT or OUTPUT
*/
MCP23017.prototype.pinMode = function (pin, dir) {
if (dir !== this.INPUT && dir !== this.OUTPUT) {
if (dir !== this.INPUT && dir !== this.INPUT_PULLUP && dir !== this.OUTPUT) {
console.error('invalid value', dir);
return;
}
Expand All @@ -56,87 +62,114 @@ var MCP23017 = (function() {
}

//delegate to funktion that handles low level stuff
this._setGpioDir(pin >= 8 ? pin - 8 : pin, dir, pin >= 8 ? DIRECTION_GPIOB : DIRECTION_GPIOA);
this._setGpioDir(pin >= 8 ? pin - 8 : pin, dir, pin >= 8 ? REGISTER_GPIOB : REGISTER_GPIOA, pin >= 8 ? REGISTER_GPIOB_PULLUP : REGISTER_GPIOA_PULLUP);
};

/*
internally used to set the direction registers
*/
MCP23017.prototype._setGpioDir = function (pin, dir, register) {
MCP23017.prototype._setGpioDir = function (pin, dir, registerDirection, registerPullUp) {
var pinHexMask = Math.pow(2, pin),
registerValue;
registerDir,
registerPullUpDir;

if (register === DIRECTION_GPIOA) {
registerValue = this.oldADir;
if (registerDirection === REGISTER_GPIOA) {
registerDir = this.dirAState;
if (dir === this.OUTPUT) {
if ((this.oldADir & pinHexMask) === pinHexMask) {
if ((this.dirAState & pinHexMask) === pinHexMask) {
this.log('setting pin \'' + pin + '\' as an OUTPUT');
this.oldADir = this.oldADir ^ pinHexMask;
registerValue = this.oldADir;
this.dirAState = this.dirAState ^ pinHexMask;
registerDir = this.dirAState;
} else {
this.log('pin \'' + pin + '\' already an OUTPUT');
}
} else if (dir === this.INPUT) {
if ((this.oldADir & pinHexMask) !== pinHexMask) {
} else if (dir === this.INPUT || dir === this.INPUT_PULLUP) {
if ((this.dirAState & pinHexMask) !== pinHexMask) {
this.log('setting pin \'' + pin + '\' as an INPUT');
this.oldADir = this.oldADir ^ pinHexMask;
registerValue = this.oldADir;
this.dirAState = this.dirAState ^ pinHexMask;
registerDir = this.dirAState;
} else {
this.log('pin \'' + pin + '\' already an INPUT');
}
if (dir === this.INPUT_PULLUP) {
registerPullUpDir = this.dirAPullUpState;
if ((this.dirAPullUpState & pinHexMask) !== pinHexMask) {
this.log('activate INPUT_PULLUP for pin \'' + pin + '\'');
this.dirAPullUpState = this.dirAPullUpState ^ pinHexMask;
registerPullUpDir = this.dirAPullUpState;
} else {
this.log('pin \'' + pin + '\' already activated INPUT_PULLUP');
}
}
}
} else if (register === DIRECTION_GPIOB) {
registerValue = this.oldBDir;
} else if (registerDirection === REGISTER_GPIOB) {
registerDir = this.dirBState;
if (dir === this.OUTPUT) {
if ((this.oldBDir & pinHexMask) === pinHexMask) {
if ((this.dirBState & pinHexMask) === pinHexMask) {
this.log('setting pin \'' + pin + '\' as an OUTPUT');
this.oldBDir = this.oldBDir ^ pinHexMask;
registerValue = this.oldBDir;
this.dirBState = this.dirBState ^ pinHexMask;
registerDir = this.dirBState;
} else {
this.log('pin \'' + pin + '\' already an OUTPUT');
}
} else if (dir === this.INPUT) {
if ((this.oldBDir & pinHexMask) !== pinHexMask) {
} else if (dir === this.INPUT || dir === this.INPUT_PULLUP) {
if ((this.dirBState & pinHexMask) !== pinHexMask) {
this.log('setting pin \'' + pin + '\' as an INPUT');
this.oldBDir = this.oldBDir ^ pinHexMask;
registerValue = this.oldBDir;
this.dirBState = this.dirBState ^ pinHexMask;
registerDir = this.dirBState;
} else {
this.log('pin \'' + pin + '\' already an INPUT');
}
if (dir === this.INPUT_PULLUP) {
registerPullUpDir = this.dirBPullUpState;
if ((this.dirBPullUpState & pinHexMask) !== pinHexMask) {
this.log('activate INPUT_PULLUP for pin \'' + pin + '\'');
this.dirBPullUpState = this.dirBPullUpState ^ pinHexMask;
registerPullUpDir = this.dirBPullUpState;
} else {
this.log('pin \'' + pin + '\' already activated INPUT_PULLUP');
}
}
}
}
this._send(register, [registerValue]);
this.log('register: ' + register + ', value: ' + registerValue);

this._send(register, [registerDir]);
this.log('pin: ' + pin + ', register: ' + register + ', value: ' + registerDir);

if(registerPullUpDir !== undefined){
this._send(registerPullUp, [registerPullUpDir]);
this.log('pin: ' + pin + ', register: ' + registerPullUp + ', pull up value: ' + registerPullUpDir);
}
};

MCP23017.prototype._setGpioAPinValue = function (pin, value) {
var pinHexMask = Math.pow(2, pin);
if (value === 0) {
if ((this.oldGpioA & pinHexMask) === pinHexMask) {
this.oldGpioA = this.oldGpioA ^ pinHexMask;
this._send(TO_GPIOA, [this.oldGpioA]);
if ((this.gpioAState & pinHexMask) === pinHexMask) {
this.gpioAState = this.gpioAState ^ pinHexMask;
this._send(WRITE_GPIOA_ADDR, [this.gpioAState]);
}
}
if (value === 1) {
if ((this.oldGpioA & pinHexMask) !== pinHexMask) {
this.oldGpioA = this.oldGpioA ^ pinHexMask;
this._send(TO_GPIOA, [this.oldGpioA]);
if ((this.gpioAState & pinHexMask) !== pinHexMask) {
this.gpioAState = this.gpioAState ^ pinHexMask;
this._send(WRITE_GPIOA_ADDR, [this.gpioAState]);
}
}
};

MCP23017.prototype._setGpioBPinValue = function (pin, value) {
var pinHexMask = Math.pow(2, pin);
if (value === 0) {
if ((this.oldGpioB & pinHexMask) === pinHexMask) {
this.oldGpioB = this.oldGpioB ^ pinHexMask;
this._send(TO_GPIOB, [this.oldGpioB]);
if ((this.gpioBState & pinHexMask) === pinHexMask) {
this.gpioBState = this.gpioBState ^ pinHexMask;
this._send(WRITE_GPIOB_ADDR, [this.gpioBState]);
}
}
if (value === 1) {
if ((this.oldGpioB & pinHexMask) !== pinHexMask) {
this.oldGpioB = this.oldGpioB ^ pinHexMask;
this._send(TO_GPIOB, [this.oldGpioB]);
if ((this.gpioBState & pinHexMask) !== pinHexMask) {
this.gpioBState = this.gpioBState ^ pinHexMask;
this._send(WRITE_GPIOB_ADDR, [this.gpioBState]);
}
}
};
Expand Down Expand Up @@ -168,7 +201,7 @@ var MCP23017 = (function() {
};

MCP23017.prototype.digitalRead = function (pin, callback) {
var register = pin >= 8 ? FROM_GPIOB : FROM_GPIOA; //get the register to read from
var register = pin >= 8 ? READ_GPIOB_ADDR : READ_GPIOA_ADDR; //get the register to read from
pin = pin >= 8 ? pin - 8 : pin; //remap the pin to internal value
var pinHexMask = Math.pow(2, pin); //create a hexMask

Expand All @@ -188,13 +221,13 @@ var MCP23017 = (function() {
};

MCP23017.prototype._initGpioA = function () {
this._send(DIRECTION_GPIOA, [this.oldADir]); //Set Direction to Output
this._send(TO_GPIOA, [0x0]); //clear all output states
this._send(REGISTER_GPIOA, [this.dirAState]); //Set Direction to Output
this._send(WRITE_GPIOA_ADDR, [0x0]); //clear all output states
};

MCP23017.prototype._initGpioB = function () {
this._send(DIRECTION_GPIOB, [this.oldBDir]); //Set Direction to Output
this._send(TO_GPIOB, [0x0]); //clear all output states
this._send(REGISTER_GPIOB, [this.dirBState]); //Set Direction to Output
this._send(WRITE_GPIOB_ADDR, [0x0]); //clear all output states
};

MCP23017.prototype._send = function (cmd, values) {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-mcp23017",
"version": "0.0.2",
"version": "0.0.3",
"description": "Library to use the MCP23017 16bit I/O Expander with the Raspberry Pi",
"main": "main.js",
"author": "Kai Henzler",
Expand All @@ -10,6 +10,6 @@
},
"license": "MIT",
"dependencies": {
"i2c": "0.1.4"
"i2c": "0.2.3"
}
}

0 comments on commit 0be64b9

Please sign in to comment.