rwaldron / johnny-five

JavaScript Robotics and IoT programming framework, developed at Bocoup.
http://johnny-five.io
Other
13.3k stars 1.77k forks source link

MCP23S17 support #644

Closed mcinnes01 closed 9 years ago

mcinnes01 commented 9 years ago

Hi,

I just wondered if it possible or if there already is some support/implementation for control an MCP23S17 with johnny-five and an arduino or raspberry pi?

Many thanks

Andy

rwaldron commented 9 years ago

Not currently—what are they generally used for?

mcinnes01 commented 9 years ago

They are an spi driven real gpio expander allowing for all 16 pins to be controlled individually as inputs or outputs. There is also an i2c version. Apparently the piface expansion board uses one. Also they have 2 pins that can be pull high or low to give 4 combinations to address up to 4 chips individually on the same chip select. I've seen drivers for written for arduino, wiring pi and netduino and wondered if it would be possible to incorporate in johnny five?

mcinnes01 commented 9 years ago

Forgot to mention can also assign interrupts to pins.

haydockjp commented 9 years ago

Hi,

I noticed that if I install the npm package (npm install johnny-five) I get "expander.js" in the lib and the eg folder. It seems to be an interface for MCP23017. I can't find it in the Git Hub repository.

If I add this to the johnny-five.js file, I can get an example to work. Expander: require("./expander"),

Is this okay to use?

Jon

rwaldron commented 9 years ago

It's a secret!

I'm kidding ;)

I have this problem where I always forget that npm will publish all the files that aren't "npmignored". So, as you've discovered, I'm working on a new class that will allow users to take advantage of io expanders and allow Johnny-Five to use io expanders in controller definitions. Since you're interested, I encourage you to play with the class, but with the understanding that the interface and semantics may change. TBH I'm sort of thankful for this opportunity—a happy accident I think :)

haydockjp commented 9 years ago

I'll have a play. I have a few other components to master for my project too.

I assume you have seen the Ada Fruit Arduino library?

Jon On May 12, 2015 7:05 AM, "Rick Waldron" notifications@github.com wrote:

It's a secret!

I'm kidding ;)

I have this problem where I always forget that npm will publish all the files that aren't "npmignored". So, as you've discovered, I'm working on a new class that will allow users to take advantage of io expanders and allow Johnny-Five to use io expanders in controller definitions. Since you're interested, I encourage you to play with the class, but with the understanding that the interface and semantics may change. TBH I'm sort of thankful for this opportunity—a happy accident I think :)

— Reply to this email directly or view it on GitHub https://github.com/rwaldron/johnny-five/issues/644#issuecomment-101295053 .

rwaldron commented 9 years ago

Ada Fruit Arduino library?

I'm using this as a baseline for the implementation, it's not really a "port" since the sync reads aren't possible, but I've found what I hope is a smart strategy. I've made a bunch of changes to this today, so please don't fall in love yet ;)

rwaldron commented 9 years ago

I pushed more to the expander branch!

haydockjp commented 9 years ago

I'll have a play when I can. I was concentrating on the ht16k33. Just started trying to understand the mcp23017 last night.

Thanks Jon On May 18, 2015 4:25 PM, "Rick Waldron" notifications@github.com wrote:

I pushed more to the expander branch!

— Reply to this email directly or view it on GitHub https://github.com/rwaldron/johnny-five/issues/644#issuecomment-103258683 .

haydockjp commented 9 years ago

Hey, Thanks for the update.

What you have works. For what I am trying to do, there are a few more pieces to the puzzle (assuming I am doing it correctly :0) )

I have four MCP23017 expanders and I want to read the GPIO for A and B on an interrupt and quickly workout the current state of all the pins from the one read.

I saw how you were using i2cRead and i2cWrite, and this is what I am currently playing with in a test script:

var raspi = require('raspi-io');
var five = require('johnny-five');

var board = new five.Board({
    io: new raspi()
});

board.on("ready", function() {

    var addresses = [0x20,0x21,0x22,0x23];

    var lastValues = new Array(addresses.length);
    for (var r=0; r<addresses.length; r++) {
        lastValues[r] = new Array(2);
    }

    // Create new expander object - address 0x20
    console.log("Create expanders");
    var expander = new five.Expander({
        addresses: addresses,
        controller: "MCP23017"
    });

    // Set values in the main array so we can output them together
    function setValue(a, r, value) {
        var info = "" + value;
        var changed = (lastValues[a][r] != info);
        lastValues[a][r] = info;

        // if info changes, output
        if (changed) {
            //show all the values
            showValues();
        }
    }

    // Display all of the values together
    function showValues() {
        process.stdout.clearLine();
        process.stdout.cursorTo(0);

        for (var v=0; v<lastValues.length; v++) {
            process.stdout.write("\t" + addresses[v].toString(16) + ">");
            for (var r=0; r<lastValues[v].length; r++) {
                process.stdout.write("\t " + lastValues[v][r]);
            }
        }
    }

    process.stdout.write("\n");
    for (var v=0; v<lastValues.length; v++) {
        process.stdout.write("\t" + addresses[v].toString(16) + ">\t0x12\t0x13");
    }
    process.stdout.write("\n");

    this.i2cConfig();

    for (e=0; e<addresses.length; e++) {
        //console.log(e, " = ", addresses[e]);

        //console.log("i2cTest: ", addresses[e]);
        // Set inputs on port A
        this.i2cWrite(addresses[e], [ 0x00, 0xFF ]);
        // Set inputs on port B
        this.i2cWrite(addresses[e], [ 0x01, 0xFF ]);
        // Set polarity to be inverse
        this.i2cWrite(addresses[e], [ 0x02, 0xFF ]);
        this.i2cWrite(addresses[e], [ 0x03, 0xFF ]);
        // Enable interupts
        this.i2cWrite(addresses[e], [ 0x04, 0xFF ]);
        this.i2cWrite(addresses[e], [ 0x05, 0xFF ]);
        // NOT setting default value

        // interrupt on change from previous value
        this.i2cWrite(addresses[e], [ 0x08, 0x00 ]);
        this.i2cWrite(addresses[e], [ 0x09, 0x00 ]);

        // set INTA/B mirrored
        this.i2cWrite(addresses[e], [ 0x0A, 0x60 ]);

        // enable pull up resistors
        this.i2cWrite(addresses[e], [ 0x0C, 0xFF ]);
        this.i2cWrite(addresses[e], [ 0x0D, 0xFF ]);

        (function(board, ee) {
            // GPIOA
            board.i2cRead(addresses[ee], 0x12, 1, function(data) {
                setValue(ee, 0, data);
            });

            // GPIOB
            board.i2cRead(addresses[ee], 0x13, 1, function(data) {
                setValue(ee, 1, data);
            });
        })(this, e);
    }

});

One of the things I don't quite understand is why, when I do the i2cread, does it continuously read. I was expecting it to just read once.

I am not sure if this helps with additional use cases or not?

Thanks again!

rwaldron commented 9 years ago

Landed with Expander class