Lots of GPIO using multiple PCA9698

Hi all,

Id really appreciate some input on this one...(sorry, no pun intended)

I'm planning a project which in reality needs to be a large pin matrix, so a large number of inputs, a large number of outputs and then the ability to determine which output is connected to which input.

Its like a big cable harness tester i suppose but I'm not worried about multiple pins being shorted, it would only ever be one output connected to one input.

So, I've been looking at the NXP PCA9698 ic's as they offer a load of IO and lots of available addresses on on one i2C bus.

The only thing I'm concerned about is resources, I haven't got a great deal of experience with handling lots of IO - so for example, if I wanted to test 240 x 240 pins, I'd need 12 of these ICs, so far so good - the datasheet says that 64 address are available for this chip.

I'm thinking the programme would work in very simplistic terms by holding the first output to a know state (high), and then scan all the inputs to see which one is also high, and then do the same with the second, output etc etc.

Am I likely to run into any issues with this just in the way of time it takes to query all the I/O or with the amount of available memory to process/store all these states? I've been using the 16Mhz Pro Mini's (ATMega328P).

Also, can anyone tell me if the wire.h library supports this chip?

Thanks for reading,

Joel.

The wire lib will "support" this chip as the wire lib just do the very low protocols.

check - Arduino Playground - I2CPortExpander8574 - to see how that can be done

or write a library a bit like this

Hi,

