Using interrupts to output a square wave of variable frequency.

Post started here:

http://forum.arduino.cc/index.php?topic=258073.msg1825745#msg1825745

For a learning exercise I decided to build myself a square wave generator and see how far I could get in terms of maximun output frequency.
The code on the above link uses pooling with the micros function to detect when a certain ammount of time has passed, however I wish to use an interrupt to archieve the same goal, while doing other things such as printing the frequency via serial or an LCD

How could I archieve this?

If you particularly want to use interrupts then you need to configure a hardware timer to trigger the interrupt at the required frequency. You can use the Timer1 library to do this, or write your own code to access the hardware directly. But you can probably achieve this just by configuring the hardware timer to output the square wave directly onto an I/O pin i.e. not using interrupts at all.

PeterH:
But you can probably achieve this just by configuring the hardware timer to output the square wave directly onto an I/O pin i.e. not using interrupts at all.

How would I archieve that? Can I vary the frequency using such method?

I must live in a different Time Warp to @casemod.

When I want to figure out the stuff that these questions are about I just take a bit of time, read the Atmel datasheet and write several test sketches to figure out how things work.

...R

casemod:

PeterH:
But you can probably achieve this just by configuring the hardware timer to output the square wave directly onto an I/O pin i.e. not using interrupts at all.

How would I achieve that? Can I vary the frequency using such method?

PeterH's idea is a good one. The AVR's hardware timers can count from zero to some top value, then start over at zero. The top value can be specified in one of the timer control registers. By changing this value, the timer will reach the top value in different amounts of time. This determines the period (and therefore the frequency). Timers can also be configured to toggle an output pin when they roll over. This gives us an instant square wave, and once the timer is set and running, the code can do whatever else it pleases. There is also a prescaler which divides the system clock frequency to determine how fast the timer counts so this affects frequency as well.

I have no idea how interrupts might be used to achieve this, perhaps you can elaborate on that line of thinking. But as ever, if there is a reasonable way to accomplish some end without interrupts, that might be the preferred method.

Some links to learn about timers (in addition to the datasheet of course):

Brilliant description, Thanks

Robin2:
I must live in a different Time Warp to @casemod.

When I want to figure out the stuff that these questions are about I just take a bit of time, read the Atmel datasheet and write several test sketches to figure out how things work.

...R

Best to get the teory first and then search the datasheet for the relevant bits.

Here's the classic blink example using a timer (for ATmega328P, Uno or similar). The prescaler divides the 16MHz clock frequency by 256, then the timer further divides that by 62500, giving 1Hz. OC1A is digital pin 9, so it gets toggled once per second.

const int ledPin = 9;

void setup(void)
{
    pinMode(ledPin, OUTPUT);
    TCCR1A = _BV(COM1A0);              //toggle OC1A on compare match
    OCR1A = 62499;                     //top value for counter
    TCCR1B = _BV(WGM12) | _BV(CS12);   //CTC mode, prescaler clock/256
}

void loop(void)
{
}

This is a brilliant example, Thank you.!
So I only need to change the top value for the counter, while the hardware does all the rest.

But now, due to all the abstraction on the arduino itself perhaps I should ask - What other functions will be affected when changing this? I've read that pretty much everything uses timer 0, am I OK using the other 2?

Regards

casemod:
But now, due to all the abstraction on the arduino itself perhaps I should ask - What other functions will be affected when changing this? I've read that pretty much everything uses timer 0, am I OK using the other 2?

Good question, I wish there were a concise and definitive answer somewhere. It's been discussed on the forum, so search around and also Google for info elsewhere.

On an Uno or other ATmega328-based board:
Timer0 provides the time base for millis(), so normally would want to leave it alone.
Timer1 and Timer2 can be used, but various functions and libraries use them also.
PWM, i.e. analogWrite() makes use of all three depending on the pin. Pins 5 and 6 use Timer0, pins 9 and 10 use Timer1, pins 3 and 11 use Timer2.
I think the Servo library uses Timer1 and Tone may use Timer2.
Different MCUs are different too. The Mega has six timers and I think the Leonardo has four.

Edit: corrected PWM pin numbers.