LOLshield line skipping

Hello everyone,

I’m currently trying to code simple animations using an LOLshield. My animations are just simple boxes, squares, and lines moving across the LED screen (ie. a black line moving against a lit background). I just started using the LOLshield library so I’m not quite familiar with all the functions. At the moment, what I did was copied the “basic example” in the LOLshield library and modified it to my liking. However, when I play my animation, the code is skipping every other line that assigns the animation in my Bitmap. How can I stop this? It was suggested that I modify
data = pgm_read_word_near (&BitMap[frame][line]);
However, I’m still not sure how to do it.
Any suggestions would be greatly appreciated. Thanks!

Here is my code

#include <avr/pgmspace.h>  //AVR library for writing to ROM
#include <Charliplexing.h> //Imports the library, which needs to be
                           //Initialized in setup.

//Sets the time each frame is shown (milliseconds)
const unsigned int blinkdelay = 1000;

/*
The BitMap array is what contains the frame data. Each line is one full frame.
Since each number is 16 bits, we can easily fit all 14 LEDs per row into it.
The number is calculated by adding up all the bits, starting with lowest on
the left of each row. 18000 was chosen as the kill number, so make sure that
is at the end of the matrix, or the program will continue to read into memory.

Here PROGMEM is called, which stores the array into ROM, which leaves us
with our RAM. You cannot change the array during run-time, only when you
upload to the Arduino. You will need to pull it out of ROM, which is covered
below. If you want it to stay in RAM, just delete PROGMEM
*/
PROGMEM const uint16_t BitMap[][9] = 
{
//Diaganal swipe across the screen

//vertical bar moving horizontally
{16383,16383,16382,16382,16382,16382,16383,16383,16383},
{16383,16383,16381,16381,16381,16381,16383,16383,16383},
{16383,16383,16379,16379,16379,16379,16383,16383,16383},
{16383,16383,16375,16375,16375,16375,16383,16383,16383},
{16383,16383,16367,16367,16367,16367,16383,16383,16383},
{16383,16383,16351,16351,16351,16351,16383,16383,16383},
{16383,16383,16319,16319,16319,16319,16383,16383,16383},
{16383,16383,16255,16255,16255,16255,16383,16383,16383},
{16383,16383,16127,16127,16127,16127,16383,16383,16383},
{16383,16383,15871,15871,15871,15871,16383,16383,16383},
{16383,16383,15359,15359,15359,15359,16383,16383,16383},
{16383,16383,14335,14335,14335,14335,16383,16383,16383},
{16383,16383,12287,12287,12287,12287,16383,16383,16383},
{16383,16383,8191,8191,8191,8191,16383,16383,16383},


{18000}
};

void setup() 
{
  LedSign::Init(DOUBLE_BUFFER | GRAYSCALE);  //Initializes the screen
}
void loop()
{
  //for (uint8_t gray = 7; gray < SHADES; gray+0)
  uint8_t intensity=1;
  DisplayBitMap(intensity);  //Displays the bitmap
  //uint8_t intensity2=7;
 //DisplayBitMap(intensity2);  
}

void DisplayBitMap(uint8_t grayscale)
{
  boolean run=true;    //While this is true, the screen updates
  byte frame = 0;      //Frame counter
  byte line = 0;       //Row counter
  unsigned long data;  //Temporary storage of the row data
  unsigned long start = 0;

  while(run == true)
  {

    for(line = 0; line < 9; line++)
    {

      //Here we fetch data from program memory with a pointer.
      data = pgm_read_word_near (&BitMap[frame][line]);
      
      //Kills the loop if the kill number is found
      if (data==18000)
      {
        run=false;
      }
      
      //This is where the bit-shifting happens to pull out
      //each LED from a row. If the bit is 1, then the LED
      //is turned on, otherwise it is turned off.
      else for (byte led=0; led<14; ++led) 
      {
        if (data & (1<<led)) 
        {
          LedSign::Set(led, line, grayscale);
        }
        else 
        {
          LedSign::Set(led, line, 0);
        }
      }
    }

    LedSign::Flip(true);   
    
    unsigned long end = millis();
    unsigned long diff = end - start;
    if ( start && (diff < blinkdelay) )
        delay( blinkdelay - diff );
    start = end;

    frame++;  
  }
}

It was suggested that I modify

Suggested by whom? If that person couldn't suggest how, perhaps the advice wasn't all that good.

What are you reading from PROGMEM? Is it what you think you are reading? If so, the advice to change the statement that reads from PROGMEM was wrong. If not, then you should what what you are reading, as well as the actual values of frame and line.

