2015-06-10 33 views
1

我試圖製作比ATtiny85 8位定時器/計數器分辨率更高的伺服控制器。到目前爲止,我已經在21'000μs的時間範圍內獲得了大約2000個伺服位置(1μs/步)。我也設法按順序移動5個舵機,速度不同,但現在我想將它們同步移動。是否有可能將16位值與8位比較匹配進行比較ISR

我最大的問題是,我不明白我應該怎麼做!我環顧了其他伺服代碼,包括伺服8位庫,並試圖找到一種方法。看起來,大多數例子使用比較匹配ISR來移動舵機「同時」,我的問題是我有一個16位整數,我想比較。

有沒有辦法做一些魔術,所以我可以使用8位比較匹配ISR與我的16位整數?或者是否有人對我如何在不使用比較匹配ISR的情況下同步移動我的舵機提出了一些其他建議?

我希望我的問題有道理!

因爲我還沒有任何代碼可以顯示(只有有缺陷的嘗試沒有比較匹配的ISR,沒有任何意義),我發佈鏈接到我的TinyServo代碼,如果有幫助。

EDIT 1:

這裏是我提到,沒有發佈第一時間代碼的一部分:

void servoMove(void) 
{ 
uint16_t nextPulse = hPulse[0]; 

timerSetup();  //16-bit setup for counter 

for (i = 0; i < sizeof(servo)/sizeof(servo[0]); i++) 
{ 
    if ((oTime > nextPulse) && (channel < sizeof(servo)/sizeof(servo[0])))  //check if HIGH pulse (pos) is 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 
    } 

} 

for (i = 0; i < sizeof(servo)/sizeof(servo[0]); i++) 
{ 
    if ((oTime > tPulse - nextPulse) && (channel < sizeof(servo)/sizeof(servo[0])) )   //check if LOW pulse (period) is done 
    { 
     PORTB |= (1 << servo[channel]); 
     nextPulse -= hPulse[i]; 
     channel++; 
    } 

} 

} 


void servoPosSet(volatile uint16_t pos[], uint8_t size) 
{ 
    for (i = 0; i < size; i++) 
    { 
     hPulse[i] = pos[i]; 
    } 

} 


int main(void) 
{  
TCCR1 |= (1 << CS12); //set Timer/Counter1 prescaler to increment every 1 µs (PCK/8) 

for (channel = 0; channel < size); channel++) 
{ 
    DDRB |= (1 << servo[channel]); //sets PB0-PB4 as output pins 
} 

channel = 0; 

uint16_t pos[] = {2000, 1500, 1900, 1300, 1700}; 
uint8_t size = 5; 

while(1)   
{ 
     servoPosSet(pos); 

     servoMove(); 
} 

} 

編輯2:

這是如何我的圖示認爲代碼應該工作: enter image description here

...但它不!

+0

在鏈接TinyServo所示的代碼沒有直接說明它是什麼你想不工作。你應該考慮展示你所嘗試過的東西,即使如你所說,它沒有任何意義。 – ryyker

+1

您可以使用整數的較低8位來觸發ISR,在ISR中您可以發送多少次它發生增加另一個8位值。如果這個值匹配你的高8位,那麼你做了這個伎倆。 – Nidhoegger

+0

@ryyker我現在發佈了代碼;-) – CrowStudio

回答

1

如果你有沒有別的脈衝期間做的,你可以使用一個忙 循環,而不是中斷:

#include <avr/io.h> 
#include <util/delay_basic.h> 

/* Send a 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; 
} 

這會給你的4個時鐘週期,或0.5  微秒與分辨率 MHz時鐘。

向5個舵機發送脈衝最多應爲10  毫秒。由於 重複脈衝序列每21個時間,這會使您計算下一組位置,這應該是很多的。你可以 程序定時器來喚醒你每21  毫秒,那麼你的main()可能 樣子:

int main(void) 
{ 
    static uint16_t pos[] = {4000, 3000, 3800, 2600, 3400}; 
    uint8_t i; 

    /* Wake up every 21 ms. */ 
    setup_timer(); 
    sleep_enable(); 

    for (;;) { 
     /* Update the servos. */ 
     for (i = 0; i < 5; i++) pulse(pos[i], i); 

     /* Compute the next set of positions. */ 
     ... 

     /* Wait for timer interrupt. */ 
     sleep_cpu(); 
    } 
} 
+0

這與我前段時間看到的東西非常接近!它感覺正確,但我目前並不理解它,也不是那樣就像這個例子!現在我所要做的就是設法釋放一些時間,並打開那裏的燈光!;-) – CrowStudio