Matrix led 7x10

Good morning community, I am making a 70 led matrix display (7 rows and 10 columns) for a personal project of a smart parking lot with an access control system. In the led matrix I will display messages like "Welcome to...", "Thank you for coming to...", "Incorrect user or password", etc.
To manage the 10 columns I use two 74HC595 shift registers connected in cascade.
To control the 7 rows I use a CD4017BE which will scan the rows quickly from top to bottom. The 8 rows of the LED array are independently connected to a 2N3904 NPN transistor which provide a ground path to sink the combined current of all the LEDs in a row.
I have much of the code done, the section that is causing me difficulty is the programming logic of multiplexing the leds using the shift register. What data do I need to send to the shiftOut function so that my led matrix will shift the characters in the string from right to left? I appreciate your help, thank you.
Thanks for your help, thanks.

Components used:

  • 1 PCB 10x10 (Main Board)
  • 1 PCB 10x5 (Matrix led)
  • 40 Pin header
  • 1 28-pin socket
  • 2 16-pin sockets
  • 1 terminal block
  • 1 push button
  • 1 ATMEGA328p
  • 1 CD4017BE
  • 2 74HC595
  • 1 16 MHz crystal
  • 2 Ceramic capacitors 22 pF
  • 1 7805
  • 1 Capacitor 0.22 uF
  • 1 Capacitor 100 uF
  • 1 Diode 1N4147
  • 1 Slide switch
  • 1 Led 5 mm
  • 7 NPN 2N3904 transistors
  • 1 Resistor 220Ω
  • 13 Resistors 10kΩ
  • 10 Resistors 150Ω
  • 70 Leds 3 mm

Control circuit:

LED matrix circuit:

Code:

const byte char_data[95][7]={
    {0, 0, 0, 0, 0, 0, 0}, // space
    {0b100, 0b100, 0b100, 0b100, 0b100, 0, 0b100}, // !
    {0b1010, 0b1010, 0b1010, 0, 0, 0, 0}, // "
    {0b1010, 0b1010, 0b11111, 0b1010, 0b11111, 0b1010, 0b1010}, // #
    {0b100, 0b1111, 0b10100, 0b1110, 0b101, 0b11110, 0b100}, // $
    {0b11000, 0b11001, 0b10, 0b100, 0b1000, 0b10011, 0b11}, // %
    {0b1000, 0b10100, 0b10100, 0b1000, 0b10101, 0b10010, 0b1101}, // &
    {0b100, 0b100, 0b100, 0, 0, 0, 0}, // '
    {0b100, 0b1000, 0b10000, 0b10000, 0b10000, 0b1000, 0b100}, // (
    {0b100, 0b10, 0b1, 0b1, 0b1, 0b10, 0b100}, // )
    {0b100, 0b10101, 0b1110, 0b100, 0b1110, 0b10101, 0b100}, // *
    {0, 0b100, 0b100, 0b11111, 0b100, 0b100, 0}, // +
    {0, 0, 0, 0, 0b100, 0b100, 0b1000}, // ,
    {0, 0, 0, 0b11111, 0, 0, 0}, // -
    {0, 0, 0, 0, 0, 0, 0b100}, // .
    {0, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0}, // /
    {0b1110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b1110}, // 0
    {0b110, 0b1100, 0b100, 0b100, 0b100, 0b100, 0b1110}, // 1
    {0b1110, 0b10001, 0b1, 0b110, 0b1000, 0b10000, 0b11111}, // 2
    {0b11111, 0b1, 0b10, 0b110, 0b1, 0b10001, 0b1111}, // 3
    {0b10, 0b110, 0b1010, 0b10010, 0b11111, 0b10, 0b10}, // 4
    {0b11111, 0b10000, 0b11110, 0b1, 0b1, 0b10001, 0b1110}, // 5
    {0b01110, 0b10001, 0b10000, 0b11110, 0b10001, 0b10001, 0b1110}, // 6
    {0b11111, 0b1, 0b10, 0b100, 0b1000, 0b1000, 0b1000}, // 7
    {0b01110, 0b10001, 0b10001, 0b1110, 0b10001, 0b10001, 0b1110}, // 8
    {0b01110, 0b10001, 0b10001, 0b1111, 0b1, 0b10001, 0b1110}, // 9
    {0, 0, 0b100, 0, 0b100, 0, 0}, // :
    {0, 0, 0b100, 0, 0b100, 0b100, 0b1000}, // ;
    {0b10, 0b100, 0b1000, 0b10000, 0b1000, 0b100, 0b10}, // <
    {0, 0, 0b11111, 0, 0b11111, 0, 0}, // =
    {0b1000, 0b100, 0b10, 0b1, 0b10, 0b100, 0b1000}, // >
    {0b1110, 0b10001, 0b1, 0b10, 0b100, 0, 0b100}, // ?
    {0b1110, 0b10001, 0b10111, 0b10101, 0b10110, 0b10000, 0b1111}, // @
    {0b1110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // A
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b11110}, // B
    {0b1110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001, 0b1110}, // C
    {0b11110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b11110}, // D
    {0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b11111}, // E
    {0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b10000}, // F
    {0b1110, 0b10001, 0b10000, 0b10111, 0b10101, 0b10001, 0b1110}, // G
    {0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // H
    {0b11111, 0b100, 0b100, 0b100, 0b100, 0b100, 0b11111}, // I
    {0b1, 0b1, 0b1, 0b1, 0b1, 0b10001, 0b1110}, // J
    {0b10001, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001, 0b10001}, // K
    {0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111}, // L
    {0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001, 0b10001}, // M
    {0b10001, 0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001}, // N
    {0b1110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1110}, // O
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000, 0b10000}, // P
    {0b1110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10011, 0b1111}, // Q
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b10001}, // R
    {0b1111, 0b10000, 0b10000, 0b1110, 0b1, 0b1, 0b11110}, // S
    {0b11111, 0b100, 0b100, 0b100, 0b100, 0b100, 0b100}, // T
    {0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1110}, // U
    {0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b1010, 0b100}, // V
    {0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b11011, 0b10001}, // W
    {0b10001, 0b10001, 0b1010, 0b100, 0b1010, 0b10001, 0b10001}, // X
    {0b10001, 0b10001, 0b1010, 0b100, 0b100, 0b100, 0b100}, // Y
    {0b11111, 0b1, 0b10, 0b100, 0b1000, 0b10000, 0b11111}, // Z
    {0b1110, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1110}, // [
    {0, 0b10000, 0b1000, 0b100, 0b10, 0b1, 0}, // backward slash
    {0b1110, 0b10, 0b10, 0b10, 0b10, 0b10, 0b1110}, // ]
    {0, 0, 0b100, 0b1010, 0b10001, 0, 0}, // ^
    {0, 0, 0, 0, 0, 0, 0b11111}, // _
    {0b1000, 0b100, 0b10, 0, 0, 0, 0}, // `
    {0, 0, 0b1110, 0b1, 0b1111, 0b10001, 0b1111}, // a
    {0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110}, // b
    {0, 0, 0b1110, 0b10001, 0b10000, 0b10001, 0b1110}, // c
    {0b1, 0b1, 0b1, 0b1111, 0b10001, 0b10001, 0b1111}, // d
    {0, 0, 0b1110, 0b10001, 0b11111, 0b10000, 0b1111}, // e
    {0b1110, 0b1001, 0b11100, 0b1000, 0b1000, 0b1000, 0b1000}, // f
    {0, 0, 0b1110, 0b10001, 0b1111, 0b1, 0b1110}, // g
    {0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b10001}, // h
    {0b100, 0, 0b100, 0b100, 0b100, 0b100, 0b1110}, // i
    {0b1, 0, 0b11, 0b1, 0b1, 0b10001, 0b1110}, // j
    {0b10000, 0b10000, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001}, // k
    {0b1100, 0b100, 0b100, 0b100, 0b100, 0b100, 0b1110}, // l
    {0, 0, 0b11110, 0b10101, 0b10101, 0b10101, 0b10101}, // m
    {0, 0, 0b11110, 0b10001, 0b10001, 0b10001, 0b10001}, // n
    {0, 0, 0b1110, 0b10001, 0b10001, 0b10001, 0b1110}, // o
    {0, 0, 0b1111, 0b1001, 0b1110, 0b1000, 0b1000}, // p
    {0, 0, 0b1111, 0b10001, 0b1111, 0b1, 0b1}, // q
    {0, 0, 0b10111, 0b11000, 0b10000, 0b10000, 0b10000}, // r
    {0, 0, 0b1111, 0b10000, 0b1110, 0b1, 0b11110}, // s
    {0b100, 0b100, 0b1110, 0b100, 0b100, 0b100, 0b11}, // t
    {0, 0, 0b10001, 0b10001, 0b10001, 0b10011, 0b1101}, // u
    {0, 0, 0b10001, 0b10001, 0b10001, 0b1010, 0b100}, // v
    {0, 0, 0b10001, 0b10001, 0b10101, 0b11111, 0b10101}, // w
    {0, 0, 0b10001, 0b1010, 0b100, 0b1010, 0b10001}, // x
    {0, 0, 0b10001, 0b10001, 0b1111, 0b1, 0b11110}, // y
    {0, 0, 0b11111, 0b10, 0b100, 0b1000, 0b11111}, // z
    {0b10, 0b100, 0b100, 0b1000, 0b100, 0b100, 0b10}, // {
    {0b100, 0b100, 0b100, 0b100, 0b100, 0b100, 0b100}, // |
    {0b1000, 0b100, 0b100, 0b10, 0b100, 0b100, 0b1000}, // }
    {0, 0, 0, 0b1010, 0b10101, 0, 0} // ~
};
char message[] = "abc";
 
