Play different Animations at a time - DMD P10

Hi everyone,

Need an urgent help -
I am using 4 number of 16x32 P10 LED in a combination of 32x64 - 2 Row and 2 Column.

I need to display different animations on each row. Example - 1st row should display the sliding text and 2nd row should perform the flashing text.

However, I am able to play the animation at one row keeping 2nd row animation static. Can anybody please let me know how we can achieve it to play the animations on both rows?

Below is the code that I am using -

  dmd.drawString(event_len1,17,"Hello",strlen("Hello"),GRAPHICS_NORMAL); // the stationary string
  dmd.drawString(event_len2,25,"World",strlen("World"),GRAPHICS_NORMAL); // the stationary string

  dmd.drawMarquee("CODE BLINKING!",strlen("CODE BLINKING!"),0, 4); // set up the marquee
  time = millis();
  n=0;
  while(n<3) {
    while (!ret) {
      if ((time+20) < millis()) {
        ret = dmd.stepSplitMarquee(0,16); // parameters are the top & bottom rows to be scrolled
        time = millis();
      }
    }
    ret = false;
    n++;
  }
  dmd.clearScreen( true );

  dmd.drawString(name_len1,1,"HELLO",strlen("HELLO"),GRAPHICS_NORMAL); // the stationary string
  dmd.drawString(name_len2,9,"WORLD!",strlen("WORLD!"),GRAPHICS_NORMAL); // the stationary string
  unsigned long currentMillis = millis();
  for (int i=0; i <= 8; i++) {
     if(previousMillis - currentMillis > interval) {
       dmd.drawString(event_len1,17,"TOGGLE",strlen("TOGGLE"),GRAPHICS_TOGGLE); // the stationary string
       dmd.drawString(event_len2,25,"TEST",strlen("TEST"),GRAPHICS_TOGGLE); // the stationary string
       delay(300);
    }  
  }
  dmd.clearScreen( true ); 

First of all - what the DMD library you are using?

@b707 , thank you for your quick response. I am using below libraries -

#include "SPI.h"        
#include "DMD.h"        
#include "TimerOne.h"
#include "SystemFont5x7.h"
#include "Arial14.h"

Library - GitHub - freetronics/DMD: Arduino library to support the Freetronics Dot Matrix Display

DMD library doesn't has, for example, this method :

Yes, for that I have added external function in the library -

boolean DMD::stepSplitMarquee(int topRow, int bottomRow)
{
  boolean ret=false;
  marqueeOffsetX += -1;  // only scroll horizontally, 1 place left
  if (marqueeOffsetX < -marqueeWidth) { // if text has scrolled off the screen
    marqueeOffsetX = DMD_PIXELS_ACROSS * DisplaysWide; // set up to scroll again from the far right
    drawFilledBox(0, topRow, DisplaysWide*DMD_PIXELS_ACROSS-1, bottomRow, GRAPHICS_INVERSE); // clear the scroll rows
    ret=true; // indicates that this scroll has completed
  }

// This is the main change from the original function.
// It splits the left shift task into rows and bytes within a row to allow rows to be identified
// and treated separately.
  for (int row=topRow ;row<=bottomRow; row++) { // loop for each row in the scroll area
    for (int byteInRow=0; byteInRow<DisplaysWide*4; byteInRow++) { // loop for each byte within a row (4 per DMD across)
      int thisIndex = (DisplaysTotal*4)*(row%16) + (4*DisplaysWide*(row/16)) + byteInRow; //calculate index into screen buffer
      if ((byteInRow%(DisplaysWide*4)) == (DisplaysWide*4) -1) {  // if it's the last byte in a row
        bDMDScreenRAM[thisIndex]=(bDMDScreenRAM[thisIndex]<<1)+1;
        // shift bits left, and puts a '1' in last position (a '1' = LED OFF)
    
      } else {                                            // if it's NOT the last byte in a row
        bDMDScreenRAM[thisIndex]=(bDMDScreenRAM[thisIndex]<<1) +
                    ((bDMDScreenRAM[thisIndex+1] & 0x80) >>7);
        // shift bits left as well as the shifting the MSB of the next byte into the LSB
      }
    }
  }
  // Redraw last char on screen
  // required because 
  int strWidth=marqueeOffsetX;
  for (byte i=0; i < marqueeLength; i++) {
    int wide = charWidth(marqueeText[i]);
    if (strWidth+wide >= DisplaysWide*DMD_PIXELS_ACROSS) {
      drawChar(strWidth, marqueeOffsetY,marqueeText[i],GRAPHICS_NORMAL);
      return ret;
    }
    strWidth += wide+1;
  }
  return ret;
}

