roboforum.ru

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

SERVO - как управлять на AVR в прерываниях - FAQ

SERVO - как управлять на AVR в прерываниях - FAQ

=DeaD= » 23 апр 2008, 13:11

СервоКонтроллер на 32 SERVO на ATmega8 и CVAVR с исходниками и прошивками для
пауков и прочей робототехники ! бесплатно:

http://www.active-robots.com/products/m ... ervo.shtml

Исходники и прошивки
http://www.lynxmotion.com/images/html/proj078.htm

С графической оболочкой для програаммирования движения
http://www.lynxmotion.com/Product.aspx? ... egoryID=15

Как программировать управление 8-ю сервами на AVR на таймере
и прерывании
- http://avr123.nm.ru/z13.htm
И программа для управления 8 servo с ПК.

< добавил avr123.nm.ru >
================================================

Тема создана по мотивам переписки меня и denissyslo по электронной почте, которую принято решение перетащить сюда, чтобы осталось для следующих "поколений" :)

Добавлено спустя 3 минуты 40 секунд:
denissyslo писал(а):Разбираюсь второй день - не могу сообразить как рулить сервами от портов, но
которых нет аппаратного шима (наверное я тупой). Нашел только на 8 странице
курса в примерах для меги 128, но там подключают их на ноги с аппаратным
шимом...

Хотел просить тебя дать кусок кода от твоего касательно серв контроллера на
изучение.


Добавлено спустя 31 секунду:
=DeaD= писал(а):Попробую пояснить - я вешаю на прерывание по таймеру, которое срабатывает каждые 160 тактов (с частотой 100КГц), что даёт мне разрешение 10мкс, то есть учитывая, что я должен выдать на серву сигнал шириной 1000-2000мкс (1-2мс), я имею 100 позиций сервы. то есть шаг 1.8 градуса.

SIGNAL(SIG_OVERFLOW0){
TCNT0=0x5F; //0x5F=255-160 - to get this interrupt each 160/16'000'000=1/100'000 sec

//***************************************************************************************************
//Here is servo-controlling block
//***************************************************************************************************
if(tmr<200){

uint8_t tmp=tmr; //Тут надо вычитать соответствующий отступ, а тут это ноль

if(types[0]==2){ //Тут у меня лежит тип выхода, 2 - выход на серву
if(tmp==0){ outb(PORTA,inb(PORTA) | 0x01); }; //Set PA0 pin to 1
uint16_t xxx=value[0];
if(xxx>MAXSERVO){ xxx=MAXSERVO; };
if(xxx<MINSERVO){ xxx=MINSERVO; };
if(tmp==xxx){ outb(PORTA,inb(PORTA) & 0xFE); }; //Set PA0 pin to 0
};
if(types[1]==2){
if(tmp==0){ outb(PORTA,inb(PORTA) | 0x02); }; //Set PA1 pin to 1
uint8_t xxx=value[1];
if(xxx>MAXSERVO){ xxx=MAXSERVO; };
if(xxx<MINSERVO){ xxx=MINSERVO; };
if(tmp==xxx){ outb(PORTA,inb(PORTA) & 0xFD); }; //Set PA1 pin to 0
};

};

tmr++;
if(tmr==2150){
tmr=0;
};

};

ну и инициализация прерывания:

// Initiating Timer/Counter-0 Control Registers:
//
// TCCR0 = FOC0:WGM00:COM01:COM00:WGM01:CS02:CS01:CS00
// 0 0 0 0 0 0 0 1
//
// COM1x1:COM1x0 = 0:0 => OC1x disconnected from output pin
// FOC1A:FOC1B = 0:0 => Don't force output compare event
// WGM13:WGM12:WGM11:WGM10 = 0:0:0:0 => Normal timer/counter operation
// ICNC1 = 0 => Input Capture Noise Canceller disabled (because not needed)
// ICES1 = 0 => Input Capture Edge Select set to "falling" mode (no matter)
// CS12:CS11:CS10 = 0:0:1 => Timer "on", no prescaling (1 clock every cpu tact)
// TCCR1A = 00000000 = 0x00
TCCR0=0x01;

TCNT0=0x69;


// Initiating internal program subcounter with zero
tmr=0;

