2D array with spi seems to be really slow

I am working on an 5x5x5 RGB LED cube. The hardware now should be fine and works but i run into some troubles with the SPI and an 2D array.
In Short:

  • I do have 80 bit in a register which i write out and set with spi in interupt cycles of 8kHz.
  • Every cycle just light up 1 whole level of the cube by disabling/enabling the level with one of the last 5 bit of the 80bit
  • the 75 other bit are for the colors. (rgb rgb rgb rgb and so on)
  • to create different colors i push up to 5 bit through one led(00001 so 4 times off 1 time on. After one cube light up (all 5 levels lite up one time) the counter get increased). So i got level * 5 *10 byte

To handle this i thought about 1 2D array for each level of the cube. So if i set a coloe i can iterate over the right byte. But i noticed that if i take a 2D array it seems to flicker and if i take a regular array it does not flicker.

At the moment i got 5 LEDs at a register. So all5 get 3 lines for the color and 5 last bit for enabling the level.
Here is the interupt and how i write out the one byte i need to test it:

int i = 0; //bit angle counter
int j = 0;
ISR(TIMER1_COMPA_vect){
  digitalWrite(blank_pin, HIGH);//shut down the led
  //push the test byte
  switch(j){
  case 0:
    {
      SPI.transfer(led0[i]);
      break;
    }
  case 1:
    {
      SPI.transfer(led1[i]);
      break;
    }
  case 2:
    {
      SPI.transfer(led2[i]);
      break;
    }
  case 3:
    {
      SPI.transfer(led3[i]);
      break;
    }
  case 4:
    {
      SPI.transfer(led4[i]);
      i++;
      if(i>5)
      {
        i = 0;
      }
      break;
    }
  }
  j++;
  if(j > 5)
  {
    j=0;
  }

  // shift register to storage register
  digitalWrite(latch_pin, HIGH);//to storage
  digitalWrite(latch_pin, LOW);// to storage
  digitalWrite(blank_pin, LOW);  //enable the leds
  pinMode(blank_pin, OUTPUT);//Output Enable  important to do this last, so LEDs do not flash on boot up
}

In this case every LED has 5 byte for the coloring as explained above. But if i try to store everything in one array like led[5][5] and transfare it like SPI.transfer(led*[j]) it does flicker. Seems to be way slower or such.*
Can someone explain why this could be?
I start writing the code for the whole cube. At the Moment i would have 5 arrays out of 10byte for every level. Is there some other construct which i could easy do?
Regards
BennX

The digitalWrite and pinMode statements can be replaced with far more efficient direct port manipulation code, if you are using an AVR based arduino fat16libs library makes it simple: Fast digital I/O, software I2C, and software SPI libraries - Libraries - Arduino Forum

It will speed up the ISR code greatly, which should produce less 'off time' flicker.

pYro_65:
The digitalWrite and pinMode statements can be replaced with far more efficient direct port manipulation code, if you are using an AVR based arduino fat16libs library makes it simple: Fast digital I/O, software I2C, and software SPI libraries - Libraries - Arduino Forum

It will speed up the ISR code greatly, which should produce less 'off time' flicker.

Yea i know that it can be made faster but as already mentioned without a 2D arrray it works with no problems but with the 2D array it does flicker. I'd rather take some simple statement like PORTD |= 1<<blank_pin; instead of including a whole lib for it. Just dont know how to get my pins to high/low like that since it's 49 and 48.

Hi BennX

Please post the code that uses 2D arrays.

Thanks

Ray

Hackscribble:
Hi BennX

Please post the code that uses 2D arrays.

Thanks

Ray

Here is the total testcode:

#include <SPI.h>// SPI Library used to clock data out to the shift registers

// can use any pin you want to latch the shift registers
// push the to storage register, Pin 12 at IC
#define latch_pin 49
// to shut enable/disable the register. Low enables, Pin 13 at IC
#define blank_pin 48
// used by SPI, must be pin 51 at Mega 2560
#define data_pin 51
// used by SPI, must be 52 at mega 2560, Pin 11 at IC
#define clock_pin 52
//These variables can be used for other things
unsigned long start;//for a millis timer to cycle through the animations

byte leds[5][5];

