roboforum.ru

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

Проблема управление сервы с кнопки

Проблема управление сервы с кнопки

AVRus » 08 фев 2011, 00:19

Захотелось поуправлять сервой кнопкой, задача такая, нажимаю кнопку серва поварачивается на ~10гр., и в этоже время на семисегментный индикатор выводится цифра, и так серва поворачивается под управлением кнопки сначала в одну сторону, а достигнув минимума в другую.
Но симулирую в протеусе и возникает проблема, нехочет серва двигаться, хотя символы меняются :(
Сигнал сервы - portd.0
portc - аноды светодиода
portd - катод

Код: Выделить всёРазвернуть
#include <mega16.h>
unsigned char n=0; //переменная для вывода цифр и вычитания\суммирования угла сервы
int mass[9]={0,237,171,15,227,143,141,47,233}; //цифры
unsigned char push=0; // проверка нажатия
unsigned char i=0; //для разделения паузы и сигнала на серву
unsigned char m=0; //задает направление движения сервы
unsigned int preangle=2250; // середина для сервы
unsigned int angle; //значения для угла поворота

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
TCCR1B=0x00;
        if (PINB.2==0){   
        push++;               
        if (push==4){
         n++;                 //обработка для устранения дребезга
        }
        if (push==100) {
         push=5;
        }
        }
       
if (i==0) {    //20мс сервы между сигналами
PORTD |= 0x01;
OCR1AH=0x75;
OCR1AL=0x30;
i=1;
} else {
                                 
  if (angle<=1503) { //если минимум то
   m=1;
  }
  if (angle>=2997) {//если максимум то
   m=2;
  }
 
  if (n>=1 && n<9) {
 
   if (m==1) {
    angle=preangle + (n*83); //угол увеличиваем в зависимости от кол-ва нажатий     
   } else {
    angle=preangle - (n*83);//угол уменьшаем в зависимости от кол-ва нажатий
   }
 
  }   
 
  OCR1AH=(char)(angle >> 8); // задаем угол
  OCR1AL=(char)(angle << 8); 
i=0;
 
PORTD &= 0x00;
}

TCCR1B=0x1A;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTA=0x00;
DDRA=0xFF;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00;
DDRC=0xFF;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=0
PORTD=0x00;
DDRD=0x01;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1500,000 kHz
// Mode: Fast PWM top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x03;
TCCR1B=0x1A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x75;
OCR1AL=0x30;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
// INT2 Mode: Falling Edge
GICR|=0x00;
MCUCR=0x00;
MCUCSR=0x00;
GIFR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
     
      if (PINB.2==1) {//кнопка отжата
       push=0;
      }             
     
      if (n<9 && n>=1) {//зажигаем светодиоды
       PORTC=mass[n];
       PORTA=0x29;     
       } else {
        n=0;
       }

      };
}


Помогите пожалуйста увидеть ошибку :)

Re: Проблема управление сервы с кнопки

avr123.nm.ru » 08 фев 2011, 00:45

Советую в PROTEUS посмотреть - там все наглядно - http://proteus123.narod.ru

Re: Проблема управление сервы с кнопки

Myp » 08 фев 2011, 09:32

он там и смотрит =)

приложи проект полностью

Re: Проблема управление сервы с кнопки

avr123.nm.ru » 08 фев 2011, 10:44

Я в смысле осцилом прота посмотреть меняется ли ширина импульса.

Re: Проблема управление сервы с кнопки

AVRus » 09 фев 2011, 01:00

Я планировал что таймер на меге считает до 20мс с опущеной ногой сервы, прерывается, дальше считает нужное кол-во для импульса сервы с поднятой ногой сервы, и так зацикливается, но в протеусе творится жесть :)
bin.zip
квавр
(30.6 КиБ) Скачиваний: 0

Proteus 7 Professional.zip
isis
(17.15 КиБ) Скачиваний: 0

Re: Проблема управление сервы с кнопки

dccharacter » 09 фев 2011, 12:50

Вы привыкайте проблемы локализовывать. Напишите простую программу, которая просто управляет сервой. Без всяких 10-ти градусов и кнопок. Заработало? Копайте дальше? Не заработало? Значит пред-делители таймера криво настроены или МК работает не на той частоте, поставьте светодиод и мигайте им раз в секунду. Мигает раз в четыре секунды? Делайте выводы.

Добавлено спустя 4 минуты 26 секунд:
20ms между импульсами он ждет ОК, а вот сам импульс длительностью 42мс

Добавлено спустя 4 минуты 49 секунд:
Я с атмегой не работаю, но ошибка с большой долей вероятности вот тут:

Код: Выделить всёРазвернуть
  OCR1AH=(char)(angle >> 8); //0x08 2250=1.5ms
  OCR1AL=(char)(angle << 8); //0xCA 2250=1.5ms


Обычно, когда есть int (я так понимаю angle сложными математическими действиями приводится к количеству тиков таймера), и его надо раскидать на чары, то это делается так:

Код: Выделить всёРазвернуть
  OCR1AH=(unsigned char)(angle >> 8); //0x08 2250=1.5ms
  OCR1AL=(unsigned char)(angle); //0xCA 2250=1.5ms


