LAUNCHXL-F280039C: UMCSDK PI current controller __fsat

Guru 56208 points

Part Number: LAUNCHXL-F280039C

Hello team,

We were able to stop motor deceleration DC voltage bouncing by diving the PI ±currents. The linear DC supply >13,000uF and the Inverter 1300uF bulk capacitors. The same motor and DC inverter functions well with trapezoidal waveform with this linear supply >16A sustained. I

            #else  // !MOTOR1_ISBLDC

                /* Reduce half the min/max deceleration current */
                if(bMainDecel)
                {
                    PI_setMinMax(obj->piHandle_spd, -obj->maxCurrent_A / 2 , obj->maxCurrent_A / 2);
                }
                else
                {
                    PI_setMinMax(obj->piHandle_spd, -obj->maxCurrent_A / 1.25, obj->maxCurrent_A / 1.25);
                }

                SVGEN_setMode(obj->svgenHandle, obj->svmMode);
            #endif  // !MOTOR1_ISBLDC

 When the motor estimated current is being set high as to reach the trajectory speed hertz, the PI integrator swings current wildly nonmonotonic linear ramp between the negative and positive integrator input values below! Oddly that also causes DC inductive voltage in the PI run series to bounce DC in Idq frame (motor1_drive.c).

Analyzing the PI set series function it seems __fsat missing but the compiler skips over it or  CCS cannot find it?

  Anyway the bMainDecel we added now stops DC bouncing in the PI min/max current controller during deceleration, also stops tripping OVC faults!  Yet still has excessive nonlinear Acceleration to trajectory current swings, seemingly caused by integrator in the PI current controller not saturating?

Why to use function __fsat ?

Why is the VsMaxV being multiplied by PU 0.5f? That math makes +165v DC bus voltage = 82.5VsMax. Notice the rotors Speed_Hz is not being factored into the PI integrator Error factor. That seemingly is causing the trajectory to fall behind because the current starts to lag the voltage by significant amount whenever Speed_Hz is < 1000 RPM. This motor requires 14-16 amps of current to reach well beyond 1000 RPM at the rated voltage 235vdc.

Oddly we can only set USER_MOTOR1_MAX_CURRENT_A   <=   10.535f or the PI starts to oscillate (bounce) the stator voltage when Speed_Hz >250Hz and still hear current bounce >420Hz. The problem is the current needs to be set >12A to cross the frequency barrier where the inertia moment is crossed at a specific Idq and rotor speed. The PI controller has to not overflow a 32-bit error multiplication! Yet it seems the float- 32 is overflowing the integrator Error in the PI_run function. Perhaps why Luminary Micro did 32-bit multiply in Thumb assembler, so CCS compiler optimizer does not affect the multiply of the speed integrator error amount. And the integral remains stable at most all rotor speeds when seemingly inductive current starts lagging behind the voltage more than a few hundred revolutions of the rotor >250Hz.  

Error = refValue - fbackValue;

// Compute the proportional output
Up = Kp * Error;

 // Maximum voltage output
obj->VsMax_V = objUser->maxVsMag_pu * obj->adcData.VdcBus_V;
PI_setMinMax(obj->piHandle_Id, -obj->VsMax_V, obj->VsMax_V);

  image.png

    // Maximum voltage output
    obj->VsMax_V = objUser->maxVsMag_pu * obj->adcData.VdcBus_V;
    PI_setMinMax(obj->piHandle_Id, -obj->VsMax_V, obj->VsMax_V);

#else     // !SFRA_ENABLE
        // run the Id controller
        PI_run_series(obj->piHandle_Id,
                      obj->IdqRef_A.value[0], obj->Idq_in_A.value[0],
                      obj->Vdq_ffwd_V.value[0], (float32_t*)&obj->Vdq_out_V.value[0]);

        // calculate Iq controller limits
        float32_t outMax_V = __sqrt((obj->VsMax_V * obj->VsMax_V) -
                          (obj->Vdq_out_V.value[0] * obj->Vdq_out_V.value[0]));

        PI_setMinMax(obj->piHandle_Iq, -outMax_V, outMax_V);

        // run the Iq controller
        PI_run(obj->piHandle_Iq, obj->IdqRef_A.value[1],
               obj->Idq_in_A.value[1], (float32_t*)&obj->Vdq_out_V.value[1]);
