74HC595 & 74HC165 - 5 wire

Hi all,

Quick info:
74HC595 = 8bit output shift register
74HC185 = 8bit input shift register

Story:
Ok so I heard that I can actually connect these using 4 wires together but after a lot of hassle I simply settled for the 5 wire solution.

5 Wire Solution:
Input Latch, Input Data, Clock (common to both ICs), Output Latch, Output Data

Problem:
I am trying to read what I am writing. Assuming that the outputs are connected to the inputs, should this code fail?

lcdLine1 = "Outputting 54";
updateLCD();
shiftOut(outDataPin, clockPin, MSBFIRST, 54);
digitalWrite(outLatchPin, HIGH);

digitalWrite(inpLatchPin, LOW);
digitalWrite(inpLatchPin, HIGH);
    
lcdLine2 = "Reading " + String((int)shiftIn(inpDataPin, clockPin, MSBFIRST));
updateLCD();

It is giving me the following result
Outputting 54
Reading 253

I am kinda lost.
Thanks
X

I now tried to change one line from MSBFIRST to LSBFIRST as follows:

lcdLine2 = "Reading " + String((int)shiftIn(inpDataPin, clockPin, LSBFIRST));

And I got :

Outputting 54
Reading 63

Attached is the schematic as I am confused a little.
The main scope of the circuit is to blow the fuse.

R19 and R20 are just a potential divider to lower the voltage from 12v to 5v.
D6 ensures that 5v are present for the input shift register which reads from I5
The output is connected to O5
T5 attempts to read the status of the fuse.

If you think I have a flaw in the circuit, please help with that too :smiley:

Thanks
X

io.jpg

Are you sure about those part numbers?
The 74HC185 in particular.
The 185s I've seen are a binary to BCD converter.
Perhaps a 165? instead?

Also the schematic is not complete.
I don't see a 74HC595 or a 74HC185 in that schematic.
It is difficult to predict what is happening without seeing how everything is hooked up.

-- bill

Oh silly me I meant to say 165 (sorry) :frowning:

Also I5 is directly connected to the 165 and the O5 is connected directly to the 595.
Attached is a schematic of the ics. what is labeled DM is going directly to the Arduino while the LM labels are not connected but in the future will be so you can ignore those as they do not have effect.

While I’m at it I might also add that what is labeles 12V Test and 12V live, that is just 12V coming from a mechanical relay. I wanted to be able to shutdown power mechanically too.

Thanks for your help :slight_smile:

io.jpg

Xenobius:
Also I5 is directly connected to the 165 and the O5 is connected directly to the 595.

What do you mean by this?
Do you have all 8 pins connected to each other? Q0-Q7 to D0 to D7 or
are you saying that I5 and O5 (data bit 4) are connected to the previous circuit?

If so, I'd suggest first testing it with no other connections to ensure that shiftin()
is properly reading the result of shiftout().

NOTE: It might help remove some potential confusion in the future if the I and O bits
were numbered the same as the Q and D bits instead of being off by one.

Can you post the full sketch?
It isn't obvious from the code fragment which pins are being used for which connections and
if things like pinMode() are setting up all the pins properly or if the initial state of the clock line is
set properly before the call to shiftOut() or shiftIn() or how the latch pins are initialized.
There is also edge direction for latching the data.
The 165 latches data in on H->L on the latch pin but I see a L->H in the code fragment.
The 595 latches data on the L->H on the latch pin.

--- bill

Hi Bill,

Thanks for your replies. Ok so let me clear the confusion :blush:.

So here is the code (relevant to this problem ofcoarse.. I mean usless showing you the LCD handling code or the speaker handling code ^_^)

const byte inpDataPin = 8;
const byte outDataPin = 9;
const byte clockPin = 10;
const byte inpLatchPin = 13;
const byte outLatchPin = 11;

void setup(){
  //Set Control PinModes
  pinMode(inpDataPin,         INPUT);
  pinMode(clockPin,           OUTPUT);
  pinMode(inpLatchPin,        OUTPUT);
  pinMode(outLatchPin,        OUTPUT);
  pinMode(outDataPin,         OUTPUT);
  
  digitalWrite(clockPin,      HIGH);
  digitalWrite(inpLatchPin,   HIGH);
  
  //Reset Shift Registers
  shiftOut(outDataPin, clockPin, MSBFIRST, 0); //Am not sure here... was just trying
  digitalWrite(outLatchPin,      HIGH);
}