// Initiating Timer/Counter Interrupt Mask register:
//
// TIMSK = OCIE2:TOIE2:TICIE1:OCIE1A:OCIE1B:TOIE1:OCIE0:TOIE0
// 0 0 0 0 0 1 0 0
//
// OCIE2 = 0 => Timer/Counter2 Output Compare Match Interrupt disabled
// TOIE2 = 0 => Timer/Counter2 Timer Overflow disabled
// TICIE1 = 0 => Timer/Counter1 Input Capture Interrupt disabled
// OCIE1x = 0 => Timer/Counter1 Output Compare Match Interrupt disabled
// TOIE1 = 0 => Timer/Counter1 Timer Overflow enabled
// OCIE0 = 0 => Timer/Counter0 Output Compare Match Interrupt disabled
// TOIE0 = 1 => Timer/Counter0 Timer Overflow disabled
TIMSK=0x01;

И разрешение на работу прерываний:

sei();

Вроде всё.

Задавай вопросы :)


Добавлено спустя 1 минуту 5 секунд:
denissyslo писал(а):> Антон, привет! Начинаю раскидывать твой код:
> Еще посылаю мой исходник. В нем пытаюсь рулить одной сервой на ПОРТА.1.
> Посмотри пожалуйста. Компилятор коде визионАВР. Не могу там кое-что понять.
> Ниже то как я разбирал твой код.
>
>
> Попробую пояснить - я вешаю на прерывание по таймеру, которое срабатывает
> каждые 160 тактов (с частотой 100КГц), что даёт мне разрешение 10мкс, то
> есть учитывая, что я должен выдать на серву сигнал шириной 1000-2000мкс
> (1-2мс), я имею 100 позиций сервы. то есть шаг 1.8 градуса.
>
>
> SIGNAL(SIG_OVERFLOW0){
> TCNT0=0x5F; //0x5F=255-160 - to get this interrupt each
> 160/16'000'000=1/100'000 sec !!! это пишем в блоке объявления
> переменных!!!???
>
> !!!т.к. у меня кварц 10Мгц, то будет так:
>
> Попробую пояснить - я вешаю на прерывание по таймеру, которое срабатывает
> каждые 100 тактов (с частотой 100КГц), что даёт мне разрешение 10мкс, то
> есть учитывая, что я должен выдать на серву сигнал шириной 1000-2000мкс
> (1-2мс), я имею 100 позиций сервы. то есть шаг 1.8 градуса.
>
> TCNT0=0x9B; //0x9B=255-100 - to get this interrupt each
> 100/10'000'000=1/100'000 sec
>
> Правильно?
>
>
> //**************************************************************************
> *************************
> //Here is servo-controlling block
>
> //**************************************************************************
> *************************
> if(tmr<200){ !!!тут мы проверяем - накопилось ли 20мс. В начале
> надо объявить tmr integer'ом????
>
> uint8_t tmp=tmr; //Тут надо вычитать соответствующий отступ, а тут это
> ноль !!!немного не понял - это чисто ФИЧА ТВОЙ программы. Точнее вообще не
> понял. ?????
>
> if(types[0]==2){ //Тут у меня лежит тип выхода, 2 - выход на серву
> !!!тут надо понимать тоже ПРИМОЧКА твоего контроллера!!!?
> if(tmp==0){ outb(PORTA,inb(PORTA) | 0x01); }; //Set PA0 pin to 1
> !!!тут вроде ясно - если начало цикла то устанавливаем порт А.1 как выход!!!
>
> uint16_t xxx=value[0]; !!! вот тут немного не ясно ххх - это
> задание угла сервы???? Т.е. это какая-то переменная? Т.е. мы должна в начале
> программы ее объявить, например int? Если да, то в каком формате задавать
> угол - ххх это количество тактов по 10мкс?????
>
> if(xxx>MAXSERVO){ xxx=MAXSERVO; }; !!! Тут понял - проверяем - не
> уехали ли мы за предельное значение - что бы небыло зависания проги!!!
> if(xxx<MINSERVO){ xxx=MINSERVO; }; !!! Аналогично проверка
> минимального значения, все продумано Вначале программы необходимо
> объявить MAXSERVO и MINSERVO типами int и присвоить значения, только тогда
> КАКИЕ ЗНАЧЕНИЯ??? В тиках по 10мкс???? Т.е 21 и 9 соответственно??? !!!
>
> if(tmp==xxx){ outb(PORTA,inb(PORTA) & 0xFE); }; //Set PA0 pin to 0
> !!! тут вроде разобрался - все просто если текущее значение, того сколько
> времени прошло по 10мкс (переменная tmp) равно установленному углу, то
> поускаем на нашу ножку 0! Т.е. в начале надо объявить tmp int & tmp=0;???
> };
>
> !!!Ну ниже я так понимаю все АБСОЛЮТНО так же только для следующей ножки.
> Антон, такой вопрос: ххх естественно это другая переменная и вообще имя ххх
> для читабельности лучше заменить на что-то типа servo_2 (хотя это конечно не
> принципиально). А переменная tmp для всех ножек будет одна и таже???!!!
>
> if(types[1]==2){ !!! вот этот ИФ (и выше): if(types[1]==2){};Я могу
> смело убрать? Оставивто что в скобках???!!!
>
> if(tmp==0){ outb(PORTA,inb(PORTA) | 0x02); }; //Set PA1 pin to 1
> uint8_t xxx=value[1];
> if(xxx>MAXSERVO){ xxx=MAXSERVO; };
> if(xxx<MINSERVO){ xxx=MINSERVO; };
> if(tmp==xxx){ outb(PORTA,inb(PORTA) & 0xFD); }; //Set PA1 pin to 0
> };
>
> };
>
> tmr++; !!! тут тоже вроде понял - следующий шаг - инкримент
>
> if(tmr==2150){ !!! а вот тут я действительно не понял...по идее тут могла
> быть проверка на выполнения полного цикла, но цикл то у нас 200 раз по
> 10мкс???? И вообще что за цифра в 2150 и откуда она...как говорил ДЖАМШУТ
> ПонятнА....ннепонЯтА.
> tmr=0;
> };
>
> };
>
>
> Вот этот блок с сервами я пишу в основном цикле программы (после вайл(1)
> )????? А где обнуление переменной tmp ????
>
>
>
>
> ОГО...с этим будет трудно для меня...
> Это где мы пишем?????? Это сделано генератором кода КВАРА???? Пойдет ли мне
> этот прибамбас, если у меня кварц 10, а не 16?
>
> ну и инициализация прерывания:
>
> // Initiating Timer/Counter-0 Control Registers:
> //
> // TCCR0 = FOC0:WGM00:COM01:COM00:WGM01:CS02:CS01:CS00
> // 0 0 0 0 0 0 0 1
> //
> // COM1x1:COM1x0 = 0:0 => OC1x disconnected from output pin
> // FOC1A:FOC1B = 0:0 => Don't force output compare event
> // WGM13:WGM12:WGM11:WGM10 = 0:0:0:0 => Normal timer/counter operation
> // ICNC1 = 0 => Input Capture Noise Canceller disabled (because not
> needed)
> // ICES1 = 0 => Input Capture Edge Select set to "falling" mode (no
> matter)
> // CS12:CS11:CS10 = 0:0:1 => Timer "on", no prescaling (1 clock every cpu
> tact)
> // TCCR1A = 00000000 = 0x00
> TCCR0=0x01;
>
> TCNT0=0x69;
>
>
> К этому куску аналогичные вопросы .
>
> // Initiating internal program subcounter with zero
> tmr=0;
>
> // Initiating Timer/Counter Interrupt Mask register:
> //
> // TIMSK = OCIE2:TOIE2:TICIE1:OCIE1A:OCIE1B:TOIE1:OCIE0:TOIE0
> // 0 0 0 0 0 1 0 0
> //
> // OCIE2 = 0 => Timer/Counter2 Output Compare Match Interrupt disabled
> // TOIE2 = 0 => Timer/Counter2 Timer Overflow disabled
> // TICIE1 = 0 => Timer/Counter1 Input Capture Interrupt disabled
> // OCIE1x = 0 => Timer/Counter1 Output Compare Match Interrupt disabled
> // TOIE1 = 0 => Timer/Counter1 Timer Overflow enabled
> // OCIE0 = 0 => Timer/Counter0 Output Compare Match Interrupt disabled
> // TOIE0 = 1 => Timer/Counter0 Timer Overflow disabled
> TIMSK=0x01;
>
> И разрешение на работу прерываний:
>
> sei(); !!! В кваре, кажется пишется немного по-другому...


