MAL4X Научно-технический форум разработчиков симуляторов и автоматики


Симуляторы перегрузок. DIY электроника. ЭВМ. Компьютерные сети.
Up

Разработка нового контроллера

Строим реалистичный симулятор перегрузок своими руками. Рекомендации. Советы.

Модераторы: Death_Morozz, null, Ale

Сообщение Ale » 10 апр 2012, 13:36

Хорошо, тогда последний (на сегодня) вопрос - кто нибудь может выложить осциллограммы импульсов, идущих с выходов PWM контроллера? или хотя бы измерить их период. Хоть пойму, какой частотой Танос ШИМ запитывает.

Ну и поскольку я собираюсь начинать кодить, вопрос о предпочтениях? Нужен ли Си кому нибудь? Или лучше как раз на ассемблере? Текст, конечно, менее читаем и более громоздок. Зато демократичен, поскольку AVR-студия распространяется бесплатно.

С другой стороны, как я уже писал, имею вскрытый CodeVision AVR. И могу проект на нем сделать. Даже допускаю, что это получится быстрей.
Аватара пользователя
Ale
Разработчик
 
Сообщения: 1477
Зарегистрирован: 01 фев 2011, 20:48
Откуда: Дубна
Благодарил (а): 570 раз.
Поблагодарили: 595 раз.
Баллы репутации: 277
ТехнарьТехнарьТехнарь

Сообщение AlexVr » 10 апр 2012, 14:40

Ale писал(а):Нужен ли Си кому нибудь?


Я был бы счастлив! Переделать под себя программу на Си и на ассемблере как говорится две большие разницы.
Да и под программу есть заготовки на Си. У Павла по рабочему интерфейсу (надеюсь поделится), у меня по калибровке sima и работе с энкодерами.
Аватара пользователя
AlexVr
SIMER
 
Сообщения: 449
Зарегистрирован: 05 апр 2010, 20:48
Благодарил (а): 23 раз.
Поблагодарили: 32 раз.
Баллы репутации: 71
Технарь

Сообщение null » 10 апр 2012, 15:40

Ale писал(а):Хоть пойму, какой частотой Танос ШИМ запитывает.

Осциллограммы проблема, такого оборудования у нас нет Изображение . А насчет частоты скажу и так. В зависимости от частоты кварца (у таноса несколько прошивок) она от 14 до 24кгц.

И это, даешь студию с тулчейном!!! Изображение
Русский X-Simulator
Изображение
За пределами форума. Мой инстаграмм.
Аватара пользователя
null
SIMER
 
Сообщения: 1041
Зарегистрирован: 03 мар 2010, 18:42
Откуда: Ростов-на-Дону
Благодарил (а): 219 раз.
Поблагодарили: 160 раз.
Баллы репутации: 138
ТехнарьТехнарь

Сообщение AlexVr » 10 апр 2012, 15:40

Ale писал(а):Хоть пойму, какой частотой Танос ШИМ запитывает.


ШИМ или как взорвать MOSFET http://arduino.ru/forum/obsh...k-vzorvat-mosfet
Аватара пользователя
AlexVr
SIMER
 
Сообщения: 449
Зарегистрирован: 05 апр 2010, 20:48
Благодарил (а): 23 раз.
Поблагодарили: 32 раз.
Баллы репутации: 71
Технарь

Сообщение FELiS » 10 апр 2012, 16:36

null писал(а): она от 14 до 24кгц.

На 14кгц слышно писк должно быть, телек кинескопный 16 кгц дает в строчной развертке, их слышно.
По поводу формы импульса скажу что там прямоугольники с меняющейся скважностью.
Изображение
Аватара пользователя
FELiS
Добрый Фелис
 
Сообщения: 532
Зарегистрирован: 11 янв 2007, 23:21
Благодарил (а): 27 раз.
Поблагодарили: 123 раз.
Баллы репутации: 156
ТехнарьТехнарь

Сообщение null » 10 апр 2012, 16:51

FELiS
У меня 22кгц - не слышно. Ты где такую картинку взял? Изображение
Русский X-Simulator
Изображение
За пределами форума. Мой инстаграмм.
Аватара пользователя
null
SIMER
 
Сообщения: 1041
Зарегистрирован: 03 мар 2010, 18:42
Откуда: Ростов-на-Дону
Благодарил (а): 219 раз.
Поблагодарили: 160 раз.
Баллы репутации: 138
ТехнарьТехнарь

Сообщение FELiS » 10 апр 2012, 18:03

вики статья про скважность
Аватара пользователя
FELiS
Добрый Фелис
 
