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.

Why need simultaneous sampling nearly twice as long as single sampling - F28027?

Other Parts Discussed in Thread: LAUNCHXL-F28027F

Hello

I use a LAUNCHXL-F28027F and tried to day the" Example_2802xAdcSoc".

I modified it to convert channel 4 with all 16 SOCs triggered by EPMW1A

AdcRegs.ADCSOC0CTL.bit.CHSEL = 4; //set SOC0 channel select to ADCINA4

...

AdcRegs.ADCSOC15CTL.bit.CHSEL = 4; //set SOC0 channel select to ADCINA4

and

AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;

..

AdcRegs.ADCSOC15CTL.bit.TRIGSEL = 5;

I enabled the GPIOs for the pwm outputs and toggle GPIO1 every call of the adc_isr routine.

If I set the single sampe mode with

AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0  = 0; // single sample mode

for all SIMULEN0  ... SIMULEN14.

it needs about 4us seconds between the SOC (EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPA; // Select SOC from from CPMA on upcount)

and the pin toggle on GPIO1 (adc_isr => AdcRegs.INTSEL1N2.bit.INT1SEL = 15; //setup EOC15 to trigger ADCINT1 to fire)

But if I enable the simultaneous sampling mode (SIMULEN0  ... SIMULEN14 = 1) it needs about 7us to toggle GPIO1.

Why? I expect nearly half the time of the single sample mode! What did I missed?

Kind regards

René

  • Hi René-

    For F28027 there are two S/H circuits which provide for parallel sampling, but only one converter so switching to simultaneous sampling only reduces the S/H time.  When using OVERLAP mode, the first 7 ADCCLK of S/H are already "free" since they overlap with the previous cycle's conversion, therefore there really is no throughput benefit to simultaneous+OVERLAP mode unless you use an increased sample window.  Hopefully this representation helps illustrate the point, the numbers in the boxes represent the number of ADCCLKs for each phase:

    Regards,

    Joe

  • Hi Joe

    Thanks for the answer.

    In your drawing the sequential mode sample only 3 values and the simultaneous sample 6 values. If you extend our sequential drawing to 6 values it needs more time to do this than the simultaneous mode.

    But my problem is that I have 1 channel sampled with all 16 SOCs but the sequential mode is faster (4us) than the simultaneous mode (7us).

    Why?

    Kind regards

    René

    Here are the signals

    Channel 1 (yellow): ADC Interrupt toggle GPIO1 at EOC. (AdcRegs.INTSEL1N2.bit.INT1SEL = 15; //setup EOC15 to trigger ADCINT1 to fire)

    Channel 2 (red); signal on ADC input

    Channel 3 (blue): PWM signal, falling edge SOC (EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPA; // Select SOC from from CPMA on upcount)

    Sequential mode:

    Simultaneous mode:

  • Here is my source code:


    // TI File $Revision: /main/4 $ // Checkin $Date: October 6, 2010 14:42:13 $ //########################################################################### // // FILE: Example_2802xAdcSoc.c // // TITLE: f2802x ADC Start-Of-Conversion (SOC) Example Program. // // ASSUMPTIONS: // // This program requires the f2802x header files. // // Make sure the CPU clock speed is properly defined in // f2802x_Examples.h before compiling this example. // // Connect signals to be converted to A2 and A3. // // As supplied, this project is configured for "boot to SARAM" // operation. The 2802x Boot Mode table is shown below. // For information on configuring the boot mode of an eZdsp, // please refer to the documentation included with the eZdsp, // // $Boot_Table // While an emulator is connected to your device, the TRSTn pin = 1, // which sets the device into EMU_BOOT boot mode. In this mode, the // peripheral boot modes are as follows: // // Boot Mode: EMU_KEY EMU_BMODE // (0xD00) (0xD01) // --------------------------------------- // Wait !=0x55AA X // I/O 0x55AA 0x0000 // SCI 0x55AA 0x0001 // Wait 0x55AA 0x0002 // Get_Mode 0x55AA 0x0003 // SPI 0x55AA 0x0004 // I2C 0x55AA 0x0005 // OTP 0x55AA 0x0006 // Wait 0x55AA 0x0007 // Wait 0x55AA 0x0008 // SARAM 0x55AA 0x000A <-- "Boot to SARAM" // Flash 0x55AA 0x000B // Wait 0x55AA Other // // Write EMU_KEY to 0xD00 and EMU_BMODE to 0xD01 via the debugger // according to the Boot Mode Table above. Build/Load project, // Reset the device, and Run example // // $End_Boot_Table // // // DESCRIPTION: // // This example sets up the PLL in x12/2 mode. // // For 60 MHz devices (default) // (assuming a 10Mhz input clock). // // Interrupts are enabled and the ePWM1 is setup to generate a periodic // ADC SOC - ADCINT1. Two channels are converted, ADCINA4 and ADCINA2. // // Watch Variables: // // Voltage1[10] Last 10 ADCRESULT0 values // Voltage2[10] Last 10 ADCRESULT1 values // ConversionCount Current result number 0-9 // LoopCount Idle loop counter // // //########################################################################### // $TI Release: 2802x C/C++ Header Files and Peripheral Examples V1.29 $ // $Release Date: January 11, 2011 $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File // Prototype statements for functions found within this file. __interrupt void adc_isr(void); void Adc_Config(void); // Global variables used in this example: uint16_t LoopCount; uint16_t ConversionCount; uint16_t Voltage0[10]; uint16_t Voltage1[10]; uint16_t Voltage2[10]; uint16_t Voltage3[10]; uint16_t Voltage4[10]; uint16_t Voltage5[10]; uint16_t Voltage6[10]; uint16_t Voltage7[10]; uint16_t Voltage8[10]; uint16_t Voltage9[10]; uint16_t Voltage10[10]; uint16_t Voltage11[10]; uint16_t Voltage12[10]; uint16_t Voltage13[10]; uint16_t Voltage14[10]; uint16_t Voltage15[10]; Uint16 ACQPS_Value = 6; Uint16 u16SaveTrimOffset = 0; main() { // WARNING: Always ensure you call memcpy before running any functions from RAM // InitSysCtrl includes a call to a RAM based function and without a call to // memcpy first, the processor will go "into the weeds" #ifdef _FLASH memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize); #endif // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2803x_SysCtrl.c file. InitSysCtrl(); // Step 2. Initialize GPIO: // This example function is found in the f2802x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio(); // Skipped for this example // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the f2802x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in f2802x_DefaultIsr.c. // This function is found in f2802x_PieVect.c. InitPieVectTable(); // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected register PieVectTable.ADCINT1 = &adc_isr; EDIS; // This is needed to disable write to EALLOW protected registers // Step 4. Initialize all the Device Peripherals: // This function is found in f2802x_InitPeripherals.c // InitPeripherals(); // Not required for this example InitAdc(); // For this example, init the ADC AdcOffsetSelfCal(); EALLOW; // reset the RRPOINTER set to 0 will not work AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 16; EDIS; // Step 5. User specific code, enable interrupts: // Enable ADCINT1 in PIE PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE IER |= M_INT1; // Enable CPU Interrupt 1 EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM LoopCount = 0; ConversionCount = 0; EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; // GPIO1 output GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1; // Pullup's disabled for GPIO1 EDIS; EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // Disable pull-up on GPIO0 (EPWM1A) GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A EDIS; EALLOW; // SOC priority is handled in round robin mode for all channels. // before it was set to 16 to reset it because set to 0 will not work AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 0; EDIS; // Configure ADC //Note: Channel ADCINA4 will be double sampled to workaround the ADC 1st sample issue for rev0 silicon errata EALLOW; AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINT1 trips after AdcResults latch AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1 AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode AdcRegs.INTSEL1N2.bit.INT1SEL = 15; //setup EOC15 to trigger ADCINT1 to fire AdcRegs.ADCSOC0CTL.bit.CHSEL = 4; //set SOC0 channel select to ADCINA4 AdcRegs.ADCSOC1CTL.bit.CHSEL = 4; //set SOC1 channel select to ADCINA4 AdcRegs.ADCSOC2CTL.bit.CHSEL = 4; //set SOC2 channel select to ADCINA4 AdcRegs.ADCSOC3CTL.bit.CHSEL = 4; //set SOC3 channel select to ADCINA4 AdcRegs.ADCSOC4CTL.bit.CHSEL = 4; //set SOC4 channel select to ADCINA4 AdcRegs.ADCSOC5CTL.bit.CHSEL = 4; //set SOC5 channel select to ADCINA4 AdcRegs.ADCSOC6CTL.bit.CHSEL = 4; //set SOC6 channel select to ADCINA4 AdcRegs.ADCSOC7CTL.bit.CHSEL = 4; //set SOC7 channel select to ADCINA4 AdcRegs.ADCSOC8CTL.bit.CHSEL = 4; //set SOC8 channel select to ADCINA4 AdcRegs.ADCSOC9CTL.bit.CHSEL = 4; //set SOC9 channel select to ADCINA4 AdcRegs.ADCSOC10CTL.bit.CHSEL = 4; //set SOC10 channel select to ADCINA4 AdcRegs.ADCSOC11CTL.bit.CHSEL = 4; //set SOC11 channel select to ADCINA4 AdcRegs.ADCSOC12CTL.bit.CHSEL = 4; //set SOC12 channel select to ADCINA4 AdcRegs.ADCSOC13CTL.bit.CHSEL = 4; //set SOC13 channel select to ADCINA4 AdcRegs.ADCSOC14CTL.bit.CHSEL = 4; //set SOC14 channel select to ADCINA4 AdcRegs.ADCSOC15CTL.bit.CHSEL = 4; //set SOC15 channel select to ADCINA4 //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1, then SOC2, then SOC3, than ... AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC7CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC8CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC9CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC10CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC11CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC12CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC13CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC14CTL.bit.TRIGSEL = 5; AdcRegs.ADCSOC15CTL.bit.TRIGSEL = 5; //Set the ADC sample window to the desired value (Sample window = ACQPS + 1) AdcRegs.ADCSOC0CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC1CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC2CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC3CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC4CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC5CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC6CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC7CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC8CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC9CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC10CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC11CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC12CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC13CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC14CTL.bit.ACQPS = ACQPS_Value; AdcRegs.ADCSOC15CTL.bit.ACQPS = ACQPS_Value; /// enable SIMULATANEOUS SAMPLING AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN2 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN4 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN6 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN8 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN10 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN12 = 1; AdcRegs.ADCSAMPLEMODE.bit.SIMULEN14 = 1; EDIS; // Assumes ePWM1 clock is already enabled in InitSysCtrl(); EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTRU_CMPA; // Select SOC from from CPMA on upcount EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event EPwm1Regs.CMPA.half.CMPA = 0x7FFF; // Set compare A value EPwm1Regs.TBPRD = 0xFFFF; // Set period for ePWM1 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // count up and start // Set actions EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on CMPA EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // Wait for ADC interrupt for(;;) { /* Uint16 i; Uint32 temp; for (i = 0; i < 10; i++) { temp += Voltage0[i]; } MeanVoltage0 = temp; temp = 0; */ LoopCount++; } } __interrupt void adc_isr(void) { GpioDataRegs.GPATOGGLE.bit.GPIO1 = 1; Voltage0[ConversionCount] = AdcResult.ADCRESULT0; Voltage1[ConversionCount] = AdcResult.ADCRESULT1; Voltage2[ConversionCount] = AdcResult.ADCRESULT2; Voltage3[ConversionCount] = AdcResult.ADCRESULT3; Voltage4[ConversionCount] = AdcResult.ADCRESULT4; Voltage5[ConversionCount] = AdcResult.ADCRESULT5; Voltage6[ConversionCount] = AdcResult.ADCRESULT6; Voltage7[ConversionCount] = AdcResult.ADCRESULT7; Voltage8[ConversionCount] = AdcResult.ADCRESULT8; Voltage9[ConversionCount] = AdcResult.ADCRESULT9; Voltage10[ConversionCount] = AdcResult.ADCRESULT10; Voltage11[ConversionCount] = AdcResult.ADCRESULT11; Voltage12[ConversionCount] = AdcResult.ADCRESULT12; Voltage13[ConversionCount] = AdcResult.ADCRESULT13; Voltage14[ConversionCount] = AdcResult.ADCRESULT14; Voltage15[ConversionCount] = AdcResult.ADCRESULT15; // If 20 conversions have been logged, start over if(ConversionCount == 9) { ConversionCount = 0; } else ConversionCount++; AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE return; }

  • Rene,

    plese recall that in simultaneous mode always two Inputs are sampled at the same time, one from groupA and the other from groupB, e.g. A4 and B4. To take 16 samples you have to initialize only 8 SOC's - but you get 16 results. To take adavantage of the reduces conversion time in simultaneous mode you would have to connect your input-Signal to two ADC-Inputs (e.g. A4 and B4) then request 8 SOC's and read 16 results.

    .

     

  • Hello Frank

    You are right and its what I do. I put the same signal on A4 and B4.
    For testing I configured all 16 channels for ADC4 (the highest bit doesn't matter in simultaneous mode) and than I just switch the simultaneous mode on without deconfig the other channels.
    I expected thats not necessary.

    But why is the sequential mode faster than the simultaneous mode?

    Kind regards
    René

  • Sequential mode is not faster than simultaneous mode. Look at Joe's drawing and let's assume that ACQPS is set to 6 (which is minimum):

    In Sequential mode you will get two results (A4-CONV1, A4-CONV2) after 7+ 13 + (7-7) + 13 = 33 cycles.
    In SImultaneous mode you will get two results (A4-CONV1, B4-CONV1) after 7 + 13 + 13 = 33 cycles.

    If ACQPS must be longer, let's say 15 then you get:
    Seq: 16 + 13 + (16-7) + 13 = 51 cylces
    Sim: 16 + 13 + 13 = 42 cycles.

    Frank
  • "Sequential mode is not faster than simultaneous mode." - Your are right thats what I expect out of the datasheet.

    At minimum sample window both modes at the same rate Figure 33 and 35 in the datasheet.
    If its higher than the simultaneous mode is faster.

    The simultaneous are never slower than the sequential, right?

    But this is exactly my problem. With my example code above the simultaneous mode is 7us long and the sequential 4us. So nearly twice as fast as simultaneous mode.

    Could you test my code above?

    René
  • Rene,

    as mentioned in my first reply, for simultaneous mode you have to initialize and enable SOC0...SOC7 only - and connect your sensor-signal both to ADCINA4 and ADCINB4. This will generate 16 results.
    Your code, which enables all 16 SOC's will produce 32 results ( overwriting the first 16), which doesn't look correct.
    Therefore your measurement of 32 samples will of course take longer than a 16-SOC sequential run for 16 samples.

    Frank

  • How can I deconfig/disable the SOCs?
  • Hi Rene,

    I think you want to do this:

    //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1, then SOC2, then SOC3, than ...
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC7CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC8CTL.bit.TRIGSEL = 0
    AdcRegs.ADCSOC9CTL.bit.TRIGSEL = 0;
    AdcRegs.ADCSOC10CTL.bit.TRIGSEL = 0;
    AdcRegs.ADCSOC11CTL.bit.TRIGSEL = 0;
    AdcRegs.ADCSOC12CTL.bit.TRIGSEL = 0;
    AdcRegs.ADCSOC13CTL.bit.TRIGSEL = 0;
    AdcRegs.ADCSOC14CTL.bit.TRIGSEL = 0;
    AdcRegs.ADCSOC15CTL.bit.TRIGSEL = 0;
  • Hi Devin

    this was my first intention too but that doesn't work.

    If I change it I'll only get results from the first 8 channels.

    Here a printscreens of the AdcRegs and ADCRESULT with this config.

    Could you test my example above?

    René

     

  • Hi Rene,

    Sorry, after re-reading the documentation, I think you actually want this:

    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC7CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC8CTL.bit.TRIGSEL = 5

    AdcRegs.ADCSOC9CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC10CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC11CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC12CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC13CTL.bit.TRIGSEL = 0;

    AdcRegs.ADCSOC14CTL.bit.TRIGSEL = 5;

    AdcRegs.ADCSOC15CTL.bit.TRIGSEL = 0;

    SOC0 or SOC1 act as the same unit when using simultaneously sampling, so only one needs to be enabled.  The result from channel A goes into ADCRESULT0 and the result from channel B goes into ADCRESULT1.