Simple Timer using 8 Digit, 7 Segment Display (MAX7219)

Hi all. This if my first post and one of my first arduino projects so go easy on me :D.

For now, i want to build a simple "high speed" timer.
ideally i would like the first digit to represent 0.01mS/ the second digit 0.1mS and so on. But so far the fastest i've managed to get the first digit clock speed is 1mS (using the delay command). is there anyway i can get a faster clock speed?

I will post the code as im guessing you are going to ask for it. The code is messy and far from perfect but it works. If there is a neater, easier way of coding this project im all open to good advice :). - the code is not commented, but it does work.

Thanks

#include "LedControl.h"


 pin 12 is connected to the DataIn 
 pin 11 is connected to the CLK 
 pin 10 is connected to LOAD 
 We have only a single MAX72XX.

LedControl lc=LedControl(12,11,10,1);

unsigned long delaytime=1;

void setup() {
  /*
   The MAX72XX is in power-saving mode on startup,
   we have to do a wakeup call
   */
  lc.shutdown(0,false);
  /* Set the brightness to a medium values */
  lc.setIntensity(0,8);
  /* and clear the display */
  lc.clearDisplay(0);
}

int time = 0;
int s0 = 0;
int s1 = -1;
int s2 = -1;
int s3 = -1;
int s4 = -1;
int s5 = -1;
int s6 = -1;
int s7 = -1;
void loop() { 
  
  s0=time;
  
  if (time==9){
    time=-1;
  }
  
  if (s0==0){
    s1=s1+1;
  }
  
  //---------------------------------------------------------
  
    if (s1==10){
    s1=0;
  }
  
  if (s1==0&&s0==0){
    s2=s2+1;
  }
  
  //---------------------------------------------------------
  
     if (s2==10){
    s2=0;
  }
  
  if (s2==0&&s1==0&&s0==0){
    s3=s3+1;
  }
  
    //---------------------------------------------------------
  
     if (s3==10){
    s3=0;
  }
  
  if (s3==0&&s2==0&&s1==0&&s0==0){
    s4=s4+1;
  }
  
      //---------------------------------------------------------
  
     if (s4==10){
    s4=0;
  }
  
  if (s4==0&&s3==0&&s2==0&&s1==0&&s0==0){
    s5=s5+1;
  }
  
        //---------------------------------------------------------
  
     if (s5==10){
    s5=0;
  }
  
  if (s5==0&&s4==0&&s3==0&&s2==0&&s1==0&&s0==0){
    s6=s6+1;
  }
  
          //---------------------------------------------------------
  
     if (s6==10){
    s6=0;
  }
  
  if (s6==0&&s5==0&&s4==0&&s3==0&&s2==0&&s1==0&&s0==0){
    s7=s7+1;
  }
  
  
  lc.setChar(0,0,s0 ,false);
  lc.setChar(0,1,s1 ,false);
  lc.setChar(0,2,s2 ,false);
  lc.setChar(0,3,s3 ,false);
  lc.setChar(0,4,s4 ,false);
  lc.setChar(0,5,s5 ,false);
  lc.setChar(0,6,s6 ,false);
  lc.setChar(0,7,s7 ,false);
  
   delay(delaytime);
  time=time+1;
}

Welcome,

Please go back and modify your original post and include the code inside [ code] [ /code] tags.

Instead of using delay(), take that out and use the millis() function to determine what digits to display. This will ensure your timer is accurate.

Thanks for the pointer - post edited.

I had a feeling someone would say that.
my attempts of using the millis function have so far all failed when i've tried to replace the delay function.
I find the arduino site doesn't break each part of the code up enough for me to understand how each part comes together to create a sequence/ function that actually works.

maybe i should learn more "basics" before trying to build the things i need from the off :roll_eyes:

Oh, sorry. I just realised you want to go faster than 1ms accuracy. millis() won't do that.

Hopefully someone here can let you know if it's possible with the Arduino.

hmm. What if i used an external high speed clock and have the arduino "count" that? .. with no delay/ millis function, is that viable or will it just make the segments do funny things?
... feed the PWM output back into intself on another pin and count that? lol

Thanks for your help

I haven't really looked at the arduino core as my projects didn't need this level of accuracy. I have seen people doing things with ISRs and the onboard timers though, so it's probably possible to do something. Just not anything I've looked into personally.

I have a page about the 7219 and displays:

Your code looks rather complex for displaying 8 digits. From that page I displayed 4 digits, doing 8 would be a minor change:

#include <SPI.h>

