реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> MC3PHAC+AVR, установка связи AVR c MC3PHAC поUART
a-6539x
сообщение Jan 30 2011, 09:38
Сообщение #1





Группа: Новичок
Сообщений: 9
Регистрация: 20-10-10
Пользователь №: 60 297





Выкладываю драйвер для связи MC3PHAC и AVR



//***************************************************

// Драйвер управления MC3PHAC по UART *

// V1.0 30.01.2011 *

//***************************************************

//CodeVisionAVR V 2.03.4 Standart






//********************** UART ************************

#define RXB8 1

#define TXB8 0

#define UPE 2

#define OVR 3

#define FE 4

#define UDRE 5

#define RXC 7

#define FRAMING_ERROR (1<<FE)

#define PARITY_ERROR (1<<UPE)

#define DATA_OVERRUN (1<<OVR)

#define DATA_REGISTER_EMPTY (1<<UDRE)

#define RX_COMPLETE (1<<RXC)

#define RX_BUFFER_SIZE 64

#define TX_BUFFER_SIZE 64

char rx_buffer[RX_BUFFER_SIZE];

char tx_buffer[TX_BUFFER_SIZE];

unsigned char tx_wr_index,tx_rd_index,tx_counter=0;

unsigned char rx_wr_index=0,rx_rd_index,rx_counter=0;

bit rx_buffer_overflow;

// инициализация UART

void USART_init(){

UCSRA=0x00;

UCSRB=0xD8;

UCSRC=0x86;

UBRRH=0x00;

UBRRL=0x19;

}

// 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_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;

if (++rx_counter == RX_BUFFER_SIZE)

{

rx_counter=0;

rx_buffer_overflow=1;

};

};

}

// USART Transmitter interrupt service routine

interrupt [USART_TXC] void usart_tx_isr(void){

if (tx_counter)

{

--tx_counter;

UDR=tx_buffer[tx_rd_index];

if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;

};

}

// загрузить байт в буфер для последующей передачи

char getbyte(void){

char data;

while (rx_counter==0){}

data=rx_buffer[rx_rd_index];

if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;

#asm("cli")

--rx_counter;

#asm("sei")

return data;

}

// выгрузить из буфера байт

void putbyte(unsigned char c){

while (tx_counter == TX_BUFFER_SIZE);

#asm("cli")

if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))

{

tx_buffer[tx_wr_index]=c;

if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;

++tx_counter;

}

else {UDR=c;}

#asm("sei")

}

//****************************************************









//**** Команды управления контроллером MC3PHAC ********

// 3.5В(зн.АЦП=717) на выводе DC_bus принято за 100% (310В) напряжения питания инвертора

unsigned char const cmd_RESET[5] = {0xE3, 0x10, 0x00, 0x30, 0x00};

unsigned char const cmd_PPWM[5] = {0xE3, 0x10, 0x00, 0x50, 0x00};

unsigned char const cmd_DEADT[5] = {0xE3, 0x00, 0x36, 0x24, 0x00}; // 4.5 мкс мертвое время

unsigned char const cmd_ACB[5] = {0xE3, 0x10, 0x00, 0x61, 0x00}; // 50 Гц базовая частота

unsigned char const cmd_ACC[5] = {0xE4, 0x00, 0x60, 0x05, 0x00}; // 5 Гц/c ускорение

unsigned char const cmd_F[5] = {0xE4, 0x00, 0x62, 0x06, 0x80}; // 6.5 Гц задание синусоидальной частоты

unsigned char const cmd_FPWM[5] = {0xE3, 0x10, 0x00, 0x42, 0x00}; //10.6 кГц частота ШИМ

unsigned char const cmd_VBOOST[5] = {0xE3, 0x00, 0x6C, 0x00, 0x00}; // 0 % амплитуда синуса при нулевой синусоидальной частоте

unsigned char const cmd_MODIN[5] = {0xE3, 0x00, 0x75, 0xFE, 0x00}; // 99 % индекс модуляции синуса (амплитуда)

unsigned char const cmd_FTOUT[5] = {0xE4, 0x00, 0x6A, 0x00, 0x05}; // 1.3 c таймаут после аварии

unsigned char const cmd_VBDEC[5] = {0xE4, 0x00, 0xC9, 0x03, 0x55}; // 119 % значение Vbus при котором начинается снижение скорости торможения

unsigned char const cmd_VBRAKE[5] = {0xE4, 0x00, 0x64, 0x03, 0x55}; // 119 % значение Vbus при котором появляется сигнал вкл. тормозного VT

unsigned char const cmd_VBROWN[5] = {0xE4, 0x00, 0x66, 0x01, 0xF6}; // 71 % нижнее значение Vbus при откл. ШИМ и появляется сигнал аварии

unsigned char const cmd_VBOVR[5] = {0xE4, 0x00, 0x68, 0x03, 0x71}; // 123 % верхнее значение Vbus при откл. ШИМ и появляется сигнал аварии

unsigned char const cmd_FORW[5] = {0xE3, 0x10, 0x00, 0x10, 0x00}; // "вперед"

unsigned char const cmd_REW[5] = {0xE3, 0x10, 0x00, 0x11, 0x00}; // "назад"

unsigned char const cmd_STOP[5] = {0xE3, 0x10, 0x00, 0x20, 0x00}; // "стоп"

unsigned char const read_ACTF[3] = {0xD1, 0x00, 0x85}; // прочитать текущюю синусоидальную частоту

unsigned char const read_SETUP[3] = {0xD0, 0x00, 0xAE}; // прочитать регистр установок

