Page 1 of 1

Same arduino program works with 1 DMD and fails with 2

Posted: Mon Apr 14, 2014 12:18 pm
by Rutho
I have put together a simple arduino program to update a marquee display based on text sent to a webserver. The program works great when using a single DMD but seems to slow to a halt when a second DMD is added.

I have powered the two and the etherten board and, given how bright the single board is when testing, I think the second is powered sufficiently as well.

The program is slightly different to other samples I've seen as I use a timeout in the loop() to update the marquee but as I said it works great with one DMD so I don't it is the program as the only difference is the WIDTH value (2 instead of 1).

I have double checked the alignment of the boards and based on the diagrams I have it aligned correctly. I have also double checked the power leads to ensure they are all correct as well.

I there something I've missed to get the marquee to go over two DMD boards?

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Mon Apr 14, 2014 2:19 pm
by stryker
Hi,

Are you trying to power the 2x DMDs via the ribbon cable data connection alone ? That's not going to be sufficient for two. You'll need to run an external 5V power supply to the DMD panels and join the grounds of that and your Arduino together.

Cheers ! Geoff

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Mon Apr 14, 2014 8:54 pm
by Rutho
Each board and the arduino are powered. I did some surgery on a 5V power pack cable to add leads for the second board and a plug for the arduino.

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 12:42 am
by stryker
That's good. Can you please post your code?

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 3:17 am
by Rutho

Code: Select all

#include "SPI.h"
#include "Ethernet.h"
#include "WebServer.h"
#include "DMD.h"
#include "TimerOne.h"
#include "Arial_black_16.h"
//#include "SystemFont5x7.h"

#define DEBUG  //uncomment for serial debug output

#define DISPLAYS_ACROSS 2
#define DISPLAYS_DOWN 1
DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);

static uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

WebServer webserver("", 80);

P(html) = "<html>";
P(head) = "<head><title>Alerter</title></head>";
P(body) = "<body>";
P(h1) = "<h1>Alerter</h1>";
P(ebody) = "</body>";
P(ehtml) = "</html>";

P(startForm) = 
      "<form action='/start' method='POST'>"
        "<p><input type='text' name='message' value='' /></p>"
        "<p><input type='submit' name='submit' value='Start' /></p>"
      "</form>";

P(stopForm) = 
      "<form action='/stop' method='POST'>"
        "<p><input type='submit' value='Stop' /></p>"
      "</form>";

#define MSGLEN 100
char* message = new char[MSGLEN];

#define MARQUEE_OFF 0
#define MARQUEE_DRAW 1
#define MARQUEE_MOVE 2

int marquee = MARQUEE_OFF;

void ScanDMD() { 
  dmd.scanDisplayBySPI();
}


void indexCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
  #ifdef DEBUG
    Serial.println("index");
  #endif
  
  server.httpSuccess();
  server.printP(html);
  server.printP(head);
  server.printP(body);
  server.printP(h1);
  server.printP(marquee == MARQUEE_OFF ? startForm : stopForm);
  server.printP(ebody);
  server.printP(ehtml);
}


char* name = new char[10];
char* value = new char[MSGLEN];

void startCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
  #ifdef DEBUG
    Serial.println("start");
  #endif
  
  if (type == WebServer::POST) {
    while (server.readPOSTparam(name, 10, value, MSGLEN)) {
      if (strcmp(name, "message") == 0) {
        strcpy(message, value);
      }
    }
  }
  
  marquee = MARQUEE_DRAW;
  
  server.httpSeeOther("/");
}


void stopCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
  #ifdef DEBUG
    Serial.println("stop");
  #endif
  
  strcpy(message, "");
  marquee = MARQUEE_OFF;

  dmd.clearScreen(true);
  
  server.httpSeeOther("/");
}


void setup() {
  #ifdef DEBUG
    Serial.begin(9600);
    Serial.println("debugging");
  #endif
  
  Timer1.initialize(1500);
  Timer1.attachInterrupt(ScanDMD);

  dmd.clearScreen(true);
  dmd.selectFont(Arial_Black_16);
//  dmd.selectFont(SystemFont5x7);

  int result = Ethernet.begin(mac);
  
  #ifdef DEBUG
    Serial.print("address: ");
    for (byte thisByte = 0; thisByte < 4; thisByte++) {
      // print the value of each byte of the IP address:
      Serial.print(Ethernet.localIP()[thisByte], DEC);
      Serial.print("."); 
    }
  Serial.println();
  #endif

  webserver.setDefaultCommand(&indexCmd);
  webserver.setFailureCommand(&indexCmd);

  webserver.addCommand("start", &startCmd);
  webserver.addCommand("stop", &stopCmd);

  webserver.begin();
}


void loop() {
  int len = 128;
  char buff[len];
 
  webserver.processConnection(buff, &len);

  if (marquee == MARQUEE_OFF) {
    return;
    
  } else if (marquee == MARQUEE_DRAW) {
     dmd.drawMarquee(message, strlen(message), (32*DISPLAYS_ACROSS)-1, 0);
     marquee = MARQUEE_MOVE;

  } else if (marquee == MARQUEE_MOVE) {
    if (!timeout()) return;
     marquee = dmd.stepMarquee(-1,0) ? MARQUEE_DRAW : MARQUEE_MOVE;
  }
}

// Cycle handling
#define INTERVAL 50
unsigned long prevTime = millis();

boolean timeout() {
  unsigned long currentTime = millis();
  if (currentTime - prevTime < INTERVAL) return false;
  prevTime = currentTime;
  return true;
}


Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 5:21 am
by stryker
Hi,

Thanks for posting. That took a while to work through but nothing stands out as broken in that loop() section where you actually do the marquee work. Does the DMD demo run in your present hardware configuration with 2 panels?

Cheers ! Geoff

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 5:56 am
by Rutho
I'll check the basic DMD demo tonight.

If I change the DISPLAYS_ACROSS define to 1 and run it with one DMD it works great. If I connect two DMDs and have DISPLAYS_ACROSS defined as 2 it takes about a minute to move 1 pixel across. Something is causing the program to run incredibly slowly :-( The pixels that *are* lit are extremely bright so I don't think lack of power is the problem...

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 6:40 am
by stryker
Ah well that's different to it not working, and now I have some suggestions for you. There's been lots of discussions about race conditions being created with multiple DMD displays. That made me look to your

Code: Select all

Timer1.initialize(1500);
line. Try that with the 5000 default and see what you get. Counter-intuitively, by reducing to 1500 you may find the display is unable to complete everything it needs to within the time the service routine has to operate.

Then you might try modifying your DMD.cpp to reduce the SPI clock divider to something like

Code: Select all

    SPI.setClockDivider(SPI_CLOCK_DIV2);
The default is

Code: Select all

SPI.setClockDivider(SPI_CLOCK_DIV128);
which is very slow. I found I could get 3 working with the default clock speed, but 4 or more caused it to hang the code entirely.

Cheers ! Geoff

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 12:10 pm
by Rutho
I've made the suggested changes and it looks great. 2 boards working together. Thanks

Re: Same arduino program works with 1 DMD and fails with 2

Posted: Tue Apr 15, 2014 12:20 pm
by stryker
Glad to hear it! All the best with your project - Geoff