Цитата(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)