unsigned char const read_VBUS[3] = {0xD1, 0x00, 0x79}; // прочитать напряжение питания инвертора (DC_bus)

unsigned char const read_F[3] = {0xD1, 0x00, 0x62}; // прочитать задание на синусоидальную частоту

unsigned char const read_STATUS[3] = {0xD0, 0x00, 0xC8}; // прочитать регистр статуса

//******************************************************





//***************** Процедуры **************************

// посылка команды

void MC3PHAC_Send(flash unsigned char *msg,unsigned char len){

unsigned char CRC=0;

putbyte(0x2B);

while(len>0){

if(*msg==0x2B){putbyte(0x2B);} // повторить байт

putbyte(*msg);

CRC+=*msg;

*msg++;

len--;

}

putbyte((unsigned char)(~CRC+1));

delay_ms(40);

}

// прием ответа типа Word (формат ответа: 2B_00_Hi_Lo_CRC)

unsigned int RxWord(){

unsigned char CRC,Lo,Hi;

unsigned int data=0;

getbyte(); //2B

CRC=getbyte(); //00

Hi=getbyte();CRC+=Hi; //Hi

if(Hi==0x2B){getbyte();}//пропустить байт подтверждения

Lo=getbyte();CRC+=Lo; //Lo

if(Lo==0x2B){getbyte();}//пропустить байт подтверждения

data=Hi;

data<<=8;

data+=Lo;

while((~CRC+1)!=getbyte()){} //CRC

return data;

}

// прием ответа типа Byte (формат ответа: 2B_00_Lo_CRC)

unsigned char RxByte(){

unsigned char CRC,Lo;

getbyte(); //2B

CRC=getbyte(); //00

Lo=getbyte();CRC+=Lo; //Lo

while((~CRC+1)!=getbyte()){} //CRC

return Lo;

}

// Прием ответа на команду (формат ответа: 2B_Lo_CRC)

unsigned char Response(){

unsigned char CRC,Lo;

getbyte(); //2B

Lo=getbyte(); //Lo

CRC=Lo;

while((~CRC+1)!=getbyte()){} //CRC

return Lo;

}

// идентификация MC3PHAC

void MC3PHAC_Identification(){

unsigned char i,j;

unsigned char Test_Link1[3] = {0x2B,0xC0, 0x40};

for (j=0; j<3;j++){

for (i=0;i<3;i++){

putbyte(Test_Link1[i]);

}

while(Response()!=0x81){}

}

}

// иницилизация MC3PHAC

void MC3PHAC_Init(){

MC3PHAC_Send(cmd_RESET, sizeof(cmd_RESET));

delay_ms(100);

MC3PHAC_Send(cmd_DEADT, sizeof(cmd_DEADT));

Response();

MC3PHAC_Send(cmd_PPWM, sizeof(cmd_PPWM));

Response();

MC3PHAC_Send(cmd_ACB, sizeof(cmd_ACB));

Response();

MC3PHAC_Send(cmd_ACC, sizeof(cmd_ACC));

Response();

MC3PHAC_Send(cmd_FPWM, sizeof(cmd_FPWM));

Response();

MC3PHAC_Send(cmd_F, sizeof(cmd_F));

Response();

MC3PHAC_Send(cmd_VBOOST, sizeof(cmd_FPWM));

while(Response()!=0x00){}

MC3PHAC_Send(cmd_MODIN, sizeof(cmd_MODIN));

while(Response()!=0x00){}

MC3PHAC_Send(cmd_FTOUT, sizeof(cmd_FTOUT));

while(Response()!=0x00){}

MC3PHAC_Send(cmd_VBDEC, sizeof(cmd_VBDEC));

while(Response()!=0x00){}

MC3PHAC_Send(cmd_VBRAKE, sizeof(cmd_VBRAKE));

while(Response()!=0x00){}

MC3PHAC_Send(cmd_VBROWN, sizeof(cmd_VBROWN));

while(Response()!=0x00){}

MC3PHAC_Send(cmd_VBOVR, sizeof(cmd_VBOVR));

while(Response()!=0x00){}

}

//******************************************************













Пример основной программы в которую подгружается драйвер

примечание : при отсутствии связи (ошибке ответа) прога заходит в бесконечный цикл while(1){}

#include <mega16.h>


#include <delay.h>
#include <stdio.h>

//************** Глобальные переменные *************

unsigned int period,timer;
unsigned int f;
unsigned int zad_f;
unsigned int voltage_bus;
bit PUSK=0;
unsigned char status;
//**************************************************

#include "driver_mc3phac.h"

void init(){
PORTC=0b00000000;
DDRC= 0b11111111;
PORTD=0b00001000;
DDRD= 0b10001000;
PORTA=0b00111100;
DDRA= 0b11111100;
PORTB=0b00000000;
DDRB= 0b00000000;
// и т.д и т.п.
}

void main(void){
init();
USART_init();
#asm("sei")
delay_ms(1000);
MC3PHAC_Identification();
MC3PHAC_Init();
MC3PHAC_Send(read_SETUP,sizeof(read_SETUP));
while(RxByte()!=0xFF){} // проверка готовности перед включением ШИМ

while (1){
MC3PHAC_Send(cmd_FORW,sizeof(cmd_FORW)); // включение двигателя вперед
Response();


MC3PHAC_Send(read_ACTF,sizeof(read_ACTF)); // пример чтения текущей синусоидальной частоты
f=RxWord();


}


}
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 30 2011, 15:09
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Сделайте в своем сообщении так: весь код заключите в codebox \codebox - теги в квадратных скобках.
Go to the top of the page
 
