SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By blaag
#94886
I am having difficulty daisy chaining two 8x8 RGB matrix backpacks. They are both running the latest firmware and they both work fine as standalones.

The process as I understand it is:
1) Break the chain apart and attach a single backpack via SPI.
2) Send the character '%' to the backpack to enter command mode.
3) Send a decimal digit (not character digit) in the range 1 - 8 to the board indicating how many module are daisy chained.
4) Repeat for each module in the chain.

This part is complete. I am assuming it works since the color bar that first appears at the top changed slightly.

I am not quite sure how I am to send a frame. Looking at RGB_Backpack_v4.c it appears that all I need to do is send 64 * NUMBOARDS bytes - in my case, 128 bytes. However rgbmatrixbackpack_userguide.pdf states that I need to send a 64 byte frame using this process for each backpack in the chain:
1) Assert CS
2) Send 64 byte buffer
3) De-assert CS
4) Repeat for next backpack

I have tried sending 128 bytes within a single assert/deassert and also sending two 64 byte frames broken up by the assest/deassert process. Neither appears to work. I also read in a posting that you need to send the command code at each boot. I tried that, but there was no change.

I took the example backpack sketch and modified it only very slightly. I took the assert/deassert process and put it in a function called sendframe and then move a single blue pixel forward. The first matrix in the chain displays acts somewhat normal, and the second matrix in the chain mirrors the first except it is always shifted a single pixel forward - so if I display something at char_buffer[5] on the first matrix, it appears at the 6th pixel on the second.

Does anyone have any suggestions?

I'd also like to make a quick comment on the firmware code - RGB_Backpack_v4.c appears to track how many times it has booted. On the 255th boot it forces NUMBOARDS back to 1 and writes it to EEPROM.

Here is the code.
// Writing to the RGB Serial Backpack Matrix from SparkFun Electronics
// by Ryan Owens
// Copyright SparkFun Electronics

//Define the "Normal" Colors
#define BLACK  0
#define RED  0xE0
#define GREEN  0x1C
#define BLUE  0x03
#define ORANGE  RED|GREEN
#define MAGENTA  RED|BLUE
#define TEAL  BLUE|GREEN
#define WHITE (RED|GREEN|BLUE)-0xA0

//Define the SPI Pin Numbers
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//Define the variables we'll need later in the program
char color_buffer [128];
byte count = 0;

void setup()
{  
  //SPI Bus setup
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1); //Enable SPI HW, Master Mode, divide clock by 16 //SPI Bus setup
  
  //Set the pin modes for the RGB matrix
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  
  //Make sure the RGB matrix is deactivated
  digitalWrite(SLAVESELECT,HIGH);
  
  color_buffer[0] = '%';
  color_buffer[1] = 2;
  sendframe(1);
  sendframe(2);
  delay(1000);



void sendframe(byte whatboard) {
  //Activate the RGB Matrix
  digitalWrite(SLAVESELECT, LOW);
  delay(1);
  //Send the color buffer to the RGB Matrix
  if (whatboard == 1) {
    for(int LED=0; LED<64; LED++){
      spi_transfer(color_buffer[LED]);
    }
  }
  if (whatboard == 2) {
    for(int LED=64; LED<128; LED++){
      spi_transfer(color_buffer[LED]);
    }
  }
  delay(1);
  //Deactivate the RGB matrix.
  digitalWrite(SLAVESELECT, HIGH);
}
 
void loop()
{
  //Load colors into the first row color buffer array.
  //This will be the array of colors sent to the RGB matrix.
  //color_buffer[0]=BLACK;
  //color_buffer[1]=RED;
  //color_buffer[2]=GREEN;
  //color_buffer[3]=BLUE;
  //color_buffer[4]=ORANGE;
  //color_buffer[5]=MAGENTA;
  //color_buffer[6]=TEAL;
  //color_buffer[7]=WHITE;
  
  //color_buffer[0] = TEAL;
  
  for (byte i = 0; i < 128; i++) {
    color_buffer = BLACK;
  }
  
  //for (byte j = 64; j < 128; j++) {
    //color_buffer[j] = BLUE;
  //}
  
  color_buffer[count++] = BLUE;
  
  if (count > 127) {
    count = 0;
  }
  
  sendframe(1);
  sendframe(2);
  
  //delay(15);
  
  //Activate the RGB Matrix
  //digitalWrite(SLAVESELECT, LOW);
  //delay(1);
  //for(int LED=64; LED<128; LED++){
    //spi_transfer(color_buffer[LED]);
  //}
  //Deactivate the RGB matrix.
  //delay(1);
  //digitalWrite(SLAVESELECT, HIGH);
  //while(1);
  delay(500); // allow some time for the Serial data to be sent


//Use this command to send a single color value to the RGB matrix.
//NOTE: You must send 64 color values to the RGB matrix before it displays an image!
char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF))) // Wait for the end of the transmission
  {
  };
  return SPDR; // return the received byte
}

#94901
As a workaround I'm just going to set all the backpacks to single mode and use separate slave select pins for each. Initial testing shows this to work fine, I'll just have to do some extra pointer arithmetic to get things to flow from one to the other.

It seems this question has been asked numerous times in the forums with not much luck.

Thanks for reading.
#95421
I also have an hard time with this one.

I could get it working with 3 modules. See here:


http://www.youtube.com/watch?v=gvCp5MJVv4s


But no luck with 4.

What seems to work for 3 is to send the frame %3 once at the start of your application.

I also discovered that any % in a 64 chars video frame seems to reprogram the LED tile.

If I can get it working with 4 I will post my solution.
#95663
FraKtus wrote:I also have an hard time with this one.

I could get it working with 3 modules. See here:


