roboforum.ru

Технический форум по робототехнике.

Управление Сервами в WinAvr

Ответить

avr123.nm.ru » 14 авг 2006, 03:28

Сергей писал(а):Почему не симметрично? +- 0.8мс от центра.


действительно. значит я ошибся.

avr123.nm.ru » 14 авг 2006, 03:38

там же и робот футболист обитает по непомерной цене:
http://www.robotstorehk.com/soccer/RS-M ... HOTOS.html

=====  извините за офтоп !

Lirzman » 14 авг 2006, 14:23

avr123.nm.ru писал(а):вот вам и GOOGLE.com

МЫ не ищем легких путей :!:  :!:  :!:
НАШ девиз - посмотреть и сделать лучше!!! :D  :D  :D

avr123.nm.ru » 14 авг 2006, 15:07

Lirzman писал(а):НАШ девиз - посмотреть и сделать лучше!!! :D  :D  :D


да я именно и предлагаю посмотреть, а делать надо конечно по своему.

Lirzman » 14 авг 2006, 15:35

Ребята возникла следующая проблема:

Код: Выделить всёРазвернуть
//**************ПРОЦЕДУРА ПЕРЕПОЛНЕНИЯ ТАЙМЕРА***********************
SIGNAL(SIG_OVERFLOW0)
{

__asm__("nop;");//Инструкция ничего-неделанья

PORTB CLR_B(gservo);//В ПРОТЕУСЕ загорелся соответствующий пин!!!!
delaysa(period);//Задержка в 20мс, ПОКА использую силы CPU
}


Каждая инструкция "__asm__("nop;");" передвигает серву на 0.05гр
(РОВНО),так что получается ФЕНОМЕНАЛЬНАЯ точность.

НО так как мне нужен промежуток от 0.7мс до 2.3мс, при попытке загнать эту инструкцию в цикл, точность падает до 2.5гр.
КАК мне это обойти???

PS. В последствии я бы хотел выложить код в общий доступ, что-бы люди не изобретали велосипед, хочется поднять точность до максимума!!!

aesok » 14 авг 2006, 15:36

То Lirzman: У вас получилось управлять 1 сервомашинкой? Можно код посмотреть.

Анатолий.

Lirzman » 14 авг 2006, 15:44

Код ещё достаточно сырой :?.
Т.к я управление под аппаратный таймер ещё не закончил, то управляющий импульс в 1.5мс делается  аппаратно(таймером), а импульс в 20мс - программно  :?
Вложения
demo.c
(4.15 КиБ) Скачиваний: 281

aesok » 14 авг 2006, 15:48

Lirzman писал(а):
Код: Выделить всёРазвернуть
//**************ПРОЦЕДУРА ПЕРЕПОЛНЕНИЯ ТАЙМЕРА***********************
SIGNAL(SIG_OVERFLOW0)
{

__asm__("nop;");//Инструкция ничего-неделанья

PORTB CLR_B(gservo);//В ПРОТЕУСЕ загорелся соответствующий пин!!!!
delaysa(period);//Задержка в 20мс, ПОКА использую силы CPU
}



Запомните: НИКОГДА НЕ ИСПОЛЬЗУЙТЕ ЗАДЕРЖКИ В ПРЕРЫВАНИЯХ!!!

Прерывания должны обрабатываться максимально быстро. Точка. Если вы хотите вставить задержку в прерывание значит, вы что-то делаете неправильно, подумайте как обойтись без задежки. Обязательно есть другой вариант, и он не на много сложнее!!

Анатолий.

Lirzman » 14 авг 2006, 15:55

aesok писал(а):Запомните: НИКОГДА НЕ ИСПОЛЬЗУЙТЕ ЗАДЕРЖКИ В ПРЕРЫВАНИЯХ!!!

Я руководствовался шестой задачей курса AVR123.nm.ru
Там ясно сказано:" Боле "тонко" можно подогнать время между прерываниями добавив в самом начале функции обработчика прерывания по переполнению таймера_0 нужное количество ассемблерных инструкций NOP."

К тому-же инструкция nop занимает всего 1 машинный цикл так что это не так много.

Другое дело что я попытался всё это дело в цикл запихнуть :D  :D  :D

aesok писал(а):подумайте как обойтись без задежки

А как тогда управлять сервами с помощью таймера???


ЗЫ Кстати а почему прерывания должны обрабатываться максимально быстро, там что ограничения стоят какие-то?

avr123.nm.ru » 14 авг 2006, 17:09

Lirzman писал(а):Кстати а почему прерывания должны обрабатываться максимально быстро, там что ограничения стоят какие-то?