Добавлено спустя 33 секунды:
=DeaD= писал(а):Итак по порядку:

1. Со средой CVAVR не знаком, могу только про WinAVR говорить, но регистры и порты все те же, если ты разбираешься с CVAVR - легко переделаешь под себя;

2. Переделка TCNT0 под кварц 10МГц правильная;

3. Нулевой отступ при расчете переменной tmp - это если мне надо будет рулить скажем 20-ю сервами, в этом случае мне нельзя будет сразу их все обрабатывать, потому что я тогда не уложусь скорее всего в 100 тактов которые проходят между прерываниями, поэтому я буду первые 2мс из 20мс обрабатывать первые несколько серв, потом следующие несколько и т.д. Я сейчас по 2-3 сервы обрабатываю за раз, чтобы успевать оставшееся время работать с UART'ом и движками. То есть если надо будет рулить 4 сервами, я их буду обрабатывать не в if(tmr<200), а в if(tmr>=200 && tmr<400) и там уже напишу tmp=tmr-200;

4. xxx=value[0] - это должно быть число от 100 до 199 означающее количество тактов прерывания (по 10мкс) которое будет длиться импульс для управления сервой;

5. MIN/MAXSERVO объявлять лучше через #define, а не переменными - не перегружаем программу лишними переменными;

