Arduino and P10 display, using TimerOne interrupt

Hello there,

I'm trying to use http://playground.arduino.cc/Code/Stopwatch in my project. As far as I use only this code, everything works OK.
Then I try to show this stopwatch on P10 display, using DMD and TimerOne library.

//initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
Timer1.initialize( 5000 ); //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
Timer1.attachInterrupt( ScanDMD ); //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()

When I include this two lines of code into project I get delay, which cause my stopwatch second is no more one second but more.

Can someone tell me why this delay occur and how to solve it?

Thanks in advance

We need to see all your sketch.

What is a D10 display?
What is DMD?
What is scanDMD supposed to do?
Why should I have to research all of these terms?

Don

Code:

/*--------------------------------------------------------------------------------------

 dmd_clock_readout.cpp 
   Example clock readout project for the Freetronics DMD, a 512 LED matrix display
   panel arranged in a 32 x 16 layout. - [u]P10 display[/u]

 Copyright (C) 2011 Marc Alexander (info <at> freetronics <dot> com)

 See http://www.freetronics.com/dmd for resources and a getting started guide.

 Note that the DMD library uses the SPI port for the fastest, low overhead writing to the
 display. Keep an eye on conflicts if there are any other devices running from the same
 SPI port, and that the chip select on those devices is correctly set to be inactive
 when the DMD is being written to.

 USAGE NOTES
 -----------

 - Place the DMD library folder into the "arduino/libraries/" folder of your Arduino installation.
 - Get the TimerOne library from here: http://code.google.com/p/arduino-timerone/downloads/list
   or download the local copy from the DMD library page (which may be older but was used for this creation)
   and place the TimerOne library folder into the "arduino/libraries/" folder of your Arduino installation.
 - Restart the IDE.
 - In the Arduino IDE, you can open File > Examples > DMD > dmd_demo, or dmd_clock_readout, and get it
   running straight away!

 * The DMD comes with a pre-made data cable and DMDCON connector board so you can plug-and-play straight
   into any regular size Arduino Board (Uno, Freetronics Eleven, EtherTen, USBDroid, etc)
  
 * Please note that the Mega boards have SPI on different pins, so this library does not currently support
   the DMDCON connector board for direct connection to Mega's, please jumper the DMDCON pins to the
   matching SPI pins on the other header on the Mega boards.

 This example code is in the public domain.
 The DMD library is open source (GPL), for more see DMD.cpp and DMD.h

--------------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------------
  Includes
--------------------------------------------------------------------------------------*/
#include <SPI.h>        //SPI.h must be included as DMD is written by SPI (the IDE complains otherwise)
#include <DMD.h>        //
#include <TimerOne.h>   //
#include "SystemFont5x7.h"

#define StopButton 4                 // button on pin 4
#define StartButton 2                 // button on pin 2

int buttonStateStart;                    // variable to store button state
int lastButtonStateStart;                // variable to store last button state
int buttonStateStop;                    // variable to store button state
int lastButtonStateStop;                // variable to store last button state
int fractional;
int fractionalOld;
byte StopWatchRun = LOW;
unsigned long start, finished, elapsed;
//Fire up the DMD library as dmd
DMD dmd(2,1);
unsigned int ui;
int fontNr=0;
int minute=20;
int sec=0;
byte secOver = HIGH;
int i=0;

/*--------------------------------------------------------------------------------------
  Interrupt handler for Timer1 (TimerOne) driven DMD refresh scanning, this gets
  called at the period set in Timer1.initialize();
--------------------------------------------------------------------------------------*/
void ScanDMD()
{ 
  dmd.scanDisplayBySPI();
}

/*--------------------------------------------------------------------------------------
  setup
  Called by the Arduino architecture before the main loop begins
--------------------------------------------------------------------------------------*/
void setup(void)
{ 
    Serial.begin(9600);
    
    pinMode(StartButton, INPUT); // the start button
    pinMode(StopButton, INPUT); // the stop button
    Serial.println("Press 1 for Start/reset, 2 for elapsed time");
   
   //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
   Timer1.initialize( 5000 );           //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
   Timer1.attachInterrupt( ScanDMD );   //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()

   //clear/init the DMD pixels held in RAM
   dmd.clearScreen( true );   //true is normal (all pixels off), false is negative (all pixels on)
   dmd.selectFont(System5x7);
}

