# Large range delay at medium frequency for MC

I have a program that varies the step time and duty cycle for a 6 step commutation sequence. It takes an 8-bit ADC result and stores it as the TMR0 value, when TMR0 overflows, the ISR selects the next sequence.

I have 2 problems:

1. This only works at low INTOSC frequencies, where UART will not work, and
2. I don't get a large enough step range.

Any general ideas on how to create a larger ranged delay at a higher frequency? My first idea is to use a nested loop, still using a TMR0 value, then putting that inside of a loop the steps the inverse of TMR0 times...

• What microcontroller platform? Which toolchain? Commented Feb 23, 2013 at 22:17
• pic18 & breadboard Commented Feb 23, 2013 at 22:25
• Can you give us a rough indication of the relationship you need between ADC value and step rate? From the sounds of it, it's step frequency = k/(255-ADC). What is the value of k? Commented Feb 24, 2013 at 0:24
• sure, if I'm looking for 302.5 RPM, I get 5.04 RPS * 12 poles = 60 Hz, so k = .0166. This gives me my delay in uS, which could be plugged into a delay_uS function, but I'd like to use a timer/ counter so as not to waste cycles. Commented Feb 24, 2013 at 3:22
• I'm not sure I understand the example you gave. So 60Hz = 0.0166 / (255-254.9997). That can't be right because an 8-bit ADC can't give a value of 254.9997. Sorry to be picky about this, but if I can understand it, then I can give you a good answer. Commented Feb 24, 2013 at 16:40

One way to approach the problem would be to introduce some additional variables that keep track of the timer interval and how many times it's been called so that a fixed number of interrupts may be ignored. For example the following C pseudo-code to slow the execution time down by a factor of 10.

uint_8 ticks_left, timer_interval;

void my_isr()
{
ticks_left--;
if (ticks_left == 0)
{
disable_timer();
// Move to next ADC etc
} else
setup_timer(timer_interval);
}
}

void main()
{
timer_interval = your_calculated_value;
ticks_left = 10;
setup_timer(timer_interval);
}


It won't be perfectly accurate because of the (probably less than 10 cycle) instruction delay between the interrupt and the new timer value being set, although if that's a concern you could check the assembler output to find the number of cycles it will take and reset the timer to a slightly lower value in the ISR if that's likely to be a problem.