[solved] shift register 74hc595

Hello everyone,

I currently trying to get the 74hc595 shift register to work using the SPI method from Nick Gammon

http://www.gammon.com.au/forum/?id=11518

I want to conserve my I/O pins and therefore I use SPI versions of my other chips. I read in another forum post

that I send the relevant data with one byte over the SER on the shift register. In my case I want to switch on a LED on Qc (Pin 2 on the 595)

// Pin 2 --> B01000000
// All pins off --> B000000000

Now the problem: It works only the first two times, then the LED keeps on.

I measured the incoming signal off the data pin (SER) and it shows the correct byte value.

// changed code from Nick Gammon
#include <Arduino.h>
#include <SPI.h>

const byte LATCH = 10;

void setup ()
{
  Serial.begin(9600);
  SPI.begin ();
  pinMode(LATCH, OUTPUT);
}  // end of setup

byte c;
byte onoff = 0;
void loop ()
{
  c++;

  byte x = Serial.read();


  if(x=='x') {

    digitalWrite (LATCH, LOW);
    onoff = !onoff;

    Serial.print("state "); Serial.println(onoff);
    if(onoff) {
      SPI.transfer(B01000000);
    } else {
      SPI.transfer(B00000000);
    }

    digitalWrite (LATCH, HIGH);
    // delay (20);
  }

  delay(15);
}  // end of loop

I tested the same setup using the shiftout method on the Arduino pins 4,5,6 (like in my old manual) and it worked without problems.

What am I doing wrong?

Short update:
I rearranged some parameters and rewrote the shift-register library from Nick Gammon to better understand whats happening.

For some reason it is working now.

I now can toggle the individual pins using the numbers 0-7 and ‘c’ to clear the board. I tested it with the standard configuration, but then the SPI would be blocked as constant OUTPUT.

main.h

#include <Arduino.h>
#include <SPI.h>

#include "SN74HC595.h"

// SN74HC595 SHIFTREGISTER = SN74HC595(11,10,13);
SN74HC595 SHIFTREGISTER = SN74HC595(10);


void setup() {

  SHIFTREGISTER.initialize();

  SPI.begin();

  Serial.begin(9600);



  Serial.println("--- Setup ---");


}

void normalMode() {
  byte x = Serial.read();

  if(x=='x') {
    Serial.println(SHIFTREGISTER.SLAVESELECT);
  } else if(x=='c') {
    Serial.println("clear");
    SHIFTREGISTER.writeData(0);
    SHIFTREGISTER.update();
  }

  x = x - '0';

  if(x>=0 && x<8) {
    Serial.println(x);
    // onoff = !onoff;
    SHIFTREGISTER.writeData(x, OR);
    SHIFTREGISTER.update();
  }

  delay(100);
}

void spiMode() {

  byte x = Serial.read();

  if(x=='c') {
    SHIFTREGISTER.writeData(0);
    SHIFTREGISTER.updateSpi();
  }

  x = x-'0';

  if(x>=0 && x<8) {
    SHIFTREGISTER.writeData(x, OR);
    SHIFTREGISTER.updateSpi();
  }

}

void loop() {

  spiMode();

}

The library contains a normal operation mode (for test purposes) and the communication using SPI

SN74HC595.h

#ifndef SN74HC595_H
#define SN74HC595_H

#include <Arduino.h>
#include <SPI.h>

class SN74HC595 {
public:
  SN74HC595(uint8_t datapin, uint8_t latchpin, uint8_t clockpin) {
    DATAPIN=datapin;
    SLAVESELECT=latchpin;
    CLOCKPIN=clockpin;
  }

  SN74HC595(uint8_t slaveselect) {
    SLAVESELECT=slaveselect;
    // pinMode(SLAVESELECT, OUTPUT);
    // pinMode(DATAPIN, OUTPUT);
    // pinMode(CLOCKPIN, OUTPUT);
  }


  uint8_t DATAPIN = 0;
  uint8_t SLAVESELECT = 0;
  uint8_t CLOCKPIN = 0;

  uint8_t STATUS = 0;