void loop(){
    lcdLine1 = "Outputting 54";
    updateLCD();
    shiftOut(outDataPin, clockPin, MSBFIRST, 54);
    digitalWrite(outLatchPin, HIGH);
    
    digitalWrite(inpLatchPin, LOW);
    digitalWrite(inpLatchPin, HIGH);
    
    lcdLine2 = "Reading " + String((int)shiftIn(inpDataPin, clockPin, LSBFIRST));
    updateLCD();
    
    delay(10000);
}

Connections:
The schematic posted previously shows pins labeled DM13 etc... this corresponds to the arduino pins. So if its DM8 than its connected to pin 8 and from the code above this would mean that it is referring to 'Input Data Pin'

I think now with the full code, and full schematic it should be clearer. Please let me know if something is still not clear!
And thanks for your precious time! You are really of good help.

Ok so there are a few issues.
The thing to look at is your latching and clock signals.
First look at the output latch.
The 595 uses a rising edge to latch the data. “edge” being the key term.
The line must move from low to high in order to latch the shifted data.
The code isn’t cause an L->H transition it is only writing a H.
So the first latch works (because the register is L from reset) then no other latches will work
since it is only writing a H.

The 74165 is a falling edge, but part seems ok as the code was already handling that as it wrote a H in setup()
then wrote L then H in the loop before the shiftIn().

The next thing is the clocking signals.
Both parts use rising edge here.
But it is a bit tricky to share the clock due to the way the clocking works on the data.

To get the output clocking to work for the 595 you need the clock line to be L when you call shiftOut().
To get the input clocking to work for the 165 you need the clock line to be H when you call shiftIn().
If this is not the case the first bit can be clocked incorrectly for shiftOut() or lost with shiftIn().

I have attached two logic analyzer pictures to help show this
as well as a slightly modified version of the code.
The only real change to the code is to write out 0xAA and 0x55 so you can see the clocking
of each unique bit.

The first picture is of the original code, and the second is with a few changes
(turn on the BAP define) to get the additional modifications.
If you look at the first image you see the first bit of the shiftout() data is misclocked
and you can see the output latch not working correctly.
You can see the difference in the second image.

Hope that helps.

— bill

sOutSin.pde (1.5 KB)

SR1.png

Hey Bill,

Thanks for your detailed reply. Just saw it but am at work so I will read it again tonight and let you know.

Thanks once again :slight_smile:
X

Hey Bill,

How did you connect that logic analyser with the code? Can you refer me to another post to learn more on this?

In the mean time I am trying to make it work. No luck yet

Xenobius:
Hey Bill,

How did you connect that logic analyser with the code? Can you refer me to another post to learn more on this?

In the mean time I am trying to make it work. No luck yet

I am going to jump in here and go out on a limb. It looks like he cloned your the shift register portion of your design and hooked it up to this very popular analyzer. So he really went out of the way here.

http://www.saleae.com/logic/features

So you just connect the probes to the pins you want to watch on the circuit and the ground line to ground it and you are all set with this analyzer.

The analyzer is a saleae Logic
http://www.saleae.com/logic
but any logic analyzer would do for this.
I like the saleae because it works on linux.

channel 0 is hooked up to Arduino pin 9
channel 1 is hooked up to Arduino pin 10
channel 2 is hooked up to Arduino pin 11
channel 3 is hooked up to Arduino pin 13
and then I used Arduino pin 2 as a “strobe” to trigger the capture.
It is connected to channel 4.
Channel 4 is set to trigger on a rising edge.
So you see in the code there is a digitalWrite() sequence of L,H,L on STROBE which is
Arduino pin 2. That will start the analyzer capturing the signals when it goes from L->H

As far as the code not working.
I’d simplify the test environment as much as possible to test the shift registers.
i.e. hookup only the two shift registers to the Arduino and disconnect any thing else.
(I’d try it but I don’t have any 165s handy).

Below is a sketch that you can run which will use the serial port and will
display the values in binary to be able to see the individual bits.
This should help diagnosing any issues.
— bill

const byte inpDataPin = 8;
const byte outDataPin = 9;
const byte clockPin = 10;
const byte inpLatchPin = 13;
const byte outLatchPin = 11;

//#define STROBE 2

void setup()
{
  //Set Control PinModes
  pinMode(inpDataPin,         INPUT);
  digitalWrite(inpDataPin, HIGH); // turn on pullup for debugging
  pinMode(clockPin,           OUTPUT);
  pinMode(inpLatchPin,        OUTPUT);
  pinMode(outLatchPin,        OUTPUT);
  pinMode(outDataPin,         OUTPUT);
#ifdef STROBE
  pinMode(STROBE, OUTPUT);
  digitalWrite(STROBE, LOW);
  digitalWrite(STROBE, HIGH);
  digitalWrite(STROBE, LOW);
#endif
  
  digitalWrite(inpLatchPin,   HIGH);
  
  //Reset Shift Registers
  shiftOut(outDataPin, clockPin, MSBFIRST, 0xAA); //Am not sure here... was just trying
  digitalWrite(outLatchPin,      HIGH);
  digitalWrite(outLatchPin,      LOW);
  Serial.begin(9600);
}

