What's the best digital inputs expansion practice ?

Hi,

i'm used to expand digital outputs using the 74HC595, also cascading them, easily as you know.

Now i have the need to expand my digital inputs, and i would like to be in a similar easy cascading way of doing it.

I have read about several methods to do this: 4051 (but as i understood, it takes away one analog pin on my arduino for each 4051 cascaded), 4021 (didn't understando which is the difference between this and the 4051) and 74HC165 shiftin.

To me the last one (74HC165) seems to be the most similar to the 595 approach; from what i've understood, i'll use three digital pins only from my arduino, despite the number of 74HC165 attached and cascaded. Is this right ? Is it easily supported by arduino code (maybe with some ready library ?)..

Which is the best method ? I plan to have, finally in my project, at least three sets of 8 digital inputs; i need to have them cascaded because i need to have identical modular circuits to expand the project if needed.

Thanks very much in advance.

HC165. Library - you don't need a library for that!

digitalWrite (latchPin, LOW); digitalWrite (latchPin, HIGH); // latch the state of the inputs - maybe swap these 2 inByte0 = SPI.transfer(0); // read in data while performing dummy write out. inByte1 = SPI.transfer(0); inByte2 = SPI.transfer(0);

or use an array: inByte[0] = SPI.transfer(0); inByte[1] = SPI.transfer(0); inByte[2] = SPI.transfer(0);

(unless technically using SPI.transfer() is using a library ...)

Thank you very much. So the 165 is the best option? I have some 4051s, i imagine that it works slightly different, right?

for now, thanks once again

4051, intended for analog signals, One of 8 inputs is passed to output based on 'address' lines. Set up address, analogRead(Ax); repeat 8 times. Results nearly 900uS later.

165 is a shift register, state of 8 digital inputs passed out in one read. inByte = SPI.transfer(), result in just over 1uS with SPI.divisor set to 2 for 8 MHz transfers.

Thanks! I think there's no more doubt now, i'll go for the 165s.

Have a nice time, regards

you can also consider I2C e.g. PCF8574 chips

Actually, the 74HC4051 does have one interesting advantage.

You do not need individual pull-ups for the digital inputs, as the input to which you connect the common can provide the pull-up, either by the internal pull-up, or a resistor.

Is this 74HC4051 the same chip we were talking about previously in this post ?

As i said, i understood that with the 4051 i also loose one arduino pin for each cascaded chip (at least, using it as analog input).

Does this can be used also as digital input, without this 'problem' ?

If it works as the 74HC165, with the plus of the integrated pullups, that would be interesting.

Sorry for the many questions... but with the web literature about the subject i got really confused.

Is there some good example that you know of ?

Thanks very much !

demym: Is this 74HC4051 the same chip we were talking about previously in this post ?

As i said, i understood that with the 4051 i also loose one arduino pin for each cascaded chip (at least, using it as analog input).

You lose three pins per chip. It takes three pins to select the source.

But why do you want to use an analog chip? Are you connecting it to the analog pins so you can read the input voltage?

demym:
I have read about several methods to do this: 4051 (but as i understood, it takes away one analog pin on my arduino for each 4051 cascaded), 4021 (didn’t understando which is the difference between this and the 4051) and 74HC165 shiftin.

One is analog, one is digital. One passes analog voltage through the chip to the ADC converter, one doesn’t.

demym:
To me the last one (74HC165) seems to be the most similar to the 595 approach; from what i’ve understood, i’ll use three digital pins only from my arduino, despite the number of 74HC165 attached and cascaded. Is this right ?

Yes.

demym:
Which is the best method ? I plan to have, finally in my project, at least three sets of 8 digital inputs; i need to have them cascaded because i need to have identical modular circuits to expand the project if needed.

The most ‘modular’ way is with I2C chips. Two wires can read a lot of chips. The only slight disadvantage is that I2C isn’t as fast as SPI/shiftin. Whether this is a problem or not is up to you. You can still read them thousands of times a second (where SPI could do tens of thousands).

eg. The PCF8574A has 8 inputs (with pullups) and you can connect 8 of those to an Arduino with just two pins (A4 and A5 have the I2C bus).

'4051 does not have internal pullups - you are relying on the '328P pullup working.

Hi, so i've tried using an 74LS165,

if have the following connections:

pin1 165 ---> pin D9 arduino pin2 165 ---> pin D10 arduino pin8 165 ---> GND pin9 165 ---> pin D8 arduino pin15 165 ---> GND pin16 165 ---> 5V

if i connect each of the 8 datalines of 165 (pin 11,12,13,14,3,4,5,6) to a 10k resistor to GND, i have a constant reading of 255 in my serial monitor (whereas i expected to have 0)...

i have all 0's only if i connect the 8 datalines directly to GND....and if untie one of these datalines from the GND, i have the correct reading, based upon the bit disconnected.... so, in this way, it works... but i expected it to work when connecting the datalines to 10k and then to GND... also, in this last case, i have no changes in serial monitor if i send a 5V to the datapin....

Can't understand why it is behaving this way... i followed the following schematic and guide:

http://www.mcmajan.com/mcmajanwpr/?p=1376

I've read that connecting the datalines to 10k and then GND is crucial to avoid floating values.....

Can someon please help me ?

Thanx in advance...

edit:

using 1k resistors (with 74LS165) it works correctly… i’ve found a similar issue here:

http://list.dprg.org/archive/1999-August/011392.html

… also, i have two 74ls165 that i would like to cascade… to read the 8bits value on the first i’m using this bit of code:

void loop(){
// Set the latchPin LOW …
digitalWrite (latchPin, LOW);
// … then wait very briefly for the chipe to read digital inputs
delayMicroseconds(10);
// … then set the latchPin HIGH in preparation for shifting
digitalWrite (latchPin, HIGH);

// Shift in 8 bits (1 byte). Choose MSBFIRST
// (retrieve the bits of your inByte starting with the most
// significant bit first) or LSBFIRST (retrieve the bits of your
// inByte starting with the least significant bit).
int inByte = shiftIn165(dataPin,clockPin,MSBFIRST);

Serial.println(inByte); //debugging in serial window of switches 1 through 8)

// take a breather to prevent serial buffer overflow
delay (10);
}

/*

  • Here we define an alternate shiftIn function. The only difference
  • between this shift in function and the built-in shiftIn function
  • is that the clock must got LOW before shifting and HIGH after
  • shifting. This is the opposite of the built in Arduino shiftIn.
    */

uint8_t shiftIn165(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;

for (i = 0; i < 8; ++i) {
digitalWrite(clockPin, LOW);
if (bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, HIGH);
}
return value;
}

How do i read the other cascaded 165 ?

thanx once again

Use the SPI pins and do it like this:
(or shiftIn() if you prefer slow transfers)

thank you very much, i've managed some result... good !

thx