Go Down

Topic: Arduino Micro Multiplexing Interrupt setup delay  (Read 771 times) previous topic - next topic

10starjester

I am trying to drive a multiplexed 6x6 LED display using an arduino micro with timer interrupt 1.  The code works fine except for around the first 5 seconds where the interrupt doesn't seem to fire, after this it works perfectly!

I have the following code to test this problem.  A power LED is lit as soon as soon as the interrupt setup finishes and the interrupt prints to Serial every time it fires, it takes a little under 5 seconds for this to occur after setup.

Any ideas would be greatly appreciated!

Code: [Select]

const byte LEDa[6] = {12, 8, 9, 10, 5, 13};//Maps LEDs to pins
const byte LEDc[6] = {15, 16, 17, 18, 19, 14};
volatile byte LEDs[6][6];//Stores curent LED values
volatile byte r=0;//Keeps track of current multiplex column

void setup() {
  Serial.begin(115200);

  pinMode(6, OUTPUT);//Motor
  pinMode(7, OUTPUT);//Power
 

  pinMode(A0, OUTPUT);//LEDs
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);

  pinMode(12, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(13, OUTPUT);


  interruptSetup();
  digitalWrite(7, HIGH);
  delay(5000);
 
}

void loop() {
 
  test();
   


}
  void test() {
    for (int i = 0; i < 6; i++) {
      for (int j = 0; j < 6; j++) {
        LEDs[i][j] = 1;
        delay(250);
        LEDs[i][j] = 0;
      }
    }
    digitalWrite(6, HIGH);
    delay(20);
    digitalWrite(6, LOW);
  }


  void interruptSetup() {

    cli();          // disable global interrupts
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // same for TCCR1B
    // set compare match register to desired timer count
    OCR1A = 10;
    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);
    // Set CS10 and CS12 bits for 1024 prescaler
    TCCR1B |= (1 << CS10);
    TCCR1B |= (1 << CS12);
    // enable timer compare interrupt
    TIMSK1 |= (1 << OCIE1A);
    // enable global interrupts
    sei();
  }

  ISR(TIMER1_COMPA_vect) {
    Serial.println("Here");
    for (int c = 0; c < 6; c ++) {
      digitalWrite(LEDa[c], 0);
    }

    switch (r) {
      case 0: digitalWrite(A0, 0); break;
      case 1: digitalWrite(A2, 0); break;
      case 2: digitalWrite(A3, 0); break;
      case 3: digitalWrite(A4, 0); break;
      case 4: digitalWrite(A5, 0); break;
      case 5: digitalWrite(A1, 0); break;
    }

    switch (r) {
      case 0: digitalWrite(A2, 1); break;
      case 1: digitalWrite(A3, 1); break;
      case 2: digitalWrite(A4, 1); break;
      case 3: digitalWrite(A5, 1); break;
      case 4: digitalWrite(A1, 1); break;
      case 5: digitalWrite(A0, 1); break;
    }
    for (int c = 0; c < 6; c ++) {
      digitalWrite(LEDa[c], LEDs[r][c]);
    }

    r++;
    if (r > 5) {
      r = 0;
    }

  }

Grumpy_Mike

Quote
The code works fine except for around the first 5 seconds where the interrupt doesn't seem to fire
I suspect this is because of the 5 second delay at the end of the setup function.

10starjester

Unfortuanately this is not the problem.  With or without this delay the interrupt fails to start immediately, by adding this delay it means the first part of the animation is not missed by the interrupt not starting.

Delta_G

#3
Nov 08, 2017, 12:31 am Last Edit: Nov 08, 2017, 12:33 am by Delta_G
Don't put Serial prints inside an interrupt routine.  Serial relies on interrupts that are turned off during your ISR.  That can hang things up. 

You might also want to reset the TCNT register back to 0 at the end of the timer setup.  If it has already passed OCR register when you enable then you have to wait for it to wrap back around. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

10starjester

All sorted, thanks very much!  Working interrupt setup routine below:

Code: [Select]

void interruptSetup() {

    cli();          // disable global interrupts
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // same for TCCR1B
    // set compare match register to desired timer count
    OCR1A = 10;
    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);
    // Set CS10 and CS12 bits for 1024 prescaler
    TCCR1B |= (1 << CS10);
    TCCR1B |= (1 << CS12);
    // enable timer compare interrupt
    TIMSK1 |= (1 << OCIE1A);
    // enable global interrupts
    TCNT1=0;
    sei();
  }

Go Up