cli() affects delay

Hello,

Is it normal that cli() affects delay? The following code does not toggle the voltage every two seconds.

void setup() {
  pinMode(8, OUTPUT);
  cli();
}

void loop() {
  digitalWrite(8, HIGH);
  delay(2000);
  digitalWrite(8, LOW);
  delay(1000); 
}

Thanks.

cli() disables interrupts, like the clock ticking.

Without the clock going tick tock, delay() doesn't know when to return.

Why are you disabling interrupts?

Thanks PaulS. I’m just a neophyte so I was copying the code for enabling timer interrupts from here: http://www.instructables.com/id/Arduino-Timer-Interrupts/step2/Structuring-Timer-Interrupts/

In it, they use cli(), then do the interrupt setup, and then finally sei(). However, the delay function still gets affected after the sei().

The trick will be not to use delay but do things as reaction on the millis() counter

check for the famous - arduino blink without delay - example

However, the delay function still gets affected after the sei().

It would have been helpful if you had mentioned that in the first place

Incidentally, your original code would not

toggle the voltage every two seconds.

even without the cli() because the on/off delays are not equal. Did you meant that the LED does not turn on/off at all after cli() ?

Yes, thanks UKHellibob, I was trying to type the essence of the code for illustrative purposes. Mistyped 1000 when I meant 2000. Anyway, the problem is that the delay becomes much shorter. delay(2000) is only a 30 millisecond delay according to the oscilloscope.

Thanks, robtillaart. I have taken a look at it. It will definitely make my code more complex if I don't use delay, but there is the advantage of it being more responsive to to input. Nevertheless, I am still curious why setting up a timer interrupt (even without first calling the cli() function), would affect the delay. Any ideas?

Post the code that is showing this behavior. The code you posted turns off the interrupts and then it's clear that a call to delay() will never return.

My guess is that you have code in the setup routine that is changing the Timer0 registers which is responsible for the correct function of millis(), delay(), etc.

As far as I can tell from the oscilloscope, the following code does not toggle pin 8 every 200ms 8 times every 2 seconds.The toggle is every 4ms.

void setup() {
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  //cli();//stop interrupts
//set timer1 interrupt at 0.5Hz

  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 0.5hz increments
  OCR1A = 31249;// = (16*10^6) / (0.5*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 = 0;
  TIMSK1 |= (1 << OCIE1A);
  sei();//allow interrupts
  
 
 
  
}
ISR(TIMER1_COMPA_vect){
  for (int i = 0; i < 4; i++) {
  digitalWrite(8,HIGH);
  delay(200);
  digitalWrite(8,LOW);
  delay(200);
  }
}
void loop() {


}

Interrupts are disabled in an interrupt service routine. You can NOT call delay in an ISR. ISRs are supposed to be FAST!

Thanks, PaulS. It seems like most people know the prerequisites for delay. The prerequisites aren't mentioned in the reference page.

http://arduino.cc/en/Reference/Delay

It seems like most people know the prerequisites for delay. The prerequisites aren't mentioned in the reference page.

I don't think that "the prerequisites for delay" are what you need to understand. It is how to use interrupts, and what, exactly, an ISR should (and should NOT) do that you need to understand.

Interrupts and interrupt servicing are not beginner topics. It is expected that, by the time you know you need to use interrupts, that you will have understood what an ISR should (and should not) do.

yangres2002:
As far as I can tell from the oscilloscope, the following code does not toggle pin 8 every 200ms 8 times every 2 seconds.The toggle is every 4ms.

void setup() {

pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  //cli();//stop interrupts
//set timer1 interrupt at 0.5Hz

TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 0.5hz increments
  OCR1A = 31249;// = (1610^6) / (0.51024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 = 0;
  TIMSK1 |= (1 << OCIE1A);
  sei();//allow interrupts

}
ISR(TIMER1_COMPA_vect){
  for (int i = 0; i < 4; i++) {
  digitalWrite(8,HIGH);
  delay(200);
  digitalWrite(8,LOW);
  delay(200);
  }
}
void loop() {

}

Try this on your scope and tell me how much you need to play with timer registers, interrupts and interrupt control.

unsigned long nowMillis, saveMillis = 0UL;
int  blinkDelay = 200;
byte  outPin = 8;
byte  pinState = 0; 

void setup() 
{
  pinMode( outPin, OUTPUT );
  digitalWrite( outPin, pinState );
}

}
void loop() 
{
  nowMillis() = millis();
  if ( nowMillis - saveMillis >= blinkDelay )
  {
    pinState ^= 1;
    digitalWrite( outPin, pinState );
    saveMillis = nowMillis;
  }
}

Thanks to everyone for their contributions. I am going to use the millis() function instead of delay. The discussion from here on in is strictly academic. The problem I had to begin with stemmed from not knowing the prerequisites of the delay function. I can take my time and read all about interrupts in the atmel manual for the chip, but there seems to be no detailed reference of the delay function on how it is implemented.

but there seems to be no detailed reference of the delay function on how it is implemented.

This sounds a bit like: "Nobody told me and the manual doesn't specify that the breaks of my car do not work as intended on the frozen lake."

If you would have read the page of the reference regarding interrupt service routines (http://arduino.cc/en/Reference/AttachInterrupt) there is a note that delay() and other stuff don't work correctly inside interrupt handlers. Don't blame the Arduino documenters for you not reading the necessary documentation but using stuff (ISR) not specified in the reference.

there seems to be no detailed reference of the delay function on how it is implemented

Actually there is and you already have it. It's the source code for your IDE, which has been brought out on the forum, dissected and IIRC improved versions posted.

There is no more accurate comment than the code itself.

Ah, yes, thank you GoForSmoke. That was what I was wondering about. It is useful to know.