5

I made a simple circuit with an Arduino Nano ESP32, where I have connected a 74HC595 8-bit shift register chip, as well as a 7 segment display with a 100 ohm resistor on common (cathode) to show the shift register's state.

Expected Behavior

Seven segment display shows binary counting from 0-255.

Observed Behavior

The seven segment display continuously shows 8., which basically means the state of the shift register is 0b11111111.

When I use 5V (VBUS) instead of 3.3V for VCC of the IC, the shift register shows all zeros instead of all ones.

Attempts at Debugging

I have checked all input cables with my multimeter to check for any broken connections and everything seems to be fine. I also replaced the chip itself multiple times, same results. I tried replacing the resistor at the common of the seven segment display to something like 1,000 ohm, then back. Same results. I also used different sketches for testing, same results.

Resources

I made the current version of my circuit and code as a WOKWI (emulator) project: https://wokwi.com/projects/396140725340271617 [OUTDATED (also wont update for some reason)]

It features about the same exact connections I have on my breadboard.

Here is a screenshot of the circuit: enter image description here

And the code, just in case wokwi might cease to exist in the future..

//**************************************************************//
//  Name    : shiftOutCode, Hello World
//  Author  : Carlyn Maw,Tom Igoe, David A. Mellis
//  Date    : 25 Oct, 2006
//  Modified: 23 Mar 2010
//  Version : 2.0
//  Notes   : Code for using a 74HC595 Shift Register           //
//          : to count from 0 to 255
//****************************************************************
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
void setup() {
//set pins to output so you can control the shift register
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// count from 0 to 255 ankKomd display the number
// on the LEDs
for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) {
// take the latchPin low so
// the LEDs don't change while you're sending in bits:
   digitalWrite(latchPin, LOW);
// shift out the bits:
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay);
//take the latch pin high so the LEDs will light up:
digitalWrite(latchPin, HIGH);
// pause before next value:
delay(500);
}
}
13
  • 2
    Consider copying that circuit image and code to your question above. People here don't like off site links as they can break over time. The idea is to keep these questions / answers for others to read even years from now.
    – st2000
    Commented Apr 25 at 13:04
  • 1
    If you need LED current limiting resistors, you will need one for each segment. Not just one for the entire display. By the way, there are no resistors in the circuit diagram. Did you forget to place them?
    – st2000
    Commented Apr 25 at 13:06
  • Yes, sorry. I unfortunately dont have enough resistors to place one for each segment, so for now I've placed one for common. I'll edit my question to include the screenshot in the question, thanks.
    – Niko
    Commented Apr 25 at 13:08
  • You haven't made it very clear what you are attempting to do. If you are trying to use an 7 segment display to represent 8 bit binary numbers (between 0 and 255 dec.) then you have to show a mapping between each segment and the position of that segment between high order and low order binary bit. For example, it could be decimal point = high order bit (bit7), middle dash (segment G) = bit 6 etc.
    – 6v6gt
    Commented Apr 25 at 15:04
  • The line setting latch to low is commented out. That alone breaks the code, as 74595 latches on the rising edge only.
    – Matt
    Commented Apr 25 at 15:39

3 Answers 3

4

I can't believe a one second delay is needed to clock data out. I have loops that clock out bits using SPI with no delays, which is even faster than shiftOut. See Using a 74HC595 output shift register as a port-expander.

You have some other issue.

Possibly what is happening is that it is working perfectly, but the number is changing so quickly that it appear that all segments are on.

Plus, you really shouldn't be testing without current-limiting resistors on every segment. A single common one will behave weirdly depending on how many segments are on at a time.

2
  • Hi, thanks for your answer. I did some more experimenting and turns out that you're right, I don't need a one second delay to clock data out, but I do need SOME kind of delay to see the segments light up. So yes, I guess the numbers were changing so quickly that I couldn't see them changing.
    – Niko
    Commented Apr 25 at 21:56
  • As for the resistors, I sadly don't have enough resistors to do that right now, and I've done some reading and concluded that the only side effect of having a single common one is a dimmer display when more segments are enabled. For now I should be fine but once I get some better resources I'll make sure to put resistors for each segment.
    – Niko
    Commented Apr 25 at 21:58
