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.

LAUNCHXL-F280049C: SDK motor ID control status messages

Guru 56358 points

Part Number: LAUNCHXL-F280049C
Other Parts Discussed in Thread: C2000WARE-MOTORCONTROL-SDK, C2000WARE, MOTORWARE

Hello,

Need to print motor ID 3 tear controller status messages seen in debug Expressions view via java script. Oddly they are not part of the java script and seem debug simulator can port these (struct enum) status messages directly to expressions view pain. Is there some other file the estimator status messages are being staged?

Trying to print the speed controller motor ID messages to external device via est.h/ctrl.h inline calls gives "handle not defined" as it was never exported from isLAB's. And the controller (struct enum) status messages are not linked to motorVars shown code snip below. The status message sent at start of motor ID is only (k), versus expected Est_State_Online.

Has handle error been fixed in motor control SDK v4.02 and how could get ID status have not been made part of the est.h Inlines? Did SDK intend laptop computers CCS debug to determine each motor ID? Assume that was the case then assembly line workers use JTAG or CAN dongle rather than a lightweight handheld or application integrated motor ID when temperatures fall below freezing. We can't expect Lq/Ld inductance will be anywhere close to the values determined at room temperature or even desert heat conditions. Ideally motor ID process needs to be refined as highspeed runtime algorithms in the very near future. Though for now baby steps later jump into the fire with some real ammunition. 

 

    char EstCtrlState[30];
    char EstState[30];
    char TrajectState[30];

/* Synchronize current states */
EstCtrlState[0] = motorVars.ctrlState;
EstState[0] = motorVars.estState;
TrajectState[0] = motorVars.trajState;

EstCtrlState[0] = CTRL_getState(ctrlHandle); // Handle not defined error