void setup(){
    // PORTB as output.
    // Pin 13: ClockRegister
    // Pin 12: Latch
    // Pin 11: Data
    // Pin 10: Reset
    // Pin 9: Clock4017
    DDRB = 0b111111;
    // Makes sure the 4017 value is 0.
    PORTB = 0b100;
    PORTB = 0;
}

void send_data(unsigned int data){
    byte mask = 0b1, flag = 0;
    for (byte i=0; i<10; i++){
        flag = data & mask;
        if (flag) digitalWrite(11, HIGH);
        else digitalWrite(11, LOW);
        digitalWrite(13, HIGH);
        digitalWrite(13, LOW);
        mask <<= 1;
    }
    digitalWrite(12, HIGH);
    digitalWrite(12, LOW);
}
 
void loop(){
    for (byte i=0; i<7; i++){
        send_data(0b10001111);
        delay(1000);
        digitalWrite(9, HIGH);
        digitalWrite(9, LOW);
    }
    digitalWrite(10, HIGH);
    digitalWrite(10, LOW);
}

If you mean scrolling, it has nothing to do with shiftOut(), or with shift register operation at all.

I would configure it as 10x7. You would set all the LEDs in a given row on or off depending on your pattern, then turn the column on then off. Repeat ror the remaining 7 rows then start over. The reason for the 10 by 7 is you can have a higher duty cycle keeping the display brighter. The bulk of your code will probably be defining bit patterns. You will probably have to treat the columns as 16 bit integers and ignoring 6 bits. Later you can tweak it.

Before you go to all that trouble, set up a demo on some easy hardware, like a matrix module. I suspect you will not be able to read scrolling text on that display very well.

1 Like

I upvote this answer.
10 x 7 will give you roughly a two letter display. I don't believe that your "Welcome to" will be readable at all.
Try what aarg has posted. Get a 8 x 64 digit matrix, pull out two modules or cover several columns and try to read a scrolling text ...

I would recommend an ht16k33 module to replace your shift registers, multiplexer, transistors and resistors. This will simplify your circuit and code significantly.
s-l400 (7)

Changing the circuit is not an option, I already have all the pcb's done and assembled and working. I don't want to waste the work I did, maybe some other time I will make an improved version, but now I want to make it work as it is.

Please post the code, that just writes to the array. It doesn't matter that it doesn't scroll yet. We want to see what you have, so it can be modified. Have you not made some "setPixel(x, y)" function? It is the first thing I do when I'm writing code for my custom displays.

Also please fix your schematic where the ground for the common emitter transistors is obscured by a weird symbol (maybe a data terminal??). Please assign values to the passive components and at least one transistor. Clarify where *MR from the SR goes.

You are missing bypass caps on the SR's. I hope they are present on the actual PCB.

Perhaps when you post your code, your strategy for sharing the MR line between the SR's and the row counter IC will become clear. It wouldn't hurt to explain it anyway. At first glance, it looks like the counter will reset to row 0, any time the *MR line to the SR's is exercised.

Edit, I now see that you linked to the code. The normal thing to do is post it, so I will do that for you... most people won't follow a Wastebin link.

