Sequential loss of output from shift register

I'll try to explain what I'm seeing here. I'm trying out a concept by sending a number from the serial monitor to the Arduino, which sends the binary equivalent to LEDs through a 74HC595 shift register. If I send any number which includes the lowest bit, i.e. an odd number, there is a 2 to 3 second delay before the LEDs are energized. There is no delay for even numbers that don't include the lowest bit.

For example If I send 90 there is an immediate response. If I send 89 or 91, I see the delay. It doesn't matter what was previously displayed. Any odd number, even if twice in a row gets the delay.

Can someone explain what is happening here?

// Pin connections to 74HC595
const int latchPin = 8;   // To 74HC595 pin 12
const int clockPin = 12;  // To 74HC595 pin 11
const int dataPin  = 11;  // To 74HC595 pin 14

byte outputData = 0; // Stores the byte to send

void setup() {
  pinMode(dataPin, OUTPUT);  // Serial data to register
  pinMode(latchPin, OUTPUT); // Latches register outputs
  pinMode(clockPin, OUTPUT); // Clock signal

  Serial.begin(9600);
  Serial.println("Enter a number (0-255) to send to 74HC595:");
}
/* R-R = 129  \
   R-Y = 130  |  These are the
   R-G = 132   > five possible
   Y-R = 65   |  signal aspects
   G-R = 33   /
*/

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n'); // Read until newline
    input.trim(); // Remove spaces

    if (input.length() > 0) {
      int value = input.toInt();
      if (value >= 0 && value <= 255) {
        outputData = (byte)value;
        digitalWrite(latchPin, LOW); // To allow data flow
          shiftOut(dataPin, clockPin, MSBFIRST, outputData);
        digitalWrite(latchPin, HIGH); // Hold data in register
        Serial.print("Entered ");
        Serial.println(outputData, DEC);
        Serial.print("Binary: ");
        Serial.println(outputData, BIN); // Output as binary no.
        Serial.print("Hex: ");
        Serial.println(outputData, HEX); // Hexadecimal equivalent
      } else {
        Serial.println("Invalid number. Enter 0-255.");
      }
    }
  }
}

readStringUntil('\n') waits until it sees a newline. If your Serial Monitor is not set to send a newline, Arduino waits for the serial timeout, usually about 1 second. That looks like a delay.

Set the Serial Monitor line ending to:Both NL & CR. After serial.begin add Serial.setTimeout(50);

Your problem also appears when you have bit 0 set. So check whatever is connected to Q0 of the 74HC595. It may be driving a heavier load, wrong LED polarity, transistor base, relay input, missing resistor, or something with capacitance. Without a schematic this is only a guess.

Rather than waiting to read "\n", count the bits and terminate when the bit count is satisfied.

I am not sure, what happened, but I suggest add one Serial.print before the shiftOut, to see, where the pause happens

If you see the Shifting: immediatelly followed by Entered, then the problem is not in shifting, but somewhere else

I will try these suggestions to see what happens. Looking at similar posts, I think I see others having an issue with bit 0. Anyway here is the schematic. Right now it's using a Sparkfun Redboard QWIIC instead of the nano shown here.

Just small detail:
on 74HC595 the serial data are clocked inside on each rising edge of clock and are latched on each rising edge of latch

So it does not need the latch high or low to clock the data in, it just need to make the rising edge after the data are there.
Your program should work correctly in this detail, just comments suggest something slightly different.

@k6mug
Try the following schematic (Fig-1) for SPI Protocol instaed of bit-banging:

1. Build the following circuit.


Figure-1:

2. Upload the following sketch.
Reeceive New Line terminated string of decimal digits from InputBox of Serial Monitor, extract the single-valued decimal number, save it and then transmits to 74C595 shift register over SPI port. Check that the corresponding LEDs are On.

Sketch:

#include <SPI.h>

const int storePin = 10;  // ST_CP
char myData[10];

void setup() 
{
  Serial.begin(9600);
  pinMode(storePin, OUTPUT);
  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  digitalWrite(storePin, LOW);  // Prepare latch
  //--------------------
  SPI.transfer(0b00000000);      // 0x00  ; all LEDs are Off
  digitalWrite(storePin, HIGH);  // Output appears on Q0–Q7
  delayMicroseconds(5);
  digitalWrite(storePin, LOW);
}