  void initialize() {

    // pinMode(DATAPIN, OUTPUT);
    // pinMode(CLOCKPIN, OUTPUT);
    pinMode(SLAVESELECT, OUTPUT);
    delay(25);

    // update();
  }

  void update() {
    digitalWrite(SLAVESELECT,LOW);
    shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, STATUS);
    digitalWrite(SLAVESELECT,HIGH);
  }

  void updateSpi() {
    digitalWrite(SLAVESELECT,LOW);
    SPI.transfer(STATUS);
    digitalWrite(SLAVESELECT,HIGH);
  }

  void writeData(uint8_t data, uint8_t operation) {

    uint8_t temp = 0;
    bitSet(temp,data);

    if(operation==AND) {
      STATUS = STATUS & temp;
    } else if(operation==OR) {
      STATUS = STATUS | temp;
    }

    Serial.println(STATUS,BIN);
  }

  void writeData(uint8_t data) {
    STATUS = data;
    Serial.println(STATUS,BIN);
  }

};

#endif

I did not change the hardware setup! The only difference in the codes is that I now initialize the SS-Pin before I begin the SPI communication and at last the Serial communication for debugging reasons (will be removed in the final revision).

Does the initialization starting position influence the communication? Maybe someone can explain this.
Or is it something I am completely missing?

Can you post a schematic, please? Not one of Nick's, your own, drawn from your circuit exactly as-is. Hand-drawn is fine. Also a close-up picture or two of your circuit, well-lit and focussed.

I noticed an error on Nick's page. There is a component missing on the picture of the breadboard. That component is shown on the schematics on the same page. Perhaps you made the same error?

Here is the schematic.

I added a decoupling capacitor and a pull-up on the latch pin. I currently use an Arduino Nano, so I added the pin numbers on the labels

Ok, the missing component I was talking about was the 0.1uF decoupling cap, but you have that. It should be as close to the 5V & gnd pins of the chip as possible.

The 10K resistor on the clock line is a new one! Get rid of that. Any different?

Sorry. My mistake again. The schematic was wrong, not the hardware.

The pull-up is on the SS-pin (Pin 10).

It seems to work for now with the Software in my earlier post.

v3xX:

But I do not understand why. That makes me a little nervous.


That 10K is still wrong. It is not needed.

You mentioned a "pull up". Were you referring to that 10K? If so, you are not using the resistor as a pull up. A pull up resistor is connected between a pin and 5V, not between two pins. Its called a pull up because it pulls the pin up to 5V. Similarly, a "pull down" resistor is connected between a pin and 0V. But I don't see any need for any pull up in this circuit.

PaulRB:
But I don’t see any need for any pull up in this circuit.

Did you look at Nick’s reference?

There is essentially always a need for a pull-up on a 74HC595 or MAX7219, on either latch or clock line. 47k would generally suffice.

Hi Paul. Yes, I did look. Can you give a more precise indication where Nick uses these pull ups? He does show a pull down on the latch pin, and says that this is to prevent accidental latching of bits during Arduino startup. But this is a nice to have, rather than a necessity, with LEDs. I can see that if the SRs were driving relays/pumps etc, it would be more important to prevent that.

I should really sleep more.

Once again the schematic is wrong and I rebuild the circuit with the false one. It still works, but sometimes it does not switch. The communication is fine.

I upload the (hopefully) final schematic of my circuit, with the pull-up and decoupling in the right places. There are no problems so far. The communication is fast and even the startup of the system is stable (looking at the peak voltages).

sn74hc595.jpg

I changed to software and rebuild the circuit and now it works. Since I lost track where the real problem begin (a hardware error I overlooked or some line of code in the wrong position) I will close this thread, since all is working fine now.

The code I use is in post

v3xX:

Thanks for all your help and once again sorry for the schematic confusion. I will pay more attention in the future.

PaulRB:
Hi Paul. Yes, I did look. Can you give a more precise indication where Nick uses these pull ups? He does show a pull down on the latch pin, and says that this is to prevent accidental latching of bits during Arduino startup.

Pull down, pull up ...