const byte char_data [95][7]={
    {0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b0}, // space
    {0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b0, 0b00100}, // !
    {0b01010, 0b01010, 0b01010, 0b0, 0b0, 0b0, 0b0}, // "
    {0b01010, 0b01010, 0b11111, 0b01010, 0b11111, 0b01010, 0b01010}, // #
    {0b00100, 0b01111, 0b10100, 0b01110, 0b00101, 0b11110, 0b00100}, // $
    {0b11000, 0b11001, 0b00010, 0b00100, 0b01000, 0b10011, 0b00011}, // %
    {0b01000, 0b10100, 0b10100, 0b01000, 0b10101, 0b10010, 0b01101}, // &
    {0b00100, 0b00100, 0b00100, 0b0, 0b0, 0b0, 0b0}, // '
    {0b00100, 0b01000, 0b10000, 0b10000, 0b10000, 0b01000, 0b00100}, // (
    {0b00100, 0b00010, 0b00001, 0b00001, 0b00001, 0b00010, 0b00100}, // )
    {0b00100, 0b10101, 0b01110, 0b00100, 0b01110, 0b10101, 0b00100}, // *
    {0b0, 0b00100, 0b00100, 0b11111, 0b00100, 0b00100, 0b0}, // +
    {0b0, 0b0, 0b0, 0b0, 0b00100, 0b00100, 0b01000}, // ,
    {0b0, 0b0, 0b0, 0b11111, 0b0, 0b0, 0b0}, // -
    {0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b00100}, // .
    {0b0, 0b00001, 0b00010, 0b00100, 0b01000, 0b10000, 0b0}, // /
    {0b01110, 0b10001, 0b10011, 0b10101, 0b11001, 0b10001, 0b01110}, // 0
    {0b00110, 0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110}, // 1
    {0b01110, 0b10001, 0b00001, 0b00110, 0b01000, 0b10000, 0b11111}, // 2
    {0b11111, 0b00001, 0b00010, 0b00110, 0b00001, 0b10001, 0b01111}, // 3
    {0b00010, 0b00110, 0b01010, 0b10010, 0b11111, 0b00010, 0b00010}, // 4
    {0b11111, 0b10000, 0b11110, 0b00001, 0b00001, 0b10001, 0b01110}, // 5
    {0b01110, 0b10001, 0b10000, 0b11110, 0b10001, 0b10001, 0b01110}, // 6
    {0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b01000, 0b01000}, // 7
    {0b01110, 0b10001, 0b10001, 0b01110, 0b10001, 0b10001, 0b01110}, // 8
    {0b01110, 0b10001, 0b10001, 0b01111, 0b00001, 0b10001, 0b01110}, // 9
    {0b0, 0b0, 0b00100, 0b0, 0b00100, 0b0, 0b0}, // :
    {0b0, 0b0, 0b00100, 0b0, 0b00100, 0b00100, 0b01000}, // ;
    {0b00010, 0b00100, 0b01000, 0b10000, 0b01000, 0b00100, 0b00010}, // <
    {0b0, 0b0, 0b11111, 0b0, 0b11111, 0b0, 0b0}, // =
    {0b01000, 0b00100, 0b00010, 0b00001, 0b00010, 0b00100, 0b01000}, // >
    {0b01110, 0b10001, 0b0001, 0b00010, 0b00100, 0b0, 0b00100}, // ?
    {0b01110, 0b10001, 0b10111, 0b10101, 0b10110, 0b10000, 0b01111}, // @
    {0b01110, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // A
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b11110}, // B
    {0b01110, 0b10001, 0b10000, 0b10000, 0b10000, 0b10001, 0b01110}, // C
    {0b11110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b11110}, // D
    {0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b11111}, // E
    {0b11111, 0b10000, 0b10000, 0b11110, 0b10000, 0b10000, 0b10000}, // F
    {0b01110, 0b10001, 0b10000, 0b10111, 0b10101, 0b10001, 0b01110}, // G
    {0b10001, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001, 0b10001}, // H
    {0b11111, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b11111}, // I
    {0b00001, 0b00001, 0b00001, 0b00001, 0b00001, 0b10001, 0b01110}, // J
    {0b10001, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001, 0b10001}, // K
    {0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b11111}, // L
    {0b10001, 0b11011, 0b10101, 0b10101, 0b10001, 0b10001, 0b10001}, // M
    {0b10001, 0b10001, 0b11001, 0b10101, 0b10011, 0b10001, 0b10001}, // N
    {0b01110, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110}, // O
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10000, 0b10000, 0b10000}, // P
    {0b01110, 0b10001, 0b10001, 0b10001, 0b10101, 0b10011, 0b01111}, // Q
    {0b11110, 0b10001, 0b10001, 0b11110, 0b10001, 0b10001, 0b10001}, // R
    {0b01111, 0b10000, 0b10000, 0b01110, 0b00001, 0b00001, 0b11110}, // S
    {0b11111, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100}, // T
    {0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110}, // U
    {0b10001, 0b10001, 0b10001, 0b10001, 0b10001, 0b01010, 0b00100}, // V
    {0b10001, 0b10001, 0b10001, 0b10101, 0b10101, 0b11011, 0b10001}, // W
    {0b10001, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001, 0b10001}, // X
    {0b10001, 0b10001, 0b01010, 0b00100, 0b00100, 0b00100, 0b00100}, // Y
    {0b11111, 0b00001, 0b00010, 0b00100, 0b01000, 0b10000, 0b11111}, // Z
    {0b01110, 0b01000, 0b01000, 0b01000, 0b01000, 0b01000, 0b01110}, // [
    {0b0, 0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b0}, // diagonal invertida
    {0b01110, 0b00010, 0b00010, 0b00010, 0b00010, 0b00010, 0b01110}, // ]
    {0b0, 0b0, 0b00100, 0b01010, 0b10001, 0b0, 0b0}, // ^
    {0b0, 0b0, 0b0, 0b0, 0b0, 0b0, 0b11111}, // _
    {0b01000, 0b00100, 0b00010, 0b0, 0b0, 0b0, 0b0}, // `
    {0b0,0b0, 0b01110, 0b00001, 0b01111, 0b10001, 0b01111}, // a
    {0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b11110}, // b
    {0b0, 0b0, 0b01110, 0b10001, 0b10000, 0b10001, 0b01110}, // c
    {0b00001, 0b00001, 0b00001, 0b01111, 0b10001, 0b10001, 0b01111}, // d
    {0b0, 0b0, 0b01110, 0b10001, 0b11111, 0b10000, 0b01111}, // e
    {0b01110, 0b01001, 0b11100, 0b01000, 0b01000, 0b01000, 0b01000}, // f
    {0b0, 0b0, 0b01110, 0b10001, 0b01111, 0b00001, 0b01110}, // g
    {0b10000, 0b10000, 0b10000, 0b11110, 0b10001, 0b10001, 0b10001}, // h
    {0b00100, 0b0, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110}, // i
    {0b00001, 0b00000, 0b00011, 0b00001, 0b00001, 0b10001, 0b01110}, // j
    {0b10000, 0b10000, 0b10001, 0b10010, 0b11100, 0b10010, 0b10001}, // k
    {0b01100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b01110}, // l
    {0b0, 0b0, 0b11110, 0b10101, 0b10101, 0b10101, 0b10101}, // m
    {0b0, 0b0, 0b11110, 0b10001, 0b10001, 0b10001, 0b10001}, // n
    {0b0, 0b0, 0b01110, 0b10001, 0b10001, 0b10001, 0b01110}, // o
    {0b0, 0b0, 0b01111, 0b01001, 0b01110, 0b01000, 0b01000}, // p
    {0b0, 0b0, 0b01111, 0b10001, 0b01111, 0b00001, 0b00001}, // q
    {0b0, 0b0, 0b10111, 0b11000, 0b10000, 0b10000, 0b10000}, // r
    {0b0, 0b0, 0b01111, 0b10000, 0b01110, 0b00001, 0b11110}, // s
    {0b00100, 0b00100, 0b01110, 0b00100, 0b00100, 0b00100, 0b00011}, // t
    {0b0, 0b0, 0b10001, 0b10001, 0b10001, 0b10011, 0b01101}, // u
    {0b0, 0b0, 0b10001, 0b10001, 0b10001, 0b01010, 0b00100}, // v
    {0b0, 0b0, 0b10001, 0b10001, 0b10101, 0b11111, 0b10101}, // w
    {0b0, 0b0, 0b10001, 0b01010, 0b00100, 0b01010, 0b10001}, // x
    {0b0, 0b0, 0b10001, 0b10001, 0b01111, 0b00001, 0b11110}, // y
    {0b0, 0b0, 0b11111, 0b00010, 0b00100, 0b01000, 0b11111}, // z
    {0b00010, 0b00100, 0b00100, 0b01000, 0b00100, 0b00100, 0b00010}, // {
    {0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100, 0b00100}, // |
    {0b01000, 0b00100, 0b00100, 0b00010, 0b00100, 0b00100, 0b01000}, // }
    {0b0, 0b0, 0b0, 0b01010, 0b10101, 0b0, 0b0} // ~
};
char message[] = "abc";
 
