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);
}
}
jsotola
  • 1,554
  • 2
  • 12
  • 20
Niko
  • 93
  • 8

3 Answers3

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(&quot;Displaying: &quot;);
//   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 &lt; 8; i++)  {
        if (bitOrder == LSBFIRST)
              digitalWrite(dataPin, !!(val &amp; (1 &lt;&lt; i)));
        else      
              digitalWrite(dataPin, !!(val &amp; (1 &lt;&lt; (7 - i))));

        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);            
  }

}

Niko
  • 93
  • 8
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.

Nick Gammon
  • 38,901
  • 13
  • 69
  • 125
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.

Matt
  • 176
  • 1
  • 4