Я пытаюсь создать сервоконтроллер с более высоким разрешением, чем 8-битный таймер/счетчик ATtiny85. На данный момент мне удалось получить около 2000 позиций на моем сервоприводе (1 мкс/шаг) за время 21 000 мкс. Мне также удалось переместить 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:
Это иллюстрация того, как, по моему мнению, должен работать код:
...но это не так!
servoPosSet()
должна иметь два аргумента: один — массив, а второй — количество элементов в массиве. sizeof() предоставляет количество байтов в переменной, поэтому ваш цикл будет отключен вservoPosSet()
и в других местах, где вы пытаетесь использоватьsizeof()
для определения количества элементов массива. - person Richard Chambers   schedule 10.06.2015sizeof(ray)/sizeof(ray[0])
, которое будет принимать общее количество байтов во всех элементах массива, а затем делить на размер одного элемента массива. Также, когда вы вызываете функцию и передаете ей массив, как вы это делаете, функция не будет знать количество элементов массива. Массив в основном превращается в постоянный указатель. Многие люди называют этот массив распадом на указатель, например, здесь вопросы/1461432/что такое-распад-массива - person Richard Chambers   schedule 10.06.2015ui16Val
— это ваше 16-битное значение, аui8Val
— 8-битное значение для загрузки в ISR, вы должны сделать что-то вроде:ui8Val = (ui16Val & 0x00ff; while (ui16Val) { SendISR (ui8Val); ui16Val &= 0xff00; ui16Val >>= 1; if (ui16Val) ui8Val = 0xff; }
Идея состоит в том, чтобы рассматривать старший байт 16-битного значения как счетчик количества раз отправки. вниз 0xff в качестве значения счетчика ISR после отправки начальных младших 8 бит. Но какая-то ISR синхронизация нужна. - person Richard Chambers   schedule 10.06.2015