const byte MAX7219_REG_NOOP        = 0x0;
// codes 1 to 8 are digit positions 1 to 8
const byte MAX7219_REG_DECODEMODE  = 0x9;
const byte MAX7219_REG_INTENSITY   = 0xA;
const byte MAX7219_REG_SCANLIMIT   = 0xB;
const byte MAX7219_REG_SHUTDOWN    = 0xC;
const byte MAX7219_REG_DISPLAYTEST = 0xF;

void sendByte (const byte reg, const byte data)
  {    
  digitalWrite (SS, LOW);
  SPI.transfer (reg);
  SPI.transfer (data);
  digitalWrite (SS, HIGH); 
  }  // end of sendByte
 
void setup () 
  {
  SPI.begin ();
  sendByte (MAX7219_REG_SCANLIMIT, 7);      // show 8 digits
  sendByte (MAX7219_REG_DECODEMODE, 0xFF);  // use digits (not bit patterns)
  sendByte (MAX7219_REG_DISPLAYTEST, 0);    // no display test
  sendByte (MAX7219_REG_INTENSITY, 7);      // character intensity: range: 0 to 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);       // not in shutdown mode (ie. start it up)
}   // end of setup
 
void number (const unsigned long num)
  {
 
 char buf [9];
 sprintf (buf, "%08ld", min (max (num, 0), 99999999));
 
 // send all 8 digits
 for (int digit = 0; digit < 8; digit++)
   {
   byte c = buf [digit];
   if (c == ' ' )
     c = 0xF;  // code for a blank
   else
     c -= '0';
   sendByte (8 - digit, c);  
   }   
  }  // end of number
  
unsigned long i;

void loop () 
 {
 number (i++);
 }  // end of loop

The above displays 8 digits on the LEDs.

programmable:
hmm. What if i used an external high speed clock and have the arduino "count" that?

Do you want it to count faster? In my test the last two digits are unreadable, it is counting so fast. Or do you want to time some external event? If so, what? How do you know it has started and stopped? You can use a timer to count up to 62.5 nS accuracy, and then just display the results of that on the LEDs.

Thanks the replies guys.

Yes, in an ideal world i would like to count 1 million every second. 100,000 would do though.
It would be to measure the speed of objects etc... obviously there would be some slight modifications to the code but for now i just need it to count real fast. so it would be to time an external event like you say :slight_smile:
I just tried the delayMicrosecond function with no luck.
62.5nS... now we're talking! i looked at the code on that link you sent me and erm :astonished:... it's a bit beyond me
using the delay(1) or millis function i can get the last 2 digits unreadable but the 4th digit is very slow.

I built this circuit before using 6 segment driver, 6 decade counters and a few 555's IC. could i not use a 555 clock output to feed the arduino a sort of clock pulse? should get 100kHz out of it.
Thanks

You don't need an external timer, the CPU chip has one. Here is my code that times a ball running down a ramp:

const byte LED = 12;
const float DISTANCE = 0.9; // m

unsigned long startTime;
volatile unsigned long elapsedTime;
volatile boolean done;
boolean started;

void ballPassesGate1 ()
{
  startTime = micros (); 
  started = true;
    
  digitalWrite (LED, HIGH);  
}  // end of ballPassesGate1

void ballPassesGate2 ()
{
  if (!started)
    return;
    
  elapsedTime = micros () - startTime;  
  done = true;
  started = false;
  
  digitalWrite (LED, LOW);  
}  // end of ballPassesGate2


void setup ()
{
  Serial.begin (115200);
  Serial.println ("Timer sketch started.");  
  pinMode (LED, OUTPUT);
  attachInterrupt (0, ballPassesGate1, FALLING);
  attachInterrupt (1, ballPassesGate2, FALLING);
}  // end of setup

void loop ()
  {
  if (!done)
    return;
    
  Serial.print ("Time taken = ");
  Serial.print (elapsedTime);
  Serial.println (" uS");
  float secs = float (elapsedTime) / 1.0e6;
  float velocity = DISTANCE / secs;
  Serial.print ("Time taken = ");
  Serial.print (secs);
  Serial.println (" seconds.");
  Serial.print ("Average velocity = ");
  Serial.print (velocity);
  Serial.println (" m/s.");
  Serial.println ();
  
  done = false;
  }  // end of loop

You don't want delays, you want to measure the start and end point. micros() has a 4 µS resolution. To get better than that you need to use Timer 1 or Timer 2 with no prescaler.

That code doesn't display with LEDs, that's a separate issue, but it shows how to time things.