16x9 Led Display "Ghosting"

:zipper_mouth_face:So I have built myself a 16x9 led display following this guy's instructions:

The hardware works and I have fully tested each led in code to make sure I can access every one individually. My problem is figuring out how to display text, numbers, images, etc on the screen. I was able to partially display the number one on the screen, however I am having issues with it ghosting leds as the code switches each row on the display. What I am finding is that there are two leds on the diagonal part that should not be there. When I run my code slowly (the delay at say 500), then I notice that the leds that are "ghosting" flicker for the briefest of moments before turning on the right leds for that row.

Here is my code:

int dataPin = 12; //B4
int latchPin = 11; //B3
int clockPin = 10; //B2
int d_clockPin = 9; //B1
int d_resetPin = 8; //B0


byte data; 

//10 values, one for each pin of the decade counter
byte num1[10] = {0x08, //00001000
                 0x18, //00011000
                 0x28, //00101000
                 0x08, //00001000
                 0x08, //00001000
                 0x08, //00001000
                 0x08, //00001000
                 0x08, //00001000
                 0x3E, //00111110
                 0x00};//00000000

void setup()
{
  //sets up the decade/shift pins as outputs
  for(int i=8; i<13; ++i)
   pinMode(i, OUTPUT);
  
  //these two functions reset everything so there is blank slate
  decadeReset(); 
  shiftReset();
  
}

void loop()
{
  for(int i=0; i<10; ++i){
    data = num1[i]; //loads in the byte from num1[i]
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data); //writes in the data to both shift registers
    shiftOut(dataPin, clockPin, MSBFIRST, data);
    digitalWrite(latchPin, HIGH);
    delay(1); //for some reason without this delay the "1" doesn't display right
    decadeCount(); //switches the decade counter to the next line
  }
  decadeReset(); //resets the decade counter 
}


//clocks the decade counter to the next pin
void decadeCount(){
  PORTB |=_BV(PB1); //writes d_clockPin high
  PORTB &=~_BV(PB1); //writes d_clockPin low 
}

//resets decade counter to the first row
void decadeReset(){
  PORTB |=_BV(PB0); //writes d_resetPin high
  PORTB &=~_BV(PB0); //writes d_resetPin low
}

//resets the shift register to zero
void shiftReset(){
  PORTB |=_BV(PB3); //writes latchPin low
  shiftOut(dataPin, clockPin, MSBFIRST, 0x00);
  shiftOut(dataPin, clockPin, MSBFIRST, 0x00);
  PORTB &=~_BV(PB3); //writes latchPin high
}

Few odd things there - most notably you say you have built a 16x9 led display but you have a data structure of ten rows and cycle through all ten.

I gather the intent of duplicating shiftOut is to show two copies of the number on the display.

Curious that you use defined pin designators for the control pins, but then use the "_BV(PBx)" constructor to actually manipulate them. I can only imagine that the compiler will optimise to the same code as "digitalWrite(x)", so I do not see the point here.

The reason you need the "delay(1)" (which could be better coded) is that if you latch the data in and advance the decade counter the very next moment, the data you have just latched will predominantly appear on the next row instead of the current one.

Hi codex. In the loop () function, you need to shift zeroes into your shift registers, then update the decade counter, then shift in the required pattern in, then have your delay.

Paul