I'm working on making a scrolling LED matrix display. I'm storing a 1-bit bitmap of the entire display content that's being scrolled in ram and then using a moving pointer to update the display with a portion of the ram area. It my own idea, but I don't know if I'm reinventing the wheel or there's a better way to do it. It's working beautifully; the problem is that I'm burning way too much ram with this technique. A 100-character message will use 600 bytes of ram with my 5x7 font, which seems excessive when the MCU only has 1 or 2k.

I'm working on making a scrolling LED matrix display. I'm storing a 1-bit bitmap of the entire display content that's being scrolled in ram and then using a moving pointer to update the display with a portion of the ram area. It my own idea, but I don't know if I'm reinventing the wheel or there's a better way to do it. It's working beautifully; the problem is that I'm burning way too much ram with this technique. A 100-character message will use 600 bytes of ram with my 5x7 font, which seems excessive when the MCU only has 1 or 2k.

What do people normally do to implement a scrolling display?

You are taking your message which is in RAM and decoding it with the font which is in flash to precreate a bitmap which is necessarily large, in RAM.

Why?

I have a scroller and I do basically what you do but there is no problem decoding the text via the font on the fly with no need to store the bitmap anywhere except in the driver/shift registers. The Arduino is fast enough for that, at least it was for me with 6 8x8 displays.

I have a scroller and I do basically what you do but there is no problem decoding the text via the font on the fly with no need to store the bitmap anywhere except in the driver/shift registers. The Arduino is fast enough for that, at least it was for me with 6 8x8 displays.

Very nice looking display. That's what I'm working on, currently I have one 8x8 matrix on breadboard wired as you described and I just ordered some PCBs for 7219 backpacks to build a row of modules, exactly what you have but I haven't decided how many modules I'll use yet.

Is your actual display as choppy as the video? I thought about decoding the font on the fly but figured it would make the timing more difficult and just feel kludgy in code. Are you using a blocking delay or using millis() to make sure the time interval between updating the display is constant? Being more careful with the time between updates could make your scroll more smoothly.

Right now, my code is incredibly simple, I don't even need to read all the symbols from the font. For a time display when I want a colon, I just set 2 columns to 0x24, and to make the colon blink seamlessly as it scrolls, I can blank and reset those 2 columns every second. Replicating that functionality without the buffered bitmap would be difficult. Same goes for any scrolling animations.

Anyway, thanks for your reply, I guess you've given me the right answer, which is to work out the more complicated code. Either that or upgrade my mega168 to a 328 and limit my messages to 150 characters or so .

Edit: I didn't notice you posted code at first, I just read through it, it's not quite as difficult as I thought, so I really should spend some time trying to do it that way (at least if I don't want animations). I'm a bit confused by your triple loop, is it because your font is storing columns but you're updating the displays as rows so you're twisting around bits?

Is the delay(10) after the for i loop the only time keeping? If so, is it scrolling as fast as it's able right now?

It is choppy and I was not able to determine why exactly. The delay is to slow it down, it's not timekeeping. At first I thought the problem was that the amount of time through the loop was variable so I got the time at the start of the loop using the micros() function call and delayed the end of the loop variably as 10000 micros - the number of microseconds spent in the loop to make sure the time for every loop iteration was constant (10ms). However, that did nothing at all to fix the problem nor did some other stuff I tried before I benched it for the time being. Still not sure if it is the way I am using the MAX chips or what, but it doesn't seem to be because of variable execution time. The fact is, those bitwise operations are very fast and execute in constant time so I don't think that is part of the problem at all. All the other stuff is integer looping and comparison, these should all get translated to one clock instructions. Maybe it is in the driver library, or maybe it wasn't really designed for scrolling. I am not sure yet.

I just wanted to demonstrate that you can use bitmap operations to figure out "what bit you are on" when displaying text from a bitmapped font rather than blowing it up into a huge array in advance.

As far as the loops. You can see the data is being sent to the MAX chips using the MAX library here:

lc.setRow(i, j, outputbyte);

So the outer loop i determines the display, it runs 0 to 5. (the comment says "loop through our 8 displays" this is wrong)

The center loop j determine which row we are on, it runs 0 to 7. The MAX library sets a row at a time with a bitmapped byte.

The inner loop k sets up that byte so it too runs from 0 to 7. It copies bits from the font map for the current character into the output byte that will be sent to the MAX chip. It also does work to determine when we have advanced past the current character using the font length array or have advanced past the end of the message itself.

Too bad the MAX chips can't be used as "dumb" shift registers. You could just send a new column of data and let the last one fall off the most significant end of the register. Instead you are sending the whole damn dataset every time you want to advance the display a column.

I have attached some test code I used to perfect monochrome scrolling and the use of PROGMEM. The output routine is currently configured for testing on the Rainbowduino but was intended for MAX7219 chips. The final code went into a 16x8 MAX7219 driven matrix and would support 24x8 as it stands and *maybe 56x8 with minimal modification. *I say maybe because I'm not sure how fast it would scroll.

wgarrido

I am using JoeN's code for scrolling text and I was wondering if you ever fixed the choppiness? I was also wondering if there was a way using your code to display text that is short enough to display without scrolling?

I am little confused how your loops only which char is which in the array.

I am able to send text from the serial port and display it using your code. Thank you for posting it.

I am using a 24x8.)