Добавлено спустя 11 минут 57 секунд:
Но это вроде не должно так сильно повлиять, ошибка только в LSB появляется, т.е. порядок длительности должен быть тем же.

А зачем вам Compare? Взводите таймер на -angle, когда он перекатится через ноль, отработает прерывание. Кроме того, я не вижу - вы таймер где-нибудь обнуляете?

Re: Проблема управление сервы с кнопки

AVRus » 09 фев 2011, 18:00

Вот 42мс меня и смутили, я планировал что 20мс, а дальше таймер сам сбросится в ноль, а дальше я уже задам ему импульс для сервы...
1) вообще я думал что таймер в режиме Fast PWM доходит до TOP значения в OCR1A и дальше сбрасывается в нуль - как написано в даташите "The counter counts from BOTTOM to TOP then restarts from BOTTOM" ?
2) Можно\Нужно ли при остановленном таймере просто обнулять значение TCNT1, дабы сбросить его в нуль ?
3) TCCR1B=0x00; просто останавливает таймер на последнем тике или останавливает и сбрасывает в ноль ?

Насчет unsigned char - спасибо, исправил :)
Насчет последнего недопонял, я и задаю в OCR1A значение angle, чтобы достигнув его таймер прерывался...

Спасибо за советы , надеюсь на дальнейшую помощь :)

P.S. Да видимо я спутал назначение TIM1_COMPA и TIM1_OVF...как я понял как раз по этому весь сигнал был 42мс?

Re: Проблема управление сервы с кнопки

AVRus » 12 фев 2011, 17:36

Сделал без кнопок пока, в протеусе шим дает нужный от 1 до 2 мс с 20мс паузами, серва протеусовская движется, попробовал на живой - двигается в одну сторону до предела а дальше жужжит и испытывает явный дискомфорт :(

Подаю просто 1,5мс стабильные, в протеусе серва держится центра, реальная снова клонится до конца в угол, эххх осцила нет жаль :(((

В чем может быть проблема ?

Я не понимаю вот мк включился для управления сервой, он же не знает в каком она положении, нужно наверно делать в первую секунду установку на центр ?

Re: Проблема управление сервы с кнопки

dccharacter » 12 фев 2011, 18:46

Это скорее всего значит, что процессор работает не на той частоте, которую вы планировали. Если нет осцилла - мигайте светодиодом раз в секунду. Если светик будет мигать слишком часто или слишком медленно - вы нашли проблему.

Re: Проблема управление сервы с кнопки

HarryStar » 12 фев 2011, 19:55

У меня еще была проблема, сервы начинали самопроизвольно дергаться туда сюда, причем сильно, а по программе должны были удерживать угол.
Оказалось проблема в питании. При питании от 1 источника 16 серв очень нехило просаживали питание в момент перемещения и видимо у МК от скачков напряжения менялось что-то (может быстродействие как то зависит от напряжения, может таймеры, хз) и система входила в колебательный режим. Сервы дергаются на нужный угол, напряжение падает, импульсы сбиваются, сервы уходят на новую точку, и опять.

Вылечилось разделением питания. Теперь у меня электроника питается от маленького акка, а все сервы от силового с большими конденсаторами.

Но на 1-4 сервах эффект был незаметен, так что скорее всего согласен с предыдущим ответчиком.

Re: Проблема управление сервы с кнопки

AVRus » 13 фев 2011, 02:36

В том же прерывании по таймеру сделал мигание светиком 1 секунду, на глаз вполне точная 1 секунда...

Re: Проблема управление сервы с кнопки

dccharacter » 13 фев 2011, 13:13

AVRus писал(а):В том же прерывании по таймеру сделал мигание светиком 1 секунду, на глаз вполне точная 1 секунда...

Проект усушите до минимума кода, и давайте его сюда, посмотрим.

Re: Проблема управление сервы с кнопки

HarryStar » 13 фев 2011, 14:19

Самый простой код для сервы это что то типа следующего:

Код: Выделить всёРазвернуть
while(1)
{
  PORTD = 0xFF;   // Старт импульса
  delay_us(1500); // Длительность импульса. 1500 = центр. Тут можно менять число от 1000 до 2000.
  PORTD = 0x00;   // Стоп импульса

  delay_ms(19);   // Задержка между импульсами
}


Попробуйте такой вариант для начала.

Re: Проблема управление сервы с кнопки

AVRus » 13 фев 2011, 17:07

HarryStar писал(а):Самый простой код для сервы это что то типа следующего:

Код: Выделить всёРазвернуть
while(1)
{
  PORTD = 0xFF;   // Старт импульса
  delay_us(1500); // Длительность импульса. 1500 = центр. Тут можно менять число от 1000 до 2000.
  PORTD = 0x00;   // Стоп импульса

  delay_ms(19);   // Задержка между импульсами
}


Попробуйте такой вариант для начала.

Попробовал в старом проекте закоментировать все что в обработке прерывания стоит, и ставил ваш код в основное тело цикла программы- серва начала вести себя странно...
затем сделал новый проект без таймера - все работает вроде...
Последний раз редактировалось AVRus 13 фев 2011, 17:16, всего редактировалось 1 раз.

Re: Проблема управление сервы с кнопки

Duhas » 13 фев 2011, 17:15

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


cron
Rambler\'s Top100 Mail.ru counter