All the tests and codes used were done with Arduino and Arduino IDE 1.0.3.

This is a experiment about a 2 wire latched shift register driver. Latched shift registers usually needs 3 signal wires to work. In this post I will show how to drive such a shift register using a propagation delay circuit made out from discrete parts, in this case 3 transistors and 5 resistors. With this setup you can save one microcontroller pin.

There are some specialized IC’s that can do this job like SN74LS122. The point about this circuit is that it can be conceived from very cheap and easy to find components.

This post consider that you know already the basic concept about the serial communication used to drive the shift register.

A monostable propagation delay circuit is used to achieve the goal. In the circuit, the transistor Q3 is used to produce a inverted signal at output. You can try this circuit using only transistors Q1 & Q2. (details about the non-inverting circuit at the end of this post)

.


The concept:


The concept is show on the block diagrams.

 3-wire SR  2-wire SR
 SR  dl

.


Components for this experiment:


1x Arduino

1x 74HC595 shift register

2x PNP transistors (BC558)

1x NPN transistor (BC547)

5x Resistors (3x 10K, 1x 30K, 1x 1K)

.


Monostable propagation delay circuit


The images below show the used circuit and the waves input/output.

 Circuit diagram  IO waves
 trigger  IO

You usually need  8 clock pulses to drive each bit of a  8-bit shift register. In the scope picture you can see 9 clock pulses. The spare clock pulse (first one), is used to trigger the circuit and change and hold the latch line to LOW, preparing the shift register to start receiving each of the 8 subsequent bits.

After the last clock pulse the trigger will bring the latch line to HIGH,  updating the information on SR outputs.

Note that in the circuit, the main resistor that adjusts the trigger is the resistor R3. With R3 set too low, trigger starts failing.

As said before transistor Q3 purpose is to produce a  inverted signal at output.

The following image show different results on the latch line varying resistor R3:

 R3

Timing:

This test was done with clock frequency = 62.5KHz

Amount of time to trigger return to initial state after the last clock pulse: 40µs.

The reset time was taken from the scope, considering the worst case scenario observed (averaged readings): sc4

.


Working code:


The code bellow is nothing more than the Shift Out example sketch adapted to work with this circuit.

// We dont need the next line, we are saving a pin
//const int latchPin = 9;

////Pin connected to Clock pin in (DS) of 74HC595
const int clockPin = 10;

////Pin connected to Data in (DS) of 74HC595
const int dataPin = 8;
byte trd = 0 ;

void setup() {
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}

void loop () {

trd=random(255);
// We dont need the next line anymore
//digitalWrite(latchPin, LOW);

// Next two lines to generate the extra clock pulse to trigger the delay circuit
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);

shiftOut(dataPin, clockPin, MSBFIRST, trd);

// We dont need the next line anymore
//digitalWrite(latchPin, HIGH);

// You need to wait some time so the trigger can return to its initial state before the next SR cycle
// You probably dont need this line if you have some amount of code after shifOut
// Set a larger delay here if you want to visualize (trough leds e.g.), each shifted byte.
delayMicroseconds(40);

 }

.


Reliability check:


A reliability check was performed after the initial test. For this test each pin on PORTD (pins from 0 to 7 on Arduino), was wired directly to shift register outputs using internal pull-up resistors. The sketch performs a SR write and this original byte is compared to one found by reading PORTD pins. If some fail occurs a variable is set. The final result of the test can be viewed on the led attached to Arduino pin 13.

This sketch test indivudual SR cycles 9,000,000 times. I ran this sketch 4 times and got successful results in all times.

You can find more details on the commented lines:


// This sketch is a reliability check on the 2-wire latched SR driver
// It writes a byte value to the shift register and uses PORTD to check for the same byte in return
// Each pin on PORTD is directly wired to shift register outputs using internall pull-up resistors
// After each SR cycle the byte found on PORTD is compared against the original value
// The final result of the test is displayed on the led attached to Arduino pin 13.
// If led blinks fast (100ms interval), the circuit passed the test. If it blinks slow (500ms interval), the circuit didnt passed the test

const int clockPin = 10;
const int dataPin = 8;

// Some variables to be used in the loop
int ctr = 0 ;
unsigned long ctr2 = 0 ;
int ctr3 = 0 ;
byte trd = 0 ;

void setup() {

pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(13, OUTPUT); // Led pin for visualziation of the final status of test

// loop to initialize PORTD inputs with internal pull-ups
for(int i=0;i<8;i++) {
pinMode(i, INPUT);
digitalWrite(i, HIGH);
}

// Next line isnt much important
randomSeed(analogRead(A0)) ;

// Next line to just avoid power source transients after turning the entire circuit ON
delay(1000);

}

void loop () {

//  The following loop performs a single tests and comparison against PORTD values while "ctr==0".
//  It sets "ctr3=1" incase the shifted byte isnt equal the one on PORTD
if(ctr == 0) {
ctr2++;
trd=random(255);
//trd = 75 ;
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);

// You may need to change next line bit order to LSBFIRST depending the way you wired PORTD pins to SR outputs.
shiftOut(dataPin, clockPin, MSBFIRST, trd);

// You need to wait some time so the trigger can return to its initial state before the next SR cycle
// You probably dont need this line if you have some amount of code after shifOut
// Set a larger delay here if you want to visualize (trough leds e.g.), each byte shifted
delayMicroseconds(40);

// Next lines read a byte from PORTD and compare against the original byte "trd".
// It sets "ctr3=1" in case it fails in this comparison
if(trd != PIND) {
ctr3 = 1 ;
}
}

// next test stops single tests and blink the led fast incase the test was a success
// In this test it will perform 9,000,000 single tests then stop. You can lower this value
if(ctr2 > 9000000 && ctr3 == 0) {
ctr = 1;
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW) ;
delay(100);
}

// next test stops single tests and blink the led slow incase the test failed
// In this test it will perform 9,000,000 single tests then stop. You can lower this value
if(ctr2 > 9000000 && ctr3 == 1) {
ctr = 1;
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW) ;
delay(500);
}
}

Experiment on breadboard:
bread
.


non-inverting circuit


The non-inverting signal was achieved with the following circuit:

noninverting

non-inverting circuit

This non-inverting version presented a much larger falling time after last clock pulse. While the  inverting circuit presented 40µs this non-inverting one presented 150µs. Also the signal isn’t much stable considering the same clock frequency used in the first test (62.5KHz). To adjust the larger falling time, resistor R3 was replaced to 10K value. This reduced the falling time to 80µs, while making the signal a bit worse regarding stability.

With this circuit a stable signal was achieved using clock frequency of  96KHz but without much place for transients until spikes starts occurring . The inverting version seems much more reliable in tested frequency ranges.

62.5KHz 96KHz
ni62 ni96

.

That’s all !

Advertisements