6. Обнуление переменной tmp не нужно, поскольку она в каждом цикле заново инициализируется из tmr;

Re: Управление RC-Servo на AVR на прерываниях

denissyslo » 23 апр 2008, 13:39

Да типа того... только у меня робот на CodeVisonAVR, а тут код для ВИНАВР.
Думаю идея всем понятна...
Сейчас необходимо этот код портировать на КВАР.
параметры: АТМЕГА16
10Мгц
Сервы на порте А первые 7 ножек.
Очень жду помощи. Сам тоже буду выкладывать.
вот мои творения - результат почти 0.
Вложения
Pioner.rar
(41.63 КиБ) Скачиваний: 66

Re: Управление RC-Servo на AVR на прерываниях

=DeaD= » 23 апр 2008, 14:08

А какой помощи ты ждешь? :)

Отлаживать твою прошивку врядли кто-то сможет, у нас же твоего робота с подцепленными устройствами нету.

Ситуация очень даже штатная. Как говориться - поздравляем вы дошли до уровня сложного проекта, и поскольку он собирается вами с нуля - вы остаётесь с ним почти один на один :)

Re: Управление RC-Servo на AVR на прерываниях

Сергей » 23 апр 2008, 14:17

Могу выложить старый проект управления сервами по i2c на ATmega8, нужно?

Re: Управление RC-Servo на AVR на прерываниях

avr123.nm.ru » 23 апр 2008, 14:44

Интересный топик.

Сергей писал(а):Могу выложить старый проект управления сервами по i2c на ATmega8, нужно?


Нужно конечно - выложи. Только опиши что к чему.

http://OpenServo.org тоже по i2c управляется и вроде считавает положение сервы даже.

Добавлено спустя 8 минут 7 секунд:
denissyslo писал(а):АТМЕГА16 - 10Мгц .


Я бы взял 14 "с копейками" - по даташиту из таблицы USART.

denissyslo писал(а):servo Сервы на порте А первые 7 ножек.


Можно разбить управление 7 servo на 7 фаз. Один таймер прерывается каждые 2800 мкС и в прерывании включает очередную серву и отсчет ВТОРЫМ таймером длины импульса для нее. Когда второй таймер отсчитает сколько нужно он выключает импульм на серву.

Таким образом все сервы получают импульс раз в 19,6 мСек.

Добавлено спустя 3 минуты 15 секунд:
======

А можно взять готовый проект для CVAVR с исходниками сервоконтроллера на 32 servo.
http://www.active-robots.com/products/m ... ervo.shtml

С БЕСПЛАТНОЙ графической оболочкой для програаммирования движения
http://www.lynxmotion.com/Product.aspx? ... egoryID=15

Re: Управление RC-Servo на AVR на прерываниях

denissyslo » 23 апр 2008, 14:45