/*--------------------------------------------------------------------------------------
  loop
  Arduino architecture main loop
--------------------------------------------------------------------------------------*/
void loop(void)
{
  buttonStateStart = digitalRead(StartButton);
  buttonStateStop = digitalRead(StopButton);
  
  if (buttonStateStart == LOW && lastButtonStateStart == HIGH)
    {
    start = millis();
    delay(5); // for debounce
    Serial.println("Started...");
    lastButtonStateStart = buttonStateStart; 
    StopWatchRun = HIGH;
    }
  else if (buttonStateStop == LOW && lastButtonStateStop == HIGH)
    {
    finished = millis();
    delay(5); // for debounce
    displayResult();
    lastButtonStateStop = buttonStateStop; 
    StopWatchRun = LOW;
    }
  else
    {
     if (StopWatchRun == HIGH)
      {
       fractional = (int)(millis() % 1000L);
       if (fractional < fractionalOld)
        {
         finished = millis();
         displayResult();

           if (secOver == 1)
           {
            minute=minute--;
            sec=60;
            secOver = 0;
           }
           sec=sec--; 
           ui = minute * 100 + sec;   
           Blink(ui);
           if(sec==0)
           {   
            secOver = 1;  
           }
        }   
      }
             
     lastButtonStateStart = buttonStateStart;
     lastButtonStateStop = buttonStateStop;
     fractionalOld = fractional;    
    }
}

/*--------------------------------------------------------------------------------------
  Display result in serial monitor
--------------------------------------------------------------------------------------*/
void displayResult()
{
float h, m, s, ms;
unsigned long over;

  elapsed = finished - start;
  h = int(elapsed / 3600000);
  over = elapsed % 3600000;
  m = int(over / 60000);
  over = over % 60000;
  s = int(over / 1000);
  ms = over % 1000;
  Serial.print("Raw elapsed time: ");
  Serial.println(elapsed);
  Serial.print("Elapsed time: ");
  Serial.print(h, 0);
  Serial.print("h ");
  Serial.print(m, 0);
  Serial.print("m ");
  Serial.print(s, 0);
  Serial.print("s ");
  Serial.print(ms, 0);
  Serial.println("ms");
  Serial.println();
}

/*--------------------------------------------------------------------------------------
  Show clock colon overlay on and off
--------------------------------------------------------------------------------------*/
void Blink(unsigned int uiTime)
{
    if(i) 
     {
      ShowClockNumbers( uiTime, false );
      i = 0;
     }
     else
      {
       ShowClockNumbers( uiTime, true );
       i=1;
      }
}

/*--------------------------------------------------------------------------------------
  Show clock numerals on the screen from a 4 digit time value, and select whether the
  flashing colon is on or off
--------------------------------------------------------------------------------------*/
void ShowClockNumbers( unsigned int uiTime, byte bColonOn )
{
   dmd.clearScreen(true);
   dmd.drawChar(  19,  1,'0'+((uiTime%10000)/1000), GRAPHICS_NORMAL );   // thousands
   dmd.drawChar(  25,  1, '0'+((uiTime%1000) /100),  GRAPHICS_NORMAL );   // hundreds
   dmd.drawChar( 34,  1, '0'+((uiTime%100)  /10),   GRAPHICS_NORMAL );   // tens
   dmd.drawChar( 40,  1, '0'+ (uiTime%10),          GRAPHICS_NORMAL );   // units
   if( bColonOn )
      dmd.drawChar( 30,  1, ':', GRAPHICS_OR     );   // clock colon overlay on
   else
      dmd.drawChar( 30,  1, ':', GRAPHICS_NOR    );   // clock colon overlay off
}
  • First I comment lines " Timer1.initialize( 5000 );" and “Timer1.attachInterrupt( ScanDMD )”,
    If you start serial monitor and compare time with stopwatch you will see that both are counting same time

  • Second I insert lines " Timer1.initialize( 5000 );" and “Timer1.attachInterrupt( ScanDMD )”, which are necessary for P10 display.
    If you start serial monitor now and compare time with stopwatch you will see that some delay occure. For example: 10 second in serial monitor is actually around 13 seconds.

Don:
Please see comment above code to clear terms around P10 display.

Joze

For those who know what is DMD and P10, use DMD2 library instead of DMD. I solved this problem with it.

joze_dornik, can you explain how to migrate from dmd to dmd2 library? or post code?