roboforum.ru

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

 

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

Программирование микроконтроллеров AVR, PIC, ARM.
Разработка и изготовление печатных плат для модулей.

Сообщение avr123.nm.ru » 14 авг 2006, 03:28

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


действительно. значит я ошибся.
Аватара пользователя
avr123.nm.ru
отсылающий читать курс
 
Сообщения: 14200
Зарегистрирован: 06 ноя 2005, 04:18
Откуда: Москва
Предупреждения: -8

Сообщение avr123.nm.ru » 14 авг 2006, 03:38

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

=====  извините за офтоп !
Аватара пользователя
avr123.nm.ru
отсылающий читать курс
 
Сообщения: 14200
Зарегистрирован: 06 ноя 2005, 04:18
Откуда: Москва
Предупреждения: -8

Сообщение Lirzman » 14 авг 2006, 14:23

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

МЫ не ищем легких путей :!:  :!:  :!:
НАШ девиз - посмотреть и сделать лучше!!! :D  :D  :D
Аватара пользователя
Lirzman
 
Сообщения: 257
Зарегистрирован: 22 мар 2005, 03:59
Откуда: Питер

Сообщение avr123.nm.ru » 14 авг 2006, 15:07

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


да я именно и предлагаю посмотреть, а делать надо конечно по своему.
Аватара пользователя
avr123.nm.ru
отсылающий читать курс
 
Сообщения: 14200
Зарегистрирован: 06 ноя 2005, 04:18
Откуда: Москва
Предупреждения: -8

Сообщение 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. В последствии я бы хотел выложить код в общий доступ, что-бы люди не изобретали велосипед, хочется поднять точность до максимума!!!
Аватара пользователя
Lirzman
 
Сообщения: 257
Зарегистрирован: 22 мар 2005, 03:59
Откуда: Питер

Сообщение aesok » 14 авг 2006, 15:36

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

Анатолий.
aesok
 
Сообщения: 69
Зарегистрирован: 11 авг 2006, 01:02
Откуда: ----

Сообщение Lirzman » 14 авг 2006, 15:44

Код ещё достаточно сырой :?.
Т.к я управление под аппаратный таймер ещё не закончил, то управляющий импульс в 1.5мс делается  аппаратно(таймером), а импульс в 20мс - программно  :?
Вложения
demo.c
(4.15 КиБ) Скачиваний: 58
Аватара пользователя
Lirzman
 
Сообщения: 257
Зарегистрирован: 22 мар 2005, 03:59
Откуда: Питер

Сообщение aesok » 14 авг 2006, 15:48

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

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

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



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

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

Анатолий.
aesok
 
Сообщения: 69
Зарегистрирован: 11 авг 2006, 01:02
Откуда: ----

Сообщение Lirzman » 14 авг 2006, 15:55

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

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

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

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

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

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


ЗЫ Кстати а почему прерывания должны обрабатываться максимально быстро, там что ограничения стоят какие-то?
Аватара пользователя
Lirzman
 
Сообщения: 257
Зарегистрирован: 22 мар 2005, 03:59
Откуда: Питер

Сообщение avr123.nm.ru » 14 авг 2006, 17:09

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


Это в рассказе о механизме и работе прерываний в AVR подробно.
На странице avr123.nm.ru/03.htm
Аватара пользователя
avr123.nm.ru
отсылающий читать курс
 
Сообщения: 14200
Зарегистрирован: 06 ноя 2005, 04:18
Откуда: Москва
Предупреждения: -8

Сообщение Lirzman » 14 авг 2006, 17:39

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

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

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


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

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

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

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

Так что надо искать выход из данной ситуации!!!!
Аватара пользователя
Lirzman
 
Сообщения: 257
Зарегистрирован: 22 мар 2005, 03:59
Откуда: Питер

Сообщение 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(); - была бы изменена.

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

Анатолий.
aesok
 
Сообщения: 69
Зарегистрирован: 11 авг 2006, 01:02
Откуда: ----

Сообщение Lirzman » 14 авг 2006, 18:34

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

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

Самое интересное что ошибку  я потом заметил, исправлять прикрепленный файл просто лень было.  :D  :D  :D
Аватара пользователя
Lirzman
 
Сообщения: 257
Зарегистрирован: 22 мар 2005, 03:59
Откуда: Питер

Сообщение 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
 
Сообщения: 69
Зарегистрирован: 11 авг 2006, 01:02
Откуда: ----

Сообщение aesok » 14 авг 2006, 18:57

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


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

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

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

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

Анатолий.
aesok
 
Сообщения: 69
Зарегистрирован: 11 авг 2006, 01:02
Откуда: ----

Пред.След.

Вернуться в Микроконтроллеры

Кто сейчас на конференции

Сейчас этот форум просматривают: Bing [Bot], GoGo.Ru [Bot], Google [Bot] и гости: 1

Mail.ru counter