+Quote Post
a-6539x
сообщение Jan 30 2011, 19:48
Сообщение #3





Группа: Новичок
Сообщений: 9
Регистрация: 20-10-10
Пользователь №: 60 297



Цитата(_Pasha @ Jan 30 2011, 18:09) *
Сделайте в своем сообщении так: весь код заключите в codebox \codebox - теги в квадратных скобках.
хотелось бы но редактировать неполучается
Go to the top of the page
 
+Quote Post
Chip115
сообщение Feb 26 2011, 15:01
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 43
Регистрация: 28-12-07
Пользователь №: 33 709



Доброго времени суток!
В данный момент пишу софт для контроллера C8051F410 который будет управлять таким же контроллером. Есть некоторые вопросы относительно управления MC3PHAC. Не могли бы Вы мне помочь разобраться так как чтение документации не дает всех ответов для меня .
В общем случае мне надо реализовать функцию,выполняющею следующие действия : запуск на n секунд - остановка - реверс - запуск на n секунд... . и т.д.
Для второго двигателя должны ввести скорость вращения ротора, а затем гонять туда - сюда. т.е запуск - стоп-реверс-запуск...
Так вопросы следующие: Функция инициализации MC3PHAC должна быть такая же как и у Вас? И что значит ускорение? он будет постепенно разгоняться с определенной dw/dt или сразу после старта он выйдет на нужную скорость?
Go to the top of the page
 
+Quote Post
a-6539x
сообщение Feb 27 2011, 20:31
Сообщение #5





Группа: Новичок
Сообщений: 9
Регистрация: 20-10-10
Пользователь №: 60 297



Цитата(Chip115 @ Feb 26 2011, 18:01) *
Доброго времени суток!
В данный момент пишу софт для контроллера C8051F410 который будет управлять таким же контроллером. Есть некоторые вопросы относительно управления MC3PHAC. Не могли бы Вы мне помочь разобраться так как чтение документации не дает всех ответов для меня .
В общем случае мне надо реализовать функцию,выполняющею следующие действия : запуск на n секунд - остановка - реверс - запуск на n секунд... . и т.д.
Для второго двигателя должны ввести скорость вращения ротора, а затем гонять туда - сюда. т.е запуск - стоп-реверс-запуск...
Так вопросы следующие: Функция инициализации MC3PHAC должна быть такая же как и у Вас? И что значит ускорение? он будет постепенно разгоняться с определенной dw/dt или сразу после старта он выйдет на нужную скорость?

инициализация должна быть такая же единственное - не обязательно выполнять идентификацию (ее я делаю для тестирования связи с MC3PHAC - можно исключить или наоборот сделать несколько раз) еще задержки могут быть другие это не так кретично, может быть другая последовательность инициализации, но самое главное в конце установки всех параметров (при инициализации) проверить регистр setup -все биты в нем должны быть установленны иначе потом пуск не пройдет.

Разгоняться двигатель будет с заданным ускарением (минимальное вроде 0,5Гц /c) c нуля. при сигнале аварии мгновенно отключается ШИМ, отчитывается таймаут и автоматически начинается перезапуск (опять же с нуля и тем же ускорением). При остановке все происходит аналогично но в обратной последовательности. скорость разгона - константа. Ниже выложу ссылку на видео там видно как наростает частота (по лампочке и индикатору

)

обновленный драйвер (исправленный и дополненный)


CODE


//***************************************************
// Драйвер управления MC3PHAC по UART *
// V2.0 15.02.2011 *
//***************************************************

// CodeVisionAVR V 2.03.4 Standart

// Драйвер использует следующие аппартные
// средства контроллера: UART; Timer2
// при инициализации драйвера включается глоб. прерывание
// тактовая частота контроллера 4 MHz

//********************** UART ************************


#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
#define RX_BUFFER_SIZE 64
#define TX_BUFFER_SIZE 64
unsigned char Copy_Buffer[10],h=0;
char rx_buffer[RX_BUFFER_SIZE];
char tx_buffer[TX_BUFFER_SIZE];
unsigned char tx_wr_index,tx_rd_index,tx_counter=0;
unsigned char rx_wr_index=0,rx_rd_index,rx_counter=0;
bit rx_buffer_overflow;


// инициализация UART
void driver_init(){
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;

// Clock source: System Clock
// Clock value: 31,250 kHz
// Mode: CTC top=OCR2
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0xF0; // величина таймаута при ожидании ответа (шаг = 256 мкс)
TIMSK|=0x80; // включение прерывания по таймауту (таймер 2)

#asm("sei") // глобальное включение прерывания

}

// 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_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
}
}
}

/*
коды ошибок
301 - таймаут UART превышен
302 - ошибка CRC
303 - потеряно начало сообщения
*/

Error_UART(unsigned char N){ // аварии по интерфейсу можно исключить для упрощ.
while(!BUT){
IntToDec(300+N); // я например вывожу на индикатор }
delay_ms(500);
}

// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void){
if (tx_counter)
{
--tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
}
}
// прерываниие по истечению таймаута (нет ответа от MC3PHAC)
interrupt [TIM2_COMP] void timer2_comp_isr(void)
{TCCR2=0x00;} // остановили таймаут


