1

我正在尝试制作一个分辨率比 ATtiny85 8 位定时器/计数器更高的伺服控制器。到目前为止,我已经设法在 21'000 µs 的时间内在我的伺服系统上获得了大约 2000 个位置(1µs/步)。我还设法以不同的速度顺序移动 5 个伺服系统,但现在我想同步移动它们。

我最大的问题是我不明白我应该如何实现它!我环顾了其他伺服代码,包括servo8bit库,并试图找到一种方法。似乎大多数示例都使用比较匹配 ISR 来“同时”移动伺服系统,我的问题是我有一个 16 位整数要比较。

有没有办法做一些魔术,所以我可以使用 8 位比较匹配 ISR 和我的 16 位整数?或者你们中是否有人对我如何在不使用比较匹配 ISR 的情况下同步移动伺服系统有其他建议?

我希望我的问题有意义!

因为我还没有任何代码可以显示(只有没有比较匹配 ISR 的有缺陷的尝试是没有意义的)如果有帮助,我会将链接发布到我的TinyServo代码。

编辑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:

这是我认为代码应该如何工作的说明: 在此处输入图像描述

......但它没有!

4

1 回答 1

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 µs 的 8 MHz 时钟。

将脉冲发送到 5 个伺服系统最多需要 10 毫秒。由于您每 21 毫秒重复一次脉冲序列,因此您有 11 毫秒的时间来计算下一组位置,这应该足够了。您可以编写一个定时器,每 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();
    }
}
于 2015-06-15T12:30:51.817 回答