Matrix LED 16*16 shift Register 74HC595 - Help

Hello,

I am french, so excuse my english.

I did a led matrix 16*16 with 4 shift Register 74HC595
The both first are connected on + and the two others on -.

I have a problem to do what i want, I think the first 8 lines ares ok but after I have problem
this is the code :

#include <TimerOne.h>
#include <stdio.h>

//Pin connected to Pin 12 of 74HC595 (Latch)
int latchPin = 8;
//Pin connected to Pin 11 of 74HC595 (Clock)
int clockPin = 12;
//Pin connected to Pin 14 of 74HC595 (Data)
int dataPin = 11;

uint8_t myMatrice[32];

long counter1 = 0;
long counter2 = 0;

void setup()
{
          Serial.begin(9600) ;

      //set pins to output
      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);

      myMatrice[31]  = B00000000; myMatrice[30]  = B00000000;
      myMatrice[29]  = B00000000; myMatrice[28]  = B00000000;
      myMatrice[27]  = B00000000; myMatrice[26]  = B00000000;
      myMatrice[25]  = B00000000; myMatrice[24]  = B00000000;
      myMatrice[23]  = B00000000; myMatrice[22]  = B00000000;
      myMatrice[21]  = B00000000; myMatrice[20]  = B00000000;
      myMatrice[19]  = B00000000; myMatrice[18]  = B00000000;
      myMatrice[17]  = B00000000; myMatrice[16]  = B00000000;

      myMatrice[15] = B00000000; myMatrice[14] = B00000000;
      myMatrice[13] = B00000000; myMatrice[12] = B00000000;
      myMatrice[11] = B00000000; myMatrice[10] = B00000000;
      myMatrice[9]  = B00000000; myMatrice[8]  = B00000000;
      myMatrice[7]  = B00000000; myMatrice[6]  = B00000000;
      myMatrice[5]  = B00000000; myMatrice[4]  = B00000000;
      myMatrice[3]  = B00000000; myMatrice[2]  = B00000000;
      myMatrice[1]  = B00000000; myMatrice[0]  = B00000000;

        Timer1.initialize(1000);
        Timer1.attachInterrupt(screenUpdate);
}

void loop()
{

}

void screenUpdate()
{
  uint8_t myRow1 = B00000001;
  uint8_t myRow2 = B00000001;

  int j = 0;
  boolean passe = false;
  for( byte k = 0; k < 16; k++)
  {
    //Serial.print("k : ");Serial.println(k,BIN);
    digitalWrite(latchPin, LOW);
    if( (k < 8)) {
      shiftIt(~myRow1);
      shiftIt(B00000000);
      //Serial.print("shift 1 : ");Serial.println(B00000000,BIN);
      //Serial.print("shift 2 : ");Serial.println(~myRow1,BIN);
    } else {
      shiftIt(B00000000);
      shiftIt(~myRow2);
      //Serial.print("shift 1 : ");Serial.println(~myRow2,BIN);
      //Serial.print("shift 2 : ");Serial.println(B00000000,BIN);
    }

    //Serial.print("shift 3 : ");Serial.println(j);
    //Serial.print("shift 3 : ");Serial.println(j+1);

    shiftIt(myMatrice[j]);
    shiftIt(myMatrice[j+1]);
    digitalWrite(latchPin, HIGH);
    myRow1 = myRow1 << 1;
    if( (k >= 8)) {
      myRow2 = myRow2 << 1;
    }

    j = j+2;

    //delay(5000);
  }

}

