improved testing, significant start to readme, added sample demo

master
David Kebler 2017-05-28 00:00:07 -07:00
parent f428abc394
commit 02b291811d
10 changed files with 287 additions and 467 deletions

53
demo/sample.js Normal file
View File

@ -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
})()

View File

@ -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 }
}

View File

@ -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"
}
}

116
readme.md
View File

@ -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)

View File

@ -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 }
// }

View File

@ -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)}`
let mcp = new MCP[CHIP](bus, ADDR, {
pin_cfg_default: 'output',
id: id
});
describe('set up MCP Chip', () => {
before(async() => {
await mcp.init()
})
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)
}
})
}
// console.log(bus1)
// bus1.scan((devs)=>{console.log('devices: ', devs)})
//bus1.scan().then(results=>console.log(results))
function somepins() {
it('==> on, off toggle some pins', async function () {
describe('I2C Device Classes - ', 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)
let mcp17 = new MCP.MCP23017(bus, 0x20, {
pin_cfg_default: 'momentary_switch',
name: 'switches 1-16'
})
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)
describe('MCP23017 Class - ', function () {
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)
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)
})
})
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)
})
})
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)
})
}

View File

@ -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
})
}

View File

@ -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))

View File

@ -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 }
}