1
votes

im trying to stop and resume again my interrupt timer on Arduino after he count 500. So, the interrupt timer count to 500, then delay for few second, and then resume the interrupt timer again

this is my code, i can stop the interrupt but dunno how to delay and resume the timer again

#define ledPin 13
int count=0;
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
cli();//stop interrupts
//set timer0 interrupt at 2kHz
  TCCR1A = 0;// set entire TCCR0A register to 0
  TCCR1B = 0;// same for TCCR0B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 2khz increments
  OCR1A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR1A |= (1 << WGM01);
  // Set CS01 and CS00 bits for 64 prescaler
  TCCR1B |= (1 << CS01) | (1 << CS00);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
sei();
}

ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
count++;
if(count%2==0)digitalWrite(ledPin,HIGH);
if(count%2==1)digitalWrite(ledPin,LOW);
if(count>=500)
{
  count=0;
  TCCR1B=0;
  digitalWrite(ledPin,LOW);
  //TCCR1B |= (1 << CS01) | (1 << CS00); 
}

}

void loop()
{
// your program here...

Serial.println(count);
delay(1000);

}

void berhenti()
{
cli();//stop interrupts
digitalWrite(ledPin,LOW);
count=0;
delay(3000);
sei(); 
}
1
What is the purpose of the routine named "berhenti()"? Do you ever call this routine?mhopeng

1 Answers

0
votes

You can use the millis() function to count the time you need.

#define ledPin 13
int count=0;

// A boolean to know if the timer is stopped or not.
// You can use the TIMSK1 bit, but I prefer a seperate variable.
boolean  timerStopped = false; 

// Time when the timer stopped.
long timerStoppedTime = 0;

// Your delay in milliseconds.
// You can use a macro here as well.
long timerStoppedDelay = 1000; 

// I'll explain this variable in the answer.
boolean takeTimeTimerStopped = true; 

void setup()
{
     // I haven't change this function.
}

ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
    count++;
    if(count%2==0)digitalWrite(ledPin,HIGH);
    if(count%2==1)digitalWrite(ledPin,LOW);
    if(count>=500)
    {
        count=0;
        TCCR1B=0;
        digitalWrite(ledPin,LOW);
        TIMSK1 |= (0 << OCIE1A); // deactivate timer's interrupt.
        timerStopped = true;
    }

}

void loop()
{
    // your program here...

    Serial.println(count);
    delay(1000);

    if(timerStopped)
    {
        if(takeTimeTimerStopped)
        {
            timerStoppedTime = millis();
            takeTimeTimerStopped = false;
        }
        if((millis() - timerStoppedTime) >= timerStoppedDelay)
        {
            TIMSK1 |= (1 << OCIE1A); // reactivate the timer.
            timerStopped = false;
            takeTimeTimerStopped = true;
        }
    }

 }

You need the takeTimeTimerStopped boolean to not change timerStoppedTime each time you enter the if(timerStopped) statement. A logical way to avoid this ugly stuff is to take the time in the ISR. But millis() it self uses timer0 interrupt to count and should not be called inside an ISR as described in http://www.arduino.cc/en/Reference/AttachInterrupt

Note that each call to dealy() in your loop function will further delay the time to reactivate your timer. You need to consider this as well.