void loop() 
{
  byte n = Serial.available();
  if (n != 0) 
{
    byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
    myData[m] = '\0';
    byte y = atoi(myData);      //y = 23 DEC = 0x17 = 0001 0111
    Serial.println(y, BIN);     //received data shown on Serial Monitor as bit
    //--------------------
    SPI.transfer(y);               // received data s transmitted to HC595; check LEDs
    digitalWrite(storePin, HIGH);  // Output appears on Q0–Q7
    delayMicroseconds(5);
    digitalWrite(storePin, LOW);
  }
}

3. Open Serial Monitor at Bd = 9600 and New Line option.

4. Enter 23 into InputBox of Serial Monitor and then click on send button.

4. Check the LED On/Off status as follows: (23 ===> 0x17 = 0001 0111)

LED7  LED6  LED5  LED4  LED3  LED2  LED1  LED0
Off   Off   Off   On    Off   On    On    On

How are you powering this, you show a 12V source that is not used. Is that where you are applying the USB power?

If those resistors are 270Ω then they are way to small. Try 680Ω, the HC595 can only drive 6mA

At what Vcc?

OP is operating HC595 at Vcc = 5V.

If you want to know how an HC595 works, then start your own topic. Do not try to HIJACK this topic with irrelavent and off topic questions.

As far as I understand the problem, @gilshultz is investigating what I would consider the most likely direction first.

I'd want to know exactly where the delay occurs before suspecting the 74HC595 itself.

After the termination of readStringUntil() (either due to New Line or timeout whatever happens first) function, the program extracts the numerial value of the incoming string; so, that timeout delay should not be a factor here.

The OP is lazy to test the alternative method of post #7.

@k6mug
I ahve tested my circuit and sketch in Step-1,2. After that I have tested your circuit and sketch in Step-3. In bote cases, odd or even number data is instantly propagated along the output lines of HC595. There is bsolutely no delay at all. You may try chnaging the NANO.

Practical Obseravtion:
1. The following circuit (Fig-1) of @GolamMostafa and UNO R3.


Figure-1:

2. Uploading the following sketch which uses readBytesUntil() method and SPI Protocol does not show any delay whether sending odd or even numbers from the Serial Monitor. The bits get instantly transferred to the output lines of HC595.

#include <SPI.h>

const int storePin = 10;  // ST_CP
char myData[10];

void setup() 
{
  Serial.begin(9600);
  pinMode(storePin, OUTPUT);
  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  digitalWrite(storePin, LOW);  // Prepare latch
  //--------------------
  SPI.transfer(0b00000000);      // 0x00  ; all LEDs are Off
  digitalWrite(storePin, HIGH);  // Output appears on Q0–Q7
  delayMicroseconds(5);
  digitalWrite(storePin, LOW);
}

void loop() 
{
  byte n = Serial.available();
  if (n != 0) 
{
    byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
    myData[m] = '\0';
    byte y = atoi(myData);      //y = 23 DEC = 0x17 = 0001 0111
    Serial.println(y, BIN);     //received data shown on Serial Monitor as bit
    //--------------------
    SPI.transfer(y);               // received data s transmitted to HC595; check LEDs
    digitalWrite(storePin, HIGH);  // Output appears on Q0–Q7
    delayMicroseconds(5);
    digitalWrite(storePin, LOW);
  }
}

3. Now, uploading @k6mug following bit-bang code in NANO based on his following circuit of Fig-2.

// Pin connections to 74HC595
const int latchPin = 8;   // To 74HC595 pin 12
const int clockPin = 12;  // To 74HC595 pin 11
const int dataPin  = 11;  // To 74HC595 pin 14

byte outputData = 0; // Stores the byte to send

void setup() {
  pinMode(dataPin, OUTPUT);  // Serial data to register
  pinMode(latchPin, OUTPUT); // Latches register outputs
  pinMode(clockPin, OUTPUT); // Clock signal

  Serial.begin(9600);
  Serial.println("Enter a number (0-255) to send to 74HC595:");
}
/* R-R = 129  \
   R-Y = 130  |  These are the
   R-G = 132   > five possible
   Y-R = 65   |  signal aspects
   G-R = 33   /
*/

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n'); // Read until newline
    input.trim(); // Remove spaces

    if (input.length() > 0) {
      int value = input.toInt();
      if (value >= 0 && value <= 255) {
        outputData = (byte)value;
        digitalWrite(latchPin, LOW); // To allow data flow
          shiftOut(dataPin, clockPin, MSBFIRST, outputData);
        digitalWrite(latchPin, HIGH); // Hold data in register
        Serial.print("Entered ");
        Serial.println(outputData, DEC);
        Serial.print("Binary: ");
        Serial.println(outputData, BIN); // Output as binary no.
        Serial.print("Hex: ");
        Serial.println(outputData, HEX); // Hexadecimal equivalent
      } else {
        Serial.println("Invalid number. Enter 0-255.");
      }
    }
  }
}