// выгрузить из буфера байт
char getbyte(void){
char data;
TCNT2=0x00;
if (rx_counter==0){ // нет ответа
TCCR2=0x0F; //вкл таймаут ожидания
while(TCCR2==0x0F){ // начинаем ждать
HL_REW=1;
delay_ms(50);
HL_REW=0;
delay_ms(50);
if(rx_counter>0){goto next;}
}
Error_UART(1);
HL_FWR=1; // превышен таймаут
delay_ms(200);
HL_FWR=0;
delay_ms(200);
return 0x00; // выйти из таймаута
}
next:
HL_REW=0;
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
// загрузить байт в буфер для последующей передачи
void putbyte(unsigned char c){
while (tx_counter == TX_BUFFER_SIZE){}
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else {UDR=c;}
#asm("sei")
}




//**** Команды управления контроллером MC3PHAC ********
// 3.5В(зн.АЦП=717) на выводе DC_bus принято за 100% (310В) напряжения питания инвертора
unsigned char const cmd_RESET[5] = {0xE3, 0x10, 0x00, 0x30, 0x00};
unsigned char const cmd_PPWM[5] = {0xE3, 0x10, 0x00, 0x50, 0x00};
unsigned char const cmd_DEADT[5] = {0xE3, 0x00, 0x36, 0x24, 0x00}; // 4.5 мкс мертвое время 24
unsigned char const cmd_ACB[5] = {0xE3, 0x10, 0x00, 0x61, 0x00}; // 50 Гц базовая частота
unsigned char const cmd_ACC[5] = {0xE4, 0x00, 0x60, 0x05, 0x00}; // ускорение
unsigned char const cmd_F[5] = {0xE4, 0x00, 0x62, 0x3C, 0x99}; // задание синусоидальной частоты
unsigned char const cmd_FPWM[5] = {0xE3, 0x10, 0x00, 0x42, 0x00}; //10.6 кГц частота ШИМ
unsigned char const cmd_VBOOST[5] = {0xE3, 0x00, 0x6C, 0x00, 0x00}; // 0 % амплитуда синуса при нулевой синусоидальной частоте
unsigned char const cmd_MODIN[5] = {0xE3, 0x00, 0x75, 0xFE, 0x00}; // 99 % индекс модуляции синуса (амплитуда)
unsigned char const cmd_FTOUT[5] = {0xE4, 0x00, 0x6A, 0x00, 0x08}; // таймаут после аварии
unsigned char const cmd_VBDEC[5] = {0xE4, 0x00, 0xC9, 0x03, 0x55}; // 119 % значение Vbus при котором начинается снижение скорости торможения
unsigned char const cmd_VBRAKE[5] = {0xE4, 0x00, 0x64, 0x03, 0x55}; // 119 % значение Vbus при котором появляется сигнал вкл. тормозного VT
unsigned char const cmd_VBROWN[5] = {0xE4, 0x00, 0x66, 0x80, 0x00}; // 50 % нижнее значение Vbus при откл. ШИМ и появляется сигнал аварии
unsigned char const cmd_VBOVR[5] = {0xE4, 0x00, 0x68, 0x03, 0x71}; // 123 % верхнее значение Vbus при откл. ШИМ и появляется сигнал аварии
unsigned char const cmd_FORW[5] = {0xE3, 0x10, 0x00, 0x10, 0x00}; // "вперед"
unsigned char const cmd_REW[5] = {0xE3, 0x10, 0x00, 0x11, 0x00}; // "назад"
unsigned char const cmd_STOP[5] = {0xE3, 0x10, 0x00, 0x20, 0x00}; // "стоп"
unsigned char const read_ACTF[3] = {0xD1, 0x00, 0x85}; // прочитать текущюю синусоидальную частоту
unsigned char const read_SETUP[3] = {0xD0, 0x00, 0xAE}; // прочитать регистр установок
unsigned char const read_VBUS[3] = {0xD1, 0x00, 0x79}; // прочитать напряжение питания инвертора (DC_bus)
unsigned char const read_F[3] = {0xD1, 0x00, 0x62}; // прочитать задание на синусоидальную частоту
unsigned char const read_STATUS[3] = {0xD0, 0x00, 0xC8}; // прочитать регистр статуса
//******************************************************


//***************** Процедуры **************************


// посылка команды (любой)
void MC3PHAC_Send(flash unsigned char *msg,unsigned char len){
unsigned char CRC=0;

putbyte(0x2B);
while(len>0){
if(*msg==0x2B){putbyte(0x2B);} // повторить байт
putbyte(*msg);
CRC+=*msg;
*msg++;
len--;
}
CRC=~CRC+1;
putbyte(CRC);
if(CRC==0x2B){putbyte(CRC);}
//delay_ms(40); // не трогать
}
// посылка команды на задание синусоидальной частоты
void MC3PHAC_Send_F(unsigned char Hz,unsigned char Hz_Lo){
unsigned char CRC=0;
putbyte(0x2B);
putbyte(0xE4);
putbyte(0x00);
putbyte(0x62);
CRC=0x46;
putbyte(Hz);CRC+=Hz;
if(Hz==0x2B){putbyte(0x2B);} // повторить байт
putbyte(Hz_Lo);CRC+=Hz_Lo;
if(Hz_Lo==0x2B){putbyte(0x2B);} // повторить байт
putbyte((unsigned char)(~CRC+1));
}
// прием ответа типа Word (формат ответа: 2B_00_Hi_Lo_CRC)
unsigned int RxWord(){
unsigned char CRC,Lo,Hi;
unsigned int data=0;
if(getbyte()!=0x2B){Error_UART(3);}; //2B
CRC=getbyte(); //00
Hi=getbyte();CRC+=Hi; //Hi
if(Hi==0x2B){getbyte();} //пропустить байт подтверждения
Lo=getbyte();CRC+=Lo; //Lo
if(Lo==0x2B){getbyte();} //пропустить байт подтверждения
data=Hi;
data<<=8;
data+=Lo;
Lo=getbyte();
if(Lo==0x2B){getbyte();} //пропустить байт подтверждения
if((~CRC+1)!=Lo){Error_UART(2);} //проверка CRC
return data;
}
// прием ответа типа Byte (формат ответа: 2B_00_Lo_CRC)
unsigned char RxByte(){
unsigned char CRC,Lo;
getbyte(); //2B
CRC=getbyte(); //00
Lo=getbyte();CRC+=Lo; //Lo
if((~CRC+1)!=getbyte()){Error_UART(2);} //проверка CRC
return Lo;
}
// Прием ответа на команду (формат ответа: 2B_Lo_CRC)
unsigned char Response(){
unsigned char CRC,Lo;
getbyte(); //2B
Lo=getbyte(); //Lo
CRC=Lo;
if((~CRC+1)!=getbyte()){Error_UART(2);} //проверка CRC
return Lo;
}
// идентификация MC3PHAC
void MC3PHAC_Identification(){
unsigned char i,j;
unsigned char Test_Link1[3] = {0x2B,0xC0, 0x40};
for (j=0; j<3;j++){
for (i=0;i<3;i++){
putbyte(Test_Link1[i]);
}
if(Response()!=0x81){Error_UART(2);}
}
}
// иницилизация MC3PHAC
void MC3PHAC_Init(){
MC3PHAC_Send(cmd_RESET, sizeof(cmd_RESET));
delay_ms(100);
MC3PHAC_Send(cmd_DEADT, sizeof(cmd_DEADT));
Response();
MC3PHAC_Send(cmd_PPWM, sizeof(cmd_PPWM));
Response();
MC3PHAC_Send(cmd_ACB, sizeof(cmd_ACB));
Response();
MC3PHAC_Send(cmd_ACC, sizeof(cmd_ACC));
Response();
MC3PHAC_Send(cmd_FPWM, sizeof(cmd_FPWM));
Response();
MC3PHAC_Send(cmd_F, sizeof(cmd_F));
Response();
MC3PHAC_Send(cmd_VBOOST, sizeof(cmd_FPWM));
Response();
MC3PHAC_Send(cmd_MODIN, sizeof(cmd_MODIN));
Response();
MC3PHAC_Send(cmd_FTOUT, sizeof(cmd_FTOUT));
Response();
MC3PHAC_Send(cmd_VBDEC, sizeof(cmd_VBDEC));
Response();
MC3PHAC_Send(cmd_VBRAKE, sizeof(cmd_VBRAKE));
Response();
MC3PHAC_Send(cmd_VBROWN, sizeof(cmd_VBROWN));
Response();
MC3PHAC_Send(cmd_VBOVR, sizeof(cmd_VBOVR));
Response();
}




и пример самой программы (как вариант)

CODE


#include <mega16.h>
#include <delay.h>
#include <stdio.h>


#define OK4 PORTA.3 // Общий катод индикатора

#define OK3 PORTA.2 // Общий катод индикатора

#define OK2 PORTA.4 // Общий катод индикатора

#define OK1 PORTA.5 // Общий катод индикатора



#define HL_FWR PORTA.6 // Светодиод "Вперед"

#define HL_REW PORTA.7 // Светодиод "Назад"

#define ALARM PORTD.7 // Выход аварии



#define Blok_DR PORTD.3 // Выход блокировки драйвера

#define BUT PIND.5 // Вход кнопки


#define TEST 0 //Режимы работы

#define NORM 1 //Режимы работы



#define ADC_VREF_TYPE 0xC0




/*

внеш торм транз. вкл при 365В

100%=310B (3.5В)


*/


//************** Глобальные переменные *************

unsigned char DigSot,DigDec,DigEd;

unsigned char MaskaDig[11]={63,48,91,121,116,109,111,56,127,125,1};

float gl_var_dig_f=0;

unsigned char regim;

unsigned int period,timer;

unsigned int F; // текущая синусоидальная частота ШИМ

unsigned int Zad_F;

unsigned int voltage_bus;

bit PUSK=0;

unsigned char status;

//**************************************************

void IntToDec(unsigned int data){ //

unsigned char _digdec=0,_digsot=0;

while (data>=100){data-=100;_digsot++;}

while (data>=10){data-=10;_digdec++;}

DigEd=data;

DigDec=_digdec;

DigSot=_digsot;

}

#include "driver_mc3phac.h"



// прерывание динамической индикации

interrupt [TIM0_COMP] void timer0_comp_isr(void){// дин инд

if(OK1==0){OK1=1;OK2=0;PORTC=MaskaDig[DigSot];goto end;}

if(OK2==0){OK2=1;OK3=0;PORTC=MaskaDig[DigDec];goto end;}

if(OK3==0){OK3=1;OK4=0;PORTC=MaskaDig[DigEd];goto end;}

if(OK4==0){OK4=1;OK1=0;if(F==0){PORTC=MaskaDig[10];}else{PORTC=0;}}

end:

}


// External Interrupt 1 service routine

interrupt [EXT_INT1] void ext_int1_isr(void)

{

ALARM=1;delay_us(1);ALARM=0; // установка аварии

}



// проверка связи

void TestSeti(){

unsigned char i,j;

unsigned char Test_Link1[3] = {0x2B,0xC0, 0x40};

for (j=0; j<10;j++){

for (i=0;i<3;i++){putbyte(Test_Link1[i]);}

Response();

}

delay_ms(100);

for (j=0; j<10;j++){

for (i=0;i<3;i++){putbyte(Test_Link1[i]);}

Response();

}

delay_ms(100);

for (j=0; j<10;j++){

for (i=0;i<3;i++){putbyte(Test_Link1[i]);}

Response();

}

HL_REW=1;HL_FWR=1;delay_ms(500);HL_REW=0;HL_FWR=0;

}





// Read the AD conversion result

unsigned int read_zad_f(){

ADMUX=0x01 | (ADC_VREF_TYPE & 0xff);

delay_us(10);

ADCSRA|=0x40;

while ((ADCSRA & 0x10)==0);

ADCSRA|=0x10;

return ADCW ;

}



void init(){

PORTC=0b00000000;

DDRC= 0b11111111;

PORTD=0b00000000;

DDRD= 0b10000000;

PORTA=0b00111100;

DDRA= 0b11111100;

PORTB=0b00000000;

DDRB= 0b00000000;



// Timer/Counter 0 initialization

// Clock source: System Clock

// Clock value: 15,625 kHz

// Mode: CTC top=OCR0

// OC0 output: Disconnected

TCCR0=0x0C;

TCNT0=0x00;

OCR0=0x4E;


GICR|=0x80;

MCUCR=0x08;

MCUCSR=0x00;

GIFR=0x80;


ACSR=0x80;

SFIOR=0x00;

TIMSK|=0x02;

OK2=0;


// Analog Comparator initialization

ACSR=0x80;

SFIOR=0x00;

// ADC initialization

// ADC Clock frequency: 500,000 kHz

// ADC Voltage Reference: Int., cap. on AREF

// ADC Auto Trigger Source: None

ADMUX=ADC_VREF_TYPE & 0xff;

ADCSRA=0x83;

}


unsigned int digital_filtr(unsigned int input){ // для более плавного задания на частоту (необязат)

// используется глоб переменная float gl_var_dig_f=0 - накопление

float delta; // отклонение от предыдущего измерения

delta=(float)input-gl_var_dig_f;

if((delta>2)||(delta<-2)){delta/=2;goto jump;}

//if((delta>4)||(delta<-4)){delta/=20;goto jump;}

//if((delta>2)||(delta<-2)){delta/=100;goto jump;}

delta/=20;

jump:

gl_var_dig_f=gl_var_dig_f+delta;

return gl_var_dig_f;

}


void main(void){

init();

driver_init();


HL_REW=0;

HL_FWR=0;

delay_ms(1000);

TestSeti();

MC3PHAC_Identification();

MC3PHAC_Init();

MC3PHAC_Send(read_SETUP,sizeof(read_SETUP));

while(RxByte()!=0xFF){} // проверка готовности перед включением ШИМ

regim=PINB&0b00001111; // определение режима работы

delay_ms(2000);

//***** тестовый режим******

test_reg:

if(regim!=TEST){goto norm_reg;}

MC3PHAC_Send(cmd_FORW,sizeof(cmd_FORW));

Response();

while(1){

MC3PHAC_Send(read_VBUS,sizeof(read_VBUS));

voltage_bus=RxWord();

voltage_bus=voltage_bus/2.312;

IntToDec(voltage_bus); //

delay_ms(100);

}


//***** нормальный режим******

norm_reg:

if (regim!=NORM){goto test_reg;}

while(1){ // цикл ожидания включения



Zad_F=digital_filtr(read_zad_f()>>4); // чтение задания на скорость

MC3PHAC_Send(read_ACTF,sizeof(read_ACTF)); // чтение текущей синусоидальной частоты

F=RxWord()>>8;

if(F>0){IntToDec(F);} // отображение текущей синусоидальной частоты}

else{IntToDec(Zad_F);} // отображение задания на скорость



//delay_ms(200);

if(BUT){

if(PUSK){PUSK=0;delay_ms(1000);

MC3PHAC_Send(cmd_STOP,sizeof(cmd_STOP)); // стоп двигателя

Response();HL_FWR=0;HL_REW=0;

}

else{PUSK=1;delay_ms(1000);

MC3PHAC_Send_F(Zad_F,0); // задание синусоидальной частоты

Response();

MC3PHAC_Send(cmd_FORW,sizeof(cmd_FORW)); // включение двигателя вперед

Response();HL_FWR=1;

}

}

}

goto test_reg;

}




ссылка на видео

http://www.youtube.com/watch?v=J8B4RegJsdg

показан разгон и торможения двигателя (вместо него лампочка). Предварительно потонцеометром (на AVR) устанапливается задание на синусоидальную частоту. Потом происходит пуск кнопкой (на AVR). Разгон длиться до заданной частоты. Потом остановка.



схема для связи MC3PHAC c Atmega16 (формат P-Cad)

Сообщение отредактировал a-6539x - Feb 27 2011, 20:14
Прикрепленные файлы
Прикрепленный файл  atmega16_MC3PHAC.sch ( 223.99 килобайт ) Кол-во скачиваний: 233
 
Go to the top of the page
 
+Quote Post
Chip115
сообщение Mar 18 2011, 19:52
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 43
Регистрация: 28-12-07
Пользователь №: 33 709



Спасибо за такой полный ответ!
А если без "наворотов" делать... всмысле без проверки CRC и прочей защиты, можно обойтись только инициализацией ? А потом только кидать с MC3PHAC данные и принимать ответ? Мне всего надо несколько комманд: старт,стоп,реверс, частота напряжения на двигателе.
В кратце получается
Инициализация.
2B E3 10 00 30 00 crc - Сброс ИС MC3PHAC
2B E3 10 00 xx 00 crc - (xx = 50,54,58,5C) Полярность ШИМ выходов. B- T-
2B E3 00 36 xx 00 crc - (xx = 00..FF) Dead time 06*125ns = 750ns
2B E3 10 00 xx 00 crc - (xx = 60,61) Базовая частота двигателя (50Гц)
2B E4 00 60 xx xx crc - (xx xx = 0000..FFFF) Задание ускорения в Hz/sec (7.9 format)
2B E4 00 62 xx xx crc - (xx xx = 0000..7FFF) Задание частоты на двигателе в Hz (8.8 format)
2B E3 10 00 xx 00 crc - (xx = 41,42,44,48) Задание частоты ШИМ
2B E3 00 6C xx 00 crc - (xx = 00..FF) Voltage boost % =знач/FFh (при F=0 на двигателе)
2B E3 00 75 xx 00 crc - (xx = 00..FF) Максимальный индекс модуляции % =знач/FFh
2B E4 00 6A xx xx crc - (xx xx = 0000..FFFF) Fault timeout = знач*0.262с
2B E4 00 C9 xx xx crc - (xx xx = 0000..03FF) напряжение на шине reduced deceleration.
2B E4 00 64 xx xx crc - (xx xx = 0000..03FF) напряжение на шине RBRAKE pin being asserted.
2B E4 00 66 xx xx crc - (xx xx = 0000..03FF) напряжение на шине under voltage fault.
2B E4 00 68 xx xx crc - (xx xx = 0000..03FF) напряжение на шине over voltage fault.



А затем когда нужно, пихаем в него через UART нужные команды
2B E3 10 00 10 00 FD - пуск вперед
2B E3 10 00 11 00 FC - пуск назад
2B E3 10 00 20 00 ED - останов двигателя
2B E4 00 62 xx xx crc - (xx xx = 0000..7FFF) Задание частоты на двигателе в Hz (8.8 format)

на каждую комманду получаем подтверждение.
Теоретически при такой структуре будет работать?
Go to the top of the page
 
+Quote Post
a-6539x
сообщение Mar 23 2011, 05:28
Сообщение #7





Группа: Новичок
Сообщений: 9
Регистрация: 20-10-10
Пользователь №: 60 297



Цитата(Chip115 @ Mar 18 2011, 22:52) *
Спасибо за такой полный ответ!
А если без "наворотов" делать... всмысле без проверки CRC и прочей защиты, можно обойтись только инициализацией ? А потом только кидать с MC3PHAC данные и принимать ответ? Мне всего надо несколько комманд: старт,стоп,реверс, частота напряжения на двигателе.
В кратце получается
Инициализация.
2B E3 10 00 30 00 crc - Сброс ИС MC3PHAC
2B E3 10 00 xx 00 crc - (xx = 50,54,58,5C) Полярность ШИМ выходов. B- T-
2B E3 00 36 xx 00 crc - (xx = 00..FF) Dead time 06*125ns = 750ns
2B E3 10 00 xx 00 crc - (xx = 60,61) Базовая частота двигателя (50Гц)
2B E4 00 60 xx xx crc - (xx xx = 0000..FFFF) Задание ускорения в Hz/sec (7.9 format)
2B E4 00 62 xx xx crc - (xx xx = 0000..7FFF) Задание частоты на двигателе в Hz (8.8 format)
2B E3 10 00 xx 00 crc - (xx = 41,42,44,48) Задание частоты ШИМ
2B E3 00 6C xx 00 crc - (xx = 00..FF) Voltage boost % =знач/FFh (при F=0 на двигателе)
2B E3 00 75 xx 00 crc - (xx = 00..FF) Максимальный индекс модуляции % =знач/FFh
2B E4 00 6A xx xx crc - (xx xx = 0000..FFFF) Fault timeout = знач*0.262с
2B E4 00 C9 xx xx crc - (xx xx = 0000..03FF) напряжение на шине reduced deceleration.
2B E4 00 64 xx xx crc - (xx xx = 0000..03FF) напряжение на шине RBRAKE pin being asserted.
2B E4 00 66 xx xx crc - (xx xx = 0000..03FF) напряжение на шине under voltage fault.
2B E4 00 68 xx xx crc - (xx xx = 0000..03FF) напряжение на шине over voltage fault.



А затем когда нужно, пихаем в него через UART нужные команды
2B E3 10 00 10 00 FD - пуск вперед
2B E3 10 00 11 00 FC - пуск назад
2B E3 10 00 20 00 ED - останов двигателя
2B E4 00 62 xx xx crc - (xx xx = 0000..7FFF) Задание частоты на двигателе в Hz (8.8 format)

на каждую комманду получаем подтверждение.
Теоретически при такой структуре будет работать?

можно сделать без всех наворотов и проверок (если нет ошибок в программе) главное иметь в виду что при посылке команд тебе сразу же в ответ будет приходить 2B 00 00 (если все хорошо) и тебе надо будет это проигнорировать, чтобы не засорять буфер приема. Я делаю это процедурой Responce(); И тебе все равно в конце каждой команды надо послать ее CRC иначе MC3PHAC ее (команду) не примет
Go to the top of the page
 
+Quote Post
Chip115
сообщение Apr 12 2011, 06:23
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 43
Регистрация: 28-12-07
Пользователь №: 33 709



Цитата(a-6539x @ Feb 28 2011, 03:31) *
Разгоняться двигатель будет с заданным ускарением (минимальное вроде 0,5Гц /c) c нуля. При остановке все происходит аналогично но в обратной последовательности. скорость разгона - константа.

При тестовом запуске без управляющего контроллера (управление по средствам резисторов), заметил что MA3PHAC тормозит двигатель, а у меня получилось без торможения. все равно что вынуть вилку из розетки.
не могу сообразить , как мне сделать торможение, аналогичное тому что было, только по UART? мне надо что бы ускорение проходило с максимальным значением (кажется 128 Гц/с)и как можно быстро тормозил ротор?
за торможение/ускорение отвечает
Код
xdata unsigned char const cmd_ACC[5] =     {0xE4, 0x00, 0x60, 0xFF, 0xFF}; //    ускорение
?
Go to the top of the page
 
+Quote Post
a-6539x
сообщение Apr 18 2011, 17:22
Сообщение #9





Группа: Новичок
Сообщений: 9
Регистрация: 20-10-10
Пользователь №: 60 297



скорей всего это из-за ошибки в комментарии строки инициалицации ускорения. Значение следует выбирать из диапазона 0..7FFF а не 0..FFFF. Напиши:

xdata unsigned char const cmd_ACC[5] = {0xE4, 0x00, 0x60, 0x7F, 0xFF}; // ускорение

Хотя думаю ты уже догодался.

Если двигатель быстро разгоняется, но не так быстро тормозит значит все работает правильно. При торможении особенно под нагрузкой на валу резко поднимается напряжение на шине питания и чтобы недопустить перенапряжения на транзисторах и электролитах MC3PHAC начинает снижать скорость торможения на сколько это необходимо. Поэтому резкое торможение получить будет сложно конечно если не поставить мощный тормозной резистор. Включение тормозного резистора должно происходить немного раньшше чем снижение ускорения (reduced deceleration) или одновременно (как я понял).

Go to the top of the page
 
+Quote Post
_Pasha
сообщение Apr 18 2011, 18:24
Сообщение #10


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(a-6539x @ Apr 18 2011, 20:22) *
если не поставить мощный тормозной резистор.

Могу цифрами помочь: 10 10ваттных резюков впараллель. 4к7.
Лучше на радиатор.

Сообщение отредактировал _Pasha - Apr 18 2011, 18:25
Go to the top of the page
 
+Quote Post
MasterWizard
сообщение Oct 7 2012, 13:03
Сообщение #11





Группа: Участник
Сообщений: 14
Регистрация: 14-02-11
Пользователь №: 62 949



Доброе время. Сломал себе мозг и разочаровался в себе, как в специалисте. Не могу установить мертвое время и полярность ШИМ. Устанавливается что-то одно. Подключился к кристаллу гипертерминалом, шлю в самых разных комбинациях. Все команды проходят, в том числе и одна из "установить мертвое время" и "установить полярность ШИМ". При посылке второй из вышеперечисленных двух - кристалл отвечает либо FF, либо молчит.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 7 2012, 14:21
Сообщение #12


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(MasterWizard @ Oct 7 2012, 16:03) *
отвечает либо FF, либо молчит.

У меня такая засада была, когда я неверно развел плату. PLL как самая капризная там вещь - не давал ни стартовать ни поставить полярность. С тех пор понял, что микросхема эта дурная и начал писать своё, на основе той системы параметров. Получилось лучше, ессно.

Сообщение отредактировал _Pasha - Oct 7 2012, 14:22
Go to the top of the page
 
+Quote Post
MasterWizard
сообщение Oct 7 2012, 14:38
Сообщение #13





Группа: Участник
Сообщений: 14
Регистрация: 14-02-11
Пользователь №: 62 949



Цитата(_Pasha @ Oct 7 2012, 18:21) *
У меня такая засада была, когда я неверно развел плату. PLL как самая капризная там вещь - не давал ни стартовать ни поставить полярность. С тех пор понял, что микросхема эта дурная и начал писать своё, на основе той системы параметров. Получилось лучше, ессно.


с какого же перепугу все остальные команды проходят? (вопрос риторический). Может, посоветуете что-то с учетом того, что переразвести плату сейчас - не вариант? Ну, там, емкостям обставить эту ногу (которая PLLСAP, которая седьмая)?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Oct 7 2012, 15:46
Сообщение #14


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(MasterWizard @ Oct 7 2012, 17:38) *
с какого же перепугу все остальные команды проходят? (вопрос риторический). Может, посоветуете что-то с учетом того, что переразвести плату сейчас - не вариант? Ну, там, емкостям обставить эту ногу (которая PLLСAP, которая седьмая)?

Перепуг обычный - команды каким-то образом трогают ШИМ-модуль и далее по питанию пролазит иголка, которая портит PLL. Посмотреть бы Вашу плату...
Go to the top of the page
 
+Quote Post
MasterWizard
сообщение Oct 7 2012, 21:40
Сообщение #15





Группа: Участник
Сообщений: 14
Регистрация: 14-02-11
Пользователь №: 62 949



Цитата(_Pasha @ Oct 7 2012, 19:46) *
Перепуг обычный - команды каким-то образом трогают ШИМ-модуль и далее по питанию пролазит иголка, которая портит PLL. Посмотреть бы Вашу плату...

а чего бы и не посмотреть...вроде как, прикрепил...
Прикрепленные файлы
Прикрепленный файл  v00.pcb ( 223.99 килобайт ) Кол-во скачиваний: 97
 
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th June 2025 - 11:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01654 секунд с 7
ELECTRONIX ©2004-2016