Thanks.

wgarrido

I sort of got it to work. I created a new function that doesn't loop and resets the counters. Still can't get it to finish cleanly. What is a good way for it to stop when all the characters are displayed? Here is what I have.

for (i=devCount-1;i>=0;i--) // Loop through our 8 displays { for (j=0;j<8;j++) // Set up rows on current display { byte outputbyte = 0;

curchar = msg[curcharix];

curcharixsave = curcharix; curcharbitsave = curcharbit;

for (k=7;k>=0;k--) // Copy over data for 8 columns to current row and send it to current display { // This byte is the bitmap of the current character for the current row byte currentcharbits = Font8x5[((curchar-32)*8)+j];

if (currentcharbits & (1<<curcharbit)) outputbyte |= (1<<k);

// advance the current character bit of current character

curcharbit ++;

if (curcharbit > lentbl_S[curchar-32]) // we are past the end of this character, so advance. { curcharbit = 0; curcharix += 1; if (curcharix+1 > msgsize) curcharix=0; //This is what I was playing with. curchar = msg[curcharix]; } }

lc.setRow(i, j, outputbyte);

if (j != 7) // if this is not the last row, roll back advancement, if it is, leave the counters advanced. { curcharix = curcharixsave; curcharbit = curcharbitsave; }

for (i=devCount-1;i>=0;i--) // Loop through our X displays { for (j=0;j<8;j++) // Set up rows on current display { byte outputbyte = 0;

curchar = msg[curcharix];

curcharixsave = curcharix; curcharbitsave = curcharbit;

for (k=7;k>=0;k--) // Copy over data for 8 columns to current row and send it to current display { // This byte is the bitmap of the current character for the current row byte currentcharbits = Font8x5[((curchar-32)*8)+j];

if (currentcharbits & (1<<curcharbit)) outputbyte |= (1<<k);

// advance the current character bit of current character

curcharbit ++;

if (curcharbit > lentbl_S[curchar-32]) // we are past the end of this character, so advance. { curcharbit = 0; curcharix += 1; if (curcharix+1 > msgsize) k=-1; //This end the current display curchar = msg[curcharix];

} }

lc.setRow(i, j, outputbyte);

if (endFlag) return;

if (j != 7) // if this is not the last row, roll back advancement, if it is, leave the counters advanced. { curcharix = curcharixsave; curcharbit = curcharbitsave; if (curcharix+1 > msgsize) endFlag=true; //sets that we are done and exit after the next iteration }

I just noticed this message was back up on the list. Over the weekend, I soldered up this project on a pad per hole veroboard with a standalone ATMega328P replacing the Arduino on the board itself. I also increased the number of displays and 7219s to 8. I am going to rework the software soon to try to get rid of that scrolling choppiness bug. I think I may have to bypass the MAX7219 library and bitbang the chips myself. Hopefully I can figure it out. Glad you got it to work for you.

" I think I may have to bypass the MAX7219 library and bitbang the chips myself."I would suggest using SPI.transfer() to send data to the MAX7129's. That will help your speed a lot.Send out 64 bytes as one burst at whatever rate you update the display, with all devices daisy chained:

I am saving on memory by having no display buffer at all. The code generates the bits from the display message, display font, and current position every time it sends data to the MAX7219 chips, which is every time it scrolls a column over. But all of that interface code I can use, thank you.