Например TDA7294

Форум РадиоКот • Просмотр темы - Помогите разобраться с кодом управления 3-мя сервоприводами
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Вс июл 27, 2025 21:29:18

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 2 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Помогите разобраться с кодом управления 3-мя сервоприводами
СообщениеДобавлено: Чт фев 05, 2015 19:36:41 
Первый раз сказал Мяу!
Аватар пользователя

Зарегистрирован: Чт окт 24, 2013 21:16:26
Сообщений: 25
Откуда: Волгоград
Рейтинг сообщения: 0
На одном из сайтов нашел код DI HALT по управлению n -количеством сервоприводов но, перебросив код в CVAR и протестировав в Proteus, получил отрицательный результат. Т.е. запустив эмуляцию, сервоприводы смещаются, но на максимально возможный угол. Если пытаться менять показатель отклонения вала сервопривода на другой угол, то ни чего не выходит. Может где - то я ошибся в коде. Подскажите!

Код:
#include <mega16.h>
#include <delay.h>

#define MaxServo 3      // Число сервомашинок

//============== ПЕРЕМЕННЫЕ ==============
char servo_state;                  // Состояние конечного автомата.
char ServoPortState[MaxServo+1];   // Значение порта которое надо вывести
char ServoNextOCR[MaxServo+1];       // Время вывода значения
char servo_need_update;

 typedef struct
 {
   char Position;
   char Bit;
 }  SArray_def;
 
SArray_def Servo[MaxServo];
SArray_def *Servo_sorted[MaxServo];

//================== ФУНКЦИИ ==============
void Servo_sort(void);
void Servo_upd(void);
void Servo_Init(void);
//Теперь можно писать из прикладной программы любые произвольные значения (26…76 в данном случае) в поле Position, задавая произвольное положение любой из восьми сервомашинок.
//После изменения любого из полей, перед отправкой таблиц в конечный автомат, данные надо упорядочить по длительности. Это делает спец функция.

//Простейший алгоритм сортировки вставкой. Недалеко ушел от пузырька, но на столь малых количествах
// данных являетя наиболее эффективным.
void Servo_sort(void)
{
char i,k;
SArray_def *tmp;
 
// Сортируем массив указателей.
for(i=1;i<MaxServo;i++)
   {
      for(k=i;((k>0)&&(Servo_sorted[k]->Position < Servo_sorted[k-1]->Position));k--)
      {   
         tmp = Servo_sorted[k];                           // Swap [k,k-1]
         Servo_sorted[k]=Servo_sorted[k-1];
         Servo_sorted[k-1]=tmp;
      }
 
   }
}

//Массив отсортирован. Теперь надо его обработать и сформировать таблицы для автомата.
//Обработка заключается в склейке совпадающих полей. Т.е. если у нас есть, например, 5 каналов с длительностью 20,
//то их надо склеить в одно значение таблицы, а биты слепить в единую битмаску.
//А потом загрузить все в массивы конечного автомата.
//Обновление идет в функции Servo_upd

void Servo_upd(void)
{
   char i,j,k;
 
   for(i=0,k=0;i<MaxServo;i++,k++)
  {
   if(Servo_sorted[i]->Position!=Servo_sorted[i+1]->Position)   //Если значения уникальные
   {
      ServoNextOCR[k] = Servo_sorted[i]->Position;            // Записываем их как есть
      ServoPortState[k+1] = Servo_sorted[i]->Bit;            // И битмаску туда же
   }
   else                                               // Но если совпадает со следующим
   {
      ServoNextOCR[k] = Servo_sorted[i]->Position;           // Позицию записываем
      ServoPortState[k+1] = Servo_sorted[i]->Bit;           // Записываем битмаску

    // И в цикле ищем все аналогичные позиции, склеивая их битмаски в одну.

      for(j=1;(Servo_sorted[i]->Position == Servo_sorted[i+j]->Position)&&(i+j<MaxServo);j++)
      {
         ServoPortState[k+1] |= Servo_sorted[i+j]->Bit;
      }
      i+=j-1;                                 // Перед выходом корректируем индекс
   }                                         // На глубину зарывания в повторы
  }   
  ServoNextOCR[k] = 0xFF;                          // В последний элемент вписываем заглушку FF.
}

interrupt [TIM0_COMP] void timer0_comp_isr(void)   //совпадение по прерыванию
{
  if (servo_state)                                // Если не нулевое состояние то
    {
       OCR0 = ServoNextOCR[servo_state];          // В регистр сравнения кладем следующий интервал
       PORTA &= ~ServoPortState[servo_state];     // Сбрасываем биты в порту, в соответствии с маской в массиве масок.
      servo_state++;                          // Увеличиваем состояние автомата
       
     if (OCR0 == 0xFF)                          // Если значение сравнения равно FF значит это заглушка
      {                                      // И мы достигли конца таблицы. И пора обнулить автомат
         servo_state = 0;                       // Выставляем нулевое состояние.
         TCNT0 = 105;                           // Программируем задержку в 20мс (на предделителе 1024)
         TCCR0 = 0x00;                   // Сбрасываем предделитель таймера
         TCCR0 |= 0x05;                         // Устанавливаем предделитель на 1024

      if (servo_need_update)                   // Если поступил приказ обновить таблицы автомата
         {
            Servo_upd();                       // Обновляем таблицы.
            servo_need_update = 0;            // Сбрасываем сигнал обновления.
         }
      } 
   }
     else                                    // Нулевое состояние автомата. Новый цикл
        { 
           OCR0 = ServoNextOCR[servo_state];     // Берем первую выдержку.   
           TCCR0 = 0x00;               // Сбрасываем предделитель
           TCCR0 |= 0x04;                      // Предделитель на 256
           PORTA = 0b00000111;                  // Выставялем все сервоканалы в 1 - начало импульса   4
           servo_state++;                      // Увеличиваем состояние конечного автомата.
        }
}

void Servo_Init(void)
{

Servo_sorted[0] = &Servo[0];
Servo_sorted[1] = &Servo[1];
Servo_sorted[2] = &Servo[2];

Servo[0].Bit = 0b00000001;
Servo[1].Bit = 0b00000010;
Servo[2].Bit = 0b00000100;

Servo[0].Position = 50;
Servo[1].Position = 50;
Servo[2].Position = 50;

}

void main(void)
{
 DDRB &=~(1<<PORTB2);
 PORTB |= (1<<PORTB2);
 PORTA = 0b00000111;
 DDRA = 0b00000111;
 Servo_Init();
 TIMSK |= (1<<OCIE0);   
TCCR0 |= 0x04;    //предделитель 256
#asm("sei")
Servo_sort();
while (1)
      { 

        Servo[0].Position =76;
        Servo_upd();
        servo_need_update = 1;
      }
}

_________________
"Жизнь человека - это короткое мгновение во вселенной, и не стоит её тратить на обиды, оскорбления и выяснение отношений."


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Помогите разобраться с кодом управления 3-мя сервопривод
СообщениеДобавлено: Пт фев 06, 2015 10:56:36 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 235
Зарегистрирован: Пт янв 29, 2010 10:27:40
Сообщений: 3863
Откуда: Москва
Рейтинг сообщения: 0
Код смотреть некогда и лень, но я бы проверил скорость работы контроллера, возможно в настройках симулятора и\или прошивке стоит неверная частота. Нужно подключить на выходы осциллограф и измерить длины импульсов, они должны быть в пределах 1-2мс (смотря какие настройки у сервоприводов). Если есть отличие (более чем в 2 раза), ищите проблему в настройках, если нет, то действительно ошибка в коде.

_________________
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 2 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 15


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y