void shiftIt(byte dataOut)
{
      // Shift out 8 bits LSB first,
      // on rising edge of clock
      boolean pinState;

      //clear shift register read for sending data
      digitalWrite(dataPin, LOW);
      digitalWrite(clockPin, LOW);

      // for each bit in dataOut send out a bit
      for (int i=0; i<8; i++)
      {
            //set clockPin to LOW prior to sending bit
            digitalWrite(clockPin, LOW);

            // if the value of DataOut and (logical AND) a bitmask
            // are true, set pinState to 1 (HIGH)
            if ( dataOut & (1<<i) )
            {pinState = HIGH;}
            else
            //{!pinState = LOW;}
            {pinState = LOW;}

            //sets dataPin to HIGH or LOW depending on pinState
            digitalWrite(dataPin, pinState);

            //send bit out on rising edge of clock
            digitalWrite(clockPin, HIGH);
            digitalWrite(dataPin, LOW);
      }
      //stop shifting
      digitalWrite(clockPin, LOW);
}

Can you help me please?

Francki

I see no obvious error; however this depends on my fantasy of what you might have wired...

Because you program is unnessarily complicated it is not so easy to debug.. Some hints:

  • I strongly recommend that you do everything with unsigned int. This will redundantize half of your lines
  • It is of no use to set data to low in the beginning and at the end oft the shift routine.
  • you can digitalWrite(pin, anyvalue_if_0_than its_LOW_otherwise_HIGH)
  • you can program:
    insigned int myMatrix [] = {0x00, 0x00, 0x00,...}

All this will reduce thesize of your code so much that you might detect issues at the first glance

One issue is this: It is of no use to send out the data at afurious rate: Each line has to stay for awhile. A delay between the refreshes of the whole pattern is useless. Only the last line will stay visible... Maybe this is part of the problem??

Consequence: The interrupt routine has to output just one line at a time!!!

Hello,

Thank you for your answer.
If I want to change the values of my matrix, I can't use {0X00, 0X00}, I can just use it in setup. But why not.

My matrix is multiplexing matrix it's the reason why I have a routine output just one line at a time.

Thank you for your help, the problem is to display the leds between myMatrice[0] and myMatrice[15] so when "k < 8" in screenUpdate().

Franck

I fully understand your setup - this has been done a zillion times before.
I just wanted to make clear that you must give the line a chace nto shine :slight_smile:
Of course, {....} can only be used in the definition of the matrix, but that is what you are doing in your current program. It will help when change to 16 bit...Much more readable code!!

Thank you,

Have you got an example of 16 bit code, and I rewrite it.

Francki

I rewrite it and I have the same problem, can you hel me ?

#include <TimerOne.h>
#include <stdio.h>

int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

uint16_t myMatrice[16] = {0x0000, 0x0000, 0x0000, 0x0000, 
                    0x0000, 0x0000, 0x0000, 0x0000, 
                    0x0000, 0x0000, 0x0000, 0x0000, 
                    0x0000, 0x0000, 0x4000, 0xC000};

void setup() 
{
        Serial.begin(9600) ;
        
      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);

        Timer1.initialize(1000);
        Timer1.attachInterrupt(screenUpdate);
}

void loop() 
{

}

void screenUpdate()
{
  uint16_t myRow = 0x0001;

  for( byte k = 0; k < 16; k++)
  {
      digitalWrite(latchPin, LOW);

      shiftIt(~myRow);    
      shiftIt(myMatrice[k]);
      
      digitalWrite(latchPin, HIGH);

      myRow = myRow << 1;
  }

}