Yes, the Wire library should support those chips. But your whole design sounds over-complicated, if I understand your requirements (and I'm not certain I do).

Have you considered using simple demultiplexer & multiplexer chips? Sounds like you only need to set one output high at any instant, and read one input at any instant.

Can you clarify how many? Is it 240, or 240*240=57,600?

Paul

Hi Paul,

Thanks for your reply.

You are correct in that I only need to set one output high and read that input in any one instant - apologies if my description wasn't very clear.

The result I need to end up with is something like:

Out 2 is connected to Input 12
Out 26 is connected to Input 55
Out 40 is connected to Input 3

etc...

I would need 240 outs and 240 ins so yes, 57,600 combinations (sounds alot now!)

I had looked at the demultiplexer and multiplexer chips but wasn't sure if enough could be cascaded to give the required IO count.

Cheers,

Joel.

the checking can be faster as probably you need to read at least 8 lines simultaneously

30 x 240 = 7200 reads iso 57600 reads

for (line =0; line < 240; line++)
{
  setHigh(line);
  for (b = 0; b<30; b++)
  {
     byte val = getLines(b); // read 8 lines at once
     if (val == 0) continue;

     // high line detected
     // check which bit is set
     // do your thing
  }
  setLow(line);
}

optionally you might keep a list of found matches and skip these later in the loop.
Could speed up the testing at the cost of some code complexity [RAM].

jhauxwell:
I would need 240 outs and 240 ins so yes, 57,600 combinations (sounds alot now!)

Still not convinced I understand... so its 57,600 combinations to be tested? But only 240 wires (=480 connectors)?

You said 12 of those 40-bit IO extenders, that would be 480. Since you would have individual input/output control over each pin, you would indeed need 12 of those chips. One pin at a time set to output & high, then read the other 479 inputs.

jhauxwell:
I had looked at the demultiplexer and multiplexer chips but wasn't sure if enough could be cascaded to give the required IO count.

Well, the 74hc138 can be used in pairs to make a 1:16 demultiplexer. You would need 15 pairs, plus an extra pair as a second-tier demux (unless you use a Mega and can afford 15 outputs to drive them).

74hc151 would be the corresponding multiplexer.

I think I'm right with saying 480 connections. If all possibilities are to be tested then it must be 240 x 240 as output 1 could be connected to input 1,2,3, or any other input up to 240, and then the same would be true for output 2, and all the other outputs up to 240...please feel to correct me though if ive missed something

Using the combination of 74hc138 and 74hc151 chips would certainly work out more cost effective than the PCA9698 (£17 for all the mux/demux vs. about £30 for the i2C).

I'm not sure what you mean by second-tier demux, would you mind elaborating? I can see that I'd need 30 x mux and 30 x demux chips to get the required 240 ins and outs, just not entirely sure how to connect it up - like I said, I've found people cascading 2 or 3 but not 30!

Right. Forget (de)multiplexors. How about shift registers? Should be simpler overall I think.

Daisy-chain 30 x 74hc595 for outputs.
Daisy-chain 30 x 74hc165 for inputs

Use the Arduino's built-in SPI hardware to read from the '165s at high speed. That way you can read in 8 bits at a time and check for a non-zero bytes efficiently.

For the outputs (595s), you don't need to use the SPI bus, since you simply want to clock-in a single "1" and shift it along 240 times, so you can just toggle the clock line to do that.

To reduce the chip count, there are 16-bit shift registers such as 74ls673 and 74ls674, but they might cost more than double the 8-bit chips!

Paul

I think you're right - simpler, and cheaper!

I've looked at a few examples of the 74hc595 and the 74hc165 in use and they're very well documented. As far as hooking them up is concerned, presumably ill need to pull all of the inputs of the 175's down to ground via 10K resistors so that nothing is floating.

As for the outputs of the 595's, usually in the hook-up examples I've found, these are shown driving LEDs via 220ohm current limiting resistors. In my application, the outputs of the 595's will basically be driving into the inputs of the 165's - is this OK or would I need current limiting resistors on all of the output pins?

Cheers.

The '595 outputs will be connected to the '165 inputs via the cable, yes?
Output one high, read back all inputs make sure you have 1 high and the rest lows.
Maybe even do 30 highs at a time, so only 8 passes are needed.
Use SPI.transfer for both, 30 bytes out, 30 bytes in, will go fast.

Having some resistance in series will help if two adjacent pins are shorted, will keep high output from being shorted by a low output.
Can play it safer, use 1K pullup at the 165 input, and TPIC6C595 open drain shift registers to pull the 1Ks low instead. Then read all High inputs except for the 1 low input. If pins are shorted, one output can pull multiple 1K resistors low with no issue.

jhauxwell:
ill need to pull all of the inputs of the 175's down to ground via 10K resistors so that nothing is floating.

Maybe not... Does every one of the 240 outputs lead back to one (and only one) of the 240 inputs? If so, all inputs will be either high or low, so no outputs will be floating.

jhauxwell:
would I need current limiting resistors on all of the output pins?

As long as you are certain that any one of the 240 inputs can only ever connect to one of the 240 outputs, then no. But if there is a possibility that one of the inputs could connect back to another input, then a short could happen and some limiting resistors would be vital.

CrossRoads:
Maybe even do 30 highs at a time, so only 8 passes are needed.

I don't understand, Bob. If you make more than one output high at any instant, then read the inputs and find that one is high, how do you know which output produced it? Have you got some clever algorithm in mind?

CrossRoads:
Use SPI.transfer for both, 30 bytes out, 30 bytes in, will go fast.

Yes, it would be fast, but the sketch would be more complicated, and with no advantage. Each time you sent the 30 bytes out, you would need to figure out which byte needed the "1" in it and at which position. Whereas if you didn't use the SPI bus for the outputs, you would just shift in a single "1" at the beginning of your loop, then loop 240 times, pulsing the output clock line once each time. Each pulse would shift the "1" to the next position and replace it with a "0".

Hi Paul,

There could theoretically never be a short, however it is possible that pins would be not connected and I'd have to be able to pick this up.

This is why I thought that I'd need pull-down resistors (actually, 240 of them!). As for the possibility of a short ever happening then it would be good to have some protection built in so I take it I'd need a resistor in series on every pin of the 74HC595's...- can you recommend a value for this?

Ill draw up something in Eagle shortly and post so you can take a look and let me know if you think it should work.

Just thought of a small problem. The clock lines, the one to the 30 output registers, the one to the 30 input registers, and the latch line to the 30 input registers. They would each be driven by a single Arduino output. But the fan-out would need to be 30, which may be asking too much. So maybe a few buffer gates would be needed, e.g. 74hc06.

jhauxwell:
it is possible that pins would be not connected and I'd have to be able to pick this up.

This could be done in the sketch easily enough. The sketch could keep an array of 30 bytes and bitwise-or each new reading of the inputs to it. Any zeroes left at the end would indicate a no-connection.

jhauxwell:
I'd need a resistor in series on every pin of the 74HC595's...- can you recommend a value for this?

Anything small-ish would be fine, e.g. 100R ~ 1K.

My thinking was that if the lines are arranged so only groups of pins can be shorted just due to physical arrangement, for example a round military type connector where a pin has only so many neighbors it can possibly short to, then having multiple 'active' signals could be a valid way test, vs testing each individually and assuming any pin could be shorted to any other pin.

If miswiring is a concern, and being able to confirm where one end actually connected to at the other end is needed to correct miswiring, then the ability to fall back to 1 at a time testing would be good.

74xx06 is a hex inverting buffer. I think a 74ac244 would make a better buffer for fanout reasons.(+/-24mA capability)

Hi Paul,

PaulRB:
Just thought of a small problem. The clock lines, the one to the 30 output registers, the one to the 30 input registers, and the latch line to the 30 input registers. They would each be driven by a single Arduino output. But the fan-out would need to be 30, which may be asking too much. So maybe a few buffer gates would be needed, e.g. 74hc06.

I don't really understand what you mean - I know the 165's are on hardware SPI and are all daisy-chained so I'm guessing its the other 30 595's you're talking about with regard to the clock lines? Would you be able to expand on the buffer lines as i haven't used these before.

Thanks.

The SCK line and the latch line would be going to 60 devices in parallel. That could mean a lot of capacitance on the signal leading to a degraded signal. Buffering the line so only 10 or so parts are connected would help maintain signal integrity.

Joel, its only the data line that is "daisy-chained" in practice. The clock and latch lines have to be connected to each shift register in parallel. Unfortunately you can only have so many parallel connections before problems begin. The buffer gates are used to effectively increase the "fan-out" capability of a line by taking some of the strain off the Arduino output. I'm sure Bob's suggestion of the '244 is good.

I think I'm getting a bit lost. So, the inputs are on the SPI bus so they can be read fast. There's 30 chips which share the SPI bus and so this many devices paralleled off could be tricky because of capacitance. I will have a look at the buffers but again, im a bit lost by.

CrossRoads:
74xx06 is a hex inverting buffer. I think a 74ac244 would make a better buffer for fanout reasons.(+/-24mA capability)

Also...Paul said

PaulRB:
Whereas if you didn't use the SPI bus for the outputs, you would just shift in a single "1" at the beginning of your loop, then loop 240 times, pulsing the output clock line once each time. Each pulse would shift the "1" to the next position and replace it with a "0".

So where are the output devices connected? If the SCK and LATCH connections are for all the devices (60) then aren't they all on the SPI bus?

I don't know if this is relevant but the cables being tested could be quite long - up to about 5m....can you foresee any issues with this?