void setup(){
    // PORTB as output.
    // Pin 13: ClockRegister
    // Pin 12: Latch
    // Pin 11: Data
    // Pin 10: Reset
    // Pin 9: Clock4017
    DDRB = 0b111111;
    // Makes sure the 4017 value is 0.
    PORTB = 0b100;
    PORTB = 0;
}
 
void loop(){
    for (byte i=0; i<3; i++){ // For each pattern
        for (byte j=0; j<10; j++){ // For each column
            for (byte z=0; z<7; z++){ // For each row
                // Subtract 32 from the ASCII value of the character itself to obtain the corresponding row index of the char_data array.
                byte index = message[i];
                byte temp = char_data[index-32][z]; 
                // Shift out a row.
                shiftOut(11, 13, MSBFIRST, ?);
                shiftOut(11, 13, MSBFIRST, ?);
                PORTB = 0b10000;
                PORTB = 0;
                delay(3); // This delay defines the time to play each pattern.
                // Clear the row so it doesn't show up on the next row when we increment the 4017.
                shiftOut(11, 13, MSBFIRST, 0);
                shiftOut(11, 13, MSBFIRST, 0);
                PORTB = 0b10000;
                PORTB = 0;
                // Pulse the 4017 clock to select the next row.
                PORTB = 0b10;
                PORTB = 0;
            }
            delay(100); // This delay defines the time to change from one pattern to another.
            // Reset 4017
            PORTB = 0b100;
            PORTB = 0;
        }
    }      
}