void shiftIt(uint16_t dataOut)
{
      // Shift out 8 bits LSB first,
      // on rising edge of clock
      boolean pinState;
      
      //clear shift register read for sending data
      digitalWrite(dataPin, LOW);
      
      // for each bit in dataOut send out a bit
      for (int i=0; i<8; i++)
      {
            //set clockPin to LOW prior to sending bit
            digitalWrite(clockPin, LOW);
            
            // if the value of DataOut and (logical AND) a bitmask are true, set pinState to 1 (HIGH)
            if ( dataOut & (1<<i) ) 
                  {pinState = HIGH;}
            else 
                  {pinState = LOW;}

            //sets dataPin to HIGH or LOW depending on pinState
            digitalWrite(dataPin, pinState);
            
            //send bit out on rising edge of clock
            digitalWrite(clockPin, HIGH);
            digitalWrite(dataPin, LOW);
      }
      //stop shifting
      digitalWrite(clockPin, LOW);

      //clear shift register read for sending data
      digitalWrite(dataPin, LOW);
      
      for (int i=8; i<16; i++)
      {
            //set clockPin to LOW prior to sending bit
            digitalWrite(clockPin, LOW);

            // if the value of DataOut and (logical AND) a bitmask are true, set pinState to 1 (HIGH)
            if ( dataOut & (1<<i) ) 
                  {pinState = HIGH;}
            else 
                  {pinState = LOW;}

            //sets dataPin to HIGH or LOW depending on pinState
            digitalWrite(dataPin, pinState);

            //send bit out on rising edge of clock
            digitalWrite(clockPin, HIGH);
            digitalWrite(dataPin, LOW);
      }

}

void setMatrice1(int* myMat)
{
      myMat[15]  = 0x0000; //B 1100 0000 0000 0000 
      myMat[14]  = 0x4000; //B 0100 0000 0000 0000
      myMat[13]  = 0x0000; //B 0000 0000 0000 0000
      myMat[12]  = 0x0000; //B 0000 0000 0000 0000
      myMat[11]  = 0x0000; //B 0000 0000 0000 0000
      myMat[10]  = 0x0000; //B 0000 0000 0000 0000
      myMat[9]   = 0x0000; //B 0000 0000 0000 0000
      myMat[8]   = 0x0000; //B 0000 0000 0000 0000

      myMat[7]   = 0xC000; //B 0000 0000 0000 0000
      myMat[6]   = 0x0000; //B 0000 0000 0000 0000
      myMat[5]   = 0x0000; //B 0000 0000 0000 0000
      myMat[4]   = 0x0000; //B 0000 0000 0000 0000
      myMat[3]   = 0x0000; //B 0000 0000 0000 0000
      myMat[2]   = 0x0000; //B 0000 0000 0000 0000
      myMat[1]   = 0x0000; //B 0000 0000 0000 0000
      myMat[0]   = 0x0000; //B 0000 0000 0000 0000

}
  • The for loop in ShiftIt must have 16 runs now rather than 8.
  • You need a small pause after each line, otherwise you will just not see anything there

Otherwise it now looks very fine ( but with one exception :wink: )

Thank you again.

I changed the for loop with 16 runs. I did two for loop, one to 0 to 7 and the second, 8 to 15.
I didn't find where I must do a small pause and I didn't find the exception
:-/

#include <TimerOne.h>
#include <stdio.h>

int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

uint16_t myMatrice[16] = {0x0000, 0x0000, 0x0000, 0x0000,
                    0x0000, 0x0000, 0x0000, 0x0000,
                    0x0000, 0x0000, 0x0000, 0x0000,
                    0x0000, 0x0000, 0x4000, 0xC000};

void setup()
{
        Serial.begin(9600) ;

      pinMode(latchPin, OUTPUT);
      pinMode(clockPin, OUTPUT);
      pinMode(dataPin, OUTPUT);

        Timer1.initialize(1000);
        Timer1.attachInterrupt(screenUpdate);
}

void loop()
{

}

void screenUpdate()
{
  uint16_t myRow = 0x0001;

  for( byte k = 0; k < 16; k++)
  {
      digitalWrite(latchPin, LOW);

      shiftIt(~myRow);
      shiftIt(myMatrice[k]);

      digitalWrite(latchPin, HIGH);

      myRow = myRow << 1;
  }

}

