yun 8574 simultaneous input/output

If anyone has a sketch that has a framework for using the 8574 bus extender using Wire.h that is able to read 4 pins and write to the other 4 pins I'd appreciate seeing it. I've dabbled with it and am so far unsuccessful. My intention is to scan a 4X3 or 4X4 keypad using half to address the rows and the other half to read the columns. I know it can easily be done using 2 chips, but the specs on the chip alludes to the fact that I/O can be used simultaneously but goes into no detail as to how to set that up. Surely someone in the community has already done this. Thanks for any advice.

I've not used the chip, but from a quick glance at the datasheet it seems like it should be possible.

Most port expander chips require you to configure the individual pins as input or outputs. This one seems to be different. Instead, it is more of an open collector arrangement where a pullup resistor keeps the pin high, and writing a low as an output bit can pull the line low. In addition, if the output is set high, an external signal can pull the pin low.

My approach would be to wire four pins to the columns of the keypad, and four pins to the rows. You should not need any external pullup resistors. Then, to scan the keypad, write out a byte where all of the bits are high, and only one column bit is low, which will activate the column. Then read in a byte, mask off the column bits, and the remaining row bits will tell you which buttons are pressed: they will be high if not pressed, and low if pressed. Advance to the next column and repeat.

The key is if you want to read an input pin, that pin must have previously had a high written to the pin. In that case, reading the pin's bit will tell you the external state of the pin. If you had written a low to the pin, you will be reading that value you wrote, you won't be able to tell the external state of the pin.

Thanks Shapeshifter, that was exactly my approach, but my fear is that if I have an input to ground and write a high to the port, there may be excessive current. Most of these devices in the old days (circa 8255) had configuration registers to set up the chip functionality, I could go to that but I hate to tie up so many data pins. Does anyone have a proven sketch that splits the chip I/O? I will trudge on with it as my tenacity won't allow me to let go, but if the wheel has been invented already, I'd readily stick it on a couple of axles and pedal away.

heggood:
Thanks Shapeshifter, that was exactly my approach, but my fear is that if I have an input to ground and write a high to the port, there may be excessive current.

I understand what you're saying. And if this device had active drive output, I would agree with you. But this is what it has to say in the datasheet:

7.3 Quasi-bidirectional I/Os
A quasi-bidirectional I/O can be used as an input or output without the use of a control signal for data direction (see Fig.15). At power-on the I/Os are HIGH. In this mode only a current source to VDD is active. An additional strong pull-up to VDD allows fast rising edges into heavily loaded outputs. These devices turn on when an output is written HIGH, and are switched off by the negative edge of SCL. The I/Os should be HIGH before being used as inputs.

It sounds like the pins are basically an open collector output: there is a passive pullup resistor to drive the pin high, and a transistor to pull it low. When the output is high, the current is provided by the pullup resistor, and when the output is low, that same current is provided by the pullup resistor but the internal transistor is shorting it out to ground.

To use it as an input, set the output high (note the last sentence of the quoted passage.) In that case, the pullup resistor is providing the voltage and a slight amount of available current (the data sheet says 30 to 300 uA.) When you read that input, it will read high because of the pullup current source. That is such a low amount of available current (between a third and a thirtieth of a milliamp) that there is no problem grounding that out with the keypad switch. When grounded out, it will overcome the voltage pullup and be read as a low.

Now, there is an extra high current drive when the pin is first written high, which according to the referenced diagram in the quote above lasts for half of an SCL clock cycle. The point of this stronger drive is to give a reasonable rise time, since the normal pullup current is so low -- 30 uA could take a long time to charge up any wiring capacitance. So, for half a clock cycle, the stronger current source is turned on, but this is still only 1 mA. I see no problem shorting out even that amount of current.

Many I/O pins can put out 20 to 40 mA without bringing their output voltage below specs, and can put out much more if you can tolerate dragging the voltage level down. That's a significant amount of current that you don't want to short out under normal situations. But the available output current on these pins are so low, that there isn't any problem.

It's exactly the same as having a pullup resistor on the processor input pin. You don't have any problem driving an input pin like that low, do you? (Or driving an input pin high when it has a pulldown resistor on it.)

@Shapeshifter
As always you come through with good advice an clarification. Thank you so much for being so vigilant looking into the problems of new comers. If there was a choice in the Karma thing, I'd give both you and Jesse 5 yellow stars. I wish they had a yellow and blue.

@Shapeshifter,
I'm successful at writing 8 bits output and reading 8 bits input, I send 0xFF to the device and read it. I always get back 0xFF when reading no matter what signal I put on the port pins. My bad I guess, next I will resort to a 74C922 decoder chip. I just hate it when you want to order just one part but have to include other things just to justify shipping costs!

The pull-up "devices" are actually transistors designed to provide a relatively strong pull-up current when turned on (after writing HIGH to the output), BUT with high enough on-resistance so that the outputs may be safely "shorted" to ground indefinitely. This configuration requires fewer latches than the typical microcontroller I/O port structure, so there's no need to mess with data direction registers. However, the simplicity comes at a cost: the outputs cannot source much current (300uA max spec), though they can sink some 25mA.

If you are reading 0xFF after writing 0xFF and grounding port pins, either the chip is malfunctioning or something is wrong with the communication between the controller and the chip. It may be as simple as not sending the correct address, or it may be as complex as shady I2C timing.

@jverive. I am confident of proper addressing, as I have successfully driven a string of leds off and on with output. The chip functions perfectly in that respect.

Am I correct in saying that if I write say 0x0F to the port that I should see Ox0F on the next read cycle and subsequently ground D0 and do another read I should see 0xFE? That would mean that the outputs are latched and reads would return the last output value unless overridden by an electrical connection. Is that the meaning of the 'quasi-bidirectional' term described in the chip spec?

That's the way I read it, except that you should read back 0x0e, not 0xfe. I'm guessing it's just a typo in your question?

Yes, if you write 0x0F to the port, you will read back 0x0F. If you subsequently ground pin D0, the next read should report 0x0E. Because you are actually reading the pin state (and not some latched register) there's no reason why a fully functional chip would report 0x0F if D0 is grounded. Can you try another 8574 in its place?

Yep, typo. I've always had a struggle with hex. Not as much so with octal or binary. I have at least 2 and eight fingers, but when it gets over ten, I have to use my toes.