What am I missing?
Essentially, I’ve started experimenting with timer interrupts with the goal of using the Arduino Uno Plus to control GE Color Effects lights, which are apparently fussy about timing. So, to start, I decided to try making a 20us time delay using an interrupt and basically copying your example and adding the clock pre-scaling table in the comments so I don’t have to keep looking it up.
Watching an LED blink for 20us is not informative :-), so I’ve swapped out the LED toggle line for setting a semaphore and reported the state of the semaphor back via the Serial monitor. I’ve introduced the variable “semaphore” because I ultimately want my main program to be able to tell if the 20us is up before moving on the the next instruction. The library I was originally working from uses delay() to do this and the author admits that it needs to be manually tuned for each arduino. I’ve tried this, and short of dragging out my old oscilloscope to verify the timing, it’s very hit-and-miss, so I thought I would turn to the timer driven interrupt method.:
===============================================
/Table 14-9.
Clock Select Bit Description from ATmega328P Documentation p.137
CS12 CS11 CS10 Description
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 clk I/O /1 (No prescaling)
0 1 0 clk I/O /8 (From prescaler)
0 1 1 clk I/O /64 (From prescaler)
1 0 0 clk I/O /256 (From prescaler)
1 0 1 clk I/O /1024 (From prescaler)
1 1 0 External clock source on T0 pin. Clock on falling edge.
1 1 1 External clock source on T0 pin. Clock on rising edge.
Delays should be 10, 20 and 30us
10us = .000 01s which is obtained by dividing the 16MHz clock divided by 160
20us is therefore the 16Mhz clock divided by 80
30us is 16Mhz / 53
Therefore a good clock pre-scale setting would be 8 (CS11=1)
Timer will be running at 16Mhz/8 = 2Mhz or .5us per tick
Count to 20 for 10us
Count to 40 for 20us
Count to 60 for 30us
/
int semaphore=0;
void setup()
{
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
Serial.println(“Semaphore cleared”);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 20; // compare match register for 10us delay
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 8 prescaler
TCCR1B |= (1 << CS10);
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
}
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
semaphore=1;
}
void loop()
{
while(semaphore==0){Serial.println(“semaphore = 0”);}
Serial.println(“Semaphore set”);
while (true){};
}
==================================================
This produces the output …
Semaphore cleared
semaphore = 0
semaphore = 0
semaphore = 0
semaphore = 0
semaphore = 0
Semaphore set
… which is what I would expect.
Obviously, since I’m really using the interrupt in place of a delay(), I don’t want to be constantly printing “semaphore = 0”, so I simply removed it. From here on I’ll focus only on the void loop() portion of the program. I’ve changed it to …
=============================================
void loop()
{
while(semaphore==0){}
Serial.println(“Semaphore set”);
while (true){};
}
=============================================
… but now all I get is:
Semaphore cleared
The semaphore is not being set, or at least, the main program isn’t seeing it.
I had thought that while(semaphore==0){} may not be valid with an empty proceedure, so I tested it …
========================================
void setup(){Serial.begin(115200);}
void loop(){
Serial.println(“before loop”);
while(true){}
Serial.println(“after loop”);
}
======================================
which only prints “before loop” so that wasn’t it.
So, back to original loop(). This also works …
======================================
void loop()
{
while(semaphore==0){delay(0);}
Serial.println(“Semaphore set”);
while (true){};
Serial.println(“not stuck in a loop”);
}
=====================================
but this does not …
…
while(semaphore==0){true==true;}
…
It occurs to me that both “delay(0);” and “Serial.println(”"); are using timers whereas {} and {true=true;} do not, so it’s possible that these functions is doing something with the timers that my code is not. This would imply that there’s something wrong with my setup() routine, but then again, the original example (which toggled the LED) worked, so clearly I’m not understanding something.
In fairness, I realize that putting delay(0); is not a hardship, but this is more about clarifying my understanding of why it doesn’t work without it than about saving instruction cycles.
LEGOManiac