我正在尝试制作一个比ATtiny85 8位定时器/计数器具有更高分辨率的伺服控制器。到目前为止,我已经在21‘000µs的时间范围内在我的伺服上获得了大约2000个位置(1µs/step)。我还设法以不同的速度顺序移动了5个伺服,但现在我想同步移动它们。
我最大的问题是我不知道该怎么做!我已经查看了包括servo8bit库在内的其他伺服代码,并试图找到一种方法。似乎大多数示例都使用比较匹配ISR来“同时”移动伺服,我的问题是我想要比较一个16位整数。
有没有办法让我可以使用8位比较匹配ISR和我的16位整数?或者你们谁有其他的建议,关于如何在不使用compare match 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:
这是我认为代码应该如何工作的一个例子:
...but它不会!
发布于 2015-06-15 12:30:52
如果您在脉冲期间没有其他事情可做,您可以使用忙循环而不是中断:
#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个时钟周期的分辨率,或8 MHz时钟的0.5µs分辨率。
向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();
}
}
https://stackoverflow.com/questions/30756790
复制相似问题