Это в рассказе о механизме и работе прерываний в AVR подробно.
На странице avr123.nm.ru/03.htm

Lirzman » 14 авг 2006, 17:39

Люди!
Я чего-то запутался, в курсе говорится:
Делайте функции обработчики прерывания как можно короче !  Не засиживайтесь в них ...

Если сейчас произойдут события которые могут вызвать прерывания то установятся их флаги, но даже разрешенные прерывания не произойдут !

Нужно тщательно продумывать алгоритм программы
чтоб успевать обрабатывать все прерывания - т.е. не пропускать нужные события.


Управление сервами подразумевает сплошные задержки :?, что мне делать???

Если нельзя делать паузы в прерываниях, то как вообще сервами управлять то??????

ЗЫ Может взять простой МК типа TINY и полностью отвести его под сервы, а связь осуществлять по TWI(I2C)???
Получилась бы модульная архитертура.

Но мне бы очень этого НЕ ХОТЕЛОСЬ делать ввиду удорожания всего изделия!!!

Так что надо искать выход из данной ситуации!!!!

aesok » 14 авг 2006, 18:08

Код: Выделить всёРазвернуть
char s;
int angle;
char szInput [3];
s=USART_Receive();

s=s-0x31;
szInput[0] = USART_Receive();
szInput[1] = USART_Receive();
szInput[2] = USART_Receive();
szInput[3] = USART_Receive();
szInput[4] = 0;  // Строка должна заканчиваться 0

angle = atoi (szInput);


Вы правильно поняли идею и увеличили разрядность приниманмого числа до 4 знаков. Но посмотрите внимательно но размер масива szInput  - он равен 3. А вы в него записываете 5 символов!!! Вам повезло что все сработало. Но если бы переменые были объявлены в таком порядке:

int angle;
char szInput [3];
char s;

s оказалась бы на месте 4 элемента масива и командой
szInput[3] = USART_Receive(); - была бы изменена.

Всегда внимательно следите за размерностью масивов!

Анатолий.

Lirzman » 14 авг 2006, 18:34

aesok писал(а):Всегда внимательно следите за размерностью масивов!

Я знаю :D  :D  :D
Просто на момент отладки таймера, я эту функцию закомментировал
//Command();

Самое интересное что ошибку  я потом заметил, исправлять прикрепленный файл просто лень было.  :D  :D  :D

aesok » 14 авг 2006, 18:35

Lirzman писал(а):Люди!

Так что надо искать выход из данной ситуации!!!!


Пока оставим пока только одну серву. С остальными позже.

Для управления одной сервой нужен сигнал в котором, вначале '1' поддерживаеться в течении 1,6+/-0.7 ms  (назавем это t), потом '0'  в течении (20 - t)ms. И так по кругу.


t = 1,6+/-0.7 ms  

'1' -  t ms
'0' -  (20 - t)ms
'1' -  t ms
'0' -  (20 - t)ms
'1' -  t ms
'0' -  (20 - t)ms
.....

Так?

Вот это и нужно запрограмировать в обрадотчике прерывания.


Код: Выделить всёРазвернуть
SIGNAL (....)      
{
   static int cur_state;   

 if(0 == cur_state) {
    вывести '1'
    настроить таймер на задежку t ms
    cur_state = 1;
 } else {
    вывести '0'
    настроить таймер на задежку (20 - t) ms
    cur_state = 0;
 }

}



Используйте 16-битный таймер, с 8 битным будет очень маленькая точность.

Анатолий.
Последний раз редактировалось aesok 14 авг 2006, 18:59, всего редактировалось 2 раз(а).

aesok » 14 авг 2006, 18:57

Код: Выделить всёРазвернуть
void delaysa(unsigned int mks)
{
 while(mks>0){
   mks--;
 }
}


Так делать задежки опасно. На разных уровнях оптимизации может получаться код разной длины, и соответственно будет разное время выполнения этой функции.

Но это не самое страшное, AVR-GCC очень умный компилятор. И он может проанализировать код, увидеть  что переменная 'mks' не используеться после цикла, и решить что с ней ничего не надо делать в цикле, и выкинуть ее вместе с циклом. И вся эта функция выродиться в одну инструкцию 'ret'. А может быть и совсем удалена!!!

И еще для практической работы используйте оптимизацию '-0s', считайте что все другие режимы нужны для отладки компилятора.

Используйте макросы _delay_us и _delay_ms. Но в качестве параметра им можно передовать только константу!!!! Внимательно читайте их описание.

Анатолий.


Rambler\'s Top100 Mail.ru counter