[А какой помощи ты ждешь?

Да очень простой....
есть полно описание моего устройства:
Атмега16
Кварц 10 Мгц
Серва подключена на ножку ПортА.1
Требуется:
взять мой код и поправить его как надо.
Т.е. посмотреь мою программу и знаю основную идею Деада о управлении сервами по прерываниям. написать все ПРАВИЛЬНО подпраить - написаь

Отлаживать твою прошивку врядли кто-то сможет, у нас же твоего робота с подцепленными устройствами нету.

Да отлаживать то я и не прошу. На самом деле все СТАНДАРТНО и задачко-то почти стандартная - есть МК, известны параметры - кварц и нога МК, на эту ногу надо грамотно подать шим сигнал. ВСЕ.

Ситуация очень даже штатная. Как говориться - поздравляем вы дошли до уровня сложного проекта, и поскольку он собирается вами с нуля - вы остаётесь с ним почти один на один

В плане руления ервой по-грамотному - проект типовой......
Мечта идиота - примр такой программы от гуру.....

Re: SERVO группа - как управлять на AVR в прерываниях

=DeaD= » 23 апр 2008, 15:10

Нет, ну конечно может найдётся кто настолько добрый, чтобы разобраться в твоей программке что куда засунуть.

Но я бы вот не взялся... :roll: и уж тем более надеяться что без отладки всё сразу заработает... это уже не аппаратный ШИМ включить...

Re: SERVO группа - как управлять на AVR в прерываниях

Сергей » 23 апр 2008, 15:20

Я как вечером дома буду - выложу, может перепишу нормально, тк эту прогу я давно писал

Re: SERVO группа - как управлять на AVR в прерываниях

FireFly » 24 апр 2008, 02:34

Хех... а вы давайте железку разведите (к первому посту) :D
да что бы повторяемость была.....разведете - респек и уважуха, а софт там давно уже отработан и велосипеды изобретать не стоит :wink:

Re: [FAQ] SERVO - как управлять на AVR в прерываниях

sub_null » 05 авг 2008, 13:15

Зачем изобретать велосипед? Все уже есть, посмотрите руководство пользователя по контроллеру SSC32
http://www.lynxmotion.com/images/data/ssc-32.pdf с принципиальной схемой (копировать всю схему полностью не обязательно)

Прошивка с исходниками для платного CodeVision:

http://www.lynxmotion.com/images/html/proj078.htm

Портированная версия прошивки и загрузчика для бесплатного WinAVR gcc:

http://www.dot-heine.de/avr-loader-0.1.tar.bz2 -- a tiny (< 256 bytes) boot-loader for the ATMega8 and the ATMega168.
http://www.dot-heine.de/ssc-32-gcc-1.06XE.tar.bz2 -- old firmware version.

http://www.dot-heine.de/ssc-32-gcc-2.02GP.tar.bz2 -- new firmware version (brief info).

Зачем разводить плату?
У SSC32 достаточно сложная схема. Плата двухсторонняя с маленькой шириной дорожек.
Если очень припекло и нет возможности купить оригинал, то соберите макетку как сделал это я.

Если нужна помощь обращайтесь. Я собрал макет на ATMega8 в учебных целях. Мне удалось залить фирменную прошивку. Макет функционирует как ожидалось.

Когда то давно я нашел в интернете прошивку генерирующую программно PWM на мега8. Код на С для WinAVR без лишних заморочек с минимальным интерфейсом, коммуникация с PC по UART. Если интересно пишите, я дам исходники.

Ссылка на несколько видеороликов:
http://video.mail.ru/list/hotbox80/5

Re: [FAQ] SERVO - как управлять на AVR в прерываниях

Сергей » 05 авг 2008, 13:49

Никто велосипед не собирает, так сделано в образовательных целях. А так конечно выкладывай свои результаты! Оформи тему со схемами и соответствующими файлами

Re: [FAQ] SERVO - как управлять на AVR в прерываниях

sub_null » 05 авг 2008, 15:24

Выложу обязательно и исходники и схему и все платы и механику
с чертежами по моему проекту Bipedal robot. На video.mail.ru выложен
промежуточный результат.

Re: [FAQ] SERVO - как управлять на AVR в прерываниях

FireFly » 05 авг 2008, 22:14

sub_null писал(а):Зачем изобретать велосипед? Все уже есть, посмотрите руководство пользователя по контроллеру SSC32
http://www.lynxmotion.com/images/data/ssc-32.pdf с принципиальной схемой (копировать всю схему полностью не обязательно)


кто тут чего изобретает? :ROFL: - http://robozone.su/2008/06/29/modul-ser ... ytyjj.html

Re: FAQ SERVO - как управлять на AVR в прерываниях

dimamakc » 23 ноя 2008, 22:19

здрасте подскажите как упровлять 4-мя сервами на pic16f84a есть пони-прог и jdm програматор

Re: FAQ SERVO - как управлять на AVR в прерываниях

EdGull » 23 ноя 2008, 22:29

в смысле мы тебе должны по быренькому код написать?


Rambler\'s Top100 Mail.ru counter