This is a raw test program. It fast forwards past creating any useful display functions. To deal with scrolling, you should make your life easier and add a 'setPixel(x, y)', from there you can make a 'setColumn(x)'. With the latter in place, scrolling would likely be 10x easier to implement. From 'setColumn(x)' you next need a 'writeCharAt(x)' kind of function too, where x is the column offset, not character offset.

If you skip making those functions and hard code the logic, it will be a real mess and nearly impossible to debug, maintain or expand.

Is this some valid C syntax I haven't seen before? What does it mean? Does it compile?

Or, the professor is asking you to replace the "?" with working code?

What is the capacitor for and where should I put it? Could it be the reason why one output (Q4) of the first 74hc595 does not light up (it is a small problem I have with the circuit and I am trying to fix, I have tried the led matrix separately and all the leds light up)?

All 74HC series ICs and probably U4, your 4000 series CMOS need "power supply bypass capacitors" such as 100nF ceramic between Vdd and ground, as close as possible to the pins.

That's been going on since digital IC's came out in the late 1960's. Read the data sheets. Mention might be buried deep in the document, as they believe that everyone already knows about it.

However I don't believe it is actually the cause for the problem you mention.

Please provide a real, complete, updated schematic. Don't post it as a shrunken jpeg that needs reading glasses to see. Then, and only then, will I comment further on your circuit.

If Q4 doesn't light up, you've a blown output or a cold solder joint, or you're not sending the data to begin with.
What powers this beast, anyway? Please don't tell me you're running it on the Arduino's 5V rail.

It is. If you can believe the schematic. But whether that is okay, depends on knowing the unpublished component values in the diagram. Hint, hint.

Another thing, was it ever prototyped in its present form before sending the design off to the PCB fab?

I added all the components used in the question, tomorrow I will update the question and upload the complete neat diagram and a test with the LEDs.

Fair enough. It will likely gain you some progress.

Do not update previous posts, if that is what you meant! Add updates only as new messages...

First post(as updated).
10 LEDs simultaneously with 150 ohm resistors, I figure that's a current pulse between 100 and 200 ma (LED colour not known?). No decoupling. Would like to see PCB files, see if power and ground are angel-hair traces or properly thickened. TBD

The Q4 problem might also be in software...

I am powering it with an external power supply and I am supplying it with 9v and 1000 mA, then the 7805 regulates it 5v.
The Q4 output of the register is not burned, I tried with a new one and the same thing happens.

Ouch. Using the Arduino as a voltage regulator is asking for trouble. Or, do you mean an external regulator? If so, does it have a heat sink?

Ok, then check trace carefully, and if continuity exists between all LEDs on that column and Q4, look deeper into software.