Thanks for the reply. I also posted my question on another forum and it was suggested by another user. However, he wasn't sure if that was the correct suggestion either. And to be honest, I have no idea what is being read in the PROGMEM. This is something within the LOLshield library that I'm still trying to understand better.

And to be honest, I have no idea what is being read in the PROGMEM.

The thing to do, then, is find that out. Serial.print() the values of frame, line, and data, with prefixes so you know what is what. If you find that frame and line are 0, and data is 456, you know something is wrong. If frame and line are 0, and data is 16383, things are good.

At least for that one array position. But, you'll have a clue, instead of stabbing in the dark.

When you're satisfied that you're using the right data, take a look at how you manage the delay. I think that the sketch doesn't skip frames, but runs through some of them so fast that you don't see them. To test this theory, open Serial, and print the frame number sometime before it's incremented.

Rion: At the moment, what I did was copied the "basic example" in the LOLshield library and modified it to my liking. However, when I play my animation, the code is skipping every other line that assigns the animation in my Bitmap. How can I stop this?

If you have an example sketch consisting of "code and data" that compiles and runs OK, and then you only modified the data while the code was left unchanged, the only possibility with unchanged code is: You messed it up by changing the data!

If the animation does not look like you want it, you are using data that show a different animation than you want it.

How did you create the data "modified to your liking"? Did you paint something on paper and added numbers with a pocket calculator? Did you use some software tool to create the data frames?

Why are you sure, that the animation data are correct for what you want to display?

Can you describe more detailed what you want it to look like and how you want the animation to be displayed?

jurs:
… the only possibility with unchanged code is: You messed it up by changing the data!

I think something else is responsible for the OP’s primary complaint. He says that the code is “skipping every other line.” His data suggests that his animation consists of a mostly lit display, with a single dark line that moves across the long axis of the display, and back again. I think he means that he sees a dark line in row 0, then in row 2, then in 4, and so on, rather than 0, 1, 2 as he expects.

I think that the code comes from here: https://code.google.com/p/lolshield/downloads/list. I presume that he used the lates version of the library, “LoLShield v82.” I think that the sketch he started with is called, “LoLShield_BasicTest.”

Admittedly, that’s a whole lot of reading between the lines. If the OP had posted a link to the library, and a clear description of the original sketch, it would be easier to be sure what he’s talking about.

I think that this code, which is original to the library sketch, is responsible for his primary complaint:

   unsigned long end = millis();
    unsigned long diff = end - start;
    if ( start && (diff < blinkdelay) )
        delay( blinkdelay - diff );
    start = end;

After the sketch manages the display, it saves the time in variable end, calculates how much time has passed since it last logged the time in variable start, and then delays for the remainder of an interval called blinkdelay. Then, it writes over the time in start. I’d expect to see it put the current time in start, but it doesn’t - it saves the time that the delay started, rather than the time that it ended.

Even weirder, start is set to 0 at the beginning of the function. I’d have expected to find it set to the current value of millis().

Ignoring the unexpected initialization, I’ll presume that, sooner or later, start takes on a reasonable value - something close to the current value of millis(). The qualitative look below suggests that’s not a bad assumption. Looking at it from that point forward:

  • The system manages the display, and then sets the value of end to the current time.
  • It calculates how long until the display delay elapses, based on the value of start
  • It delays that long.
  • Then it sets a new value of start, not to the current time, but to the time before the delay.
  • At the next iteration, end - start will be roughly equal to the display delay, so there will only be a little bit of delay, or maybe none at all. start will be set to end, roughly the current time.
  • Next round, everything works, and the delay is as expected.
  • Next round, there’s no delay

And so on.

The code doesn’t skip “every other line,” it rushes through every other line, because the beginning of the frame interval is calculated using the wrong value. That’s original to the example sketch.

I believe that the reason it’s not obvious when running the example sketch is that the delay interval is set to a much shorter value - 20 milliseconds, as opposed to 1000 milliseconds in the OP’s sketch. Presumably, he slowed it down for development purposes. It’s hard to see in the original, but obvious in the modified code.

As a first recommendation, I’d set start to millis(), both in the initialization and the update.

Thank you so much for the inputs everyone. I really appreciated it. A great thank to tmd3! Your diagnosis and inputs were exactly what I was attempting to describe and needed help with. All I had to do was change my "start to millis() like you suggested and it fixed the skipping. Thank you so much of the inputs!