Slowing down counter using timer1

hi guys!
I am having trouble slowing down my counter. counter value is displayed on a 4 digit 7 segment CA display (digit 2cm height). i am driving the segments and common anodes using 2 uln2003. Using 4 digit Multiplexed display with each common anode connected to pnp transistor collector and each base to mcu pin via 4.7K ohm resistor. 100ohms segment resistor for each segment. diagram attached(p.s: ignore connections on pin13)
counter.pdf (41.6 KB)
display1.pdf (16.1 KB)

now the problem is the counter increments too fast and when i add delay to slow the counter the display starts blinking. i tried to use timer1 interrupt instead but then display goes blank. pls help.
cheers,
marrc

 

#include <TimerOne.h>
// CA / CC 4 digit (digit height 2cm)counter with segment and digit data going through uln 2003

long int timerInterruptPeriod = 4000;
int sensePin = 13;

int pinA = 2;
int pinB = 3;
int pinC = 4;
int pinD = 5;
int pinE = 6;
int pinF = 7;
int pinG = 8;

int D1 = 9; //msb digit
int D2 = 10;
int D3 = 11;
int D4 = 12;

int refresh = 1;

int dig_1,dig_2,dig_3,dig_4;
int counter = 0;
unsigned long delayCounter = 0;

boolean caOrCc = true; // true implies ca

void setup () {
// TODO: put your setup code here, to run once:
   Serial.begin(9600);
   pinMode (sensePin, INPUT);
   
   for (int i = 2; i < 13; i++)
      pinMode (i, OUTPUT);
       Timer1.initialize(timerInterruptPeriod);
       Timer1.attachInterrupt(timerOneIsr); 
}

void loop() {
// TODO: put your main code here, to run repeatedly:  
   if(counter>9999)
   counter=0;              
   displayNumber(counter, caOrCc);
   counter++;    
   Serial.println(counter); 
   }
void timerOneIsr() {                                                    // timer one interrupt service routine
      delay(1000);
      }

void displayDigit(int digit, boolean caOrCc)
{
  if(caOrCc == true)
  {
    switch (digit)
    {
      case 0:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,LOW);
        break;   
      case 1:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      case 2:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,HIGH);
        break;
      case 3:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,HIGH);
        break;
      case 4:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      case 5:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      case 6:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      case 7:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      case 8:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      case 9:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      default:
        break;
    };
  }
  else if(caOrCc == false)
  {
    switch (digit)
    {
      case 0:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,HIGH);
        break;   
      case 1:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      case 2:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,HIGH);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,LOW);
        break;
      case 3:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,LOW);
        break;
      case 4:
        digitalWrite (pinA,HIGH);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      case 5:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      case 6:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,HIGH);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      case 7:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,HIGH);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,HIGH);
        digitalWrite (pinG,HIGH);
        break;
      case 8:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,LOW);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      case 9:
        digitalWrite (pinA,LOW);
        digitalWrite (pinB,LOW);
        digitalWrite (pinC,LOW);
        digitalWrite (pinD,LOW);
        digitalWrite (pinE,HIGH);
        digitalWrite (pinF,LOW);
        digitalWrite (pinG,LOW);
        break;
      default:
        break;
    };
  }
  
  delay(2);
}

void displayNumber(int num, boolean caOrCc) // function switching the digit positions
{
  dig_1 = num / 1000;
  dig_2 = (num - (1000 * dig_1)) / 100;                      
  dig_3 = (num - (1000 * dig_1) - (100 * dig_2)) / 10;         
  dig_4 = num - (1000 * dig_1) - (100 * dig_2) - (10 * dig_3);   

  if(caOrCc == true)
  {
    digitalWrite(D1, LOW); // digit 1 off
    digitalWrite(D2, LOW); // digit 1 off
    digitalWrite(D3, LOW); // digit 1 off
    digitalWrite(D4, LOW); // digit 1 off
    
    displayDigit(dig_1, caOrCc);      
    digitalWrite(D1,HIGH);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D1,LOW);//digit 1 off
    
    displayDigit(dig_2, caOrCc);
    digitalWrite(D2,HIGH);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D2,LOW);//digit 1 off
    
    displayDigit(dig_3, caOrCc);
    digitalWrite(D3,HIGH);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D3,LOW);//digit 1 off
    
    displayDigit(dig_4, caOrCc);
    digitalWrite(D4,HIGH);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D4,LOW);//digit 1 off
  } 
  else if(caOrCc == false)
  {
    digitalWrite(D1, HIGH); // digit 1 off
    digitalWrite(D2, HIGH); // digit 1 off
    digitalWrite(D3, HIGH); // digit 1 off
    digitalWrite(D4, HIGH); // digit 1 off
    
    displayDigit(dig_1, caOrCc);      
    digitalWrite(D1,LOW);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D1,HIGH);//digit 1 off
    
    displayDigit(dig_2, caOrCc);
    digitalWrite(D2,LOW);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D2,HIGH);//digit 1 off
    
    displayDigit(dig_3, caOrCc);
    digitalWrite(D3,LOW);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D3,HIGH);//digit 1 off
    
    displayDigit(dig_4, caOrCc);
    digitalWrite(D4,LOW);//digit 1 on
    delay(refresh);      // display hold
    digitalWrite(D4,HIGH);//digit 1 off
  }  
}

Did you mean cathodes connected to the uln?

That's just about the worst ISR I've seen - ever :wink: Don't use delay() in an ISR, especially not a long one. But you don't really need a timer interrupt for this. Timing with millis() will be perfectly sufficient for what you're trying to do, which looks like 1-second refreshes of the display.

There's a lot of optimization that can be done in how you write the display segments by using arrays, which will reduce redundancy in your code dramatically. Look at how TM1637 libraries do more or less the same thing.

In general, make sure you only write to the display the values that have changed; if there's no change in the value that's on the display, don't write to it. It'll reduce flicker.

As to timing, you can make a millis()-based timer where you store the value of millis() of the last display refresh and then check in your main loop again using millis() if 1000 milliseconds have passed, and if yes, call the display update routine.

@marrc is multiplexing the display with the Arduino sketch, it must be frequently updated to avoid flicker.

Oh yeah, you're right. Frankly I think that's not optimal if the Arduino is also going to run other tasks and will likely be sidetracked by interrupts from time to time. I'd suggest using a run off the mill tm1637 instead; it would make things a bit easier.

Using delay to slow your counter is not an option. Use of delay() prevents the Arduino from performing other tasks such as, in your case, keeping the display running. Your project design uses the Arduino to perform the multiplexing, and this must be done continually and steadily to prevent flickering. Instead of delay() you must use millis(). See the "blink without delay" example sketch for an example of how to do this.

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