This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Dear all,
I implemented voltage and current measurement on ADCINA5 and ADCINB5, respectively using simultaneous mode. The SOCA bit is generated by ePWM1 module, which is in up-count mode with 50% duty cycle. Furthermore, the SOCA bit is generated when COMPA and the time base counter (when incrementing) match. The PWM waveforms are as expected.
I also get proper ADC readings within the ADC ISR and am therefore now trying to measure the ISR execution time. For that, I set a GPIO at the beginning of the ISR, which I clear at the end of the ISR. However, my measurements show that the ISR is entered much more often than the ePWM is generated. I attached a waveform of the PWM (magenta, 50% duty with approx. 600ns dead band) and the GPIO within the ISR (blue).
I also attached my theoretical waveforms based on my understanding when reading the documents SPRU812A and SPRAAP6A.
Any ideas on what I am doing wrong? Much appreciated.
/* * 23. Nov. 2016: Open loop for now - only PWM generation - no phase shift implemented * 13. Dec. 2016: Program to flash functionality added * 16. Dec. 2016: Phase shift for open loop PWM generation added * 04. Jan. 2017: ADC measurements added - to be cont'd */ #include "DSP28x_Project.h" void InitialADC(); void InitePWM1(); void InitePWM2(); void InitePWM5(); void InitePWM6(); __interrupt void ADC_isr(); // Flash functionality extern Uint16 RamfuncsLoadStart; extern Uint16 RamfuncsLoadEnd; extern Uint16 RamfuncsRunStart; // Variables #define DT 100 // Dead time calc: DT = Value/CLKfreq -> 100/150MHz = 666ns Uint16 phaseshift; Uint16 ConversionCount; Uint16 Voltage1[128]; Uint16 Current[128]; void main(void) { // Initialize PLL, Watchdog, enable peripheral clocks InitSysCtrl(); // Used to program to flash MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); // Initialize ePWM InitEPwmGpio(); // Initialize PIE control registers InitPieCtrl(); IER = 0x0000; IFR = 0x0000; // Initialize PIE vector table to default ISR InitPieVectTable(); // Remap the ISR function to the PIE vector table EALLOW; PieVectTable.ADCINT = &ADC_isr; EDIS; // First step of setting up the ADC sampling rate EALLOW; SysCtrlRegs.HISPCP.all = 3; // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz EDIS; // Synchronization already done in the InitSysCtrl() function --> Ask the TI support to verify /* EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable time base clock synchronization with SYSCLKOUT from DSP EDIS; */ InitFlash(); PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // Group 1, bit 6 for ADC IER |= M_INT1; // Sets the interrupt enable bit of group 1 EINT; // Enable global interrupts INTM ConversionCount = 0; // Initialize the count // Initialize the ADC InitAdc(); phaseshift = 102; // Initializing the phase shift InitialADC(); InitePWM1(); InitePWM2(); InitePWM5(); InitePWM6(); /* * Set GPIO4 as output to measure execution time within ISR */ EALLOW; // Set GPIO10 as a GPIO - already done in InitGpio() GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0; // Set GPIO10 as an output GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; EDIS; for(;;) { } } __interrupt void ADC_isr(void) { GpioDataRegs.GPASET.bit.GPIO4 = 1; Voltage1[ConversionCount] = AdcRegs.ADCRESULT0 >>4; // Read value from ADCINA5 Current[ConversionCount] = AdcRegs.ADCRESULT1 >>4; // Read value from ADCINB5 // If 128 conversions have been logged, start over if(ConversionCount == 127) { ConversionCount = 0; } else { ConversionCount++; } /* * Calculating the phaseshift between two bridges */ EPwm5Regs.TBPHS.half.TBPHS = phaseshift; EPwm6Regs.TBPHS.half.TBPHS = phaseshift; // Re-initialize for next ADC AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1 AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clears the interrupt flag bit PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE GpioDataRegs.GPACLEAR.bit.GPIO4 = 1; } void InitialADC(void) { // Configure ADC AdcRegs.ADCTRL3.bit.ADCCLKPS = 12; // Set the ADC sampling rate: 25MHz/(2*12+1) = 1MHz AdcRegs.ADCTRL1.bit.SEQ_CASC = 0; // Cascaded mode AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Continuous conversion mode AdcRegs.ADCTRL3.bit.SMODE_SEL = 1; // Simultaneous sampling mode AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // ePWM starts SOCA trigger AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0; // One conversion AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 5; // ADCINA5 and ADCINB5 AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Interrupt request enabled } void InitePWM1(void) { // Enable SOCA for ADC measurements EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOCA EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Generate SOCA pulse at 50% duty cycle EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event EPwm1Regs.TBPRD = 1499; // Set the PWM period time EPwm1Regs.CMPA.half.CMPA = (1499+1)/2; EPwm1Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm1Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Sets pin when CTR=PRD EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clears pin when CTR=COMPA EPwm1Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm1Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm1Regs.DBRED = DT; EPwm1Regs.DBFED = DT; } void InitePWM2(void) { EPwm2Regs.TBPRD = 1499; // Set the PWM period time EPwm2Regs.CMPA.half.CMPA = (1499+1)/2; EPwm2Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Master module EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm2Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm2Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clears pin when CTR=PRD EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Sets pin when CTR=COMPA EPwm2Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm2Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm2Regs.DBRED = DT; EPwm2Regs.DBFED = DT; } void InitePWM5(void) { EPwm5Regs.TBPRD = 1499; // Set the PWM period time EPwm5Regs.CMPA.half.CMPA = (1499+1)/2; EPwm5Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave module EPwm5Regs.TBCTL.bit.PRDLD = TB_SHADOW; //EPwm5Regs.TBCTL.bit. EPwm5Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Sync down-stream module EPwm5Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm5Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm5Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm5Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clears pin when CTR=PRD EPwm5Regs.AQCTLA.bit.CAU = AQ_SET; // Sets pin when CTR=COMPA EPwm5Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm5Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm5Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm5Regs.DBRED = DT; EPwm5Regs.DBFED = DT; } void InitePWM6(void) { EPwm6Regs.TBPRD = 1499; // Set the PWM period time EPwm6Regs.CMPA.half.CMPA = (1499-1)/2; EPwm6Regs.TBPHS.half.TBPHS = 0; // Set Phase register to zero EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up count mode EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave module EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // Sync down-stream module EPwm6Regs.TBCTL.bit.HSPCLKDIV = 0; // Set time base clock to SYSCLKOUT EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm6Regs.CMPCTL.bit.LOADAMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm6Regs.CMPCTL.bit.LOADBMODE = 0; // Loads on either CTR=0 or CTR=PRD EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET; // Sets pin when CTR=PRD EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clears pin when CTR=COMPA EPwm6Regs.DBCTL.bit.IN_MODE = 0; // ePWMxA source for falling and rising edge EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // DB full enable EPwm6Regs.DBCTL.bit.POLSEL = 2; // Active high complementary EPwm6Regs.DBRED = DT; EPwm6Regs.DBFED = DT; }
Hi Alexander,
I don't think you want the CONT_RUN bit to be set. I think this is causing the ADC to run continuously once started instead of being triggered once each ePWM event.
Not directly related to your issue, but you may also want to increase the ADCCLK from 1MHz to a more nominal value like 12.5MHz or 25MHz. We have an erratum stating that operating the ADC at low clock frequencies can lead to performance issues:
Alexander,
Not sure. Can you start by moving these lines to immediately before the for() loop:
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // Group 1, bit 6 for ADC
IER |= M_INT1; // Sets the interrupt enable bit of group 1 EINT; // Enable global interrupts INTM
The way you have it now, interrupts are active and modifying PWM registers before you've even initialized those peripherals. I'm wondering if initialization is getting corrupted somehow.
Regards,
Richard