I have code running off timer 2 to control a stepper
works ok most of the time
every now and then it misses a beat
put a scope on it and it confirms
it's almost as if the interrupt doesn't fire
her's the code - blast away
it's meant to increase then decrease the frequency
// stepper pin
//============
#define STEPPIN 12
// avr-libc library includes
//==========================
#include <avr/io.h>
#include <avr/interrupt.h>
// interrupt service routine
//==========================
ISR(TIMER1_COMPA_vect)
{
// fire the stepper one pulse
//===========================
digitalWrite(STEPPIN, HIGH);
digitalWrite(STEPPIN, LOW);
}
void setup(void)
{
// set stepper pin as output
//==========================
pinMode(STEPPIN, OUTPUT);
}
void loop(void)
{
int i;
for (i=30; i>10; i--)
{
// speed up
//=========
setTimer(i);
delay(2000);
}
for (i=10; i<30; i++)
{
// slow down
//==========
setTimer(i);
delay(2000);
}
}
void setTimer(int time)
{
// set up the timer
//=================
cli();
// set entire TCCR1A, TCCRIB register to 0
//========================================
TCCR1A = 0;
TCCR1B = 0;
// set compare match register to desired timer count
//==================================================
OCR1A = time;
// turn on CTC mode:
//==================
TCCR1B |= (1 << WGM12);
// Set CS12 bit for prescaler /256
//================================
TCCR1B |= (1 << CS12);
// enable timer compare interrupt
//===============================
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts
//=========================
sei();
}
mmcp42:
ok removed the sei() and cli()
still taking a rest every now and then
Could this simply be because you're reconfiguring the timer while it is running? If it's about to fire and you reconfigure it, how long do you wait until it actually fires? It'd be reasonable for it to start timing from zero when you reconfigure it, wouldn't it?
The effect is subtle on the scope, but I think I see what you mean.
I'm inclined to agree with PeterH that changing the timer while it is running is likely to introduce glitches, but it seems to me that they are inside the 2-second intervals.
Timer 2 has a higher interrupt priority than Timer 0, however once Timer 0 fires interrupts will be disabled regardless of interrupt priority. My guess is that this defers your ISR slightly.
This modified version uses the timer itself to toggle the output pin (now D11). This gives a different waveform (so you may have to double the frequency?) but as far as I can see has less glitches:
// stepper pin
//============
#define STEPPIN 11
void setup(void)
{
// set stepper pin as output
//==========================
pinMode(STEPPIN, OUTPUT);
}
void loop(void)
{
int i;
for (i=30; i>10; i--)
{
// speed up
//=========
setTimer(i);
delay(2000);
}
for (i=10; i<30; i++)
{
// slow down
//==========
setTimer(i);
delay(2000);
}
}
void setTimer(int time)
{
// set up the timer
//=================
// set entire TCCR1A, TCCRIB register to 0
//========================================
OCR1A = 0;
TCCR1A = 0;
TCCR1B = 0;
TIMSK1 = 0;
// set compare match register to desired timer count
//==================================================
OCR1A = time;
// turn on CTC mode:
//==================
TCCR1B |= (1 << WGM12);
// Set CS12 bit for prescaler /256
//================================
TCCR1B |= (1 << CS12);
// toggle D11 on match
TCCR2A = _BV (COM2A0); // toggle OC2A on Compare Match (D11)
}
Would it to be feasible to do the timer adjustments within the timer ISR, so that you know they're happening at/about the start of the interrupt period? You would continue to schedule them in loop() and just set a flag/variable to tell the ISR to reconfigure the timer at the next interrupt.
(and not set up the timer again). But it seems to ignore me. I suspect that the counter limit is cached, but my reading of the datasheet suggests it should be cached in this case. However if you could work around that, that is probably the simpler way.
in the end what I did was went for a much faster (25 microsecond) interrupt
then set a counter
the ISR decrements my counter and fires the stepper when it reaches zero
then pcks up the next value
seems to work glitch free now!
many thanks for all your input
learnt a lot today!