And to calculate the string width -

int stringWidth(const char *bChars)
{
  int strWidth = 0;
  for (byte i = 0; i < strlen(bChars); i++) {  // step through the length of the string
    strWidth += dmd.charWidth(bChars[i]) + 1;  // increment by the width of this character in pixels,
                                               // plus the 1 pixel character spacing
  }
  return strWidth - 1;                         // don't allow for a character space at the end
}

int calStringWidth(const char* thisWord) {
  int Xstart = 31 - (stringWidth(thisWord) / 2);                  // work out where to display the first character
  if (0 > Xstart) Xstart = 0;
  return Xstart;
}

Your code does this

while (n < 3) {
  // here you have the first animation
}


for (int i = 0; i <= 8; i++) {
  // here you have the second animation
}

each section is blocking for the duration of the animation, so you see the first one, then you see the second one.

you need to take a different, time based approach where you complete a small step (not blocking for long, no delay) for each animation you want to have

for example You have some global variables

const uint32_t topPeriod = 100;
uint32_t  lastTimeTop = -topPeriod;
bool topActive  = true;

const uint32_t bottomPeriod = 100;
uint32_t lastTimeBottom = -bottomPeriod;
bool bottomActive = true;

and your loop tests if there is some animation to do

void loop() {
    if (topActive && (millis() - lastTimeTop >= topPeriod)) {
      // perform one step of the animation for the top
      // set topActive to false when the animation is complete  
      ...
      lastTimeTop = millis();
    } 

    if (bottomActive && (millis() - lastTimeBottom >= bottomPeriod)) {
      // perform one step of the animation for the bottom
      // set bottomActive to false when the animation is complete  
      ...
      lastTimeBottom = millis();
    } 
 
  // here you have some business logic, non blocking. No delay

}

@J-M-L , Thank you so much for giving your valuable inputs to me.
How can I scroll this text without non blocking -

      dmd.drawMarquee("HELLO JANE!",strlen("HELLO JANE!"),0, 4); // set up the marquee
      while (!ret) {
        ret = dmd.stepSplitMarquee(0,16); // parameters are the top & bottom rows to be scrolled
        delay(50);
    }
      ret = false;

ret would be the opposite of topActive flag and the 50 (from your delay(50)) would be the topPeriod

const uint32_t topPeriod = 50;
uint32_t  lastTimeTop = -topPeriod;
bool topActive  = true;

void setup() {
  ...
  dmd.drawMarquee("HELLO JANE!",strlen("HELLO JANE!"),0, 4); // set up the marquee
}

void loop() {
    if (topActive && (millis() - lastTimeTop >= topPeriod)) {
      topActive =! dmd.stepSplitMarquee(0,16); // parameters are the top & bottom rows to be scrolled
      lastTimeTop = millis();
    } 

  // here you have some business logic, non blocking. No delay

}

First of all - non-blocking functions never use while() loops. While is a block loop itself.

@J-M-L @b707 , Thank you very much guys for giving me insights and helping me.

Yes, we can't use while for non-blocking, I understand but silly me, I wasn't able to use the millis correctly.
You solved the problem. closing it.

Please mark the thread as "Solved". I think you should choose one of the @J-M-L posts as solution

@J-M-L @b707 ,
I am facing problems when creating two sliding texts at the same time. I have created one more post for the same - Play two sliding animations at a time
I would request if you can provide me your valuable insights that would be really helpful.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.