Сообщения: 532
Зарегистрирован: 11 янв 2007, 23:21
Благодарил (а): 27 раз.
Поблагодарили: 123 раз.
Баллы репутации: 156
ТехнарьТехнарь

Сообщение Ale » 10 апр 2012, 18:32

Господа хорошие, спасибо, конечно. Но меня интересовала только частота Изображение .
Про форму и скважность я как бы знаю...
Аватара пользователя
Ale
Разработчик
 
Сообщения: 1477
Зарегистрирован: 01 фев 2011, 20:48
Откуда: Дубна
Благодарил (а): 570 раз.
Поблагодарили: 595 раз.
Баллы репутации: 277
ТехнарьТехнарьТехнарь

Сообщение null » 10 апр 2012, 19:11

Изображение Изображение Изображение
Русский X-Simulator
Изображение
За пределами форума. Мой инстаграмм.
Аватара пользователя
null
SIMER
 
Сообщения: 1041
Зарегистрирован: 03 мар 2010, 18:42
Откуда: Ростов-на-Дону
Благодарил (а): 219 раз.
Поблагодарили: 160 раз.
Баллы репутации: 138
ТехнарьТехнарь

Сообщение Pavel155 » 11 апр 2012, 08:07

Подскажите как сделать лучше.
в программе используются 3 прерывания:
1. Обработка 1 энкодера и вывод числа импульсов для основной программы. Число импульсов от 0 до 5000;
2. Обработка 2 энкодера и вывод числа импульсов для основной программы;
3. Прием данных по UART 16bit, от 0 до 1024.

и основная программа,
где вычисляется ПИД и вывод его ввиде управления для ШИМ от 0 до 1023.

Встала вот такая задача. Как перевести число импульсов в диапазон от 0 до 1024 ?
И где его лучше обработать, в цикле прерывания или основном цикле ?

На текущий момент это делается в основной программе, через деление на 5.

p.s. формула ПИД: PWM=Kp*(Usart - encoder)
Иногда пропадаю. Пишите в личку.
Аватара пользователя
Pavel155
SIMER
 
Сообщения: 172
Зарегистрирован: 06 июл 2011, 10:39
Откуда: Саратов
Благодарил (а): 0 раз.
Поблагодарили: 4 раз.
Баллы репутации: 20
Новичок

Сообщение Ale » 11 апр 2012, 09:29

Подскажите как сделать лучше


Я бы завел еще одно прерывание, по таймеру, в котором устанавливал флаг срабатывания таймера. И уже в основном цикле программы проверял этот флаг и регулирование бы делал только по флагу от таймера. Тогда регулирование пойдет через относительно равные промежутки времени, скажем, с частотой 1 КГц.

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


char TimerFlag;
int encod1, tmp_encod1;

interrupt [EXT_INT0] void ext_int0_isr(void)
{
// тут проводим считывание с энкодера и вычисление нового значения в переменную encod1

}


interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TimerFlag=1; // устанавливаем флаг и вываливаемся из перывания
}

void main(void)
{

if (TimerFlag>0)
{
TimerFlag=0; // сбрасываем флаг
cli(); // запрещаем прерывания
tmp_encod1 = encod1 // копируем данные энкодера для дальнейшего безопасного использования
sei(); // разрешаем перывания

// и дальше вычисляем все что надо для ПИД (делим, к примеру, на 5 величину tmp_encod1) и проводим регулирование

}

}

(Добавление)
естественно в процедуре main все делается внутри бесконечного цикла