//! \brief Gets the controller state
//! \param[in] handle The controller (CTRL) handle
//! \return The controller state
static inline CTRL_State_e CTRL_getState(CTRL_Handle handle)
{
CTRL_Obj *obj = (CTRL_Obj *)handle;

return(obj->state);
} // end of CTRL_getState() function

  • I'm having a little trouble following what you're trying to do. Are you saying you're trying to add some variables to the one of the InstaSPIN lab js files (like is05_motor_id.js) but it's not working? Does CCS let you add that same variable to the Expressions Window manually?

    Whitney

  • Hi Whitney,

    CCS is not being used to display the status results of the three variables. I was somewhat able to get the 3 tier struct enum status messages to print by  copying them into the output function as "text". Though motorVars.xyz  are not being passed the updated enumerated numbers of the struct as they change, when the controller or estimator global update functions are being polled by the LAB.

    The object handles to the calling inline estimator functions are a symbol train wreck. They cannot be called from any other function without causing compiler symbol not defined or missing errors. Even if we move few LAB handles into ctrl.h as externs, the calling LAB #includes to ctrl.h do not link the handle symbols to the enumerated structs. Even after cleaning the project, rebuilding the index, closing CCS, reopen CCS rebuild the index the LAB module #includes "est.h", "ctrl.h" are useless.

    Adding include paths to the project folders in the SDK under c:\ti does not help the symbol missing errors and changing order module #includes makes no difference CCS v12.2. These object handle Symbols cannot be found by the compiler as they were added to the LAB's C file, not the headers of the individual source files they belong to. The added includes that should indicate symbols new location do not work when they are moved into the header belonging to the source file. Most handles seem to work but these two below fail miserably as for mentioned.

    CTRL_Handle ctrlHandle; //!< the handle for the controller
    CTRL_Obj ctrl;                  //!< the controller object

    Does CCS let you add that same variable to the Expressions Window manually?

    They (motorVars.xyz) are already in the java script along with the struct enumerated messages as drop down boxes being the point they are not easily exported to SCI, SPI, CAN or any other peripheral. The structure of the motor Identify status messages derived from the ROM embedded estimator needs checkup.

    These are the LAB global updates and are not passing enumerated struct status message or the number to the extern variables in another polling function. They are not pointers (ui16EstCtrlState, uin16EstState, Ui16TrajectState) are the global externs in another polling function since motorVars.xyz fail to pass the enumerated strut member number as it changes status messages. See how complicated motor ID status messages was made. We should be able to call below estimator functions handles from any other project function other than labs.c or isLABs without symbol missing not defined errors occurring. 

    /* Update the HID */
    ui16EstCtrlState = CTRL_getState(ctrlHandle);

    static inline void updateGlobalVariables(EST_Handle estHandle)
    {

    motorVars.estState = EST_getState(estHandle);
    /* Update the HID */
    ui16EstState = motorVars.estState;
    //
    motorVars.trajState = EST_getTrajState(estHandle);
    /* Update the HID */
    ui16TrajectState = motorVars.trajState;

    }

  • I'm having a little trouble following what you're trying to do.

    Below is the call to the enumerated list of controller messages displayed in CCS debug Expressions window. The enumerated tag (CTRL_State_e) used in the inline call is not returning the number of the asserting messages back to the caller of the list. The return only seems to occur in CCS debug expressions window but not to any other caller of the inline.

    //! \brief Gets the controller state
    //! \param[in] handle The controller (CTRL) handle
    //! \return The controller state
    static inline CTRL_State_e CTRL_getState(CTRL_Handle handle)
    {
       CTRL_Obj *obj = (CTRL_Obj *)handle;
    
       return(obj->state);
    } // end of CTRL_getState() function
    
    typedef enum
    {
         CTRL_STATE_ERROR = 0, //!< the controller error state
         CTRL_STATE_IDLE = 1, //!< the controller idle state
         CTRL_STATE_OFFLINE = 2, //!< the controller offline state
         CTRL_STATE_ONLINE = 3, //!< the controller online state
         CTRL_NUMSTATES = 4 //!< the number of controller states
       // CTRL_RESERVED = 0x10000 //!< reserved to force 32 bit data
    } CTRL_State_e;
    #endif

  • Thanks for the additional details. I was able to add a call to CTRL_getState to updateGlobalVariables() by adding an extern for ctrlHandle to the labs.h file like there was for estHandle already.

    Do your ui16EstCtrlState, uin16EstState, ui16TrajectState variables contain the expected values? Are you able to display them in the Expressions window? Are they type uint16_t instead of the enumerated type?  If you're seeing issues with them having values different from  their motorVars counterparts, it could be optimization related--do you have them declared as volatile or with the retain attribute?

    They (motorVars.xyz) are already in the java script along with the struct enumerated messages as drop down boxes being the point they are not easily exported to SCI, SPI, CAN or any other peripheral. The structure of the motor Identify status messages derived from the ROM embedded estimator needs checkup.

    Are you saying you'd like to be able to send a string representing the enum value name instead of the integer value (like "CTRL_STATE_ERROR" instead of "0")? I'm not aware of any way to do this beyond manually declaring a table of strings into your code and indexing into it based on the state variable value.

    Whitney

  • Do your ui16EstCtrlState, uin16EstState, ui16TrajectState variables contain the expected values?

    No, they all pass enum number 3 (STATUS_~ONLINE) and never changes when expressions status does. Hence the HID can be online monitor the expressions view too, though not necessary. .

    Are you saying you'd like to be able to send a string representing the enum value name instead of the integer value (like "CTRL_STATE_ERROR" instead of "0")? I'm not aware of any way to do this beyond manually declaring a table of strings into your code and indexing into it based on the state variable value.

    The method of transport is serial string, thought the enumerated messages are symbols and should be linked to the number of the struct enum member. The struct enum key tag with a member number should port the symbol name via address but the linker does not handle backward symbolic expressions using the struct key as a pointer to the named symbol. So it makes for a lot of copy paste and added code WA shown below.

    The compiler does not allow keyword (extern) on struct enum list key tag and the enum list can't become a global export. Hence the linker has no idea what the app C code is referencing. This is symbolic C code and should be able to port the enum names just as easily as any enum member number which is broken too.

    Note I later added a tick count as serial data rate (115200) can flood terminal. Application don't use SCIprintf() but is similar to HID. 

    // Globals
    extern uint16_t ui16TrajectState;
    
    // Prototypes
    uint16_t ui16TrajectState;
    char* CchrTrajectState[4];
    
    static uint16_t ui8TickIntCount2 = 0;
        
        /* Check the states changed */
        if(ui8TickIntCount2 <= 10)
        {
            /* Clear count */
            //ui8TickIntCount2 = 0;
            /* Increment pass count */
            ui8TickIntCount2 ++;
    
            /* Trajectory Controler States */
            if(ui16TrajectState == motorVars.trajState)//motorVars.trajState
            {
                CchrTrajectState[ui16TrajectState] = "EST_TRAJ_STATE_ERROR";  //!< the trajectory generator error state
                CchrTrajectState[ui16TrajectState] = "EST_TRAJ_STATE_IDLE";   //!< the trajectory generator idle state
                CchrTrajectState[ui16TrajectState] = "EST_TRAJ_STATE_EST";    //!< the trajectory generator parameter estimation state
                CchrTrajectState[ui16TrajectState] = "EST_TRAJ_STATE_ONLINE"; //!< the trajectory generator online state
    
                /* Trajectory state text box strings */
               SCIprintf(">>TrajectState->%s \n", CchrTrajectState[ui16TrajectState]);
           
            }
            
                    /* Check count intervals */
            if(ui8TickIntCount2 >= 10)
            {
                /* Clear count */
                ui8TickIntCount2 = 0;
            }
        }

  • No, they all pass enum number 3 (STATUS_~ONLINE) and never changes when expressions status does.

    Does it make a difference if you disable optimization or make the variable volatile? I'm wondering if the compiler's doing something to remove the update or if the "get" function is actually executing.

    The method of transport is serial string, thought the enumerated messages are symbols and should be linked to the number of the struct enum member. The struct enum key tag with a member number should port the symbol name via address but the linker does not handle backward symbolic expressions using the struct key as a pointer to the named symbol. So it makes for a lot of copy paste and added code WA shown below.

    You could go ask over on the CCS/Compiler forum to see if they have any ideas. Maybe there's some compiler feature that I'm just not aware of. As far as I know, CCS is able to populate it in the Expressions window because it parses the files used in the project and is able to look up the typedef for the variable type.

    Whitney

  • Hi Whitney,

    Did you see the same odd behavior from SciPrintf() on your end?

    Can you loop the compiler guys into this thread? It seems CCS debug simulator is getting the struct enum values internally. Yet passing number up from an inline function to an global extern is not working,

    Also need to loop SDK guru to see the FAST estimator control handles (est.h), (ctrl.h) cause symbol errors when called from user added functions. Many of them are ROM calls, seemingly these handles need to be global extern found by LAB module #includes, another can of worms. Some handles do work others don't depending on the placement of the user module in added project folder with included project folder path at the bottom of project includes. So the linker has no excuse to cause Symbol not defined or missing error even when the handle has not been moved from the LAB. 

    Examples: 

    EST_setParams(estHandle, &userParams); compiles without errors from any user module in the same project folder.

    CTRL_setParams(ctrlHandle, &userParams); Symbol not defined, handle does not exist or was first defined in xyz after moving it into ctrl.h as extern. Placing handles in the top of LABS rather than using #include in the LAB's to find them really messes with the linker ability to locate the symbol. 

    Does it make a difference if you disable optimization or make the variable volatile?

    Neither adding volatile or reducing optimizations fixes any other extern being passed after #3 in struct enum via inline variable of the SDK est.h or ctrl.h.

    #pragma FUNCTION_OPTIONS (Motor_ID, "--opt_level=0 --opt_for_speed=1")

  • Can you loop the compiler guys into this thread? It seems CCS debug simulator is getting the struct enum values internally. Yet passing number up from an inline function to an global extern is not working,

    If you've declared your global state variables as uint16_t (I see "uint16_t ui16TrajectState" in your code above), CCS is going to display them as integers. You need to declare them as the enumerated type to have CCS display them with the enum value.

    Having handle variables declared in the lab main .c file shouldn't prevent you from using them elsewhere. The handle typedefs are in .h files so you should be able to #include those and add an extern for the handle variable wherever needed.

    Our FAST expert is out of the office today. I'll have to check with him next week to see if there are any limitations on where those "get" functions can be called that would explain the incorrect values.

    Whitney

  • If you've declared your global state variables as uint16_t (I see "uint16_t ui16TrajectState" in your code above), CCS is going to display them as integers. You need to declare them as the enumerated type to have CCS display them with the enum value.

    It did not pass the enumerated integer rather the enumeratyed symbol name and the extern variables were not needed. When first tried without exern variables was expecting the compiler to change the enumerated name to text inside the CchrEstCtrlState[CTRL_STATE_IDLE] but it did not. Seems the compiler used the symbol name address and not the enumerated integer linking the symbol name address.

    At first attempt unknowingly it actually did pass the enumerated name but array.c did not parse the name text and compiler errors when quotes are used with enumerated symbol name. a double edge sword. The clue was a compiler warning when adding code to clear the enum symbol name equals integer 0 in the same function. Yet it still required to cut paste every struct enum name and declare each one equals the enum name as text using quotes on the same line.

  • Our FAST expert is out of the office today. I'll have to check with him next week to see if there are any limitations on where those "get" functions can be called that would explain the incorrect values.

    Another very odd motor ID issue: motorVars.flagMotorIdentified = EST_getFlag_motorIdentified(estHandle);

    Toggles true and false during ID process called from SCIB ISR and other inlines est.h do not work as expected. The flag bool state only stays true or false when called once from say, (main.c) rather than in an while or ISR loops used for polling state changes too (EST_STATE_MOTORIDENTIFIED).

    Many of the inline est.h calls to control ROM states do not work as expected other than a while loop of main.c. So LAB is05 monitoring IA trigger is NOT the best way to poll ID control state switching events in an ISR called function. One symptom is the LED flash rate of main_ISR() goes into hyper speed when the ID process directed to stop inside identified status handler. That seems to be stack corruption or ID controller function return vectored somewhere else by the ROM estimator.

    The WA must exit the enumerated status by calling an external stop function that sets (motorVars.flagEnableSys = false) and prior to (EST_TRAJ_STATUS_IDLE) status, it must stop ID function on (EST_TRAJ_STATE_EST) or main_ISR() then loops at high uncontrolled speed. Since the while loop method code snip below does not work inside ISR called function ID process, state (IA) changes are not detected.

    LAB-is05 motor ID process example relies on it polling estimator state changes via inline calls to est,h. That only seems to handle ROM control states in slower while loop. Hence the ID example could use Switch Case via the struct enumerated control states to correct wrong vectoring to set (motorVars.flagEnableSys = false) inside any ISR other than CCS debug Expressions setting (motorVars.flagEnableSys = false) in a while loop when it must be left enabled (true) run time applications.

    This inline is not updating parameters when called via ISR after motor has identified status: EST_setParams(estHandle, &userParams); Yet it does work great when called from a Non ISR function that is also Not in a while loop. A function directive to execute the inline works but not from an ISR one time directive to execute. 

    The code snip isLAB5 fails in an ISR loop to detect identified state:

            	/* Feeds back whether or not the controller state has changed */
                motorVars.Id_target_A = EST_getIntValue_Id_A(estHandle);
    
                flagEstStateChanged = EST_updateState(estHandle,
                                                      motorVars.Id_target_A);
                                                      
                /* Estimator current state changed */
                if(flagEstStateChanged == true)
                {
                               if( (EST_isLockRotor(estHandle) == true) ||
                         ((EST_isMotorIdentified(estHandle)
                           && EST_isIdle(estHandle)) == true))
                    {
                        if(EST_isMotorIdentified(estHandle) == true)
                        {
                            motorVars.flagMotorIdentified = true;
    
                            //
                            // set up the PI control according to the identification
                            // motor parameters
                            //
                            userParams.motor_ratedFlux_Wb = motorVars.flux_VpHz / MATH_TWO_PI;
    
                            userParams.motor_Rr_d_Ohm = motorVars.Rr_Ohm;
                            userParams.motor_Rr_q_Ohm = motorVars.Rr_Ohm;
    
                            userParams.motor_Rs_a_Ohm = motorVars.Rs_Ohm;
                            userParams.motor_Rs_b_Ohm = motorVars.Rs_Ohm;
    
                            userParams.motor_Rs_d_Ohm = motorVars.Rs_Ohm;
                            userParams.motor_Rs_q_Ohm = motorVars.Rs_Ohm;
    
                            userParams.motor_Ls_d_H = motorVars.Ls_d_H;
                            userParams.motor_Ls_q_H = motorVars.Ls_q_H;
    
    
                            CTRL_setParams(ctrlHandle, &userParams);
                        }
                }

  • Can you try to disable all of the other interrupts except the interrupt for motor control? See what happens?

    Why do you move the codes in background loop into the ISR? What ISR frequency are you using?

  • Hi Yanming,

    Can you try to disable all of the other interrupts except the interrupt for motor control?

    That is not a real world solution for determining motor ID with multiple motors., like 4 motor drone. Each motor will have various inductance that changes with the weather. Seemingly the entire inductance concept is not without issues that AI could resolve some other way.

    Why do you move the codes in background loop into the ISR? What ISR frequency are you using?

    The HID device runs motor ID from LAB is07, not is05 or CCS debug. The service ISR loop through controller ID states uses SCIB TXFIFO to monitor the control states once ID started. Many of the (est.h) inline functions don't work in the ISR function control loop. Wonder if adding compiler #pragma or keyword (inline) to (est.h) module would help them to execute the ROM code. 

    Finally discover how to exit ID control loop into Est_Idle does not need to poll estimator IA event, only the ID state it is or has executed. Note ID code calls functions to select between multiple motor parameters, up to four motors can ID inductance, Rs ohms via uint16_t *Params of (user.c) functions replace a gazillion motor #defines. Ideally to use flash API to store update parameters into 4 dedicated sector blocks, one for each motor.

    /* Indicate motor ID's flag and allow multiple 
       times to check motor inductance for any
       user defined motors become user motor 4 */
    if(motorVars.estState == EST_STATE_MOTORIDENTIFIED)
    {
       /* Prime user motor4 parameters via
        * previous user motor, no cut paste */
       USER_MOTOR4((uint16_t *) &userParams);
    
       /* Copy motorVars into user parameters */
       userParams.motor_ratedFlux_Wb = motorVars.flux_VpHz / MATH_TWO_PI;
       userParams.motor_Rr_d_Ohm = motorVars.Rr_Ohm;
       userParams.motor_Rr_q_Ohm = motorVars.Rr_Ohm;
       userParams.motor_Rs_a_Ohm = motorVars.Rs_Ohm;
       userParams.motor_Rs_b_Ohm = motorVars.Rs_Ohm;
       userParams.motor_Rs_d_Ohm = motorVars.Rs_Ohm;
       userParams.motor_Rs_q_Ohm = motorVars.Rs_Ohm;
       userParams.motor_Ls_d_H = motorVars.Ls_d_H;
       userParams.motor_Ls_q_H = motorVars.Ls_q_H;
    
      userParams.flagMotorIdentified = true;
    
      USER_MOTOR4((uint16_t *)&userParams.flagMotorIdentified);
      USER_MOTOR4((uint16_t *)&userParams.motor_Rr_d_Ohm);
      USER_MOTOR4((uint16_t *)&userParams.motor_Rr_q_Ohm);
      USER_MOTOR4((uint16_t *)&userParams.motor_Rs_a_Ohm);
      USER_MOTOR4((uint16_t *)&userParams.motor_Rs_b_Ohm);
      USER_MOTOR4((uint16_t *)&userParams.motor_Rs_d_Ohm);
      USER_MOTOR4((uint16_t *)&userParams.motor_Rs_q_Ohm);
      USER_MOTOR4((uint16_t *)&userParams.motor_Ls_d_H);
      USER_MOTOR4((uint16_t *)&userParams.motor_Ls_q_H);
      USER_MOTOR4((uint16_t *)&userParams.motor_ratedFlux_Wb);
    
      /* Update the estimator new parameters */
      EST_setParams(estHandle, &userParams);
      EST_setParams(estHandle, &userParams);
    
      /* Set the motor offline not running */
      motorVars.flagRunIdentAndOnLine = false;
      /* Set bypass ID flag */
      userParams.flag_bypassMotorId = true;
    
    }
    
    /* Exit, estimator motor ID state ends. Must 
       put >0 WaitTime control flag ID state */
    if(motorVars.estState == EST_STATE_MOTORIDENTIFIED)
    {
        if(motorVars.trajState == EST_TRAJ_STATE_IDLE)
        {
            /* Clear enable state flag.
              Move it into call stops ID */
            motorVars.flagEnableSys = false;
    
        }
    }

  • That is not a real world solution for determining motor ID with multiple motors., like 4 motor drone. Each motor will have various inductance that changes with the weather. Seemingly the entire inductance concept is not without issues that AI could resolve some other way.

    I am not fully understand your answer here. You should know which motor is running and set the right parameters in the project accordingly even multiple motors are controller by a controller.

    You may refer to the universal motor control lab in the current MCSDK which can enable do the identification and run the motor in the same lab, and online change the motor parameters as you want.

    The lab can support a set of hardware kits and control algorithms for BLDC/PMSM drive. The kits include LAUNCHXL-F280025C, LAUNCHXL-F280039CLAUNCHXL-F2800137 with BOOSTXL-DRV8323RS, BOOSTXL-DRV8323RH, DRV8353Rx-EVMBOOSTXL-3PHGANINV, DRV8316REVM, or  DRV8329AEVM inverter board for low voltage motor (max: 100Vdc) . TMDSCNCD280025C, TMDSCNCD2800137 , or TMDSCNCD280039C with TMDSHVMTRINSPIN inverter board and TMDSADAP180TO100 for high voltage motor (max 350Vdc). And The control algorithms include sensorless InstaSPIN-FOC with FAST, Sensorless-FOC with eSMO, Sensored-FOC with incremental encoder, Sensored-FOC with hall sensor.

    C2000WARE-MOTORCONTROL-SDK: https://www.ti.com/tool/C2000WARE-MOTORCONTROL-SDK

    Universal Project and Lab User’s Guide: https://www.ti.com/lit/spruj26

    Example lab project at the folder: C:\ti\c2000\C2000Ware_MotorControl_SDK_<version>\solutions\universal_motorcontrol_lab\f28002x

    or                                                         C:\ti\c2000\C2000Ware_MotorControl_SDK_<version>\solutions\universal_motorcontrol_lab\f28003x

    or                                                         C:\ti\c2000\C2000Ware_MotorControl_SDK_<version>\solutions\universal_motorcontrol_lab\f280013x

  • You may refer to the universal motor control lab in the current MCSDK which can enable do the identification and run the motor in the same lab, and online change the motor parameters as you want.

    The same is true of SDK 4.01 when (motoVars.motorVars.Ls_d/q_H = 0.0) and (userParams.flagMotorIdentified = false) the estimator automatticaly enters motor ID control loop when  we set (motorVars.flagRunIdentAndOnLine = true)

    We are not using MCSDK and have hundreds of hours to add HID into SDK project. Your answer does not explain why est.h (eabi.lib) inline calls fail to execute ROM functions called in an ISR loop. Nobody is going to use CCS debug to run or change motor parameters in an evolved project that may use ISR functions to control fast estimator. The use of while loops main.c seems a good approach to enable or disable estimator but not to run motor ID from peripherals, e.g. SCI, SPI, CAN or HSI connected device. Visual feedback loop is a must until AI monitor code is evolved enough to do OnLine motor ID. HID has an emergency stop added to motor ID as it can over current a motor and user needs to quickly stop motor ID process. Seems a good reason to develop an IC for motor ID to automate user parameters via sensor logic feedback on the motor phases at a given DC inverter voltage.

    There is no user feedback from typedef enumerated messages when CCS debug is not used to run motor ID. Hence the point I make also includes MCSDK and same (est.h) inline ROM or Fast lib calls must execute from any peripheral ISR. 

    BTW: Using (fast_full_lib_eabi.lib) exclude (f28004x_fast_rom_symbols_fpu32_eabi.lib) cause symbol missing errors SDK 4.01. So adding ESMO even with MCSDK Params.h to SDK project need lot of changes to be backward compatible. Perhaps SDK4.01 LSRAM fast estimator library could fix (est.h) inline calls failing in ISR functions but is TI engineers need to verify if backward compatibility is even possible. 

    online change the motor parameters as you want

    There is no control object in UMCSDK and also has the same many #defines to indicate user motor parameters. Perhaps ok for the first motor if they are all the same type, though logic breaks down when more than two motors exist. Example code above we use functions to define motor parameters, not #defines as they cannot be changed or even stored in flash memory. Updating LSRAM parameters is only good for 1-2 motors, not 4 or after POR events.

    Does MCSDK save changed motor parameters to flash?

  • Your answer does not explain why est.h (eabi.lib) inline calls fail to execute ROM functions called in an ISR loop.

    I don't think so. There are several inline functions in est.h are called in ISR loop in the example lab.

    Nobody is going to use CCS debug to run or change motor parameters in an evolved project that may use ISR functions to control fast estimator.

    The UMC can support identification without rebuilding the project and using the CCS. Please take a look at the lab user's guide that show to run the lab for identification.

    Does MCSDK save changed motor parameters to flash?

    No. You can refer to the application note about using flash API to add this function in the motor control labs. there are some examples about this in C2000Ware.

  • I don't think so. There are several inline functions in est.h are called in ISR loop in the example lab.

    Yet in the context of ADCC1 ISR derived from ePWM SOCA trigger source, not via SCI, SPI, HSI interrupt called functions.

    Another very odd motor ID issue: motorVars.flagMotorIdentified = EST_getFlag_motorIdentified(estHandle);

    Toggles true and false during ID process called from SCIB ISR and other inlines est.h do not work as expected. The flag bool state only stays true or false when called once from say, (main.c) rather than in an while or ISR loops used for polling state changes too (EST_STATE_MOTORIDENTIFIED)

    The inline call needed to update the new motor ID parameters via  EST_setParams(estHandle, &userParams) does not update the LSRAM #pragma user params after the motor ID inductance changed via enumerated state machine name below. So the estimator indicates the new parameters but can not update inside the SCI ISR called function. This would be the same C code in UMC so it has to use same typedef enum names for the state machine changes in SCI ISR. Oddly the same inline call to update #pragma user params in LSRAM does work in function being called from the SCI RXFIFO ISR function. I do that for 3 other and different motor configurations, when the estimator needs the new parameters to drive the different motor.

    Also just tested while loop with estimator trajectory state machine enumerated names, they don't work at all in while loop. Fact being (EST_STATE_MOTORIDENTIFIED) happens immediately after the function enters the while loop. So the SCI ISR called function has added benefit to follow the state machine names by the controllers wait times executed in main.c. Again these inline calls (est.h) can have compiler keywords to handle how they are linked in the project. Yet don't see any inline compile keywords or directives being used to ensure the linker executes them correctly, especially during ISR events that are not in the same context as ADCC1 ISR. Wondering if the CALLS pragma directive might be of benefit in this update issue?

    if(motorVars.estState == EST_STATE_MOTORIDENTIFIED)
    {
            /* Copy motorVars to user parameters */
            userParams.motor_ratedFlux_Wb = motorVars.flux_VpHz / MATH_TWO_PI;
            userParams.motor_Rr_d_Ohm = motorVars.Rr_Ohm;
            userParams.motor_Rr_q_Ohm = motorVars.Rr_Ohm;
            userParams.motor_Rs_a_Ohm = motorVars.Rs_Ohm;
            userParams.motor_Rs_b_Ohm = motorVars.Rs_Ohm;
            userParams.motor_Rs_d_Ohm = motorVars.Rs_Ohm;
            userParams.motor_Rs_q_Ohm = motorVars.Rs_Ohm;
            userParams.motor_Ls_d_H = motorVars.Ls_d_H;
            userParams.motor_Ls_q_H = motorVars.Ls_q_H
        
        EST_setParams(estHandle, &userParams)
        
    }

  • Yet in the context of ADCC1 ISR derived from ePWM SOCA trigger source, not via SCI, SPI, HSI interrupt called functions.

    If the functions are called in the other ISRs, please check if there is any time overflow in the ISRs since the initialize functions need a long execution time. 

    As mentioned above, you can refer to the universal motor control lab that has the functions you want. You can implement the method on F28004x with f28004x_fast_rom_symbols_fpu32_eabi.lib as well. Or you can only use the fast_full_lib_eabi.lib on F28004x.

  • As mentioned above, you can refer to the universal motor control lab that has the functions you want.

    Yet the motor ID uses the same estimator state machine to switch wait times and don't want to modify LAB's by adding a lot of extra code calls. Hence the need for snap in modules, simply add the folder to the project set the includes and compile. Makes for easy TI updates just move the folder/s to the new release. Seemingly one advantage of SKD being a control object allows MTPA and Speed blocks. Does MCSDK via  fast_full_lib_eabi.lib allow MTPA torque control or just SDK?

    Or you can only use the fast_full_lib_eabi.lib on F28004x.

    That was a can of symbol worms since adding est folder for ESMO to SDK401 use of est.h and parmas.h has majorly changed. I may give it another try but it was refusing to cooperate on many include levels. Have you tried to do that update or just think it can be easily done?

    The hal.c for one has major changes (BSXL8320RS_REVA) versus DRV8320RS. So I used the SDK 4.01 hal.c but fast full library defines new symbols not included in SDK 4.01 headers even after moving and importing MCSDK folder links.

    If the functions are called in the other ISRs, please check if there is any time overflow in the ISRs since the initialize functions need a long execution time

    That was sort of the point that using only motor ID flag did not work out, ending on Ls calculation. This AM changed code to switch case polling of each est_wait state, seems more effective with SCI ISR (115200 BPS). By case breaks out of SCI ISR called function on state steps, no timer needed. The motorVars.Ls_q/d_H is captured as expected but the userParams.motor_Ls_d/q_H are shifted far right of the decimal point after ID case executes  EST_setParams(estHandle, &userParams). EST_setParams update call is made via #pragma FUNCTION_OPTIONS (NewMotor_ID, "--opt_level=0 --opt_for_speed=1") and it still is not working exactly the same way it does from non ISR function.

    Hence the global compile optimization of SDK can have issues with inline short functions (est.h) that call the ROM estimator functions.

    TMS320C28x Optimizing C/C++ Compiler v22.6.0.LTS 47SPRU514Y – AUGUST 2001 – REVISED JUNE 2022 page 47

    • Use of the inline keyword or the equivalent __inline keyword. Functions declared with the inline keyword may be inlined by the compiler if you set --opt_level=0 or greater. The inline keyword is a suggestion from the programmer to the compiler. Even if your optimization level is high, inlining is still optional for the compiler. The compiler decides whether to inline a function based on the length of the function, the number of times it is called, your --opt_for_speed setting, and any contents of the function that disqualify it from inlining (see Section 2.11.2). Functions can be inlined at --opt_level=0 or above if the function body is visible in the same module or if -pm is also used and the function is visible in one of the modules being compiled. Functions may be inlined at link time if the file containing the definition and the call site were both compiled with --opt_level=4. Functions defined as both static and inline are more likely to be inlined.

    • When --opt_level=3 or greater is used, the compiler may automatically inline eligible functions even if they are not declared as inline functions. The same list of decision factors listed for functions explicitly defined with the inline keyword is used. For more about automatic function inlining, see Section 3.5. 

  • Does MCSDK via  fast_full_lib_eabi.lib allow MTPA torque control or just SDK?

    MPTA is not related to the FAST library. You can add MTPA in any InstaSPIN-FOC example lab with FAST library. The Universal Lab has included a MTPA reference already.

    Have you tried to do that update or just think it can be easily done?

    As mentioned above, the  Universal Lab has included both FAST and eSMO, and enabled running the motor with these two algorithms at the same time.

     

    TMS320C28x Optimizing C/C++ Compiler v22.6.0.LTS 47SPRU514Y – AUGUST 2001 – REVISED JUNE 2022 page 47

    You are right. You may take a look at C2000Tm C28x Optimization Guide as well.

  • Have you tried to do that update or just think it can be easily done?

    As mentioned above, the  Universal Lab has included both FAST and eSMO,

    This statement is referring to the SDK4.01 using the new fast library, not the MCSDK. 

    You are right. You may take a look at

    Posted Compiler info to inform TI engineers the code they are releasing is dysfunctional as designed. This is not an end user fix when the embedded code is exclusively corporate proprietary.  The estimator control code has to be stable in all serial peripheral ISR functions when asserted. More testing by TI engineers is required to make the SDK or MCSDK more useful in the development process. A multibillion $$ company can afford to by $39.95 LCD display sold on eBay to test code functions on any serial peripheral connected device. Rather alarming as I put my neck on the line boasting to others how great the SDK MCSDK are for industrial applications, so....

    Note: USER_MOTOR_FLUX_EXC_FREQ_Hz = 20 (user.h) is toggling between presets in (motorVars.speedRef_Hz=235) during motor ID process. Should start ID at 20Hz yet jumps to 235Hz in case (EST_STATE_ROVERL:) break. When again forced 20Hz in next case (EST_STATE_RS:) motor ID ISR is backup to 235Hz and between every other step of ID process at every (break). Hence stripping statics from (est.h) ROM calls causes ISR issues in the Boolean logic being interrupted. That change to remove all the inline statics was noted in the SDK manefest.pdf. Compiler keyword static is not the same a volatile since static retains the variable value between ISR calls, volatile will not. 

    When setting { EST_setFlag_motorIdentified(estHandle, false); } that does not set motorVars.~ Boolean flag condition, inline called via SCI RXFIFO ISR. Flag { EST_setFlaguserParams.flagMotorIdentified } remains true. The example code in both MCSDK and SDK require major debug to function with C2000 peripherals other than ADC ISR triggered by ePWM SOCA. The estimator control flags linked to typedef struct members must be related when switching Boolean logic by inline estimator functions (est.h) and that clearly is not the case. The compiler linker can only do what it is instructed to do but it my have some issue with inline calls reference to typedef struct motorVars members Boolean logic in LSRAM control data pragma. TI guys are the C2000 experts, we are only the detectives report these odd issues. 

  • The example InstaSPIN-FOC labs are just focused on running the motor as a started reference, it's difficult to include everything the users want. The user can change and add the features they required by themself. We understand your concerns and questions, we will try to think about if it's possible to add more common features.

    As mentioned above, you may try to check if there is overflow when you add the other interrupts and call the FAST functions in the these ISRs.

  • Note the older Motorware control SDK required all inlines to be made static. Seemingly the removal of statics SDK 2.01 many calls to the estimator do not work in ISR context or loose value. Though it's had to know if est.h are considered inline functions calls to ROM estimator. Oddly enough C2000 compiler will not allow extern static keywords on any prototypes, yet the ARM compiler does allow both together. And it won't allow static bool in typedef struct seems to cause values to be lost in ISR events.

    Any idea why cannot get motorVars.RoverL_rps = EST_getRoverL_rps(estHandle) to return a value in the SCI ISR [case EST_STATE_ROVERL:] ?? Set time wait 2.5 seconds and it still is returns 0.0 and not in CCS debug at the same time watching behavior on the HID.

    SPRUIO7–March 2019

    .4. Function Prototypes
    • All functions must be prototyped in a module’s corresponding header file.
    • All function declarations must contain extern keyword. All inline functions must be static.
    • Prototypes must include Doxygen comments. See the example header file in the appendix for more details.

  • I was able to get the trajectory hertz static during motor ID of ( USER_MOTOR_FLUX_EXC_FREQ_Hz = 20 ) needed to modify is07.c trajectory call below to check the user motor had an ID or not.

    //
    // update the reference to the trajectory of speed
    //
    if(USER_MOTOR_IDENTIFIED == true)
    {
        motorVars.speedRef_Hz = USER_MOTOR_SPEED_REF_HZ;

    TRAJ_setTargetValue(trajHandle_spd, motorVars.speedRef_Hz);
    }
    else if(USER_MOTOR_IDENTIFIED == false)
    {
       motorVars.speedRef_Hz = USER_MOTOR_FLUX_EXC_FREQ_Hz;
    }

    The idea is to allow HID to manually tweak some ID value by LCD keyboard as it was discovered an effective way to stop vibration by best guess input USER_MOTOR_RATED_FLUX_VpHz. Spock used best guess in calculations to sling shot around the sun and get back to 26th century StarTrek Save the Whales Thinking

    Another good reason to use LCD for motor ID; Debug fumbling with motorVars.flagEnableSys, mouse click on variable to quickly set 0x0 when ID goes horribly wrong. A delay fumbling expression does not excepting 0x0 first time can cause small motor to smoke coils if the values were made to high.

  • The speed will be not set by motorVars.speedRef_Hz during the motor identification process. It's set by USER_MOTOR_RATED_FLUX_VpHz which will be set to UserParams.motor_ratedFlux_Wb. You may have to refer to the lab05 to recall the related parameters.

  • The speed will be not set by motorVars.speedRef_Hz during the motor identification process

    Oddly the user.h and motor ID ramp up speed is set via USER_MOTOR_FLUX_EXC_FREQ_Hz. Perhaps you mean after motor ID is05 that is being set for the online run speed. Yet in is07 that is not the case and global update (labs.h) set estimator UserParams.motor_ratedFlux_Wb. Anyway the function above added to is07 works to keep rampup speed set 20Hz during all enumerated estimator control states. I did have to add another function is07 that determine motor has ID or not to run motor ID set controller enable (Online), set (Idle) after motor ID omitted is05.

    How are the estimator ID states even changing with controller Offline is05? That was a Ureka moment as to why RoverL_rps is not working in is07.

    Note the same ID switch case ISR function moved into is05 does not even change control states in main.c while loop and motorVars.flagRunIdentAndOnLine = true. What is the ROM function to enable motor ID? Does not seem to have a direct Boolean call (est.h) other than EST_enable(estHandle). That call does not accurately describe the flag shown in motor ID block diagram ROM embedded estimator. Where is EST_setMotorID_EnableFlag(estHandle)?

      

    Asking again since KI/KP currents are set, controller enabled online. Yet RoverL_rps does not do anything. Even after adding switch case control wait states, put controller online and set 3 ISR ticks. Even set estimator 2 ISR ticks no values come back from calls to get motorVars.RoverL_rps mention above. Any ideas what stops estimator from retuning any R/L values? The ID'd motor (user.h) is07 has L/R (513.677734) so global update is working great.

  • How are the estimator ID states even changing with controller Offline is05? That was a Ureka moment as to why RoverL_rps is not working in is07.

    Re-calling the following functions and set userParams.flag_bypassMotorId = false for identification, set userParams.flag_bypassMotorId = true for running the motor with identified motor parameters or with the saved motor parameters.

        USER_setParams(&userParams);

        CTRL_setParams(ctrlHandle, &userParams);

        EST_setParams(estHandle, &userParams);

    Where is EST_setMotorID_EnableFlag(estHandle)?

    Just need to do the actions as mentioned above.

    . Yet RoverL_rps does not do anything.

    It's only used for identification.

  • Re-calling the following functions and set userParams.flag_bypassMotorId = false for identification, set userParams.flag_bypassMotorId = true for running the motor with identified motor parameters or with the saved motor parameters.

    That was a rhetorical question as there is no visible logic in is05 switching the ROM control states or enabling motor ID bool flag in the estimator block shown above post. There is no bypass params flag is07 and we simply clear the motorVars parameters, see code snip logic. There is no est.h call for enabling motor ID bool flag in the ROM code? The motorVars are present in CCS debug when the HID is running switch case and the NULL values shown in snip exist in &userParams prior to (motorVars.flagRunIdentAndOnLine = true). The poles count and all the other required user.h motor parameters are present. Oddly there is no codes for USER_MOTOR_FREQ_LOW_HZ or USER_MOTOR_FREQ_HIGH_HZ in is07, could that be an issue?

    Only way to start motor ID in is07 via ISR switch cases, set (motorVars.flagRunIdentAndOnLine = true). Seemingly why RoverL_rps is starting but does not return a value at step 1 of motor ID. Lab is05 checks IA trigger point seemingly polls for identification flag set but that is not possible in ISR context. So every case of the ROM estimator motor ID process has to be accounted for as I discovered after many hours of investigation. It seems after I increased the control ticks the Rs resistance is more accurate closer to the real values.

        /* Disable motor is ID flag */
    	USER_MOTOR_IDENTIFIED = false;
    
        /* set the userParam flags for ID */
        userParams.flag_bypassMotorId = false;
        motorVars.flagMotorIdentified = false;
        motorVars.flagEnableUserParams = false;
    
        userParams.motor_ratedFlux_Wb = (float)0.0;
        userParams.motor_Rr_d_Ohm = motorVars.Rr_Ohm = (float)0.0;
        userParams.motor_Rr_q_Ohm = motorVars.Rr_Ohm = (float)0.0;
        userParams.motor_Rs_a_Ohm = motorVars.Rs_Ohm = (float)0.0;
        userParams.motor_Rs_b_Ohm = motorVars.Rs_Ohm = (float)0.0;
        userParams.motor_Rs_d_Ohm = motorVars.Rs_Ohm = (float)0.0;
        userParams.motor_Rs_q_Ohm = motorVars.Rs_Ohm = (float)0.0;
        //userParams.motor_Ls_d_H = motorVars.Ls_d_H = (float)0.0;
        //userParams.motor_Ls_q_H = motorVars.Ls_q_H = (float)0.0;
        //motorVars.RoverL_rps = 0.0;
        //motorVars.flux_VpHz = 0.0;
    
        /* Update the estimator with new parameters */
        EST_setParams(estHandle, &userParams);
        
        //Run motor ID process?
        EST_setFlag_motorIdentified(estHandle, false);
        /* Set the enable flag */
        motorVars.flagEnableSys = true;
        
        // Enter SCI ISR switch case funtion 
        // Set all the enumerated cases to display on HID
        // Switch case logic HID user button enables 
        //  motorVars.flagRunIdentAndOnLine = true starts motor ID

    . Yet RoverL_rps does not do anything.

    It's only used for identification.

    Right it's not running in motor ID via switch case monitoring the controller states.

  • There is no est.h call for enabling motor ID bool flag in the ROM code?

    No. Take actions ad mentioned above to re-call the related initialization functions.

    The poles count and all the other required user.h motor parameters are present. Oddly there is no codes for USER_MOTOR_FREQ_LOW_HZ or USER_MO

    Only for lab03 with v/f pen-loop control

    Yes, you can change the related variables for identification per the motor and requirements.

  • Yes, you can change the related variables for identification per the motor and requirements.

    Yet RoverL_rps will not produce a value in motor ID process via controller setup code in is07.  The ROM calls to do motor ID mostly seem work in switch case ISR but something it quite different in the controller setup. Copy large parts controller setup is05 into is07 , still motor ID RoverL_rps is broken. That seems counter intuitive to the ROM estimator block has a simple motor id bool switch.  Now I feel lost, unable to discover difference (is05/is07) since controller setup allows motor ID in is07 below snip. What on earth is missing to make RoverL_rps give a value n motor ID? 

            //if(EST_isMotorIdentified(estHandle) == true)
    		if((motorVars.flagMotorIdentified == true) ||
    		        (userParams.flag_bypassMotorId == false))
            {
                if(motorVars.flagSetupController == true)
                {
                    //
                    // update the controller
                    // set custom current and speed controllers gains
                    //
                    updateControllers();
    
                }
                else
                {
                    //motorVars.flagMotorIdentified = true;
                    motorVars.flagSetupController = true;
    
    				// set up estimator conrollers
                    setupControllers();
    
                }
            }
            /* Update controller states */
            CTRL_updateState(ctrlHandle);

     

    Only for lab03 with v/f pen-loop control

    Check lab is05 it uses both user parameters in motor ID. Sorry was mistaken a manual search of is07 does actually set both user parameters before while loop (main.c), CCS search file did not reveal the code snip place in search file on the tab Flushed

    //
    // configure the speed reference trajectory (Hz)
    //
    TRAJ_setTargetValue(trajHandle_spd, 0.0);
    TRAJ_setIntValue(trajHandle_spd, 0.0);
    TRAJ_setMinValue(trajHandle_spd, -USER_MOTOR_FREQ_MAX_HZ);
    TRAJ_setMaxValue(trajHandle_spd, USER_MOTOR_FREQ_MAX_HZ);
    TRAJ_setMaxDelta(trajHandle_spd, USER_MAX_ACCEL_Hzps / USER_ISR_FREQ_Hz);

  • Yes, you can change the related variables for identification per the motor and requirements.

    Yanming the enumerated name is missing oddly skips RsOnline but RR wait seems to fill the void when the state machine runs unconstrained. This code below snip is not explained how the trajectory state machine is behaving in some kind of automatic mode with the controller state machine, The snip below is present in both is05 and is07 but the estimator ROM block diagram makes it seem anyone simply enable ROM bool motor ID switch in any LAB and it goes into ID based on few motor parameter in (user.h).

    The snip is used to switch the control state machine and no documentation exists to explain what it is doing in the ROM estimator. Hence it is un-useable code frame for industrial, automotive or aviation purposes being motor ID is not transportable between modules. Yet to explain why RoverL_rps is not working in is07 with motor ID process. We can't use the code snip the same way since the handle symbol is a missing and undefined in any other module.

            // No estimator error
            else
            {
                motorVars.Id_target_A = EST_getIntValue_Id_A(estHandle);
    
                flagEstStateChanged = EST_updateState(estHandle, 0.0);
    
                if(flagEstStateChanged == true)
                {
                    //
                    // configure the trajectory generator
                    //
                    EST_configureTraj(estHandle);
                }
            }

  • As mentioned before, recommend that you can refer to the universal lab or use the lab directly that could help you to start your project as you want.

  • Hi Yanmig,

    You sort of answered my question but not in the way it was directly related to the RoverL_rps not being calculated. I was clearing the values in the code snip above after the new motor had loaded the defaults. The other problem was the method of switching states is not being elaborated anywhere and the ROM source is not visible. And again is05 is not setting the controller online state flag so CCS debug shows it as being idle when it is actually online state.

    Please add code snips to RDK4.01 so it will correctly show controller state machine online during motor ID. That is very important for proper program flow feedback. You can add other state flags to trajectory such as error and estimator error state flag.

            //
            if((motorVars.flagRunIdentAndOnLine == true) &&
               (motorVars.flagEnableOffsetCalc == false))
            {
    			if(HAL_getPwmEnableStatus(halHandle) == false)
    			{
    				//
    				// enable the controller
    				//
    				CTRL_enable(ctrlHandle);
    				//
    	            motorVars.ctrlState = CTRL_STATE_ONLINE;
    				//
    				// enable the FAST estimator
    				//
    				EST_enable(estHandle);
    				
    	                //
                    // configure the controller
                    //
                    EST_configureCtrl(estHandle, ctrlHandle);
    
                    if( (EST_isLockRotor(estHandle) == true) ||
                         ((EST_isMotorIdentified(estHandle)
                           && EST_isIdle(estHandle)) == true))
                    {
                        if(EST_isMotorIdentified(estHandle) == true)
                        {
                            motorVars.flagMotorIdentified = true;
    
                            //
                            // set up the PI control according to the identification
                            // motor parameters
                            //
                            userParams.motor_ratedFlux_Wb = motorVars.flux_VpHz / MATH_TWO_PI;
    
                            userParams.motor_Rr_d_Ohm = motorVars.Rr_Ohm;
                            userParams.motor_Rr_q_Ohm = motorVars.Rr_Ohm;
    
                            userParams.motor_Rs_a_Ohm = motorVars.Rs_Ohm;
                            userParams.motor_Rs_b_Ohm = motorVars.Rs_Ohm;
    
                            userParams.motor_Rs_d_Ohm = motorVars.Rs_Ohm;
                            userParams.motor_Rs_q_Ohm = motorVars.Rs_Ohm;
    
                            userParams.motor_Ls_d_H = motorVars.Ls_d_H;
                            userParams.motor_Ls_q_H = motorVars.Ls_q_H;
    
                            CTRL_setParams(ctrlHandle, &userParams);
    
                        }
    
                        //
                        // clear the flag
                        //
                        motorVars.flagRunIdentAndOnLine = false;
    
                        //
                        // disable the controller
                        //
                        CTRL_disable(ctrlHandle);
                        //
                        motorVars.ctrlState = CTRL_STATE_IDLE;
                    }
                }
            }			

    Defaults must be present for RoverL_rps to produce a return value.

    userParams.RoverL_Kp_sf = USER_R_OVER_L_KP_SF;
    userParams.RoverL_min_rps = MATH_TWO_PI * (float32_t)5.0;
    userParams.RoverL_max_rps = MATH_TWO_PI * (float32_t)5000.0;

  • Don't change the default setting time in user.c for identification of possible.

    RoverL_rps  is only used for identification, you need to recall the EST_setParams(estHandle, &userParams) to get the new calculation value.

    We will not update the InstaSPIN labs for F28004x. Recommend that the user to the Universal Motor Control lab if they want to implement InstaSPIN on a C2000 device.

  • RoverL_rps  is only used for identification, you need to recall the EST_setParams(estHandle, &userParams) to get the new calculation value.

    What do you think I was asking about why RoverL_rps did not work during motor ID. Discovered occurs if PWM enable is not correctly clearing the fault flags and PWMA signals are in high impedance during ID. I had to add code to fix the PWM enable for CMPSS and disable to clear previously forced OST, DAC1, DAC2 event 1 flags. The PWM enable call in (hal.h) was not at all coded and did nothing to clear TZFRC Oneshot fault flags register. I had assumed it was working but clearing TZFRC register, actually gates PWM signals during the flags clear event.

    Code below stops clearing fault flags from gating PWM during fault clear events. The TZFRC fault flags are for setting fault condition flags Only and correctly clearing only via TZCLR register. Yet it was clearing the faults but putting PWM in high impedance after it cleared the events. Hence RoverL_rps was void value when enabled PWM-A instead went into high impedance, after clearing TZFRC register bits they return set. You can see that happen on scope if one is actually monitoring GPIO drive pins during the clear enable events.

     

    //! \brief      Enables the PWM devices
    //! \details    Turns on the outputs of the EPWM peripheral which will allow
    //!             the power switches to be controlled. Clears TzFlags and
    //!				CMPSS High/Low digital filter output latch/s
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    static inline void HAL_enablePWM(HAL_Handle handle)
    {
    
        HAL_Obj *obj = (HAL_Obj *)handle;
    
        /* Enable the forced OSHT evnets   18.9.2 Fig.18-41 */
        EPWM_clearTripZoneFlag(obj->pwmHandle[0],
                (EPWM_TZ_FLAG_OST | EPWM_TZ_FLAG_DCAEVT1 | EPWM_TZ_FLAG_DCBEVT1));
        //
        EPWM_clearTripZoneFlag(obj->pwmHandle[1],
                (EPWM_TZ_FLAG_OST | EPWM_TZ_FLAG_DCAEVT1 | EPWM_TZ_FLAG_DCBEVT1));
        //
        EPWM_clearTripZoneFlag(obj->pwmHandle[2],
                (EPWM_TZ_FLAG_OST | EPWM_TZ_FLAG_DCAEVT1 | EPWM_TZ_FLAG_DCBEVT1));
    
        obj->flagEnablePWM = true;
    
        return;
    } // end of HAL_enablePWM() function
    
    //! \brief      Disables the PWM device
    //! \details    Turns off the outputs of the EPWM peripherals which will put
    //!             the power switches into a high impedance state.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    static inline void HAL_disablePWM(HAL_Handle handle)
    {
        HAL_Obj *obj = (HAL_Obj *)handle;
    
        /* Enable the forced OSHT evnets   18.9.2 Fig.18-41 */
        EPWM_forceTripZoneEvent(obj->pwmHandle[0],
    				(EPWM_TZ_FORCE_EVENT_OST | EPWM_TZ_FORCE_EVENT_DCAEVT1
    							             | EPWM_TZ_FORCE_EVENT_DCBEVT1));
        EPWM_forceTripZoneEvent(obj->pwmHandle[1],
    				(EPWM_TZ_FORCE_EVENT_OST | EPWM_TZ_FORCE_EVENT_DCAEVT1
    							             | EPWM_TZ_FORCE_EVENT_DCBEVT1));
        EPWM_forceTripZoneEvent(obj->pwmHandle[2],
    				(EPWM_TZ_FORCE_EVENT_OST | EPWM_TZ_FORCE_EVENT_DCAEVT1
    							             | EPWM_TZ_FORCE_EVENT_DCBEVT1));
    
        obj->flagEnablePWM = false;
    
    
        return;
    } // end of HAL_disablePWM() function

    The SDK (user.c) setting flag (userParams.flag_bypassMotorId) developers cannot track why the code vectors differently when it is set versus cleared. Flags in the ROM and fast library have to be transparently resolved in CCS or text, that is not the case with this flag, Causes huge problems to remove the seemingly orphaned flag and no (est.h) call to enable motor ID in MCSDK is troubling to say the least. This orphaned flag removed from inertia setting the CPU IP runs down the code clears the Ls_d/q_H = 0.0. That flag is orphaned according to CCS tracking, only #define user.h has no related C code and certainly not associated with ROM library functions anyone can see or search for. This flag is not being explained in detail enough how it can vector code away from setting controller WaitTimes bottom user.c. Need to see controllers use of these states in block format text layout in the Trouble Shooting InstaSpin PDF.

    Recommend that the user to the Universal Motor Control lab if they want to implement InstaSPIN on a C2000 device.

    Right above post you say not need debug for motor ID yet text states differently. The project imported via REX put folders below SDK4.0 so the driverlib many functions do not resolve in CCS indexer or code analysis. MCSK only supports 2 ADC's and requires huge effort to make it work with x49c MCU class. The setting on the 20MHz XTAL is completely different on x25, why PLL multiplier 30 not 10?  CCS can't even locate where booster header sites are being defined (LPD_SITE_J1_J4) or (LPD_SITE_J5_J8).

    MCSDK user guide search results are empty as where to enable the booster headers, what file? One might assume (motor1_drive.h) or even (motor1_drive.c) yet no such #define exists where anyone would expect moving from SDK (user.h) motor inverter settings. TI programmers are all over the place, not keeping somewhat consistent code design practices (Symbol names for one) makes it more time consuming to get things working.  

    6. Set the variable motorVars_M1.flagEnableRunAndIdentify to' 1 in the Expressions window as shown in Figure 2-41, the motor identification will be executed, the whole process will take about 150s. Once motorVars_M1.flagEnableRunAndIdentify is equal to 0 and the motor is stopping, the motor parameters have been identified. Copy the variables value in the watch window to replace the defined motor parameters in user_mtr1.h as follows:

    • USER_MOTOR1_Rs_Ohm = motorSetVars_M1.Rs_Ohm’s value
    • USER_MOTOR1_Ls_d_H = motorSetVars_M1.Ls_d_H’s value
    • USER_MOTOR1_Ls_q_H = motorSetVars_M1.Ls_q_H’s value
    • USER_MOTOR1_RATED_FLUX_VpHz = motorSetVars_M1.flux_VpHz’s value