void setup(){
  SPI.begin();//start up the SPI library
  SPI.setClockDivider(SPI_CLOCK_DIV2);//Run the data in at 16MHz/2 - 8MHz
  //Serial.begin(115200);// if you need it?
  noInterrupts();// kill interrupts until everybody is set up

  //We use Timer 1 to refresh the cube
  TCCR1A = B00000000;//Register A all 0's since we're not toggling any pins
  TCCR1B = B00001011;//bit 3 set to place in CTC mode, will call an interrupt on a counter match
  //bits 0 and 1 are set to divide the clock by 64, so 16MHz/64=250kHz
  TIMSK1 = B00000010;//bit 1 set to call the interrupt on an OCR1A match
  OCR1A=30; // you can play with this, but I set it to 30, which means:
  //our clock runs at 250kHz, which is 1/250kHz = 4us
  //with OCR1A set to 30, this means the interrupt will be called every (30+1)x4us=124us, 
  // which gives a multiplex frequency of about 8kHz

  //finally set up the Outputs
  pinMode(latch_pin, OUTPUT);//Latch

  interrupts();//let the show begin, this lets the multiplexing start

  for(int q = 0; q < 5; q++){
    //set the stages output correct
    leds[0][q] = B10000000;
    leds[1][q] = B01000000;
    leds[2][q] = B00100000;
    leds[3][q] = B00010000;
    leds[4][q] = B00001000;
  }
  //reset all leds
  for(int i = 0; i<5; i++){
    LED(i,0,0,0);
  }
}//***end setup***end setup***end setup***end setup***end setup***end setup***end setup***end setup***end setup***end setup

//test array of bytes to shift to the one register
int oldR = 0,oldG = 0,oldB = 0;
void loop(){//***start loop***start loop***start loop***start loop***start loop***start loop***start loop***start loop***start loop
  int r = random(5);
  int g = random(5);
  int b = random(5);
  for(int p = 0; p<5;p++){
    LED(p,r,g,b);
    delay(100);
  }

  r = random(5);
  g = random(5);
  b = random(5); 
  for(int p = 5; p>=0;p--){
    LED(p,r,g,b);
    delay(100);
  }
}//***end loop***end loop***end loop***end loop***end loop***end loop***end loop***end loop***end loop***end loop***end loop***end loop


int i = 0; //bit angle counter
int j = 0;
ISR(TIMER1_COMPA_vect){
  digitalWrite(blank_pin, HIGH);//shut down the led

  SPI.transfer(leds[j][i]);

  j++;
  if(j > 4)
  {
    j=0;
    i++;
    if(i>4)
    {
      i = 0;
    }
  }

  // shift register to storage register
  digitalWrite(latch_pin, HIGH);//to storage
  digitalWrite(latch_pin, LOW);// to storage
  digitalWrite(blank_pin, LOW);  //enable the leds
  pinMode(blank_pin, OUTPUT);//Output Enable  important to do this last, so LEDs do not flash on boot up
}

void LED(int l, byte red, byte green, byte blue){
  for(int i = 0; i<5; i++){
    if(i<red){
      bitWrite(leds[l][i],0,0);
    }
    else{
      bitWrite(leds[l][i],0,1);
    }
  }

  for(int i = 0; i<5; i++){
    if(i<green){
      bitWrite(leds[l][i],1,0);
    }
    else{
      bitWrite(leds[l][i],1,1);
    }
  }

  for(int i = 0; i<5; i++){
    if(i<blue){
      bitWrite(leds[l][i],2,0);
    }
    else{
      bitWrite(leds[l][i],2,1);
    }
  }
}

I fixed the issue already. Noticed that i checked <5 in this lines:

j++;
  if(j > 4)
  {
    j=0;
    i++;
    if(i>4)
    {
      i = 0;
    }
  }

Which is clearly not6 correced if i have a 5x5 array.

Can i go further to a 5x5x10 for the whole cube?
How do i direct manipulate the Port 49 and 48 to be way faster?

Picture shows 3 color lines and 5 mass enable lines. All 5leds with 1 register. current ~125 colors. Maybe more later if it works

How do i direct manipulate the Port 49 and 48 to be way faster?

If you do not want to use the library I linked, you could at least look inside it for the answer.

pYro_65:

How do i direct manipulate the Port 49 and 48 to be way faster?

If you do not want to use the library I linked, you could at least look inside it for the answer.

I'm sorry. Found it out by checking the librarys mapping. It is PORTL 0 and 1. So i changed my routine to:

int i = 0; //bit angle counter
int j = 0;
ISR(TIMER1_COMPA_vect){
  //direct port manipulation
  PORTL |= 1 << fast_blank_pin;//disable leds
  SPI.transfer(leds[j][i]);

  j++;
  if(j > 4)
  {
    j=0;
    i++;
    if(i>4)
    {
      i = 0;
    }
  }

  // shift register to storage register with fast manipulation
  PORTL |= 1 << fast_latch_pin;//up
  PORTL &= ~(1 << fast_latch_pin);//down to storage
  pinMode(blank_pin, OUTPUT);//Output Enable  important to do this last, so LEDs do not flash on boot up
  PORTL &= ~(1 << fast_blank_pin); //enable leds
}

Thanks for all the help again.karma added