void shiftIt(uint16_t dataOut)
{
      // Shift out 8 bits LSB first, on rising edge of clock
      boolean pinState;

      //clear shift register read for sending data
      digitalWrite(dataPin, LOW);

      // for each bit in dataOut send out a bit
      for (int i=0; i<16; i++)
      {
            //set clockPin to LOW prior to sending bit
            digitalWrite(clockPin, LOW);

            // if the value of DataOut and (logical AND) a bitmask are true, set pinState to 1 (HIGH)
            if ( dataOut & (1<<i) )
                  {pinState = HIGH;}
            else
                  {pinState = LOW;}

            //sets dataPin to HIGH or LOW depending on pinState
            digitalWrite(dataPin, pinState);

            //send bit out on rising edge of clock
            digitalWrite(clockPin, HIGH);
            digitalWrite(dataPin, LOW);
      }
      //stop shifting
      digitalWrite(clockPin, LOW);

}

void setMatrice1(int* myMat)
{
      myMat[15]  = 0x0000; //B 1100 0000 0000 0000
      myMat[14]  = 0x4000; //B 0100 0000 0000 0000
      myMat[13]  = 0x0000; //B 0000 0000 0000 0000
      myMat[12]  = 0x0000; //B 0000 0000 0000 0000
      myMat[11]  = 0x0000; //B 0000 0000 0000 0000
      myMat[10]  = 0x0000; //B 0000 0000 0000 0000
      myMat[9]   = 0x0000; //B 0000 0000 0000 0000
      myMat[8]   = 0x0000; //B 0000 0000 0000 0000

      myMat[7]   = 0xC000; //B 0000 0000 0000 0000
      myMat[6]   = 0x0000; //B 0000 0000 0000 0000
      myMat[5]   = 0x0000; //B 0000 0000 0000 0000
      myMat[4]   = 0x0000; //B 0000 0000 0000 0000
      myMat[3]   = 0x0000; //B 0000 0000 0000 0000
      myMat[2]   = 0x0000; //B 0000 0000 0000 0000
      myMat[1]   = 0x0000; //B 0000 0000 0000 0000
      myMat[0]   = 0x0000; //B 0000 0000 0000 0000

}

The pause (at leatst 500us) must be after or before this line inside the k-loop

myRow = myRow << 1;

This is awkward, as I remarked before, the hole interrupt structure must be reshaped; but this is not a bug.

Never mind the "exception" :slight_smile:

Otherwise I can see no issue in the code ....

Do you really need a delay between lines?
While outputting one row, the latch is low, which means the 595s will output the previously defined row.
Outputting 4 bytes one bit at a time using slow digitalWrite() will take a while, so it seems to me the "delay" is already there.
What happens on the display when the program is run, does anything show?

Do you really need a delay between lines?

Maybe not a huge EXTRA delay.. I have not calculated the time needed for the next row-shift...My experience is that 8 bit shift-out is around 120 to 150us, so 16 bit = 170us or so..

In fact there should be not much difference - as LEDs have low latency - whether you refresh (the complete array) @600Hz and light each line for 100us or refresh with 60Hz and light a line for 1ms.

However if the array refresh is to slow one would see hardlyanything, and we are just troubleshooting....

Hello

I don't understand the last two messages, I began.

I modified the code a bit, I changed byte k to uint16_t in screenUpdate(). The code works ans displays items that I want. So thank you. If you think I can optimize it, I listen.

In contrast, the lightness is less.
I have a matrix of white LED 10 * 11. I connected to 5V and I just put the resistors on the +, do I put transistors on -? if so, what transistors?

Thank you again

Francki

Hello,

Nobody knows, I am lost?

Thank you

Franck

(1) What has this 10x11 matrix to do with it?
It is connected to shift registers? How.

(2) Your 16x16 matrix is dim. This is typical for those multiplexed things - you have to exactly calculate the current pulses, but on the basis of 1/16 there is little chance. You might look in the datasheet of your specific LEDs to find whether and how long you can pulse them with - say - 100mA or so. But note that the increase of brightness will not be proportional to that current.

Multiplexing LEDs is a complex matter - just read about in the 1000+ internet articles having been written about it during the last 20 years....

You need to post a schematic of what you have. I assume you have some other drivers apart from the shift registers because you will not be able to supply (source) enough current from a shift register alone to light a whole row (16 LEDs) at once.