4

I would've never ever expected this, but turns out that my MCU was 'too fast' (i suppose) and so nothing would show. This is the code before the fix:

    digitalWrite(latchPin, LOW); // Latch the data
    // no delay
    digitalWrite(latchPin, HIGH); // Unlatch for next data

and this is the code after:

    digitalWrite(latchPin, LOW); // Latch the data
    delay(1000);     // Short delay for visibility (adjust as needed)
    digitalWrite(latchPin, HIGH); // Unlatch for next data

I'm still experimenting with the shift register so I'll edit this answer if anything new pops up, or if my answer is entirely wrong.

EDIT: I did not need a one second delay between clock pulses, I appearantly just needed some delay to actually see the seven segment displays changing. (thanks @NickGammon)

EDIT: Here's the full code if anybody wants it, it displays a spiraling animation on the 7 segment display.

uint8_t latchPin = D8;
uint8_t clockPin = D12;
uint8_t dataPin = D11;


const byte segments[10] = { // Lookup table for digit patterns (common cathode)
  0b00111111,  // 0
  0b00000110,  // 1
  0b01011011,  // 2
  0b01001111,  // 3
  0b01100110,  // 4
  0b01101101,  // 5
  0b01111100,  // 6
  0b00000111,  // 7
  0b01111111,  // 8
  0b01101111   // 9
};

void setup() {
  // Set control pins as outputs
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  Serial.begin(115200); // Start serial communication for debugging
  Serial.println("Starting...");

  displaySegments(0x00000000); // reset on startup, not needed just makes it look better ig
  delay(1000);
}


void spiralAnimation() {


  // Loop through each segment in the spiral order
  for (int i = 0; i < 7 - 1; i++) { // 7 being the number of segments, ignoring G so it looks better
    shiftOut(dataPin, clockPin, MSBFIRST, 0b00000001 << i);
    digitalWrite(latchPin, LOW);
    delayMicroseconds(1000);
    digitalWrite(latchPin, HIGH);
    delay(80); // Adjust delay for animation speed
  }
}

void loop() {
  // Loop through each digit pattern (modify for specific display)
    // for (int i = 0; i < 10; i++) {
    //   shiftOut(dataPin, clockPin, MSBFIRST, segments[i]);
    //   digitalWrite(latchPin, LOW); // Latch the data
    //   delay(100);     // Short delay for visibility (adjust as needed)
    //   digitalWrite(latchPin, HIGH); // Unlatch for next data

    //   Serial.print("Displaying: ");
    //   Serial.println(i);
    // }

    spiralAnimation();
}

void displaySegments(byte pattern) {
  shiftOut(dataPin, clockPin, MSBFIRST, pattern);
  digitalWrite(latchPin, LOW);
  delayMicroseconds(1000); // no need to edit this
  digitalWrite(latchPin, HIGH);
}

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) // just in case
{
      uint8_t i;

      for (i = 0; i < 8; i++)  {
            if (bitOrder == LSBFIRST)
                  digitalWrite(dataPin, !!(val & (1 << i)));
            else      
                  digitalWrite(dataPin, !!(val & (1 << (7 - i))));
                  
            digitalWrite(clockPin, HIGH);
            digitalWrite(clockPin, LOW);            
      }
}
1
  • So far with some quick testing everything's actually working as expected.
    – Niko
    Commented Apr 25 at 21:36
0

First of all, the code in the question does not match the code in "the supposed solution". ShiftOut function is pretty slow, so it could work as an extra delay when put between latch settings. So the code in question looks robust in this sense, imo.

Next, it is dubious to require a whole millisecond delay even in the second case. 74hc595 chip should be able to deal with signal faster than 10 MHz even when on 3v3 power supply. And digitalWrite function is also quite slow (as it is with the whole Arduino's extra compatibility layer), so I don't see any problem here.

More likely, this is due to parasitic capacitance. So the latch line (too long?) doesn't have enough time to discharge even at few megs speed. Then the shift register will never see low voltage level, except on startup. Proper connections (soldering wires, or at least using only short jumpers) should solve the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.