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.

TMS320F28069F: InstaSPIN-FOC Lab11a project

Part Number: TMS320F28069F
Other Parts Discussed in Thread: MOTORWARE,

Hi Yanming Luo,

I have a question on an InstaSPIN-FOC Lab project in motorware.

Particularly it is on Lab11a.

We are presently attempting to implement the function of variable PWM frequency on Lab11a.

For this work, we need to split the source codes in mainISR() into two ISR funtions of fixed frequency and variable frequency as in the is12_variable_pwm_frequency lab in MotorControl_SDK.

Meanwhile in my previous post, you advised how to split the source codes in mainISR() into two ISR funtions; it is to run all of the speed, Id and Iq controllers in estISR().

However, with reference to the is12_variable_pwm_frequency lab in MotorControl_SDK, I have found out that the estISR() runs the speed controller while the mainISR() runs the Id and Iq controllers.

Please comment on this observation.

Thank you for your guidance.

With regards,

JS Yoo

  •  Yes, the Id and Iq PI controller can be called in either estISR or mainISR. It's better to call in mainISR(). It's better to change the Kp and Ki with PWM frequency if you need a good current control performance.

  • Hi Yanming Luo,

    Thank you for your review.

    First of all, our inverter built by using the TMS320F28069F runs very well in the environment of Lab11a.

    In order to implement the function of variable PWM frequency on Lab11a, I have completed the work of splitting the source codes in mainISR() into two ISR funtions of estISR() and mainISR() similar to is12_variable_pwm_frequency lab in MotorControl_SDK.

    All functions associated with reading the ADC result, writing PWM compare registers, the overmodulation and current reconstruction, and the Id and Iq controls  reside in mainISR(), whereas the other functions associated with the speed control and ESTrun() reside in estISR().

    Now when I attempt to run the motor with this modified Lab11a project, the motor generates noisy sound. It seems that the magnetic flux is not generated suitably.

    Therefore I compared the source codes in estISR() of the is12_variable_pwm_frequency project with those in mainISR() of the Lab11a.

    First, the source codes in estISR() of the is12_variable_pwm_frequency project are as follows:

            //
            // store the input data into a buffer
            //
            estInputData.dcBus_V = adcData.dcBus_V;
            estInputData.speed_ref_Hz = motorVars.speedTraj_Hz;
            estInputData.speed_int_Hz = motorVars.speedTraj_Hz;

            //
            // run the estimator
            //
            EST_run(estHandle, &estInputData, &estOutputData);

    The input parameters for EST_run() are provided ahead of calling the EST_run() function.

    Second, the source codes in mainISR() of the Lab11a are as follows:

      // run Clarke transform on current
      CLARKE_run(clarkeHandle_I,&gAdcData.I,&Iab_pu);

      // run Clarke transform on voltage
      CLARKE_run(clarkeHandle_V,&gAdcData.V,&Vab_pu);

      // run a trajectory for Id reference, so the reference changes with a ramp instead of a step
      TRAJ_run(trajHandle_Id);

      // run the estimator
      EST_run(estHandle,
              &Iab_pu,
              &Vab_pu,
              gAdcData.dcBus,
              TRAJ_getIntValue(trajHandle_spd));

    Two CLARKE_run() functions need to reside in mainISR() while the EST_run() function need to reside in estISR().

    The parameters for this EST_run() seem to be input parameters except the estHandle.

    In summary the ways that EST_run() function is used in the is12_variable_pwm_frequency project and Lab11a are quite different.

    Please inform us if it is impossible to implement the function of variable PWM frequency with the motorware FAST estimator library.

    We are ready to build a new inverter by using the TMS320F28004xC device and the MotorControl_SDK FAST estimator library.

    Otherwise please provide us with the modified Lab11a project which have the function of variable PWM frequency .

    Thank you for your guidance.

    With regards,

    JS Yoo

  • You might try to use the same frequency for mainISR() and EST_run() without online change PWM frequency to see what happens.

    And which frequency are you using to calculate the estimator parameters?

  • Hi Yanming Luo,

    Thank you for your review.

    What I did is as follows.

    (1) With respect to the original Lab11a, the PWM frequency was 8kHz and the inverter runs the motor very well.

    (2) With respect to the modified Lab11a, at first, the execution frequency for estISR() was set to 20kHz and the execution frequency for mainISR() was set to 8kHz. The motor does not run and generates noisy sound.

    (3) With respect to the modified Lab11a, secondly, the execution frequency for both estISR() and mainISR() was set to 8kHz. The motor does not run and generates noisy sound.

    What do mean by "to calculate the estimator parameters"?

    What are the estimator parameters?

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Please post the user.h and lab main file you used.

  • Hi Yanming Luo,

    Thank you for your review.

    Please enclosed find the source codes for estISR() and mainISR().

    I just splitted the source codes of the original mainISR() in Lab11a  into two ISR funtions of estISR() and the new mainISR().

    ------------------------------------------------------------------------------------------------------------------------------------

    _iq angle_pu = _IQ(0.0);
    _iq speed_pu = _IQ(0.0);
    MATH_vec2 Iab_pu;
    MATH_vec2 Vab_pu;
    MATH_vec2 phasor;

    //
    // the CPU timer0 interrupt as FAST estimator ISR
    //
    interrupt void estISR(void)
    {
        // acknowledge the interrupt that is set for estimator
        HAL_acqTimer0Int(halHandle);

    //    if(gTrjCnt >= gUserParams.numCtrlTicksPerTrajTick)
    //    {
    //        // clear counter
    //        gTrjCnt = 0;

            // run a trajectory for speed reference, so the reference changes with a ramp instead of a step
            TRAJ_run(trajHandle_spd);
    //    }

            // run the estimator
            EST_run(estHandle,
                    &Iab_pu,
                    &Vab_pu,
                    gAdcData.dcBus,
                    TRAJ_getIntValue(trajHandle_spd));

            // generate the motor electrical angle
            angle_pu = EST_getAngle_pu(estHandle);
            speed_pu = EST_getFm_pu(estHandle);

            // get Idq from estimator to avoid sin and cos
            EST_getIdq_pu(estHandle,&gIdq_pu);

            // run the appropriate controller
            if((gMotorVars.Flag_Run_Identify) || (gMotorVars.Flag_enableRsRecalc))
              {
                // when appropriate, run the PID speed controller
                if((pidCntSpeed++ >= gUserVars.numCtrlTicksPerSpeedTick) && (!gMotorVars.Flag_enableRsRecalc))
                  {
                    // calculate Id reference squared
                    _iq Id_ref_squared_pu = _IQmpy(PID_getRefValue(pidHandle[1]),PID_getRefValue(pidHandle[1]));

                    // Take into consideration that Iq^2+Id^2 = Is^2
                    _iq Iq_Max_pu = _IQsqrt(gIs_Max_squared_pu - Id_ref_squared_pu);

                    // clear counter
                    pidCntSpeed = 0;

                    // Set new min and max for the speed controller output
                    PID_setMinMax(pidHandle[0], -Iq_Max_pu, Iq_Max_pu);

                    // run speed controller
                    PID_run_spd(pidHandle[0],TRAJ_getIntValue(trajHandle_spd),speed_pu,&(gIdq_ref_pu.value[1]));
                  }
              }

    }


    //! \brief     The main ISR that implements the motor control.
    interrupt void mainISR(void)
    {
      _iq oneOverDcBus;

      // acknowledge the ADC interrupt
      HAL_acqAdcInt(halHandle,ADC_IntNumber_1);

      // convert the ADC data
      HAL_readAdcDataWithOffsets(halHandle,&gAdcData);

      // remove offsets
      gAdcData.I.value[0] = gAdcData.I.value[0] - gOffsets_I_pu.value[0];
      gAdcData.I.value[1] = gAdcData.I.value[1] - gOffsets_I_pu.value[1];
      gAdcData.I.value[2] = gAdcData.I.value[2] - gOffsets_I_pu.value[2];
      gAdcData.V.value[0] = gAdcData.V.value[0] - gOffsets_V_pu.value[0];
      gAdcData.V.value[1] = gAdcData.V.value[1] - gOffsets_V_pu.value[1];
      gAdcData.V.value[2] = gAdcData.V.value[2] - gOffsets_V_pu.value[2];

      // run the current reconstruction algorithm
      runCurrentReconstruction();

      // run Clarke transform on current
      CLARKE_run(clarkeHandle_I,&gAdcData.I,&Iab_pu);

      // run Clarke transform on voltage
      CLARKE_run(clarkeHandle_V,&gAdcData.V,&Vab_pu);

      // run a trajectory for Id reference, so the reference changes with a ramp instead of a step
      TRAJ_run(trajHandle_Id);

      // run the appropriate controller
      if((gMotorVars.Flag_Run_Identify) || (gMotorVars.Flag_enableRsRecalc))
        {
          _iq refValue;
          _iq fbackValue;
          _iq outMax_pu;

          // get the reference value from the trajectory module
          refValue = TRAJ_getIntValue(trajHandle_Id) + EST_getRsOnLineId_pu(estHandle);

          // get the feedback value
          fbackValue = gIdq_pu.value[0];

          // run the Id PID controller
          PID_run(pidHandle[1],refValue,fbackValue,&(gVdq_out_pu.value[0]));

          // set Iq reference to zero when doing Rs recalculation
          if(gMotorVars.Flag_enableRsRecalc) gIdq_ref_pu.value[1] = _IQ(0.0);

          // get the Iq reference value
          refValue = gIdq_ref_pu.value[1];

          // get the feedback value
          fbackValue = gIdq_pu.value[1];

          // calculate Iq controller limits, and run Iq controller
          _iq max_vs = _IQmpy(gMotorVars.OverModulation,EST_getDcBus_pu(estHandle));
          outMax_pu = _IQsqrt(_IQmpy(max_vs,max_vs) - _IQmpy(gVdq_out_pu.value[0],gVdq_out_pu.value[0]));
          PID_setMinMax(pidHandle[2],-outMax_pu,outMax_pu);
          PID_run(pidHandle[2],refValue,fbackValue,&(gVdq_out_pu.value[1]));

          // compensate angle for PWM delay
          angle_pu = angleDelayComp(speed_pu, angle_pu);

          // compute the sin/cos phasor
          phasor.value[0] = _IQcosPU(angle_pu);
          phasor.value[1] = _IQsinPU(angle_pu);

          // set the phasor in the inverse Park transform
          IPARK_setPhasor(iparkHandle,&phasor);

          // run the inverse Park module
          IPARK_run(iparkHandle,&gVdq_out_pu,&Vab_pu);

          // run the space Vector Generator (SVGEN) module
          oneOverDcBus = EST_getOneOverDcBus_pu(estHandle);
          Vab_pu.value[0] = _IQmpy(Vab_pu.value[0],oneOverDcBus);
          Vab_pu.value[1] = _IQmpy(Vab_pu.value[1],oneOverDcBus);
          SVGEN_run(svgenHandle,&Vab_pu,&(gPwmData.Tabc));

          // run the PWM compensation and current ignore algorithm
          SVGENCURRENT_compPwmData(svgencurrentHandle,&(gPwmData.Tabc),&gPwmData_prev);

    //      gTrjCnt++;
        }
      else if(gMotorVars.Flag_enableOffsetcalc == true)
        {
          runOffsetsCalculation();
        }
      else
        {
          // disable the PWM
          HAL_disablePwm(halHandle);

          // Set the PWMs to 50% duty cycle
          gPwmData.Tabc.value[0] = _IQ(0.0);
          gPwmData.Tabc.value[1] = _IQ(0.0);
          gPwmData.Tabc.value[2] = _IQ(0.0);
        }

      // write the PWM compare values
      HAL_writePwmData(halHandle,&gPwmData);

      // run function to set next trigger
      if(!gMotorVars.Flag_enableRsRecalc) runSetTrigger();

      return;
    } // end of mainISR() function


    //! \brief     Acknowledges an interrupt from Timer 0 so that another Timer 0 interrupt
    //!            can happen again.
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    static inline void HAL_acqTimer0Int(HAL_Handle handle)
    {
        HAL_Obj *obj = (HAL_Obj *)handle;

        // clear the Timer 0 interrupt flag
        TIMER_clearFlag(obj->timerHandle[0]);

        // Acknowledge interrupt from PIE group 1
        PIE_clearInt(obj->pieHandle,PIE_GroupNumber_1);

        return;
    } // end of HAL_acqTimer0Int() function

    ---------------------------------------------------------------------------------------------------------------------------

    A more explanation is as follows:

    (1) Timer0 interrupt generates the estISR(). I have confirmed that the estISR() is executed with a period of 8kHz.

    (2) The mainISR() is also executed with a period of 8kHz.

    (3) That is all. I just splitted two ISRs.

    (4) You may have to check if my splitting work is correct.

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Please upload the files user.h and proj_x.c, so we understand how do you calculate the parameters for the instaspin-foc and FAST estimator. Don't paste the code directly.

  • Hi Yanming Luo,

    Thank you for your review.

    I have uploaded four files including hal.c and hal.h.

    (I have just dragged the files into this window. Is this correct?)

    I have not yet implemented the function of the variable PWM frequency.

    I just splitted the original mainISR() into two ISRs of estISR() and mainISR() in order to confirm whether our motor runs well or not when two ISRs are employed.

    With the original mainISR(), our motor runs very well.

    Two ISRs are executed at 8kHz.

    Thank you for guidance.

    With regards,

    JS Yoo

    14607.user.h

    8838.hal.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /* --COPYRIGHT--,BSD (proj_lab11a_TI)
    * Copyright (c) 2012, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    lab11a_VariablePWM.c
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /* --COPYRIGHT--,BSD (lab11a_VariablePWM.c)
    * Copyright (c) 2015, Texas Instruments Incorporated
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    *
    * * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    1460.hal.h

  • As mentioned above, run all functions in estISR() except HAL_readAdcDataWithOffsets() and HAL_writePwmData(), and disable all of the additional features like over-modulation and Rs online calibration. Make sure that the estISR frequency is set correctly as the USER_ISR_FREQ_Hz.

  • Hi Yanming Luo,

    Thank you for your review.

    I need the space vector overmodulation and current reconstruction functions.

    Do you mean that the space vector overmodulation and current reconstruction functions should be abandoned if the function of variable PWM frequency has to be implemented for the F28069F DSP along with the estmator library in motorware?

    Meanwhile the is12_variable_pwm_frequency lab in MotorControl_SDK enables the space vector overmodulation and current reconstruction functions in implementing the function of variable PWM frequency for the F280049C DSP along with the estmator library in MotorControl_SDK .

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Just want you can verify if the ISR frequency is right and the estimator parameters are set correctly. Don't recommend that using over-modulation and current reconstruction for variable frequency.

  • Hi Yanming Luo,

    Thank you for your review.

    You mean that you do not recommend using over-modulation and current reconstruction for variable frequency.

    Is this associated with both F280049C and F28069F?

    You know that the is12_variable_pwm_frequency lab in MotorControl_SDK enables the space vector overmodulation and current reconstruction for variable PWM frequency on F280049C.

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Yes, both although the example project uses over-modulation since the performance is not good.