From 02b291811d95e9fe089684a79352536d56f62d08 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sun, 28 May 2017 00:00:07 -0700 Subject: [PATCH] improved testing, significant start to readme, added sample demo --- {test => demo}/read-write.js | 0 demo/sample.js | 53 +++++++++++++ lib/mcp23008-17.js | 57 ++++++++------ package.json | 21 +++-- readme.md | 116 ++++++++++++++++++++++++++- test/cntrl.js | 148 ----------------------------------- test/mcp.test.js | 144 ++++++++++++++++++---------------- test/read-write.test.js | 86 -------------------- test/relays.js | 44 ----------- test/test-relays.js | 85 -------------------- 10 files changed, 287 insertions(+), 467 deletions(-) rename {test => demo}/read-write.js (100%) create mode 100644 demo/sample.js delete mode 100644 test/cntrl.js delete mode 100644 test/read-write.test.js delete mode 100644 test/relays.js delete mode 100644 test/test-relays.js diff --git a/test/read-write.js b/demo/read-write.js similarity index 100% rename from test/read-write.js rename to demo/read-write.js diff --git a/demo/sample.js b/demo/sample.js new file mode 100644 index 0000000..adcd7ce --- /dev/null +++ b/demo/sample.js @@ -0,0 +1,53 @@ +const Bus = require('@uci/i2c').Bus, + MCP = require('../lib/mcp23008-17'), + // use this require when using your own code + // MCP = require('@uci/mcp') + pause = require('@uci/utils').pPause + +let bus = new Bus() + +let ADDR = 0x24 +let CHIP = 'MCP23017' +let MS = 300 // so humans can watch the light otherwise set to zero +let PORT = 'A' + +let mcp = new MCP[CHIP](bus, ADDR); + +(async function () { + + await mcp.init() + await mcp.allOff(PORT) // start clean + console.log('all pins off') + await pause(MS) + + let pins = [1, 7, 8] + await mcp.on(pins, PORT, 'PLC') + let result = await mcp.readPort(PORT, { format: 'PLC' }) + console.log(`${pins} on = current state: ${result.sort()}`) + await pause(MS) + + pins = [2, 1, 6] + await mcp.toggle(pins, PORT, 'PLC') + result = await mcp.readPort(PORT, { format: 'PLC' }) + console.log(`${pins} toggle = current state: ${result.sort()}`) + await pause(MS) + + pins = [2, 1, 7] + await mcp.off(pins, PORT, 'PLC') + result = await mcp.readPort(PORT, { format: 'PLC' }) + console.log(`${pins} off = current state: ${result.sort()}`) + await pause(MS) + + let pin = 7 + result = await mcp.readPin(pin) ? 'on' : 'off' + console.log(`Pin ${pin} is ${result}`) + + pin = 6 + // result = await mcp.readPin(pin) + result = await mcp.readPin(pin) ? 'on' : 'off' + console.log(`Pin ${pin} is ${result}`) + + console.log('all pins off') + await mcp.allOff(PORT) // clear port after each test + +})() diff --git a/lib/mcp23008-17.js b/lib/mcp23008-17.js index 4317c51..085d94f 100644 --- a/lib/mcp23008-17.js +++ b/lib/mcp23008-17.js @@ -2,12 +2,13 @@ const Device = require('@uci/i2c').Device, portpin = require('./port-pin'), // classes for MCP port and pins - _u = require('@uci/utils') + _ = require('@uci/utils') const Port = portpin.Port, pinConfigs = portpin.configs, // for export so pinConfigs can be accessed at runtime - pause = _u.pPause + pause = _.pPause, + debug = _.debug('mcp:23008-17') class MCP23008 extends Device { constructor(busObj, i2cAddress, opts = {}) { @@ -18,7 +19,7 @@ class MCP23008 extends Device { opts.portID = 'A' opts.pids = opts.pids ? opts.pids : opts.pidsA this.ports.A = new Port(opts) - this.ports.A.state = new _u.Byte(opts.stateA) + this.ports.A.state = new _.Byte(opts.stateA) this.ports.A.interrupt = opts.interruptA ? opts.interruptA : opts.interrupt } // end constructor @@ -44,6 +45,7 @@ class MCP23008 extends Device { // Must call after instantiating. async init() { + debug.L1(`\n=======\nInitializing ${this.id}`) await this.writeChipCfg(this.chip_config) // chip settings await this.writePinsCfg() for (let port in this.ports) { @@ -53,7 +55,7 @@ class MCP23008 extends Device { // must call after init if using interrupts async start() { - // console.log(`starting ${ this.id }`) + debug.L1(`starting ${ this.id }`) for (let port of this.ports) { // if there are interrupts being used then start them and listeners if (this.inter(port)) { @@ -63,7 +65,7 @@ class MCP23008 extends Device { let ihandler = this.inter(port).handler.bind(this) // inside the listener `this` is the interrupt not the chip/bank this.inter(port).on('fired', function () { - console.log(`interrupt from ${this.pin_number}`) + debug.L1(`interrupt from ${this.pin_number}`) ihandler(port) }) } @@ -73,19 +75,19 @@ class MCP23008 extends Device { async interruptReset(port = 'A') { await this.read(portReg(0x08, port)) await pause(100) // give enough time for mcp to reset its interupt - // console.log(`interrupt reset on ${this.id} port ${port}`) + debug.L1(`interrupt reset on ${this.id} port ${port}`) } async writeChipCfg(cfg = 'default') { - // console.log(`writing mcp chip config ${this.id}`) let setting = chip_config[cfg] - let byte = _u.byteFormat(setting.val, { in: setting.fmt, out: 'DEC' }) + let byte = _.byteFormat(setting.val, { in: setting.fmt, out: 'DEC' }) + debug.L1(`writing mcp chip config ${setting.val}`) await this.write(chip_config.cmd, byte) } // pin configurations should already be set before calling async writePinsCfg() { - // console.log(`writing mcp pins config ${this.id}`) + debug.L1(`writing mcp pins config`) for (let port in this.ports) { for (let setting in registers.pin_config) { let reg = registers.pin_config[setting] @@ -93,7 +95,7 @@ class MCP23008 extends Device { let byte = 0 for (let pin of this.ports[port].pins) { byte += pin.address * pin.cfg[setting] - // console.log(`port: ${ port } pin: ${pin.id} setting: ${ setting } reg: ${ reg } byte: ${ byte }`) + debug.L3(`port: ${ port } pin: ${pin.id} setting: ${ setting } reg: ${ reg } byte: ${ byte }`) } await this.write(portReg(reg, port), byte) } @@ -111,19 +113,26 @@ class MCP23008 extends Device { return opts.format ? this.ports[port].state.toFmt(opts.format) : result } + async readPin(pin, port, opts = {}) { + if ('AB'.indexOf(port) === -1) { + opts = port ? port : {} + port = 'A' + } + await this.readPort(port, opts) + return this.ports[port].state.bwOp(Math.pow(2, pin - 1), 'check') + } + async writePort(byte, op, port = 'A') { // byte MUST be a decimal - // console.log(`current\n ${this.ports[port].state.toFmt('PLC') }`) - // console.log(`byte passed ${op}\n ${ _u.byteFormat(byte, { in: 'DEC', out: 'PLC'})}`) + debug.L2(`port:${port}, op:${op}, current pins state\n ${this.ports[port].state.toFmt('PLC') }`) + debug.L2(`byte passed \n [${ _.byteFormat(byte, { in: 'DEC', out: 'PLC'})}]:${byte}`) if (op !== 'force') { byte = this.ports[port].state.bwOp(byte, op) } - // console.log('\nbyte to write decimal \n', byte, op, port) - // console.log(`byte to write\n ${ _u.byteFormat(byte, { in: 'DEC', out: 'PLC' }) }`) + debug.L2(`byte to write\n [${ _.byteFormat(byte, { in: 'DEC', out: 'PLC' })}]:${byte}\n=======`) await this.write(portReg(registers.pin_cmd.gpio, port), byte) - //update the saved state + //update to the saved state this.ports[port].state.value = byte - // console.log('\n\n') } async on(pins, port, format) { @@ -131,7 +140,7 @@ class MCP23008 extends Device { format = port port = 'A' } - if (format) { pins = _u.byteFormat(pins, { in: format, out: 'DEC' }) } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } await this.writePort(pins, 'on', port) } @@ -145,7 +154,7 @@ class MCP23008 extends Device { format = port port = 'A' } - if (format) { pins = _u.byteFormat(pins, { in: format, out: 'DEC' }) } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } await this.writePort(pins, 'off', port) } @@ -159,7 +168,7 @@ class MCP23008 extends Device { format = port port = 'A' } - if (format) { pins = _u.byteFormat(pins, { in: format, out: 'DEC' }) } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } await this.writePort(pins, 'toggle', port) } @@ -173,20 +182,20 @@ class MCP23008 extends Device { format = port port = 'A' } - if (format) { pins = _u.byteFormat(pins, { in: format, out: 'DEC' }) } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } await this.writePort(pins, 'force', port) } } // end 23008 class MCP23017 extends MCP23008 { - constructor(busObj, i2cAddress, opts) { + constructor(busObj, i2cAddress, opts = {}) { super(busObj, i2cAddress, opts) // add a second port opts.portID = 'B' opts.pids = opts.pidsB this.ports.B = new Port(opts) - this.ports.B.state = new _u.Byte(opts.stateB) + this.ports.B.state = new _.Byte(opts.stateB) this.ports.B.interrupt = opts.interruptB ? opts.interruptB : opts.interrupt } @@ -209,8 +218,8 @@ module.exports = { // Local Functions and Settings============================= function portReg(reg, port) { - // TODO what to return for port B will depend on chip configuration - // if not letter assume index 0,1. + // TODO check chip configuartion to know what to add for port B. CUrrenly assume IOCON=1 + // index 0,1 ==== 'A','B' if ((port === 'B') || (port === 1)) { return reg += 0x10 } else { return reg } } diff --git a/package.json b/package.json index 3ad2ff0..577b216 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,16 @@ { "name": "@uci/mcp", "main": "index.js", - "version": "0.0.1", - "description": "classes and functions for use the MCP chips", + "version": "0.1.0", + "description": "Classes and Helper Functions for using the MCP chip on I2C Bus", "scripts": { - "testw": "./node_modules/.bin/mocha --reporter list --recursive --watch", - "test": "istanbul cover ./node_modules/.bin/_mocha test/ --report lcovonly -- -R spec --recursive && codecov || true", - "rw": "./node_modules/.bin/mocha --reporter list --watch --timeout 30000 test/read-write.test" + "test": "./node_modules/.bin/mocha --reporter list --timeout 30000", + "testw": "./node_modules/.bin/mocha --reporter list -- watch --timeout 30000", + "testd": "DEBUG='1:*' ./node_modules/.bin/mocha --reporter list --watch --timeout 30000", + "testd2": "DEBUG='1:*,2:*' ./node_modules/.bin/mocha --reporter list --watch --timeout 30000", + "testd3": "DEBUG='1:*,2:*,3:*' ./node_modules/.bin/mocha --reporter list --watch --timeout 30000", + "testibc": "istanbul cover ./node_modules/.bin/_mocha test/ --report lcovonly -- -R spec --recursive && codecov || true", + "sample": "node demo/sample.js" }, "author": "David Kebler", "license": "MIT", @@ -24,13 +28,14 @@ }, "homepage": "https://github.com/uCOMmandIt/uci-mcp#readme", "dependencies": { - "@uci/utils": "0.0.1", - "p-series": "^1.0.0" + "@uci/i2c": "0.0.1", + "@uci/utils": "0.0.1" }, "devDependencies": { "chai": "^3.5.0", "codecov": "^1.0.1", + "debug": "^2.6.8", "istanbul": "^0.4.5", - "mocha": "^3.x" + "mocha": "^3.4.2" } } diff --git a/readme.md b/readme.md index 3d39f2e..1bf72b3 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# uCOMmandIt MCP - Micro Chip Library +# uCOMmandIt MCP - An I2C Micro Chip NodeJS Class Library [![Build Status](https://img.shields.io/travis/uCOMmandIt/uci-mcp.svg?branch=master)](https://travis-ci.org/uCOMmandIt/uci-mcp) [![Inline docs](http://inch-ci.org/github/uCOMmandIt/uci-mcp.svg?branch=master)](http://inch-ci.org/github/uCOMmandIt/uci-mcp) @@ -6,7 +6,115 @@ [![devDependencies](https://img.shields.io/david/dev/uCOMmandIt/uci-mcp.svg)](https://david-dm.org/uCOMmandIt/uci-mcp?type=dev) [![codecov](https://img.shields.io/codecov/c/github/uCOMmandIt/uci-mcp/master.svg)](https://codecov.io/gh/uCOMmandIt/uci-mcp) -**Classes and Library to Support Microchip corporation chips** +## What is it -http://www.microchip.com/wwwproducts/en/mcp23017 -http://www.microchip.com/wwwproducts/en/mcp23008 +This module contains ES6 Classes for the Micro Chip (MCP) I2C GPIO (general purpose input output) expander chips. The chips contain 8 GPIO pins organized in ports. The MCP23008 has a single port and the MCP23017 has two ports (A,B). Each port has a single interrupt pin which can be used to determine when any pin of a port has changed state. With this module after creating an instance of a chip class you'll be able to easily read and write to the chip's pins with simple methods such as `.read()`,`.on()`',`.off()`, and `.toggle()` + +## What's it good for + +Lots of I2C devices make use of these chips. In particular many of [Control Everything](https://learn.controleverything.com/)'s boards use these chips including their relay boards and their general purpose DIO boards. To control and read them (and any other board using these chips) using nodejs all you need is this module! + +## Prerequisites + +1. You'll need a computer with an I2C interface which is typically a set of reserved GPIO pins found on most ARM based single board computer (SBC) like the Raspberry Pi. You'll probably want a pin header shield (e.g. [Control Everything's RPi shield](https://shop.controleverything.com/search?q=i2c+shield)) to make connecting your IC2 MCP device to your SBC easy. + +2. You'll need to have an I2C bus interface library with NodeJS bindings and it will need to compile on your specific SBC. One such library, [Fivdi's I2C-Bus](https://github.com/fivdi/i2c-bus), already exists for the Raspberry Pi and will likely compile on many other ARM7 SBCs (e.g. BeagleBone Black). This module makes use the Fivdi I2C library via the [UCI-I2C](git+https://github.com/uCOMmandIt/i2c.git) module. It is possible that other I2C libraries with a nodeJS binding could be used but for now the Fivdi library is the only one. + +## Getting Started + +1. Prepare an SBC (e.g. Raspberry Pi) with an appropriate OS (e.g. Raspbian). + +2. Connect your MCP based I2C device and check that the SBC can talk to it using`i2cdetect` which is part of the `i2ctools` linux package. Assuming your I2c linux device is number 1 that would be + + `sudo i2cdetect -y 1` + +3. Install the latest nodeJS. NOTE! You MUST be using at **least node 7.6** for this module to work so just load and maintain the latest version for the best result. [Node source](https://github.com/nodesource/distributions) has the easiest way to do that. + + ``` + Using Ubuntu + curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - + sudo apt-get install -y nodejs + + Using Debian, as root + curl -sL https://deb.nodesource.com/setup_7.x | bash - + apt-get install -y nodejs + ``` + +4. Start an npm project and install the uci mpc module + + ` npm init` + `npm install @uci/mcp` + +5. Now simply run the `sample.js` code in the `demo/` directory by typing + + `npm run sample` + +if all went well the device should have been written to and read back and you can confirm the writes and reads were correct by looking at the console output. A more robust way to see that you've succeeded in talking to the mcp chip is the run the test suite + +`npm run test` + +## Using the module + + + and here is the code + +``` +const Bus = require('@uci/i2c').Bus, + MCP = require('../lib/mcp23008-17'), + // use this require when using your own code + // MCP = require('@uci/mcp') + pause = require('@uci/utils').pPause + +let bus = new Bus() + +let ADDR = 0x24 +let CHIP = 'MCP23017' +let MS = 500 // so humans can watch the light otherwise set to zero +let PORT = 'A' + +let mcp = new MCP[CHIP](bus, ADDR); + +(async function () { + + await mcp.init() + await mcp.allOff(PORT) // start clean + console.log('all pins off') + await pause(MS) + + let pins = [1, 7, 8] + await mcp.on(pins, PORT, 'PLC') + let result = await mcp.readPort(PORT, { format: 'PLC' }) + console.log(`${pins} on = current state: ${result.sort()}`) + await pause(MS) + + pins = [2, 1, 6] + await mcp.toggle(pins, PORT, 'PLC') + result = await mcp.readPort(PORT, { format: 'PLC' }) + console.log(`${pins} toggle = current state: ${result.sort()}`) + await pause(MS) + + pins = [2, 1, 7] + await mcp.off(pins, PORT, 'PLC') + result = await mcp.readPort(PORT, { format: 'PLC' }) + console.log(`${pins} off = current state: ${result.sort()}`) + await pause(MS) + + console.log('all pins off') + await mcp.allOff(PORT) // clear port after each test + +})() + + +``` + + + + + + + + + + +* [MCP23017 PDF Doc](http://www.microchip.com/wwwproducts/en/mcp23017) +* [MCP23008 PDF Doc](http://www.microchip.com/wwwproducts/en/mcp23008) diff --git a/test/cntrl.js b/test/cntrl.js deleted file mode 100644 index ffd5ca7..0000000 --- a/test/cntrl.js +++ /dev/null @@ -1,148 +0,0 @@ -const Bus = require('@uci/i2c').Bus, - MCP = require('@uci/mcp'), - Interrupt = require('@uci/interrupt').Interrupt, - _ = require('@uci/utils'), - pause = _.pPause, - aseq = _.aSeq - -let bus = new Bus() - -// let itrProcess = function (port) { -// return this.read(portReg(0x07, port)).then(resp => { -// console.log(`port ${port} resp ${resp}`) -// let sw = this.pid(resp, port) -// console.log('switch fired', sw) -// this.pinRead(sw, { cmd: 'intcap' }).then((state) => { -// console.log('switch state at interrupt', state) -// return Promise.all([ -// updateRelays(sw, state), -// this.read(portReg(0x07, port)).then(_.pDelay(100)).then(() => { return this.inter(port).reset() }) -// ]) -// }) -// }) -// } - -let itrProcess1 = function (port) { - console.log(`handler1 fired for ${this.id} on port ${port}`) - this.interruptReset(port) - return Promise.resolve("handler fired promise returned") -} - -let itrProcess2 = function (port) { - console.log(`handler2 fired for ${this.id} on port ${port}`) - this.interruptReset(port) - return Promise.resolve("handler fired promise returned") -} - -let LOAD_BANKS = [ - { id: 'lb1', address: 0x24, desc: 'left cabinet lower bank' }, - { id: 'lb3', address: 0x25, desc: 'left cabinet upper bank' }, - { id: 'lb2', address: 0x26, desc: 'right cabinet lower bank' }, - { id: 'lb4', address: 0x27, desc: 'right cabinet upper bank' } -] - -let loadBanks = LOAD_BANKS.map((bank) => { - return new MCP.MCP23017(bus, bank.address, { - pin_cfg_default: 'output', - id: bank.id, - desc: bank.desc ? bank.desc : "" - }) -}) - -// loadBanks.forEach(bank => console.log(bank.id, bank.desc)) - -let SWITCH_BANKS = [ - { id: 'sb4', address: 0x23, desc: 'bottom left', interruptA: 19, interruptB: 26 }, // red, orange - { id: 'sb1', address: 0x20, desc: 'upper right', interruptA: 12, interruptB: 16 }, // purple, blue - { id: 'sb2', address: 0x21, desc: 'upper left', interruptA: 20, interruptB: 21 }, // yellow, orange - { id: 'sb3', address: 0x22, desc: 'bottom right', interruptA: 6, interruptB: 13 } //black, brown - -] - -let switchBanks = SWITCH_BANKS.map((bank) => { - return new MCP.MCP23017(bus, bank.address, { - pin_cfg_default: 'toggle_switch', - id: bank.id, - desc: bank.desc ? bank.desc : "", - interrupt: bank.interrupt ? new Interrupt(bank.interrupt, bank) : null, - interruptA: bank.interruptA ? new Interrupt(bank.interruptA, itrProcess1) : null, - interruptB: bank.interruptB ? new Interrupt(bank.interruptB, itrProcess2) : null, - pidsA: ['sw1', 'sw2', 'sw3', 'sw4', 'sw5', 'sw6', 'sw7', 'sw8'], - pidsB: ['sw9', 'sw10', 'sw11', 'sw12', 'sw13', 'sw14', 'sw15', 'sw16'] - // chip_config: 'oneint' - }) -}) - -// switchBanks.forEach(bank => console.log(bank.id, bank.desc, bank.inter('A').pin, bank.inter('B').pin)) - -async function init(bank) { - await bank.init() - console.log(`${bank.id} ${bank.desc} is initialized`) - // if (bank.id.charAt(0) === 's') { - // console.log(`bank ${bank.id} pi interrupt set for port A: on rpi pin ${bank.inter('A').pin_number}, for port B on rpi pin ${bank.inter('A').pin_number}`) - // console.log(`rpi pin mode port A ${bank.inter('A').sbc_interrupt.getMode()}`) - // } -} - -async function start(bank) { - await bank.start() -} - -async function go() { - await aseq(loadBanks.concat(switchBanks), init) - await aseq(loadBanks.concat(switchBanks), start) -} - -go().catch(err => console.log(err)) - -// init relay board -// bus.qAdd(relays.init() -// // .then((resp) => { console.log('relays back from init', resp) }) -// .catch((err) => console.log('====error====\n', err)) -// ) - -// init switch board -// bus.qAdd(sw1_16.init() -// .then((resp) => { -// console.log('switch initilized finished\n', resp) -// return sw1_16.start() -// // .then(resp => console.log(resp)) -// }) -// // .then(console.log(sw1_16.inter().fire())) -// .catch((err) => console.log('====error switch ====\n', err)) -// ) - -// -// let test = async(function () { -// return await (delay()) -// }) -// -// console.log(test()) - -// function temp() { return Promise.resolve('test') } - -// let resp = await relays.init() -// console.log("relays ready", resp ) -// console.log( await delay(5000) ) - -// sw1_16.inter('A').on('fired', (hook) => { -// console.log('interrupt fired', hook) -// process.bind(sw1_16)('A') -// .catch(err => console.log("error:", err)) -// }) -// -// sw1_16.inter('B').on('fired', (hook) => { -// console.log('interrupt fired', hook) -// process.bind(sw1_16)('B') -// .catch(err => console.log("error:", err)) -// }) - -// function updateRelays(sid, state) { -// console.log(`sw ${sid} state ${state}`) -// return bus.qAdd(relays.write(0x09, 0x03 * state)) -// // return _.pDelay(100).then((resp) => { console.log('relays updated') }) -// } -// -// function portReg(reg, port) { -// if (port === 'B') { return reg += 0x10 } else { return reg } -// } diff --git a/test/mcp.test.js b/test/mcp.test.js index 81de301..8f0c038 100644 --- a/test/mcp.test.js +++ b/test/mcp.test.js @@ -1,80 +1,88 @@ -'use strict' +//to run this test you MUST install @uci/i2c which is not a dependency of @uci/mcp +// npm install @uci/i2c +const Bus = require('@uci/i2c').Bus, + MCP = require('../lib/mcp23008-17'), + expect = require('chai').expect, + pause = require('@uci/utils').pPause -const expect = require('chai').expect, - _u = require('@uci/utils'), - MCP = require('../lib/mcp23008-17') +let bus = new Bus() -const bus = {} +let ADDR = 0x24 +let CHIP = 'MCP23017' +let MS = 300 // so humans can watch the lights on boards with leds otherwise set to zero +let PORT = 'A' -const config_sets = { - output: { - dir: 0, // 0 output,1 input - ivrt: 0, - pullup: 0, - intr: 0, // if intr = 0 usedef,deval not used - usedef: 0, // if usedef = 0 defval not used - defval: 0 - }, - toggle_switch: { - dir: 1, // 0 output,1 input - ivrt: 1, // for reading let 1 be zero and vice versa - pullup: 1, - intr: 1, // if intr = 0 usedef,deval not used - usedef: 0, // if usedef = 0 defval not used - defval: 0 - }, - momentary_switch: { - dir: 1, // 0 output,1 input - ivrt: 1, // for reading let 1 be zero and vice versa - pullup: 1, - intr: 1, // if intr = 0 usedef,deval not used - usedef: 1, // if usedef = 0 defval not used - defval: 1 - } -} +let id = `${CHIP} at I2C bus address of 0x${ADDR.toString(16)}` -// console.log(bus1) -// bus1.scan((devs)=>{console.log('devices: ', devs)}) -//bus1.scan().then(results=>console.log(results)) +let mcp = new MCP[CHIP](bus, ADDR, { + pin_cfg_default: 'output', + id: id +}); -describe('I2C Device Classes - ', function () { +describe('set up MCP Chip', () => { - let mcp17 = new MCP.MCP23017(bus, 0x20, { - pin_cfg_default: 'momentary_switch', - name: 'switches 1-16' - }) - - describe('MCP23017 Class - ', function () { - - it('can set and get a single pin config on both ports', function () { - expect(mcp17.pin(1).cfg, 'pin configs getter failed').to.deep.equal(config_sets.momentary_switch) - expect(mcp17.pin(8).cfg.dir, 'pin config getter failed').to.equal(1) - mcp17.pin(8).cfg.dir = 0 - expect(mcp17.pin(8).cfg.dir, 'pin address setter failed').to.equal(0) - expect(mcp17.pin(8, 'B').cfg.dir, 'pin address getter port B failed').to.equal(1) - mcp17.pin(8, 'B').cfg.dir = 0 - expect(mcp17.pin(8, 'B').config.dir, 'pin address setter failed').to.equal(0) - }) + before(async() => { + await mcp.init() }) - let mcp8 = new MCP.MCP23008(bus, 0x21, { - pin_cfg_default: 'toggle_switch', - name: 'test 1-8' - }) - - describe('MCP23008 Class - ', function () { - - it('can set and get a single pin config', function () { - expect(mcp8.pin(1).cfg, 'pin configs getter failed').to.deep.equal(config_sets.toggle_switch) - expect(mcp8.pin(8).cfg.dir, 'pin address getter failed').to.equal(1) - expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1) - expect(mcp8.pin(8).cfg.usedef, 'pin address getter failed').to.equal(0) - mcp8.pin(8).cfg.dir = 0 - expect(mcp8.pin(8).cfg.dir, 'pin address setter failed').to.equal(0) - expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1) - }) - + beforeEach(async() => { + await mcp.allOff(PORT) // start clean }) }) + +describe( + `Testing Chip ${id}, port: ${PORT}`, + function () { + eachpin() + somepins() + }) + +//****************** TESTS ********************** +function eachpin() { + it('==> test each pin', async function () { + + for (let pin of mcp.ports[PORT].pins) { + await mcp.on(pin.address, PORT) + let result = await mcp.readPort(PORT) + expect(result, `pin ${pin.id} at address ${pin.address} write/read failed`).to.equal(pin.address) + await mcp.off(pin.address, PORT) + await pause(MS) + } + }) +} + +function somepins() { + it('==> on, off toggle some pins', async function () { + + let pins = [1, 7, 8] + await mcp.on(pins, PORT, 'PLC') + let shouldbe = [1, 7, 8] + let result = await mcp.readPort(PORT, { format: 'PLC' }) + expect(result.sort(), 'pin write/read failed on').to.deep.equal(shouldbe.sort()) + await pause(MS) + + pins = [2, 1, 7] + await mcp.on(pins, PORT, 'PLC') + shouldbe = [2, 1, 7, 8] + result = await mcp.readPort(PORT, { format: 'PLC' }) + expect(result.sort(), 'pin write/read failed on 2').to.deep.equal(shouldbe.sort()) + await pause(MS) + + pins = [2, 1, 6] + await mcp.toggle(pins, PORT, 'PLC') + shouldbe = [6, 7, 8] + result = await mcp.readPort(PORT, { format: 'PLC' }) + expect(result.sort(), 'pin write/read failed toggle').to.deep.equal(shouldbe.sort()) + await pause(MS) + + pins = [2, 1, 6, 7] + await mcp.off(pins, PORT, 'PLC') + shouldbe = [8] + result = await mcp.readPort(PORT, { format: 'PLC' }) + expect(result.sort(), 'pin write/read failed off').to.deep.equal(shouldbe.sort()) + await pause(MS) + + }) +} diff --git a/test/read-write.test.js b/test/read-write.test.js deleted file mode 100644 index 63a53fd..0000000 --- a/test/read-write.test.js +++ /dev/null @@ -1,86 +0,0 @@ -//to run this test you MUST install @uci/i2c which is not a dependency of @uci/mcp -// npm install @uci/i2c -const Bus = require('@uci/i2c').Bus, - MCP = require('../lib/mcp23008-17'), - expect = require('chai').expect, - pause = require('@uci/utils').pPause - -let bus = new Bus() - -let ADDR = 0x21 -let CHIP = 'MCP23017' -let MS = 0 // so humans can watch the light otherwise set to zero -let PORT = 'B' - -let mcp = new MCP[CHIP](bus, ADDR, { - pin_cfg_default: 'output', -}); - -describe( - `Testing Chip ${CHIP}, Port ${PORT} at I2C bus address of 0x${ADDR.toString(16)}`, - function () { - init() - eachpin() - somepins() - }) - -//****************** TEST SUITES ********************** -function init() { - it('==> Initialize Chip', async function () { - - await mcp.init() - await mcp.allOff(PORT) // start clean - }) -} - -function eachpin() { - it('==> test each pin', async function () { - - await mcp.init() - await mcp.allOff(PORT) // start clean - - for (let pin of mcp.ports[PORT].pins) { - await mcp.on(pin.address, PORT) - let result = await mcp.readPort(PORT) - expect(result, `pin ${pin.id} at address ${pin.address} write/read failed`).to.equal(pin.address) - await mcp.off(pin.address, PORT) - await pause(MS) - } - await mcp.allOff() // clear port after each test - }) -} - -function somepins() { - it('==> on, off toggle some pins', async function () { - - let pins = [1, 7, 8] - await mcp.on(pins, PORT, 'PLC') - let shouldbe = [1, 7, 8] - let result = await mcp.readPort(PORT, { format: 'PLC' }) - expect(result.sort(), 'pin write/read failed on').to.deep.equal(shouldbe.sort()) - await pause(MS) - - pins = [2, 1, 7] - await mcp.on(pins, PORT, 'PLC') - shouldbe = [2, 1, 7, 8] - result = await mcp.readPort(PORT, { format: 'PLC' }) - expect(result.sort(), 'pin write/read failed on 2').to.deep.equal(shouldbe.sort()) - await pause(MS) - - pins = [2, 1, 6] - await mcp.toggle(pins, PORT, 'PLC') - shouldbe = [6, 7, 8] - result = await mcp.readPort(PORT, { format: 'PLC' }) - expect(result.sort(), 'pin write/read failed toggle').to.deep.equal(shouldbe.sort()) - await pause(MS) - - pins = [2, 1, 6, 7] - await mcp.off(pins, PORT, 'PLC') - shouldbe = [8] - result = await mcp.readPort(PORT, { format: 'PLC' }) - expect(result.sort(), 'pin write/read failed off').to.deep.equal(shouldbe.sort()) - await pause(MS) - - await mcp.allOff(PORT) // clear port after each test - }) -} diff --git a/test/relays.js b/test/relays.js deleted file mode 100644 index 53b1f42..0000000 --- a/test/relays.js +++ /dev/null @@ -1,44 +0,0 @@ -const Bus = require('@uci/i2c').Bus, - MCP = require('../lib/mcp'), - pause = require('@uci/utils').pPause - -let bus = new Bus() - -let ADDRS = [0x24, 0x25, 0x26, 0x27] - -let relayBanks = ADDRS.map(devAddr => { - return new MCP.MCP23017(bus, devAddr, { - pin_cfg_default: 'output', - desc: `relays at i2c address ${devAddr.toString(16)}`, - stateB: 255, // should be read from persistant state file for when power goes out - stateA: 255 - }) -}) - -async function go(port = 'A') { - let time = 1 - await relayBanks[0].init() - await pause(time * 1000) - await relayBanks[0].allOff(port) - await pause(time * 1000) - await relayBanks[0].on([1, 5, 8], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].on([1, 2, 5, 7, 8], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].off([1, 3, 5, 8], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].off([1, 3, 5, 8, 7, 2], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].toggle([1, 5, 7], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].toggle([1, 5, 8], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].toggle([8], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].force([3, 4], port, 'PLC') - await pause(time * 1000) - await relayBanks[0].allOn(port) -} - -go('B') // .then(resp => console.log(resp)) - .catch(reason => console.error(reason)) diff --git a/test/test-relays.js b/test/test-relays.js deleted file mode 100644 index 4761eba..0000000 --- a/test/test-relays.js +++ /dev/null @@ -1,85 +0,0 @@ -const Bus = require('@uci/i2c').Bus, - MCP = require('@uci/mcp'), - _ = require('@uci/utils'), - pause = _.pPause, - pSeries = require('p-series') -const a = require('awaiting') - -let bus = new Bus() - -let ADDRS = [0x24, 0x25, 0x26, 0x27], - W = 0x09, - R = 0x0A, - WAIT = 1000 - -let relayBanks = ADDRS.map(devAddr => { - return new MCP.MCP23017(bus, devAddr, { - pin_cfg_default: 'output', - desc: `relays at i2c address ${devAddr.toString(16)}` - }) -}) - -async function testbank(bank) { - await bank.init() - console.log(`initialized ${bank.desc}...now testing device write and read`) - for (let port in bank.ports) { - let pinAddr = 0 - console.log(`Testing bank:${bank.desc} port:${port}`) - for (let i = 0; i < 8; i++) { - pinAddr = pinAddr + Math.pow(2, i) - let addr = pinAddr - await bank.write(portReg(W, port), pinAddr) - console.log(`Turning Port ${port} Pin(s) ${_.byteFormat(addr, { in: 'DEC', out: 'PLC' })} on`) - let resp = await bank.read(portReg(R, port), pinAddr) - // await pause(100) - console.log(`Port ${port} Pin(s) ${_.byteFormat(resp, { in: 'DEC', out: 'PLC' })} is/are on`) - await pause(100) - resp = await bank.write(portReg(W, port), 0x00) - console.log(`Clearing Relays On Port ${port} ${bank.desc}`) - await pause(500) - } - } - return `done ${bank.desc}` -} - -// function seq(list, fn) { -// return async function () { -// await a.map(list, 1, fn) -// } -// } - -async function aseq(list, fn) { - const resps = [] - for (const item of list) { - let resp = await fn(item); - resps.push(resp) - } - return resps -} - -async function testall() { - let resp = await aseq(relayBanks, testbank) - return resp -} - -// testall() -// .then(resp => console.log("All done", resp)) -// .catch(reason => console.error(reason)); - -async function readport(bank, port = 'A') { - let resp = await relayBanks[bank].readPins(port, { format: 'ARY', cmd: "olat" }) - return resp -} - -let bank = 1 -readport(bank, 'A') - .then(resp => { - console.log(`Reading Bank ${bank} pins ${resp.value} are on`) - }) - .catch(reason => console.error(reason)); - -//=========== - -function portReg(reg, port) { - if (port === 'B') { return reg += 0x10 } else { return reg } -}