void main(void)
{

while (1)
{
if (TimerFlag>0)
{

....
Аватара пользователя
Ale
Разработчик
 
Сообщения: 1477
Зарегистрирован: 01 фев 2011, 20:48
Откуда: Дубна
Благодарил (а): 570 раз.
Поблагодарили: 595 раз.
Баллы репутации: 277
ТехнарьТехнарьТехнарь

Сообщение Pavel155 » 11 апр 2012, 09:42

вот пока что я реализовал CVAVR
функцию вывода на LCD реализовал для наблюдения. После я это удалю.
Код: Выделить всё
  /*****************************************************  This program was produced by the  CodeWizardAVR V2.05.0 Professional  Automatic Program Generator  © Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.  http://hpinfotech.com    Project :  
Version :  
Date    : 10.04.2012  Author  :  
Company :  
Comments:      
Chip type               : ATmega8535  Program type            : Application  AVR Core Clock frequency: 18,432000 MHz  Memory model            : Small  External RAM size       : 0  Data Stack size         : 128  *****************************************************/    #include <mega8535.h>  #include <alcd.h>  #include <delay.h>    // переменные  //LCD  unsigned char buffer [64];  //Энкодер  
unsigned int enc_1 = 0; // число оборотов  на старте   оси 1  unsigned int enc_2 = 0;   // число оборотов  на старте оси 2  unsigned int max = 5120;   // максимальное число импульсов энкодера  //Uart  
union {       unsigned char all[2];             //буфер для приема данных с ПК      unsigned int bite;                          }un1;  //ШИМ  
unsigned int pwm_1 = 0;  unsigned int pwm_2 = 0;  //ПИД  unsigned int error = 0;  //unsigned char enc_err;  unsigned char kp = 3;  unsigned int pwm_er;        // External Interrupt 0 service routine  interrupt [EXT_INT0] void ext_int0_isr(void)  {  if (!PIND.2^!PIND.6)                      //условие для срабатывания подсчета импульсов с энкодера D2,D6             {  enc_1++;                    //увеличиваем              if (!PINA.1|enc_1 > max) {    //колибровка и верхний предел импульсов                  enc_1 = max;               }               }                else  {  enc_1--;          //уменьшаем                if (!PINA.0|enc_1 < 1)     //колибровка и нижний предел импульсов                 {                   enc_1 = 1;                  }                };               }    // External Interrupt 1 service routine  interrupt [EXT_INT1] void ext_int1_isr(void)  {  if (!PIND.3^!PIND.7)                      //условие для срабатывания подсчета импульсов с энкодера порт D3,D7             {  enc_1++;                    //увеличиваем              if (!PINA.1|enc_1 > max)               {    //колибровка и верхний предел импульсов                  enc_1 = max;               }               }                else  {  enc_1--;          //уменьшаем                if (!PINA.0|enc_1 < 1)     //колибровка и нижний предел импульсов                 {                   enc_1 = 1;                  }                };               }                  #ifndef RXB8  #define RXB8 1  #endif    #ifndef TXB8  #define TXB8 0  #endif    #ifndef UPE  #define UPE 2  #endif    #ifndef DOR  #define DOR 3  #endif    #ifndef FE  #define FE 4  #endif    #ifndef UDRE  #define UDRE 5  #endif    #ifndef RXC  #define RXC 7  #endif    #define FRAMING_ERROR (1<<FE)  #define PARITY_ERROR (1<<UPE)  #define DATA_OVERRUN (1<<DOR)  #define DATA_REGISTER_EMPTY (1<<UDRE)  #define RX_COMPLETE (1<<RXC)    // USART Receiver buffer  #define RX_BUFFER_SIZE 100  char rx_buffer[RX_BUFFER_SIZE];    #if RX_BUFFER_SIZE <= 256  unsigned char rx_wr_index,rx_rd_index,rx_counter;  #else  unsigned int rx_wr_index,rx_rd_index,rx_counter;  #endif    // This flag is set on USART Receiver buffer overflow  bit rx_buffer_overflow;    // USART Receiver interrupt service routine  interrupt [USART_RXC] void usart_rx_isr(void)  {  char status,data;  status=UCSRA;  data=UDR;  if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)     {     rx_buffer[rx_wr_index++]=data;  #if RX_BUFFER_SIZE == 256     // special case for receiver buffer size=256     if (++rx_counter == 0)        {  #else     if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;     if (++rx_counter == RX_BUFFER_SIZE)        {        rx_counter=0;  #endif        rx_buffer_overflow=1;        }     }  }    #ifndef _DEBUG_TERMINAL_IO_  // Get a character from the USART Receiver buffer  #define _ALTERNATE_GETCHAR_  #pragma used+  char getchar(void)  {  char data;  while (rx_counter==0);  data=rx_buffer[rx_rd_index++];  #if RX_BUFFER_SIZE != 256  if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;  #endif  #asm(\"cli\")  --rx_counter;  #asm(\"sei\")  return data;  }  #pragma used-  #endif      #include <stdio.h>      void main(void)  {  //настройка порта А  (4 входа и 4 выхода)  PORTA=0x0F;  DDRA=0xF0;    //настройка порта D  PORTD=0xCC;  DDRD=0x30;      // Timer/Counter 1 initialization  // Clock source: System Clock  // Clock value: 18432,000 kHz  // Mode: Fast PWM top=0x03FF  // OC1A output: Non-Inv.  // OC1B output: Non-Inv.  // Noise Canceler: Off  // Input Capture on Falling Edge  // Timer1 Overflow Interrupt: Off  // Input Capture Interrupt: Off  // Compare A Match Interrupt: Off  // Compare B Match Interrupt: Off  TCCR1A=0xA3;  TCCR1B=0x09;  TCNT1H=0x00;  TCNT1L=0x00;  ICR1H=0x00;  ICR1L=0x00;  OCR1AH=0x00;  OCR1AL=0x00;  OCR1BH=0x00;  OCR1BL=0x00;      // External Interrupt(s) initialization  // INT0: On  // INT0 Mode: Any change  // INT1: On  // INT1 Mode: Any change  // INT2: Off  GICR|=0xC0;  MCUCR=0x05;  MCUCSR=0x00;  GIFR=0xC0;    // USART initialization  UCSRA=0x00;  UCSRB=0x98;  UCSRC=0x86;  UBRRH=0x00;  UBRRL=0x09;      lcd_init(16);      lcd_clear();      lcd_gotoxy(0,0);      lcd_putsf(\"Pavel155 test 1\");      lcd_gotoxy(0,1);      lcd_putsf(\"Start 2dof...\");      delay_ms(10);      lcd_clear();                    #asm(\"sei\")                 while (getchar()== 0x41&getchar()== 0x42)//в этот цикл          {  // мы попадем ТОЛЬКО когда в буфере            // окажется принятый байт 255 - это 0xFF                          getchar();       //ловим байт 0хFF  (255)           //////////////////////////////////////////////////          //управление 1 осью           //////////////////////////////////////////////////                un1.all[1]=getchar();    //ловим  1 байт  оси 1                 un1.all[0]=getchar();   //ловим  2 байт  оси 1                                    //вычисляем ошибку               // enc_err=  enc_1/5;                error = (un1.bite - (enc_1 / 5)) ;                pwm_er = kp*error;                        pwm_1= pwm_er;                                   sprintf(buffer, \"%3d\",error);         //отправляем в буфер данные позиции оси 1                 lcd_gotoxy(10,0);                 lcd_putsf(\"    \");      //очищаем строку                  lcd_gotoxy(10,0);                 lcd_puts(buffer);       //вывод на LCD                                                //ШИМ для 1 оси                 // pwm_1 - это число от 0 до 1023                 // PWM(PD5) = OCR1A / 10.23  (%)                  OCR1AH = (int)(pwm_1>>8);                 OCR1AL = (int)pwm_1;                 //Выводим на дисплей                 sprintf(buffer, \"%3d\",pwm_1);        //отправляем в буфер данные позиции оси 1                 lcd_gotoxy(5,0);                 lcd_putsf(\"    \");                     //очищаем строку                 lcd_gotoxy(5,0);                                    lcd_puts(buffer);                    //вывод на LCD                      //Выводим показание энкодера 1                 sprintf(buffer, \"%3d\",enc_1);        //отправляем в буфер данные позиции оси 1                 lcd_gotoxy(0,0);                 lcd_putsf(\"    \");                   //очищаем строку                 lcd_gotoxy(0,0);                 lcd_puts(buffer);                    //вывод на LCD                          //////////////////////////////////////////////////          //управление 2 осью           //////////////////////////////////////////////////                   un1.all[1]=getchar();    //ловим  1 байт  оси 2                 un1.all[0]=getchar();    //ловим  2 байт  оси 2                    pwm_2=un1.bite;                                      //ШИМ для 2 оси                  OCR1BH = (int)(pwm_2>>8);                 OCR1BL = (int)pwm_2;                 //Выводим на дисплей                 sprintf(buffer, \"%3d\",pwm_2);         //отправляем в буфер данные позиции оси 1                 lcd_gotoxy(5,1);                 lcd_putsf(\"    \");                   //очищаем строку                 lcd_gotoxy(5,1);                 lcd_puts(buffer);                    //вывод на LCD                                            //Выводим показание энкодера 2                sprintf(buffer, \"%3d\",enc_2);         //отправляем в буфер данные позиции оси 1                lcd_gotoxy(0,1);                lcd_putsf(\"    \");                    //очищаем строку                 lcd_gotoxy(0,1);                lcd_puts(buffer);                     //вывод на LCD          }  }  


p.s. Сильно не пинайте, что не придерживаюсь плана ).

Тема закрыта! Продолжение в теме "Разработка нового контроллера - 2".
Иногда пропадаю. Пишите в личку.
Аватара пользователя
Pavel155
SIMER
 
Сообщения: 172
Зарегистрирован: 06 июл 2011, 10:39
Откуда: Саратов
Благодарил (а): 0 раз.
Поблагодарили: 4 раз.
Баллы репутации: 20
Новичок

Пред.

Вернуться в X-SIMULATOR и RU-SIMULATOR & SimTools

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

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

cron
x

#{title}

#{text}