#endif  // !SFRA_ENABLE


#if defined(MOTOR1_FAST)
        // set the Id reference value in the estimator
        EST_setId_ref_A(obj->estHandle, obj->IdqRef_A.value[0]);
        EST_setIq_ref_A(obj->estHandle, obj->IdqRef_A.value[1]);
#endif  // MOTOR1_FAST
    }

  • The SDK v4.02 PI controls the motor speed may open some insight to why the integrator is bouncing the voltage. The UMCSDK code seems to enable and then disable the speed controller, mostly disable it during rotor Seek Position and Alignment.

    Does ramp versus step trajectory toggle with the speed controller being enabled/disabled during acceleration to the trajectory and there after?

    Observation: Something is rapidly switching PI speed controller on/off and becomes very noticeable each while loop cycle runMotor1Control(). Perhaps a bug in the ladder logic to start the motor also leaves the current controller in a vicarious state? If everything logic wise was working correctly we could set the motor current Max 16A and not see the voltage bouncing when the current is only 11A and the trajectory SpeedRef_Hz is not even close to being reached!   

    The edit code insert will not allow text toe added in the popup edit window, after we click OK button. The URL shows up under the window as if it is being saved but it does not save the edit in the post.

     
    //********************************************************** 
     // run the speed controller
        obj->counterSpeed++;
    
        if(obj->counterSpeed >= objUser->numCtrlTicksPerSpeedTick)
        {
            obj->counterSpeed = 0;
    
            obj->speed_reg_Hz = obj->speed_Hz;
    
            if(obj->enableSpeedCtrl == true)
            {
                obj->Is_ffwd_A = 0.0f;
    
    
    #if defined(SFRA_ENABLE)
                PI_run_series(obj->piHandle_spd,
                       (obj->speed_int_Hz + sfraNoiseSpd), obj->speed_reg_Hz,
                       obj->Is_ffwd_A, (float32_t *)&obj->IsRef_A);
    #else     // !SFRA_ENABLE
              PI_run_series(obj->piHandle_spd,
                    obj->speed_int_Hz, obj->speed_reg_Hz,
                    obj->Is_ffwd_A, (float32_t *)&obj->IsRef_A);
    #endif  // !SFRA_ENABLE

  • The differences between UMCSDK and SDK speed control trajectory Ramp and id current are enabled in the ISR. Seemingly ld is not being modulated 20Khz and more rapidly 120MHz SYSCLK speed? Below plot shows 25KHz modulates ld/Iq being very steady.

    How can we view in CCS debug the Id/Iq waveforms via MDAC Datalog?

    Perhaps the while loop runs faster and is out of phase with Instaspin 20KHz 21µs ISR period? Anyway, the 3 phase currents wave form is not linear, becomes bottle shaped at the beginning and ends of each while loop period as if something is switching on and off.

    LAB_is07 speed control ramp

    //
    // run Clarke transform on voltage
    //
    CLARKE_run(clarkeHandle_V, &adcData.V_V, &(estInputData.Vab_V2));
    
    counterTrajSpeed++;
    
    /* Check against user.h value of IsrPerTrajTicks */
    if(counterTrajSpeed >= userParams.numIsrTicksPerTrajTick)
    {
        //
        // clear counter
        //
        counterTrajSpeed = 0;
    
        //
        // run a trajectory for speed reference,
        // so the reference changes with a ramp instead of a step
        //
        TRAJ_run(trajHandle_spd);
    
        motorVars.speedTraj_Hz = TRAJ_getIntValue(trajHandle_spd);
    }

  • Why is the PI control integrator being reset to 0.0f in the speed control section as if switching back to closed loop each 21µs period? Would it be more prudent to keep the integrator at an intermediate value as the phase current begins to rise with Speed_Hz? The motor is already in closed loop control when the speed controller was enabled?

    Seemingly the last value in the integrator should be the last static value whenever motor frequency > the force_Hz value. That way the ld current is not oscillating up and down each PI cycle? Small motor rotors jump up to 500Hz <500ms and the integrator being zeroed each cycle is not an issue for them but Industrial or automotive IPM/SPM motors >8Kg rotors (loaded) may take few seconds to reach 500Hz.

    The PI integrator controls the proportion and integral in the Id current?   

    Note the user torque current was initially set equal isSet_A and further down initialized it to 0.0f

    else if((obj->motorState >= MOTOR_CL_RUNNING) &&
                                           (obj->flagMotorIdentified == true))
    {
         if(obj->speed_int_Hz > 0.0f)
         {
              /* Set the user torque current */
              obj->IsRef_A = obj->IsSet_A;//0.0f
        }
        else
       {
              obj->IsRef_A = -obj->IsSet_A; //0.0f
        }

        // for switching back speed closed-loop control
        PI_setUi(obj->piHandle_spd, obj->IsRef_A);
    }

    This code change regulates Speed_Hz ±1Hz of the set SpeedRef_Hz and does regulate phase current in the 21µs ISR. Seemingly the PI Id could use similar Ui update?

     else if((obj->motorState >= MOTOR_CL_RUNNING) &&
    (obj->flagMotorIdentified == true))
    {
        /* Use the RMS phase currents */
        obj->IsRef_A = obj->Is_A;

    if(obj->speed_int_Hz == 0.0f)
    {
         /* Reset the integrator Ui */
        obj->IsRef_A = obj->IsSet_A; //0.0f
    }
    else if(-obj->speed_int_Hz == 0.0f)
    {
        obj->IsRef_A = -obj->IsSet_A; //0.0f
    }

         /* Update the Speed PI Ui value */
         PI_setUi(obj->piHandle_spd, obj->IsRef_A);
    }

  • Oddly the Id/Iq simulations we ran some time ago disagree with the speed PI min/max being set 1/2 the DC bus voltage. And Id/Iq being less than 7/8ths the DC supply voltage seems very wrong! Especially as current lags behind the voltage when the frequency rises the DC voltage should not be oscillating up and down. We set the filter pole RC for 1020Hz 39nF and the same problem exists. The voltage magnitude in UMCSDK is somehow being modulated by the current controller in each update of the ld/Iq controllers.

    This same issue existed in SDK versions but was much worse and has never been corrected in UMCSDK code.  

    Note in the DQ simulation we don't see the DC voltage drop to 1/2 and remains very close to the 138v simulated bus voltage. That being said the vdq_ffwd value only sets one time the current controller in the while loop then updates only ki/kp values. Perhaps the bottleneck in the PI controller as the integral seems to be way off or it overflows via _fsat compiler internal float32 multiplication of the PI Error value.   

    if(obj->enableCurrentCtrl == true)
    {
         obj->Vdq_ffwd_V.value[0] = 0.0f;
         obj->Vdq_ffwd_V.value[1] = 0.0f;

    // Half the Maximum DC voltage output
    obj->VsMax_V = objUser->maxVsMag_pu * obj->adcData.VdcBus_V;

    PI_setMinMax(obj->piHandle_Id, -obj->VsMax_V, obj->VsMax_V);

  • The InstaSPIN-FOC still uses typical FOC control loop. The Vd, Vq, and Id, Iq must meet the voltage circle and current circle limitation. So the sqrt(Vd*Vd + Vq*Vq)<sqrt(3)/2*Vdc or <0.5Vdc if overmodulation is disabled.

  • The voltage magnitude in UMCSDK is somehow being modulated by the current controller in each update of the ld/Iq controllers.

    Hi Jiaxin,

    Oddly when multiplying Rs ohms x2 (user_mtr1.h) the acceleration oscillations stopped. I would expect motor ID to test P2P resistance measures. Seemingly what motor ID detected was single phase Rs Ohms? This is a Delta winding motor, not a Star, and the neutral center point is not valid!

    AC behaves differently in a Delta winding and motor ID does not consider the difference?

      What was recently discovered; the 1ms timing loop decrement count (motor_common.c) is not in the same clock context as the SYSCLK forever while loop. Nobody would ever think to look for decrement counter causing timing issues. It is better to keep all timing loops in the same clock context (C module) and remove 1ms CPU timer in the forever while loop, seemingly it is way to slow and does not conflict with main ISR 21µs loop when switch case then has  100-200 increment counter for 1ms.

     Then switch case (motor monitor) has 5-23µs period and RMS current measures become more synchronous with 20KHz 50µs period in the main ISR loop. Just reset/load counters and decrement or increment monitor counts in runMotor1Control() while loop context. Motor ID will run when we reset the count to 0 and other test counts for flying restart / startup run timings set in user_mtr1.h. The motor wait restart timing was never loaded with an initial count, initMotor1CtlParameters()..

    BTW: if we decelerate motor in while control loop, random restarts are not a current control problem and never were in SDK code versions. Then restart is not regenerating energy during trajectory-controlled decelerations when the phase current is divided in half. 

    What this code snip actually does with uint16_t  

    // decrements count backwards??
    if(obj->stopWaitTimeCnt > 0)
    {
       obj->stopWaitTimeCnt--;

    }

    // Reset stopWaitTimeCnt or ID will not run when decrement the count in the same context. 

    if(EST_isMotorIdentified(obj->estHandle) == true)
    {
        obj->flagMotorIdentified = true;

        // clear the flag
        obj->flagRunIdentAndOnLine = false;
        obj->flagEnableRunAndIdentify = false;

        /* set state stop idle */
        obj->motorState = MOTOR_STOP_IDLE;
        /* set wait zero to restart motor */
        obj->stopWaitTimeCnt = 0;

        // disable the estimator
        EST_disable(obj->estHandle);

        // enable the trajectory generator
        EST_disableTraj(obj->estHandle);
    }

  • Hey Jiaxin,

    So the sqrt(Vd*Vd + Vq*Vq)<sqrt(3)/2*Vdc or <0.5Vdc if overmodulation is disabled.

    Yet the motor phase voltage was far less than simulations with over-modulation disabled. And +130v motor phase voltage was roughly +86v.

    Seemingly the Bus voltage SF is set lower than PU 0.5vdc? The motor was being starved for DC voltage so it could reach higher speeds at lower Hertz in the magnetic flux, not just the current being pushed higher. Current lags behind voltage in an inductor!

       

  • Hi Genatco,

    What simulation software did you use? Did you replicate the same system in MATLAB/Simulink? Could you elaborate how the simulation was conducted?

    Thanks,

    Jiaxin

  • Hi Jiaxin,

    Did you replicate the same system in MATLAB/Simulink?

      Yes, Simulink before SDK4.0 even existed, hence puzzlement as to why older trapezoidal FOC our motor will reach much greater RPM than with FAST estimator at the same DC voltage. Yet the current is much higher with older trapezoidal FOC but there is at least 450 RPM reduced speed via FAST estimator determined via reflective laser speed checks on the rotor shaft. This motor should reach at least 1650 RPM but FAST is struggling 1350 RPM. The odd thing, one time see rotor speed jumped up to 1750 RPM by DC inverter with no snubbers when the speedRef_Hz was dropped then raised back up by slider pot on LCD screen, Though Kp_spd was 42.0023456770 very stiff PI control over the rotor inertia, now Kp_spd roughly 0.02345678 for example have no idea why it dropped down like this.  

      With FAST the motor Vd/Vq  get very noisy around 400Hz even with 1RC & LSS snubbers added each half bridge and three new INA241 current amplifiers. Our filter pole cut off roughly 49nF/3.9k with 30% headroom in the ADC. We check motor ID at 170vdc, and it gives a fairly accurate inductance 350H, Rs Ohms, Rated Flux values. The Vd/Vq on scope probes are at bus voltage peaks. Except for +10v Offset above ground. Is it possible the trapezoidal high side HO drive behave differently than does Vd/Vq being offset? Seem to recall the differential voltage of HO being 10v greater than LO with trapezoidal FOC.  

    Oddly motor ID entry drives OVC the first time it runs but asserts Rover/L after the current fault is cleared. At 170vdc OVC fault motor makes snap sound, not so great on the NFETS as the flyback EMF is excessive! Perhaps something in restartMotorControl() is causing the Rover/L to drive excessive current the first time it is run? Seemingly USER_setMotor1Params() sets userParams_M1.RoverL_excFreq_Hz = USER_M1_R_OVER_L_EXC_FREQ_Hz (250Hz) but there is no motorSetVars_M1.RoverL_rps value until the first ID run. Recall we used to set the user parameter in the (user.h) motor values, seems to be missing in the UMCSDK.

    Q: Will FW produce higher or lower magnitude Vd/Vq? Our motor is not IPM, but Copilot suggest FW method to increase speed. We test with two different DC inverters that have similar issues with FAST.

    And we notice CCS debug Kp_spd value has become far less than 42.0f it was being set before then after disabling PI tuning function. So now the motor has some over/under shoot not acting as stiff around the speedRef_Hz.