/** * @brief 初始化PWM模块 * * @param None * * @retval None * * @note * @verbatim * * Phase U : EPWM3 * Phase V : EPWM2 * Phase W : EPWM1 * * Symmetrical mode * * EN : GPIO34 * * TZ1(Fault) : EPWM输出高电平,对应IR2316后结果为输出悬空 * * @endverbatim */ void InverterInit(void) { EALLOW; /* EPWM Clock */ SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 1; SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK = 1; SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK = 1; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; EPWMGPIOInit(); EPWNBaseInit(&EPwm1Regs); EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module, Time-base counter equal to zero EPWNBaseInit(&EPwm2Regs); EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave module EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // sync flow-through EPWNBaseInit(&EPwm3Regs); EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave module EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // sync flow-through /* EPWM clock synchronize enable */ SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; /* Pre-Charge */ EnableInverter(); Uint16 i = 0; for (i = 0; i < EPWM_PRECHARGE; i++) { DELAY_US(1000); } DisableInverter(); // Clear any spurious OV trip EPwm1Regs.TZCLR.bit.OST = 1; EPwm2Regs.TZCLR.bit.OST = 1; EPwm3Regs.TZCLR.bit.OST = 1; /* Enable TZ */ EPwm1Regs.TZSEL.bit.OSHT1 = TZ_ENABLE; // ePWM1 TZ1 Enable, overcurrent EPwm2Regs.TZSEL.bit.OSHT1 = TZ_ENABLE; // ePWM2 TZ1 Enable, overcurrent EPwm3Regs.TZSEL.bit.OSHT1 = TZ_ENABLE; // ePWM3 TZ1 Enable, overcurrent // INT PieVectTable.EPWM1_TZINT = &TZ_ISR; PieCtrlRegs.PIEIER2.bit.INTx1 = 1; // Enable INT 2.1 in the PIE IER |= M_INT2; // Enable CPU Interrupt 2 // SOC EPwm1Regs.ETSEL.bit.SOCASEL = 2; // Enable event time-base counter equal to period (TBCTR = TBPRD) EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event EDIS; }
//###########################################################################// // INT3.8 - EPWM8 // // PERIODIC STATE CHECKS AND ACTIONS // //###########################################################################// // __interrupt void EPWM8_INT_ISR(void) // EPWM-8 { PieCtrlRegs.PIEACK.bit.ACK3 = 1 ; // Acknowledge the PIE group if (State.bit.StartupSequence) { if (PeripheralEn.bit.Inverter) DisableInverter() ; if ( !(LED_Stable_Ctr % 512) ) { data_out.bit.led_ctrl_green = ~data_out.bit.led_ctrl_green ; data_out.bit.led_ctrl_red = ~data_out.bit.led_ctrl_red ; } LED_Stable_Ctr++; if ( abs(V_DcError) < 30 ) { stableCtr++ ; } else stableCtr = 0 ; if (stableCtr >= 30000) // Checks for 15 seconds where ISR called every 1/2kHz { stableCtr = 0 ; State.all = 0 ; State.bit.InvSoftStart = 1 ; State.bit.DcStable = 1 ; flag_bc = 1 ; // Update the LCD screen } } if (State.bit.InvSoftStart) { if ( !(PeripheralEn.bit.Inverter) ) EnableInverter(); if (softStartCtr >= 2000) // Waits 1 sec with ePWM8 @ 2kHz { DutyScale = DutyScale + 0.005; // Inverter output allowable duty cycle increments every 1s softStartCtr = 0; // Reset the counter } softStartCtr++ ; if ( !(LED_Inverter_Ctr++ % 512) ) data_out.bit.led_inverter = ~(data_out.bit.led_inverter); if (DutyScale >= DutyScaleMax) { State.bit.InvSoftStart = 0; data_out.bit.led_inverter = 1; flag_bc = 1; // Update the LCD screen softStartCtr = 0; } } if (State.bit.DcStable) { if ( abs(V_DcError) > 30 ) { unstableCtr++ ; // If error is too large, check if system has entered instability stableCtr = 0 ; } else if (unstableCtr > 0) stableCtr++ ; if (unstableCtr >= 10000) { State.all = 0 ; State.bit.Fault = 1 ; // If the system has a large error for greater than 5 seconds, change system state flag_bc = 1 ; // Update the LCD screen } else if (stableCtr >= 20000) // If signs of instability show, but the system goes back to being stable for at least { // 10 seconds, the counters reset and the system state is unchanged. stableCtr = 0 ; unstableCtr = 0 ; } } EPwm8Regs.ETCLR.bit.INT = 1 ; // Clear the interrupt flag }
void main(void) { int i=0; // Loop Variable timeout_ctr = 0 ; //############################ Initialisation ###############################// // _SOURCE_ DeviceInit(); // DeviceInit.c InitGpio(); // GpioInit.c InitPieVectTable(); // PieVect.c InitPieCtrl(); // PieCtrl.c InitSci(); // Serial.c init_lcd_menu(); // LcdMenu.c lcd_init(); // LcdDriver.c SineRefInit(); // SineRefInit.c AdcInit(); // AdcInit.c PwmInit(); // PwmInit.c State.all = 0; State.bit.Start = 1; PeripheralEn.bit.Buttons= 1; // Allow button checks EnableInterrupts(); // PieCtrl.c DisableInverter(); // Ensure inverter is disabled on start-up lcd_position(0x5,0x0); lcd_puts("Kingfisher"); // Print introductory message on top line lcd_position(0x0,0x1); // Start Cursor From First Line lcd_puts(" Hydro Controller "); // Print introductory message on bottom line asm(" CLRC INTM, DBGM"); // Enable global interrupts and real-time debug CpuTimer0Regs.PRD.all = COUNTER0_PRD; // Initialise CPU timer0 CpuTimer1Regs.PRD.all = COUNTER1_PRD; // Initialise CPU timer0 //############################# Polling Loop ################################// while(1) { //#######################################################################// // STATES // //#######################################################################// // //############################ START STATE ##############################// if(State.bit.Start) { asm("NOP"); } //######################### EXCITATION STATE ############################// if (State.bit.Excitation) { data_out.bit.led_ctrl_green = 1; data_out.bit.led_ctrl_red = 0; if ( (AdcSignal.V_HVDC < 50) && (AdcSignal.Shaft_Velocity > 2000) && !(State.bit.Fault) ) { // PeripheralEn.bit.Buttons= 0; timeout_ctr++; if (timeout_ctr > 3) { State.all = 0; State.bit.Fault = 1; timeout_ctr = 0; } else { data_out.bit.startup = 1; shift_data_out(); if (CpuTimer0Regs.TCR.bit.TIF == 1) { for (i=1;i<=2;i++) // wait 2 seconds { CpuTimer0Regs.TCR.bit.TIF = 1; // Clear flag while(!CpuTimer0Regs.TCR.bit.TIF); } } data_out.bit.startup = 0; shift_data_out(); if (CpuTimer0Regs.TCR.bit.TIF == 1) { for(i=1;i<=3;i++) // wait 3 seconds { CpuTimer0Regs.TCR.bit.TIF = 1; // Clear flag while(!CpuTimer0Regs.TCR.bit.TIF); } } } } else if ( (AdcSignal.V_HVDC >= 50) && (AdcSignal.V_HVDC < 250) ) { timeout_ctr = 0; State.all = 0; State.bit.Excited = 1; // Perhaps change LCD Screen to message saying "Slowly increase turbine speed to increase voltage." } else if ( (AdcSignal.V_HVDC > 250) ) { timeout_ctr = 0; // Resets the timeout counter for excitation State.all = 0; State.bit.StartupSequence = 1; } } //############################ EXCITED STATE ############################// if (State.bit.Excited) { if (AdcSignal.V_HVDC > 250) { timeout_ctr = 0; // Resets the timeout counter for excitation State.all = 0; State.bit.StartupSequence = 1; } else { // !!!!! ADD SOME CODE FOR THIS CONDITION !!!!! } } //############################# FAULT STATE #############################// if (State.bit.Fault) { if (PeripheralEn.bit.Inverter) { DisableInverter(); data_out.bit.led_dump1 = 0; data_out.bit.led_dump2 = 0; data_out.bit.led_inverter = 0; data_out.bit.led_update = 0; } data_out.bit.protect_trig = 1; data_out.bit.led_ctrl_green = 0; data_out.bit.led_ctrl_red = 1; if ( !(LED_Fault_Ctr++ % 16384) ) { data_out.bit.led_dump1 = ~(data_out.bit.led_dump1); data_out.bit.led_dump2 = ~(data_out.bit.led_dump2); data_out.bit.led_inverter = ~(data_out.bit.led_inverter); data_out.bit.led_update = ~(data_out.bit.led_update); } } //########################### DC STABLE STATE ###########################// if (State.bit.DcStable) { if ( !(PeripheralEn.bit.Inverter) ) EnableInverter(); data_out.bit.led_ctrl_green = 1; data_out.bit.led_ctrl_red = 0; } //############################## TEST STATE #############################// if (State.bit.Test) { } //########################### TURNED OFF STATE ##########################// if (State.bit.TurnOff) { data_out.bit.led_ctrl_green = 0; data_out.bit.led_ctrl_red = 0; data_out.bit.led_dump1 = 0; data_out.bit.led_dump2 = 0; data_out.bit.led_inverter = 0; data_out.bit.led_update = 0; } //#######################################################################// // FLAGS // //#######################################################################// // //######################## SCREEN UPDATE FLAG #######################// if (flag_bc) { menu_update_lcd(); flag_bc = 0; } asm(" nop"); //########################### READ IN DATA FLAG #########################// if (flag.bit.DataIN) { shift_data_in(); check_buttons(); flag.bit.DataIN = 0; } //########################## SEND OUT DATA FLAG #########################// if (flag.bit.DataOUT) { shift_data_out(); flag.bit.DataOUT = 0; } //######################## HVDC VOLTAGE REGULATION ######################// if (flag.bit.V_HVDC) { if ( !(State.bit.TurnOff) && !(State.bit.Fault) ) { V_DcError = V_DC_REF - AdcSignal.V_HVDC; // Calculate the DC error from the reference DutyError = 0.75*K_DC*V_DcError + 0.25*DutyError; // Modify the dump load duty cycle with respect to the DC error if (V_DcError > 0) // If the DC voltage is less than the reference, dump no power { EPwm3Regs.CMPA.half.CMPA= 0; EPwm3Regs.CMPB = 0; } else if (DutyError > DUMP1_DUTY_MAX) { DutyFeedback = 1.0*(DUMP1_DUTY_MAX)*DUMP_PRD; EPwm3Regs.CMPA.half.CMPA= DutyFeedback; DutyFeedback = 1.0*(DutyError - DUMP1_DUTY_MAX)*DUMP_PRD; EPwm3Regs.CMPB = DutyFeedback; } else { DutyFeedback = 1.0*(DutyError)*DUMP_PRD; EPwm3Regs.CMPA.half.CMPA= DutyFeedback; EPwm3Regs.CMPB = 0; } }else // If there is a fault or the system is off, dump all power { EPwm3Regs.CMPA.half.CMPA = (DUMP1_DUTY_MAX)*DUMP_PRD; // Dump all power! EPwm3Regs.CMPB = DUMP_PRD; // Dump all power! } flag.bit.V_HVDC = 0; // Reset the flag } //###################### SHAFT VELOCITY MEASUREMENT #####################// if (ShaftVelocCtr >= 1000) // Updates the measured velocity every 1000*(1/EPWM8) = 0.5s { AdcSignal.Shaft_Velocity = shaftspeedtest; //0.8*(ShaftPulseCtr/0.5)*60 + 0.2*AdcSignal.Shaft_Velocity; // Where 1 pulse = 1 rotation ShaftPulseCtr = 0; // { Reset counters ShaftVelocCtr = 0; // { } //################### OUTPUT AC VOLTAGE FREQUENCY MEASURE ################// if (V_AcOutPrdCtr >= 10) { AdcSignal.V_AcOut_Freq = (SYSCLK/ADC_SAMP_PRD+1)*(V_AcOutPrdCtr/FreqOutDivCtr); // Approximate frequency over at least 10 periods AcOutFreqError = AC_OUT_FREQ - AdcSignal.V_AcOut_Freq; // Find frequency error V_AcOutReqFreq = V_AcOutReqFreq + 0.05*AcOutFreqError; // Frequency feedback loop sinGen.freq = V_AcOutReqFreq*(BIT31)*(2*BIT32*INVERTER_PWM_PRD)*(1/(sinGen.step_max*SYSCLK)); // Alter reference sine wave frequency V_AcOutPrdCtr = 0 ; // } FreqOutDivCtr = 0 ; // } Reset counters } //####################### INVERTER CONTROL #######################// if (flag.bit.Inverter) { /* BROKEN InverterMaxDuty = V_AC_OUT_REF*(1.0/(AdcSignal.V_HVDC)); // Find the maximum duty cycle necessary to create Vacoutpeak=325V DutyScaleMax = (BIT16*InverterMaxDuty-BIT15)*30.51850948e-6; // 30.51850948e-6 = 1/(BIT15-1) if ( !(State.bit.InvSoftStart) ) { DutyScaleError = DutyScaleMax - DutyScale; DutyScale = DutyScale + 0.01*DutyScaleError; if (DutyScale < 0.2) { DutyScale = 0.2; ADD SOME CODE IN CASE IT IS DANGEROUS TO GO BELOW 0.2 } } */ // ----- Toggle the onboard LED to show inverter control is active if (GPIO34_count >= 4000) // toggle_time = GPIO34_count_limit/fpwm { GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // Toggle the pin GPIO34_count = 0; // Reset the count } flag.bit.Inverter = 0; } //################### INPUT AC VOLTAGE FREQUENCY MEASURE ################// if (V_AcInPrdCtr >= 10) { AdcSignal.V_AcIn_Freq = 0.8*((SYSCLK/ADC_SAMP_PRD+1)*(V_AcInPrdCtr/FreqInDivCtr)) + 0.2*(AdcSignal.V_AcIn_Freq); // Approximate frequency over at least 10 periods genSlip = 100*((AdcSignal.V_AcIn_Freq*60) - (AdcSignal.Shaft_Velocity))/(AdcSignal.V_AcIn_Freq*60); // Calculates slip: s= 100%*((ns-nr)/ns) V_AcInPrdCtr = 0 ; // } FreqInDivCtr = 0 ; // } Reset counters } /* if(SendADCResult) { SendADCResult = 0; SerialSendStr("Voltage: "); SerialSendInt((int)V_DC_measured); SerialSendStr(" PWM1: "); SerialSendInt((int)(EPwm3Regs.CMPA.half.CMPA*100.0/(DUMP_PRD*1.0))); SerialSendCR(); SerialSendStr(" PWM2: "); SerialSendInt((int)((EPwm3Regs.CMPB*100.0)/(DUMP_PRD*1.0))); SerialSendCR(); }*/ } }