Figure-2:

Results:
I have not found any delay at all. I have tested sending 0, 1, 2, 3; there is no absolutely no delay. The data is instatntly propgated along the output lines of HC559. There is nothing wrong in the circuit and sketch unless the NANO is a falty. He may try chnaging the NANO.

Output:

20:30:45.203 -> Enter a number (0-255) to send to 74HC595:
20:30:52.731 -> Entered 0
20:30:52.731 -> Binary: 0
20:30:52.731 -> Hex: 0
20:30:57.254 -> Entered 1
20:30:57.254 -> Binary: 1
20:30:57.254 -> Hex: 1
20:31:03.046 -> Entered 2
20:31:03.046 -> Binary: 10
20:31:03.046 -> Hex: 2
20:31:08.430 -> Entered 3
20:31:08.430 -> Binary: 11
20:31:08.430 -> Hex: 3

Since the serial monitor is connected, the USB port is powered from the computer.

You should react to post #14.

To convince me that you done the physical experiment, kindly post the camera picture of your setup.

I want to vote for the Serial Monitor "Newline" setting being None as the problem, mainly because I can't think of anything else in the sketch that would cause a delay. But I'm having trouble fitting that with the fact that the delay only occurs on odd numbers, since it seems it should occur on all numbers.

So serial traffic is always LSB first, which means that the LSB is actually sent first, and if we're talking Ascii digits, then the last bit sent would almost always be a zero followed by the stop bit. So then why a delay only on odd numbers?

As somebody stated, it seem the first task is to determine where the delay is actually occurring, and some diagnostic Serial.println()s could clarify that.

You are overloading the HC595. Once you violate the specifications, strange things can happen.

I have verified your above proposition, and you are apparently right!

I have changed the option from Newline to No line ending, and there is about 1 or 2 seconds delay for the (odd or even both) number to propagate along the output lines of HC595. (My LEDs are conneted with 2.2k series resistors.)

Conclusion: The OP has physically selected No line ending though his sketch contains Newline as terminating character. As a result, readStringUntik() function terminates after the expiry of default timeout period of 1 sec. I have verified it by setting (see OP's sketch below) the timeout period to 5 sec (Serial.setTimeout(5000)).

// Pin connections to 74HC595
const int latchPin = 8;   // To 74HC595 pin 12
const int clockPin = 12;  // To 74HC595 pin 11
const int dataPin  = 11;  // To 74HC595 pin 14

byte outputData = 0; // Stores the byte to send

void setup() {
  pinMode(dataPin, OUTPUT);  // Serial data to register
  pinMode(latchPin, OUTPUT); // Latches register outputs
  pinMode(clockPin, OUTPUT); // Clock signal
  Serial.setTimeout(5000);
  Serial.begin(9600);
  Serial.println("Enter a number (0-255) to send to 74HC595:");
}
/* R-R = 129  \
   R-Y = 130  |  These are the
   R-G = 132   > five possible
   Y-R = 65   |  signal aspects
   G-R = 33   /
*/

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n'); // Read until newline
    input.trim(); // Remove spaces

    if (input.length() > 0) {
      int value = input.toInt();
      if (value >= 0 && value <= 255) {
        outputData = (byte)value;
        digitalWrite(latchPin, LOW); // To allow data flow
        shiftOut(dataPin, clockPin, MSBFIRST, outputData);
        digitalWrite(latchPin, HIGH); // Hold data in register
        Serial.print("Entered ");
        Serial.println(outputData, DEC);
        Serial.print("Binary: ");
        Serial.println(outputData, BIN); // Output as binary no.
        Serial.print("Hex: ");
        Serial.println(outputData, HEX); // Hexadecimal equivalent
      } else {
        Serial.println("Invalid number. Enter 0-255.");
      }
    }
  }
}

I realize I am overdriving it. This just a temporary test of one stage of a larger project. The 270 ohm dip resistors was in the parts bin and I have spare shift registers