http://www.youtube.com/watch?v=gvCp5MJVv4s


But no luck with 4.

What seems to work for 3 is to send the frame %3 once at the start of your application.

I also discovered that any % in a 64 chars video frame seems to reprogram the LED tile.

If I can get it working with 4 I will post my solution.
I watched your videos, very nice. I like the plasma effect. I was thinking of putting a plasma effect in but didn't know how it worked, I will play around with some trig and feeding that into the color buffer bytes. My ethernet pieces should come in today, I will probably post a video of what I am doing before too long.

Again, nice project and thanks for the reply.
#96863
Hi, I just got these boards, 6 of them. I'm going to be playing with them next week. I too have been looking at the firmware and can't really make some stuff out. First I don't know how the data gets accross to the right modules. It looks like the buffer records all data passed over spi. I don't get what the reset after 255 boots is for. It's a little strange. Why would it be that way?

Im going to play with what I have first before trying to modify the firmware. I was thinking about giving every modules an address (1-6) and then modify the % command so that it takes more than one value. Something like %, command, value. So them I could do % LoadModule 1 and then load 64 bytes.

Have you people fixed your problems?
#96891
I guess at the same time that command thing could help with setting the NUM_BOARDS variable and storing it into the eeprom. So I coould do "% SetNumBoards 6" to set the num_boards var to 6. "SetNumBoards" would be a number between 1-255 excluding "%". I'm just spelling out the command name. I would have to connect to the boards seperately to set their ID's. "% SetBoardID 2" for ID #2. This way I don't have to reprogram every board.

Another thing I can think of is to switch graphic modes with something like "% SetGFXMode 9". This could switch me into text mode, meaning that all I'm going to show on the screens is text. So I could now have a command "% SetColor Red" that sets an internal color var to red and unstead of sending 64 bytes per 8x8 grid, I could send 8 bytes instead (64 bits). This could make it much faster and give more time for the controller to do other things. Of coarse this would only work for text. Full color (plasma) effects would have you go into graphins mode ("% SetGFXMode 1").

Would this be a good improvement??

Denis.
#97529
Hi, I have been playing with 3 of these since Sunday. I have run into the same problems as you guys. I found the problem I was having. It has to do with resetting the processor (arduino) while the Modules were already receiving data. Thous would set the CS high. What I found caused this in the firmware is that "frame_index" gets reset when you make CS high, but "byte_count" doesnt. This leads to both variable getting out of sync if you reset in the middle of writting to modules. I modified the firmware to reset the "byte_count" to zero at the same time as "frame_index". Because of this change, I now set CS Low, send NUM_BOARDS*64 bytes, and set CS high. Now it works every time!

I've tried this with 1, 2 and 3 boards chainned. Later today I'll try with 4.

Another thing that helped was to set the SPI clock to divide by 128. I think the arduino clock is 16mhz and if you divide this by 128, you get 125khz which is what the datasheet says you have to stay below. I tried this before changing the firmware and I got mixed results, but after the firmware it worked every time.

Hope this helps other people,
Denis.
#97627
I figured out something cooler too. I don't know if it works with the old firmware, but it does with the one I modified. Instead of separating the modules and sending them %3 (or how many boards you have), I can now program it while they are plugged in. For 3 chained boards I send %3000. %3 is the normal way to tell one module that there will be 3 chained together. The 3 zeros that follow just flush out the SPI stream and sends the %3 to the other modules and they just do their stuff (sets up to 3 boards). So I just have to send % then the number of boards, then a 0(zero) for each board I have in the chain.

Examples:
%10
%200
%3000
%40000
ect.

I've also remapped the LED's on the board to be aligned in vertical strips instead of horizontal strips. I think this will make it easier for scrolling text. I haven't tried scrolling text yet. This change just uses a remap look-up table. 64 look-ups per call of the "parse_frame" routine.

If anyone wants the firmware I am using, message me and I can send it to you. The credit still goes to the person who wrote the original firmware, I just changed it for my use. Without them I'd be lost!

Denis.
#98395
brainwav wrote:I guess at the same time that command thing could help with setting the NUM_BOARDS variable and storing it into the eeprom. So I coould do "% SetNumBoards 6" to set the num_boards var to 6. "SetNumBoards" would be a number between 1-255 excluding "%". I'm just spelling out the command name. I would have to connect to the boards seperately to set their ID's. "% SetBoardID 2" for ID #2. This way I don't have to reprogram every board.

Another thing I can think of is to switch graphic modes with something like "% SetGFXMode 9". This could switch me into text mode, meaning that all I'm going to show on the screens is text. So I could now have a command "% SetColor Red" that sets an internal color var to red and unstead of sending 64 bytes per 8x8 grid, I could send 8 bytes instead (64 bits). This could make it much faster and give more time for the controller to do other things. Of coarse this would only work for text. Full color (plasma) effects would have you go into graphins mode ("% SetGFXMode 1").

Would this be a good improvement??

Denis.
You have a solution? upload firmware please.
Works 100% correctly?

do I need a AVR programmer??
#98484
It does work 100%. I am out of the country right now, I will post it on Friday when I get back. Yes you will need a programmer. Just add "byte_count = 0;" without quotes to the firmware where the "frame_index" variable gets set to zero.
#98828
Ok, so now you need to solder a 2x3 pin header on the back of each 8x8 board so you can program them. If you look on the back, you'll see 6 holes (2x3), this is the programming port. This is where you will connect your program. Use WinAVR to compile the code and AVRStudios to download to the chip (or whatever your programmer uses). There are some good tutorials around on how to do this. Some say you can just hold the programmer pins to the 8x8 board to program it, but I haven't had much success with this. If you have those pogo pins sparkfun sell, they may work, otherwise just solder a header onto it.