c - is it possible compare a 16-bit value with a 8-bit compare match ISR -
i trying make servo controller have higher resolution attiny85 8-bit timer/counter. far have managed 2000 positions on servo (1µs/step) within time frame of 21'000 µs. have managed move 5 servos sequential , different speed, want move them synchronous.
my biggest problem don't how should make happen! have looked around on other servo codes including servo8bit library , tried find way. seems of examples uses compare match isr move servos "at same time", problem have 16-bit integer want compare.
is there way magic can use 8-bit compare match isr 16-bit integer? or of have other suggestions on how can move servos synchronous without using compare match isr?
i hope questions make sense!
since don't have code show yet (only flawed attempts without compar match isr makes no sense) post link tinyservo code if helps.
edit 1:
here part of code mentioned , didn't post first time:
void servomove(void) { uint16_t nextpulse = hpulse[0]; timersetup (); //16-bit setup counter (i = 0; < sizeof(servo)/sizeof(servo[0]); i++) { if ( (otime > nextpulse) && (channel < sizeof(servo)/sizeof(servo[0])) ) //check if high pulse (pos) done { portb &= ~(1 << servo[channel]); if (i+1 < sizeof(hpulse)/sizeof(hpulse[0])) { nextpulse += hpulse[i+1]; } channel++; } else { channel = 0; otime = 0; //resets 16-bit variable tot_overflow = 0; //resets tot_overflow variable tifr |= (1 << tov1); // clear counter1 overflow-flag tcnt1 = 0; //resets timer/counter1 } } (i = 0; < sizeof(servo)/sizeof(servo[0]); i++) { if ( (otime > tpulse - nextpulse) && (channel < sizeof(servo)/sizeof(servo[0])) ) //check if low pulse (period) done { portb |= (1 << servo[channel]); nextpulse -= hpulse[i]; channel++; } } } void servoposset(volatile uint16_t pos[], uint8_t size) { (i = 0; < size; i++) { hpulse[i] = pos[i]; } } int main(void) { tccr1 |= (1 << cs12); //set timer/counter1 prescaler increment every 1 µs (pck/8) (channel = 0; channel < size); channel++) { ddrb |= (1 << servo[channel]); //sets pb0-pb4 output pins } channel = 0; uint16_t pos[] = {2000, 1500, 1900, 1300, 1700}; uint8_t size = 5; while(1) { servoposset(pos); servomove(); } }
edit 2:
this illustration of how think code should work:
...but not!
if have nothing else during pulse, use busy loop instead of interrupts:
#include <avr/io.h> #include <util/delay_basic.h> /* send pulse of width = 4*count cycles. */ void pulse(uint16_t count, uint8_t channel) { uint8_t mask = 1 << channel, old_port = portb, high = old_port | mask, low = old_port & ~mask; portb = high; _delay_loop_2(count); portb = low; }
this give resolution of 4 clock cycles, or 0.5 µs 8 mhz clock.
sending pulses 5 servos should take @ 10 ms. since repeat pulse train every 21 ms, leaves 11 ms compute next set of positions, should plenty. program timer wake every 21 ms, main()
may like:
int main(void) { static uint16_t pos[] = {4000, 3000, 3800, 2600, 3400}; uint8_t i; /* wake every 21 ms. */ setup_timer(); sleep_enable(); (;;) { /* update servos. */ (i = 0; < 5; i++) pulse(pos[i], i); /* compute next set of positions. */ ... /* wait timer interrupt. */ sleep_cpu(); } }
Comments
Post a Comment