void loop()
{
static int byteval = 0x5A;

    dispval("Out: ", byteval);
    digitalWrite(clockPin, LOW); // for rising edge clock
    shiftOut(outDataPin, clockPin, MSBFIRST, byteval);
    digitalWrite(outLatchPin, HIGH);
    digitalWrite(outLatchPin, LOW);
    
    digitalWrite(inpLatchPin, LOW);
    digitalWrite(inpLatchPin, HIGH);
    
    digitalWrite(clockPin, HIGH); // start high to avoid clocking on first bit
    dispval(" In: ", shiftIn(inpDataPin, clockPin, LSBFIRST));
    delay(5000);
    byteval++;
}

void dispval(char *str, uint8_t val)
{
	Serial.print(str);
	for(uint8_t bit = 0; bit < 8; bit++)
	{
		if(val & (1 << (7-bit)))
		{
			Serial.print('1');
		}
		else
		{
			Serial.print('0');
		}
	}
	Serial.println();
}

Hey bill so I've setup a 595 which outputs directly inside the 165 without any other additional components.
I burnt the code you gave me word by word and this is what I got :slight_smile:

Out: 01011010
 In: 00101101
Out: 01011011
 In: 11101101
Out: 01011100
 In: 00011101
Out: 01011101
 In: 11011101
Out: 01011110
 In: 00111101
Out: 01011111
 In: 11111101
Out: 01100000
 In: 00000011
Out: 01100001
 In: 11000011
Out: 01100010
 In: 00100011
Out: 01100011
 In: 01100011
Out: 01100100
 In: 00010011
Out: 01100101
 In: 11010011
Out: 01100110
 In: 00110011
Out: 01100111
 In: 11110011
Out: 01101000
 In: 00001011
Out: 01101001
 In: 11001011
Out: 01101010
 In: 00101011
Out: 01101011
 In: 11101011

What do you think?
I personally looked at those values inputted but I have to admit im clueless... il be experimenting with the code but if you can drop a hint I'd be very glad :slight_smile:
They only matched once in that list but I think its random

Thanks a lot
X

Ok so I've realised that in your code, you were writing them MSBFIRST and was reading them LSBFIRST (this was my experiment previously so my fault that you copied it like that) sorry :blush:

BUT this is the output now that both are MSBFIRST

Out: 01011010
 In: 10110100
Out: 01011011
 In: 10110111
Out: 01011100
 In: 10111000
Out: 01011101
 In: 10111011
Out: 01011110
 In: 10111100
Out: 01011111
 In: 10111111
Out: 01100000
 In: 11000000
Out: 01100001
 In: 11000010
Out: 01100010
 In: 11000100
Out: 01100011
 In: 11000111
Out: 01100100
 In: 11001000
Out: 01100101
 In: 11001011
Out: 01100110
 In: 11001100
Out: 01100111
 In: 11001111
Out: 01101000
 In: 11010000
Out: 01101001
 In: 11010011
Out: 01101010
 In: 11010100
Out: 01101011
 In: 11010111
Out: 01101100
 In: 11011000
Out: 01101101
 In: 11011011
Out: 01101110
 In: 11011100
Out: 01101111
 In: 11011111
Out: 01110000
 In: 11100000
Out: 01110001
 In: 11100011
Out: 01110010
 In: 11100100
Out: 01110011
 In: 11100111
Out: 01110100
 In: 11101000
Out: 01110101
 In: 11101011
Out: 01110110
 In: 11101100
Out: 01110111
 In: 11101110
Out: 01111000
 In: 11110000
Out: 01111001
 In: 11110010
Out: 01111010
 In: 11110100
Out: 01111011
 In: 11110111
Out: 01111100
 In: 11111000
Out: 01111101
 In: 11111011
Out: 01111110
 In: 11111100
Out: 01111111
 In: 11111111
Out: 10000000
 In: 00000001
Out: 10000001
 In: 00000011
Out: 10000010
 In: 00000100
Out: 10000011
 In: 00000111
Out: 10000100
 In: 00001000
Out: 10000101
 In: 00001011

And as you can see, they are ALL SHIFTED 1 bit to the left! Must be missing some cycle somewhere :slight_smile:

Getting there :slight_smile: :stuck_out_tongue_closed_eyes: ]:slight_smile: ]:smiley:

Oops. I think I led you a stray.
I believe it is an extra clock not a missing clock.
I wish I had one of these to test with so I could see the actual results.

Move the setting of the clock pin to HIGH above
the latching of the input SR data.
As it is I believe it is clocking the data before the shiftIn() is called.

The intent is to not clock the data on the first bit read but then clock it on the remaining bits.
So the clock line has to be set in a way that keeps shiftIn() from causing a clock on the first bit.
Since shiftIn() clocks H->L on each bit, if the clock is HIGH when shifIn() starts, the first bit
will not cause a clock shift on the data when using rising edge clocks (which the 165 uses).
Then, each subsequent bit will cause a clock which shifts the bits over to be read.

Since the same clock line was used for shiftOut() the clock is LOW when shiftOut() finishes.
That is why it must be set back to HIGH before shiftIn() is called.
However, this must be done before the data is latched, or else it will clock the data accidentally
(which shifts it to the left) before shiftIn() is called.
Which is what I believe we are seeing.

So change this:

    digitalWrite(inpLatchPin, LOW);
    digitalWrite(inpLatchPin, HIGH);
    
    digitalWrite(clockPin, HIGH); // start high to avoid clocking on first bit

to:

    digitalWrite(clockPin, HIGH); // start high to avoid clocking on first bit
    digitalWrite(inpLatchPin, LOW);
    digitalWrite(inpLatchPin, HIGH);

--- bill

Out: 01011010  90
 In: 01011010  90
Out: 01011011  91
 In: 01011011  91
Out: 01011100  92
 In: 01011100  92
Out: 01011101  93
 In: 01011101  93
Out: 01011110  94
 In: 01011110  94
Out: 01011111  95
 In: 01011111  95
Out: 01100000  96
 In: 01100000  96
Out: 01100001  97
 In: 01100001  97
Out: 01100010  98
 In: 01100010  98
Out: 01100011  99
 In: 01100011  99
Out: 01100100  100
 In: 01100100  100
Out: 01100101  101
 In: 01100101  101
Out: 01100110  102
 In: 01100110  102
Out: 01100111  103
 In: 01100111  103
Out: 01101000  104
 In: 01101000  104
Out: 01101001  105
 In: 01101001  105
Out: 01101010  106
 In: 01101010  106
Out: 01101011  107
 In: 01101011  107
Out: 01101100  108
 In: 01101100  108
Out: 01101101  109
 In: 01101101  109
Out: 01101110  110
 In: 01101110  110
Out: 01101111  111
 In: 01101111  111
Out: 01110000  112
 In: 01110000  112
Out: 01110001  113
 In: 01110001  113
Out: 01110010  114
 In: 01110010  114
Out: 01110011  115
 In: 01110011  115
Out: 01110100  116
 In: 01110100  116
Out: 01110101  117
 In: 01110101  117
Out: 01110110  118
 In: 01110110  118
Out: 01110111  119
 In: 01110111  119
Out: 01111000  120
 In: 01111000  120
Out: 01111001  121
 In: 01111001  121
Out: 01111010  122
 In: 01111010  122
Out: 01111011  123
 In: 01111011  123
Out: 01111100  124
 In: 01111100  124

Bill we need people like you!! Amazing dedication! I'm so happy that if you want I can send you a bunch of these 165's free of charge! :slight_smile:

Thanks a lot buddy :slight_smile:

PS: The number you see up there? I added that to avoid comparing the bits since all I was interested in was to get the bits to read identically!
Cheers

Xenobius:
PS: The number you see up there? I added that to avoid comparing the bits since all I was interested in was to get the bits to read identically!
Cheers

Binary is really useful though, particularly in these cases where the data is all bit based.
It makes it easy to see things like reversed ordered bits or shifted bits.
(or both as was in the first listing output).
These kinds of little issues/problems are quite common when initially debugging
the code and circuit as its easy push/pull the bits in the wrong order or to accidentally skip a clock
or generate an extra clock.

Glad it works.
I am curious what the final circuit is to be used for.
Almost seems like some kind of self destruct mechanism.
Or maybe a solid fuel rocket engine igniter?

--- bill

Oh no don't get me wrong, if it wasn't for the bits, I wouldn't have noticed that they are being shifted by 1 however once I got everything matching I wanted an easy way to match hehe :slight_smile:

Also about the circuit, you're pretty close hehe I'll PM you the final circuit because its part of a Masters Dissertation that I am working on and the last thing I want is for someone to steal this :stuck_out_tongue:

Cheers
X