Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« on: February 04, 2012, 08:15:26 am » |
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(); }
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
0
Offline
Tesla Member
Karma: 71
Posts: 6603
Arduino rocks
|
 |
« Reply #1 on: February 04, 2012, 08:23:51 am » |
You seem to only be setting one bit of the counter mode field - you should overwrite them all to ensure you get the mode you think...
Why disabling interrupts when setting up the timer?
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #2 on: February 04, 2012, 08:27:21 am » |
er copied from here I tried setting TIMSK1 to 0 before setting OCTE1A no difference TCCR1A and B already cleared
|
|
|
|
« Last Edit: February 04, 2012, 08:30:42 am by mmcp42 »
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #3 on: February 04, 2012, 08:39:11 am » |
ok the setTimer routine now looks like this, but still has the odd random hiccup void setTimer(int time) { // set up the timer //================= cli();
// 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); // enable timer compare interrupt //=============================== TIMSK1 |= (1 << OCIE1A); // enable global interrupts //========================= sei(); }
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6319
-
|
 |
« Reply #4 on: February 04, 2012, 09:11:23 am » |
You seem to be disabling interrupts briefly ten times a second. Is it any surprise that occasionally you miss an interrupt?
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #5 on: February 04, 2012, 09:24:44 am » |
fair point 
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #6 on: February 04, 2012, 10:06:08 am » |
ok removed the sei() and cli() still taking a rest every now and then 
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6319
-
|
 |
« Reply #7 on: February 04, 2012, 10:12:50 am » |
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?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #8 on: February 04, 2012, 10:38:57 am » |
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) }
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #9 on: February 04, 2012, 10:49:33 am » |
thanks Peter and Nick i'll glare at the code some more! (especially TCCR2A)
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #10 on: February 04, 2012, 10:59:01 am » |
I have code running off timer 2 to control a stepper her's the code - blast away // set entire TCCR1A, TCCRIB register to 0 //======================================== TCCR1A = 0; TCCR1B = 0;
Er, isn't that Timer 1? Modified for Timer 1: // stepper pin //============ #define STEPPIN 9
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 D9 on match TCCR1A = _BV (COM1A0); // toggle OC1A on Compare Match (D9) }
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #11 on: February 04, 2012, 11:26:03 am » |
oh my word! luckily it's only the thread title that's actually wrong
|
|
|
|
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6319
-
|
 |
« Reply #12 on: February 04, 2012, 03:24:29 pm » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 218
Posts: 13896
Lua rocks!
|
 |
« Reply #13 on: February 04, 2012, 03:35:21 pm » |
I tried to change the speed by just doing this: OCR1A = time; (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.
|
|
|
|
|
Logged
|
|
|
|
|
Leighton Buzzard, UK
Offline
Edison Member
Karma: 11
Posts: 1049
|
 |
« Reply #14 on: February 04, 2012, 03:37:02 pm » |
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!
|
|
|
|
« Last Edit: February 04, 2012, 03:47:52 pm by mmcp42 »
|
Logged
|
there are only 10 types of people them that understands binary and them that doesn't
|
|
|
|
|