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.

CCS/LAUNCHXL-F28069M: eQEP Index interruption problem

Part Number: LAUNCHXL-F28069M

Tool/software: Code Composer Studio

Hi everyone,

I'm trying to make a home function based on proj_lab13f,so i wrote the code for that in proj_lab13f.c file, there are no problems with the compilation but the program does nothing.

This is part of the code, i also add the file.

#include <math.h>
#include "main_position_2mtr.h"
/*--------- INICIO Headers  y variables globales ----*/
interrupt void QEP_Index_ISR(void);
short gIndexOcurre = 0;

#include "spa_c.h"
double azi = 0, zen = 0;
spa_data spa;  //declare the SPA structure
int result;
float min, sec;
int f_err = 0;


char *azi_zeni;
double angAz, angZen;
double ang_azi_Actual = 0;
double ang_zen_Actual = 0;
double ang_azi_establecer = 0;
double ang_zen_establecer = 0;
double ang_azi_mrev = 0.0;  //_iq24
double ang_zen_mrev = 0.0;
double late = 20.6242738798, lon = -100.3663814068, ele = 1829;
/*--------- FIN Headers  y variables globales ----*/
#ifdef FLASH
#pragma CODE_SECTION(motor1_ISR,"ramfuncs");
#pragma CODE_SECTION(motor2_ISR,"ramfuncs");
#endif

// Include header files used in the main function

// **************************************************************************
// the defines

// **************************************************************************
// the globals

CLARKE_Handle   clarkeHandle_I[2];  //!< the handle for the current Clarke
                                    //!< transform
CLARKE_Obj      clarke_I[2];        //!< the current Clarke transform object

PARK_Handle     parkHandle[2];      //!< the handle for the current Parke
                                    //!< transform
PARK_Obj        park[2];            //!< the current Parke transform object

CLARKE_Handle   clarkeHandle_V[2];  //!< the handle for the voltage Clarke
                                    //!< transform
CLARKE_Obj      clarke_V[2];        //!< the voltage Clarke transform object

EST_Handle      estHandle[2];       //!< the handle for the estimator

PID_Obj         pid[2][3];          //!< three objects for PID controllers
                                    //!< 0 - Speed, 1 - Id, 2 - Iq
PID_Handle      pidHandle[2][3];    //!< three handles for PID controllers
                                    //!< 0 - Speed, 1 - Id, 2 - Iq
uint16_t        stCntPosition[2];   //!< count variable to decimate the execution
                                    //!< of SpinTAC Position Control

IPARK_Handle    iparkHandle[2];     //!< the handle for the inverse Park
                                    //!< transform
IPARK_Obj       ipark[2];           //!< the inverse Park transform object

SVGEN_Handle    svgenHandle[2];     //!< the handle for the space vector generator
SVGEN_Obj       svgen[2];           //!< the space vector generator object

ENC_Handle      encHandle[2];      //!< the handle for the encoder
ENC_Obj         enc[2];            //!< the encoder object

SLIP_Handle     slipHandle[2];     //!< the handle for the slip compensator
SLIP_Obj        slip[2];           //!< the slip compensator object

HAL_Handle      halHandle;         //!< the handle for the hardware abstraction
                                   //!< layer for common CPU setup
HAL_Obj         hal;               //!< the hardware abstraction layer object

ANGLE_COMP_Handle    angleCompHandle[2];  //!< the handle for the angle compensation
ANGLE_COMP_Obj       angleComp[2];        //!< the angle compensation object

HAL_Handle_mtr  halHandleMtr[2]; //!< the handle for the hardware abstraction
                                 //!< layer specific to the motor board.
HAL_Obj_mtr     halMtr[2];       //!< the hardware abstraction layer object
                                 //!< specific to the motor board.

HAL_PwmData_t   gPwmData[2] = {{_IQ(0.0),_IQ(0.0),_IQ(0.0)},   //!< contains the
                               {_IQ(0.0),_IQ(0.0),_IQ(0.0)}};  //!< pwm values for each phase.
                                                               //!< -1.0 is 0%, 1.0 is 100%

HAL_AdcData_t   gAdcData[2];       //!< contains three current values, three
                                   //!< voltage values and one DC buss value

MATH_vec3       gOffsets_I_pu[2] = {{_IQ(0.0),_IQ(0.0),_IQ(0.0)},  //!< contains
                                    {_IQ(0.0),_IQ(0.0),_IQ(0.0)}}; //!< the offsets for the current feedback

MATH_vec3       gOffsets_V_pu[2] = {{_IQ(0.0),_IQ(0.0),_IQ(0.0)},  //!< contains
                                    {_IQ(0.0),_IQ(0.0),_IQ(0.0)}}; //!< the offsets for the voltage feedback

MATH_vec2       gIdq_ref_pu[2] = {{_IQ(0.0),_IQ(0.0)},  //!< contains the Id and
                                  {_IQ(0.0),_IQ(0.0)}}; //!< Iq references


MATH_vec2       gVdq_out_pu[2] = {{_IQ(0.0),_IQ(0.0)},  //!< contains the output
                                  {_IQ(0.0),_IQ(0.0)}}; //!< Vd and Vq from the current controllers


MATH_vec2       gIdq_pu[2] = {{_IQ(0.0),_IQ(0.0)},   //!< contains the Id and Iq
                              {_IQ(0.0),_IQ(0.0)}};  //!< measured values

FILTER_FO_Handle  filterHandle[2][6];            //!< the handles for the 3-current and 3-voltage filters for offset calculation
FILTER_FO_Obj     filter[2][6];                  //!< the 3-current and 3-voltage filters for offset calculation
uint32_t gOffsetCalcCount[2] = {0,0};

USER_Params     gUserParams[2];

uint32_t gAlignCount[2] = {0,0};

ST_Obj          st_obj[2];      //!< the SpinTAC objects
ST_Handle       stHandle[2];    //!< the handles for the SpinTAC objects

volatile MOTOR_Vars_t gMotorVars[2] = {MOTOR_Vars_INIT_Mtr1,MOTOR_Vars_INIT_Mtr2};   //!< the global motor
                                                   //!< variables that are defined in main.h and
                                                   //!< used for display in the debugger's watch
                                                   //!< window

#ifdef FLASH
// Used for running BackGround in flash, and ISR in RAM
extern uint16_t *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart;
#endif

#ifdef DRV8301_SPI
// Watch window interface to the 8301 SPI
DRV_SPI_8301_Vars_t gDrvSpi8301Vars[2];
#endif

#ifdef DRV8305_SPI
// Watch window interface to the 8305 SPI
DRV_SPI_8305_Vars_t gDrvSpi8305Vars[2];
#endif

_iq gFlux_pu_to_Wb_sf[2];

_iq gFlux_pu_to_VpHz_sf[2];

_iq gTorque_Ls_Id_Iq_pu_to_Nm_sf[2];

_iq gTorque_Flux_Iq_pu_to_Nm_sf[2];

_iq gSpeed_krpm_to_pu_sf[2];

_iq gSpeed_pu_to_krpm_sf[2];

_iq gSpeed_hz_to_krpm_sf[2];

_iq gCurrent_A_to_pu_sf[2];


// **************************************************************************
// the functions
void main(void)
{
    // Only used if running from FLASH
    // Note that the variable FLASH is defined by the project

    #ifdef FLASH
    // Copy time critical code and Flash setup code to RAM
    // The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
    // symbols are created by the linker. Refer to the linker files.
    memCopy((uint16_t *)&RamfuncsLoadStart,(uint16_t *)&RamfuncsLoadEnd,
            (uint16_t *)&RamfuncsRunStart);
    #endif

    // initialize the Hardware Abstraction Layer  (HAL)
    // halHandle will be used throughout the code to interface with the HAL
    // (set parameters, get and set functions, etc) halHandle is required since
    // this is how all objects are interfaced, and it allows interface with
    // multiple objects by simply passing a different handle. The use of
    // handles is explained in this document:
    // C:/ti/motorware/motorware_1_01_00_1x/docs/motorware_coding_standards.pdf
    halHandle = HAL_init(&hal,sizeof(hal));


    // initialize the user parameters
    // This function initializes all values of structure gUserParams with
    // values defined in user.h. The values in gUserParams will be then used by
    // the hardware abstraction layer (HAL) to configure peripherals such as
    // PWM, ADC, interrupts, etc.
    USER_setParamsMtr1(&gUserParams[HAL_MTR1]);
    USER_setParamsMtr2(&gUserParams[HAL_MTR2]);

    // set the hardware abstraction layer parameters
    // This function initializes all peripherals through a Hardware Abstraction
    // Layer (HAL). It uses all values stored in gUserParams.
    HAL_setParams(halHandle,&gUserParams[HAL_MTR1]);

    // initialize the estimator
    estHandle[HAL_MTR1] = EST_init((void *)USER_EST_HANDLE_ADDRESS,0x200);
    estHandle[HAL_MTR2] = EST_init((void *)USER_EST_HANDLE_ADDRESS_1,0x200);

    {
      uint_least8_t mtrNum;

      for(mtrNum=HAL_MTR1;mtrNum<=HAL_MTR2;mtrNum++)
      {

        // initialize the individual motor hal files
        halHandleMtr[mtrNum] = HAL_init_mtr(&halMtr[mtrNum],sizeof(halMtr[mtrNum]),(HAL_MtrSelect_e)mtrNum);

        // Setup each motor board to its specific setting
        HAL_setParamsMtr(halHandleMtr[mtrNum],halHandle,&gUserParams[mtrNum]);

        {
          // These function calls are used to initialize the estimator with ROM
          // function calls. It needs the specific address where the controller
          // object is declared by the ROM code.
          CTRL_Handle ctrlHandle = CTRL_init((void *)USER_CTRL_HANDLE_ADDRESS,0x200);
          CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle;

          // this sets the estimator handle (part of the controller object) to
          // the same value initialized above by the EST_init() function call.
          // This is done so the next function implemented in ROM, can
          // successfully initialize the estimator as part of the controller
          // object.
          obj->estHandle = estHandle[mtrNum];

          // initialize the estimator through the controller. These three
          // function calls are needed for the F2806xF/M implementation of
          // InstaSPIN.
          CTRL_setParams(ctrlHandle,&gUserParams[mtrNum]);
          CTRL_setUserMotorParams(ctrlHandle);
          CTRL_setupEstIdleState(ctrlHandle);
        }

        //Compensates for the delay introduced
        //from the time when the system inputs are sampled to when the PWM
        //voltages are applied to the motor windings.
        angleCompHandle[mtrNum] = ANGLE_COMP_init(&angleComp[mtrNum],sizeof(angleComp[mtrNum]));
        ANGLE_COMP_setParams(angleCompHandle[mtrNum],
                        gUserParams[mtrNum].iqFullScaleFreq_Hz,
                        gUserParams[mtrNum].pwmPeriod_usec,
                        gUserParams[mtrNum].numPwmTicksPerIsrTick);


        // initialize the Clarke modules
        // Clarke handle initialization for current signals
        clarkeHandle_I[mtrNum] = CLARKE_init(&clarke_I[mtrNum],sizeof(clarke_I[mtrNum]));

        // Clarke handle initialization for voltage signals
        clarkeHandle_V[mtrNum] = CLARKE_init(&clarke_V[mtrNum],sizeof(clarke_V[mtrNum]));

        // Park handle initialization for current signals
        parkHandle[mtrNum] = PARK_init(&park[mtrNum],sizeof(park[mtrNum]));

        // compute scaling factors for flux and torque calculations
        gFlux_pu_to_Wb_sf[mtrNum] = USER_computeFlux_pu_to_Wb_sf(&gUserParams[mtrNum]);

        gFlux_pu_to_VpHz_sf[mtrNum] = USER_computeFlux_pu_to_VpHz_sf(&gUserParams[mtrNum]);

        gTorque_Ls_Id_Iq_pu_to_Nm_sf[mtrNum] = USER_computeTorque_Ls_Id_Iq_pu_to_Nm_sf(&gUserParams[mtrNum]);

        gTorque_Flux_Iq_pu_to_Nm_sf[mtrNum] = USER_computeTorque_Flux_Iq_pu_to_Nm_sf(&gUserParams[mtrNum]);

        gSpeed_krpm_to_pu_sf[mtrNum] = _IQ((float_t)gUserParams[mtrNum].motor_numPolePairs * 1000.0
                                           / (gUserParams[mtrNum].iqFullScaleFreq_Hz * 60.0));   //// 0.26666666666666666666666666666667

        gSpeed_pu_to_krpm_sf[mtrNum] = _IQ((gUserParams[mtrNum].iqFullScaleFreq_Hz * 60.0)
                                           / ((float_t)gUserParams[mtrNum].motor_numPolePairs * 1000.0));

        gSpeed_hz_to_krpm_sf[mtrNum] = _IQ(60.0 / (float_t)gUserParams[mtrNum].motor_numPolePairs / 1000.0);

        gCurrent_A_to_pu_sf[mtrNum] = _IQ(1.0 / gUserParams[mtrNum].iqFullScaleCurrent_A);

        // disable Rs recalculation
        EST_setFlag_enableRsRecalc(estHandle[mtrNum],false);

        // set the number of current sensors
        setupClarke_I(clarkeHandle_I[mtrNum],gUserParams[mtrNum].numCurrentSensors);

        // set the number of voltage sensors
        setupClarke_V(clarkeHandle_V[mtrNum],gUserParams[mtrNum].numVoltageSensors);

        // initialize the PID controllers
        pidSetup((HAL_MtrSelect_e)mtrNum);

        // initialize the inverse Park module
        iparkHandle[mtrNum] = IPARK_init(&ipark[mtrNum],sizeof(ipark[mtrNum]));

        // initialize the space vector generator module
        svgenHandle[mtrNum] = SVGEN_init(&svgen[mtrNum],sizeof(svgen[mtrNum]));

        // initialize and configure offsets using filters
        {
          uint16_t cnt = 0;
          _iq b0 = _IQ(gUserParams[mtrNum].offsetPole_rps/(float_t)gUserParams[mtrNum].ctrlFreq_Hz);
          _iq a1 = (b0 - _IQ(1.0));
          _iq b1 = _IQ(0.0);

          for(cnt=0;cnt<6;cnt++)
            {
              filterHandle[mtrNum][cnt] = FILTER_FO_init(&filter[mtrNum][cnt],sizeof(filter[mtrNum][0]));
              FILTER_FO_setDenCoeffs(filterHandle[mtrNum][cnt],a1);
              FILTER_FO_setNumCoeffs(filterHandle[mtrNum][cnt],b0,b1);
              FILTER_FO_setInitialConditions(filterHandle[mtrNum][cnt],_IQ(0.0),_IQ(0.0));
            }

          gMotorVars[mtrNum].Flag_enableOffsetcalc = false;
        }

        // initialize the encoder module
        encHandle[mtrNum] = ENC_init(&enc[mtrNum],sizeof(enc[mtrNum]));

        // initialize the slip compensation module
        slipHandle[mtrNum] = SLIP_init(&slip[mtrNum],sizeof(slip[mtrNum]));
        // setup the SLIP module
        SLIP_setup(slipHandle[mtrNum], _IQ(gUserParams[mtrNum].ctrlPeriod_sec));

        // setup faults
        HAL_setupFaults(halHandleMtr[mtrNum]);
		
        // initialize the SpinTAC Components
        stHandle[mtrNum] = ST_init(&st_obj[mtrNum], sizeof(st_obj[mtrNum]));
      } // End of for loop
    }

    // setup the encoder module
    ENC_setup(encHandle[HAL_MTR1], 1, USER_MOTOR_NUM_POLE_PAIRS, USER_MOTOR_ENCODER_LINES, 0, USER_IQ_FULL_SCALE_FREQ_Hz, USER_ISR_FREQ_Hz, 8000.0);
    ENC_setup(encHandle[HAL_MTR2], 1, USER_MOTOR_NUM_POLE_PAIRS_2, USER_MOTOR_ENCODER_LINES_2, 0, USER_IQ_FULL_SCALE_FREQ_Hz_2, USER_ISR_FREQ_Hz_2, 8000.0);

    ///   M C >>>>>>>>>>>>>
    HAL_Obj_mtr *obj_mtr = (HAL_Obj_mtr *)halHandle;
    HAL_Obj *obj = (HAL_Obj *)halHandle;
    obj_mtr = (HAL_Obj_mtr *)halHandle;
//    QEP_Obj *qep = (QEP_Obj *)obj_mtr->qepHandle;

    QEP_clear_all_interrupt_flags(obj_mtr->qepHandle); // Limpiar todas las banderas de interrupci�n
    QEP_disable_all_interrupts(obj_mtr->qepHandle);    // Deshabilitar todas las interrupciones

    PIE_enableInt( obj->pieHandle, PIE_GroupNumber_5, PIE_InterruptSource_EQEP1 ); //Grupo 5 donde se encuentra la interrupcion de EQEP1
    QEP_enable_interrupt(obj_mtr->qepHandle, QEINT_Iel); //Habilitar el bit de interrupci�n correspondiente al pulso de Index
    CPU_enableInt(obj->cpuHandle,CPU_IntNumber_5);   //Habilitar el grupo 5 en las interrupciones de la CPU

    ///   M C >>>>>>>>>>>>>

    // setup the SpinTAC Components
    ST_setupPosConv_mtr1(stHandle[HAL_MTR1]);
    ST_setupPosConv_mtr2(stHandle[HAL_MTR2]);
    ST_setupPosCtl_mtr1(stHandle[HAL_MTR1]);
    ST_setupPosMove_mtr1(stHandle[HAL_MTR1]);
    ST_setupPosCtl_mtr2(stHandle[HAL_MTR2]);
    ST_setupPosMove_mtr2(stHandle[HAL_MTR2]);

    // set the pre-determined current and voltage feeback offset values
    gOffsets_I_pu[HAL_MTR1].value[0] = _IQ(I_A_offset);
    gOffsets_I_pu[HAL_MTR1].value[1] = _IQ(I_B_offset);
    gOffsets_I_pu[HAL_MTR1].value[2] = _IQ(I_C_offset);
    gOffsets_V_pu[HAL_MTR1].value[0] = _IQ(V_A_offset);
    gOffsets_V_pu[HAL_MTR1].value[1] = _IQ(V_B_offset);
    gOffsets_V_pu[HAL_MTR1].value[2] = _IQ(V_C_offset);

    gOffsets_I_pu[HAL_MTR2].value[0] = _IQ(I_A_offset_2);
    gOffsets_I_pu[HAL_MTR2].value[1] = _IQ(I_B_offset_2);
    gOffsets_I_pu[HAL_MTR2].value[2] = _IQ(I_C_offset_2);
    gOffsets_V_pu[HAL_MTR2].value[0] = _IQ(V_A_offset_2);
    gOffsets_V_pu[HAL_MTR2].value[1] = _IQ(V_B_offset_2);
    gOffsets_V_pu[HAL_MTR2].value[2] = _IQ(V_C_offset_2);

    // initialize the interrupt vector table
    HAL_initIntVectorTable(halHandle);

    //>>>> Configuracion de la interrupcion del index <<<<<<<<<<<<//

    PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;

    ENABLE_PROTECTED_REGISTER_WRITE_MODE;

    pie->EQEP1_INT = &QEP_Index_ISR;

    DISABLE_PROTECTED_REGISTER_WRITE_MODE;

    //>>>> Configuracion de la interrupcion del index <<<<<<<<<<<<//
    // enable the ADC interrupts
    HAL_enableAdcInts(halHandle);

    // enable global interrupts
    HAL_enableGlobalInts(halHandle);

    // enable debug interrupts
    HAL_enableDebugInt(halHandle);

    // disable the PWM
    HAL_disablePwm(halHandleMtr[HAL_MTR1]);
    HAL_disablePwm(halHandleMtr[HAL_MTR2]);

    // initialize SpinTAC Velocity Control watch window variables
    gMotorVars[HAL_MTR1].SpinTAC.PosCtlBw_radps = STPOSCTL_getBandwidth_radps(st_obj[HAL_MTR1].posCtlHandle);
    gMotorVars[HAL_MTR2].SpinTAC.PosCtlBw_radps = STPOSCTL_getBandwidth_radps(st_obj[HAL_MTR2].posCtlHandle);
	// initialize the watch window with maximum and minimum Iq reference
	gMotorVars[HAL_MTR1].SpinTAC.PosCtlOutputMax_A = _IQmpy(STPOSCTL_getOutputMaximum(st_obj[HAL_MTR1].posCtlHandle), _IQ(gUserParams[HAL_MTR1].iqFullScaleCurrent_A));
	gMotorVars[HAL_MTR1].SpinTAC.PosCtlOutputMin_A = _IQmpy(STPOSCTL_getOutputMinimum(st_obj[HAL_MTR1].posCtlHandle), _IQ(gUserParams[HAL_MTR1].iqFullScaleCurrent_A));
	gMotorVars[HAL_MTR2].SpinTAC.PosCtlOutputMax_A = _IQmpy(STPOSCTL_getOutputMaximum(st_obj[HAL_MTR2].posCtlHandle), _IQ(gUserParams[HAL_MTR2].iqFullScaleCurrent_A));
	gMotorVars[HAL_MTR2].SpinTAC.PosCtlOutputMin_A = _IQmpy(STPOSCTL_getOutputMinimum(st_obj[HAL_MTR2].posCtlHandle), _IQ(gUserParams[HAL_MTR2].iqFullScaleCurrent_A));

    // enable the system by default
    gMotorVars[HAL_MTR1].Flag_enableSys = true;

    #ifdef DRV8301_SPI
        // turn on the DRV8301 if present
        HAL_enableDrv(halHandleMtr[HAL_MTR1]);
        HAL_enableDrv(halHandleMtr[HAL_MTR2]);
        // initialize the DRV8301 interface
        HAL_setupDrvSpi(halHandleMtr[HAL_MTR1],&gDrvSpi8301Vars[HAL_MTR1]);
        HAL_setupDrvSpi(halHandleMtr[HAL_MTR2],&gDrvSpi8301Vars[HAL_MTR2]);
    #endif

    #ifdef DRV8305_SPI
        // turn on the DRV8305 if present
        HAL_enableDrv(halHandleMtr[HAL_MTR1]);
        HAL_enableDrv(halHandleMtr[HAL_MTR2]);
        // initialize the DRV8305 interface
        HAL_setupDrvSpi(halHandleMtr[HAL_MTR1],&gDrvSpi8305Vars[HAL_MTR1]);
        HAL_setupDrvSpi(halHandleMtr[HAL_MTR2],&gDrvSpi8305Vars[HAL_MTR2]);
    #endif

        spa.year          = 2003;
         spa.month         = 10;
         spa.day           = 17;
         spa.hour          = 12;
         spa.minute        = 30;
         spa.second        = 30;
         spa.timezone      = -7.0;
         spa.delta_ut1     = 0;
         spa.delta_t       = 67;
         spa.longitude     = -105.1786;
         spa.latitude      = 39.742476;
         spa.elevation     = 1830.14;
         spa.pressure      = 820;
         spa.temperature   = 11;
         spa.slope         = 30;
         spa.azm_rotation  = -10;
         spa.atmos_refract = 0.5667;
         spa.function      = SPA_ALL;

    // Begin the background loop
    for(;;)
    {
        // Waiting for enable system flag to be set
        // Motor 1 Flag_enableSys is the master control.
        while(!(gMotorVars[HAL_MTR1].Flag_enableSys));

        // loop while the enable system flag is true
        // Motor 1 Flag_enableSys is the master control.
        while(gMotorVars[HAL_MTR1].Flag_enableSys)
        {
          uint_least8_t mtrNum = HAL_MTR1;
          // >>> INICIO Se le pasan los parametros al algoritmo y se obtienen los �ngulos <<<
//          spa_algorithm(late,lon, ele);
                result = spa_calculate(&spa);
                if (result == 0)  //check for SPA errors
                {
                    //display the results inside the SPA structure

                    // printf("Julian Day:    %.6f\n",spa.jd);
                    // printf("L:             %.6e degrees\n",spa.l);
                    // printf("B:             %.6e degrees\n",spa.b);
                    // printf("R:             %.6f AU\n",spa.r);
                    // printf("H:             %.6f degrees\n",spa.h);
                    // printf("Delta Psi:     %.6e degrees\n",spa.del_psi);
                    // printf("Delta Epsilon: %.6e degrees\n",spa.del_epsilon);
                    // printf("Epsilon:       %.6f degrees\n",spa.epsilon);
                    // printf("Zenith:        %.6f degrees\n",spa.zenith);
                    // printf("Azimuth:       %.6f degrees\n",spa.azimuth);
                    // printf("Incidence:     %.6f degrees\n",spa.incidence);
                    azi = spa.azimuth;
                    zen = spa.zenith;
                    min = 60.0*(spa.sunrise - (int)(spa.sunrise));
                    sec = 60.0*(min - (int)min);
                    // printf("Sunrise:       %02d:%02d:%02d Local Time\n", (int)(spa.sunrise), (int)min, (int)sec);

                    min = 60.0*(spa.sunset - (int)(spa.sunset));
                    sec = 60.0*(min - (int)min);
                    // printf("Sunset:        %02d:%02d:%02d Local Time\n", (int)(spa.sunset), (int)min, (int)sec);

                } else f_err = 1; // printf("SPA Error Code: %d\n", result);


          angAz = spa.azimuth;
          angZen = spa.zenith;
          ang_azi_establecer = (angAz - ang_azi_Actual);
          ang_zen_establecer = (angZen - ang_zen_Actual);
          ang_azi_mrev = ang_azi_establecer/360;
          ang_zen_mrev = ang_zen_establecer/360;
          ang_azi_Actual = angAz;
          ang_zen_Actual = angZen;

//          gMotorVars[HAL_MTR1].PosStepInt_MRev = 0;
//          gMotorVars[HAL_MTR1].PosStepFrac_MRev = _IQ24(ang_azi_mrev);
          gMotorVars[HAL_MTR1].RunPositionProfile = true;

//          gMotorVars[HAL_MTR2].PosStepInt_MRev = 0;
//          gMotorVars[HAL_MTR2].PosStepFrac_MRev = _IQ24(ang_zen_mrev);
          gMotorVars[HAL_MTR2].RunPositionProfile = true;

          // >>> FIN Se le pasan los parametros al algoritmo y se obtienen los �ngulos <<<
          for(mtrNum=HAL_MTR1;mtrNum<=HAL_MTR2;mtrNum++)
          {

            // If Flag_enableSys is set AND Flag_Run_Identify is set THEN
            // enable PWMs and set the speed reference
            if(gMotorVars[mtrNum].Flag_Run_Identify)
            {
                // update estimator state
                EST_updateState(estHandle[mtrNum],0);

                #ifdef FAST_ROM_V1p6
                    // call this function to fix 1p6. This is only used for
                    // F2806xF/M implementation of InstaSPIN (version 1.6 of
                    // ROM), since the inductance calculation is not done
                    // correctly in ROM, so this function fixes that ROM bug.
                    softwareUpdate1p6(estHandle[mtrNum],&gUserParams[mtrNum]);
                #endif

                // enable the PWM
                HAL_enablePwm(halHandleMtr[mtrNum]);

                // enable SpinTAC Velocity Control
                STPOSCTL_setEnable(st_obj[mtrNum].posCtlHandle, true);
                // provide bandwidth setting to SpinTAC Velocity Control
                STPOSCTL_setBandwidth_radps(st_obj[mtrNum].posCtlHandle, gMotorVars[mtrNum].SpinTAC.PosCtlBw_radps);
                // provide output maximum and minimum setting to SpinTAC Velocity Control
                STPOSCTL_setOutputMaximums(st_obj[mtrNum].posCtlHandle, _IQmpy(gMotorVars[mtrNum].SpinTAC.PosCtlOutputMax_A, gCurrent_A_to_pu_sf[mtrNum]), _IQmpy(gMotorVars[mtrNum].SpinTAC.PosCtlOutputMin_A, gCurrent_A_to_pu_sf[mtrNum]));
            }
            else  // Flag_enableSys is set AND Flag_Run_Identify is not set
            {
                // set estimator to Idle
                EST_setIdle(estHandle[mtrNum]);

                // disable the PWM
                HAL_disablePwm(halHandleMtr[mtrNum]);

                // clear integrator outputs
                PID_setUi(pidHandle[mtrNum][0],_IQ(0.0));
                PID_setUi(pidHandle[mtrNum][1],_IQ(0.0));
                PID_setUi(pidHandle[mtrNum][2],_IQ(0.0));

                // clear Id and Iq references
                gIdq_ref_pu[mtrNum].value[0] = _IQ(0.0);
                gIdq_ref_pu[mtrNum].value[1] = _IQ(0.0);

                // place SpinTAC Velocity Control into reset
                STPOSCTL_setEnable(st_obj[mtrNum].posCtlHandle, false);
                // If motor is not running, feed the position feedback into SpinTAC Position Move
                STPOSMOVE_setPositionStart_mrev(st_obj[mtrNum].posMoveHandle, STPOSCONV_getPosition_mrev(st_obj[mtrNum].posConvHandle));
            }

            // update the global variables
            updateGlobalVariables(estHandle[mtrNum], mtrNum);

            // enable/disable the forced angle
            EST_setFlag_enableForceAngle(estHandle[mtrNum],
                    gMotorVars[mtrNum].Flag_enableForceAngle);


            #ifdef DRV8301_SPI
                HAL_writeDrvData(halHandleMtr[mtrNum],&gDrvSpi8301Vars[mtrNum]);

                HAL_readDrvData(halHandleMtr[mtrNum],&gDrvSpi8301Vars[mtrNum]);
            #endif
            #ifdef DRV8305_SPI
                HAL_writeDrvData(halHandleMtr[mtrNum],&gDrvSpi8305Vars[mtrNum]);

                HAL_readDrvData(halHandleMtr[mtrNum],&gDrvSpi8305Vars[mtrNum]);
            #endif

          } // end of for loop

        } // end of while(gFlag_enableSys) loop

        // disable the PWM
        HAL_disablePwm(halHandleMtr[HAL_MTR1]);
        HAL_disablePwm(halHandleMtr[HAL_MTR2]);

        gMotorVars[HAL_MTR1].Flag_Run_Identify = false;
        gMotorVars[HAL_MTR2].Flag_Run_Identify = false;

    } // end of for(;;) loop
} // end of main() function


//! \brief     The main ISR that implements the motor control.
interrupt void motor1_ISR(void)
{
    // Declaration of local variables
    static _iq angle_pu = _IQ(0.0);
    _iq speed_pu = _IQ(0.0);
    _iq oneOverDcBus;
    MATH_vec2 Iab_pu;
    MATH_vec2 Vab_pu;
    MATH_vec2 phasor;

    HAL_setGpioHigh(halHandle,GPIO_Number_12);

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

    // convert the ADC data
    HAL_readAdcDataWithOffsets(halHandle,halHandleMtr[HAL_MTR1],&gAdcData[HAL_MTR1]);

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

    // run Clarke transform on current.  Three values are passed, two values
    // are returned.
    CLARKE_run(clarkeHandle_I[HAL_MTR1],&gAdcData[HAL_MTR1].I,&Iab_pu);

    // compute the sine and cosine phasor values which are part of the
    // Park transform calculations. Once these values are computed,
    // they are copied into the PARK module, which then uses them to
    // transform the voltages from Alpha/Beta to DQ reference frames.
    phasor.value[0] = _IQcosPU(angle_pu);
    phasor.value[1] = _IQsinPU(angle_pu);

    // set the phasor in the Park transform
    PARK_setPhasor(parkHandle[HAL_MTR1],&phasor);

    // Run the Park module.  This converts the current vector from
    // stationary frame values to synchronous frame values.
    PARK_run(parkHandle[HAL_MTR1],&Iab_pu,&gIdq_pu[HAL_MTR1]);

    // compute the electrical angle
    ENC_calcElecAngle(encHandle[HAL_MTR1], HAL_getQepPosnCounts(halHandleMtr[HAL_MTR1]));

    if(stCntPosition[HAL_MTR1] >= gUserParams[HAL_MTR1].numCtrlTicksPerSpeedTick)
    {
    	// Calculate the feedback position, this must always be ran in order to ensure there are no jumps
    	ST_runPosConv(stHandle[HAL_MTR1], encHandle[HAL_MTR1], slipHandle[HAL_MTR1], &gIdq_pu[HAL_MTR1], gUserParams[HAL_MTR1].motor_type);
    }

    // run the appropriate controller
    if(gMotorVars[HAL_MTR1].Flag_Run_Identify)
    {
        // Declaration of local variables.
        _iq refValue;
        _iq fbackValue;
        _iq outMax_pu;

        // check if the motor should be forced into encoder slignment
        if(gMotorVars[HAL_MTR1].Flag_enableAlignment == false)
        {
            gMotorVars[HAL_MTR1].MaxVel_krpm = _IQ(3);
            gMotorVars[HAL_MTR1].MaxAccel_krpmps = _IQ(65);
            gMotorVars[HAL_MTR1].MaxDecel_krpmps = _IQ(65);
            gMotorVars[HAL_MTR1].MaxJrk_krpmps2 = _IQ20(350);
            // when appropriate, run SpinTAC Position Control
            // This mechanism provides the decimation for the speed loop.
            if(stCntPosition[HAL_MTR1] >= gUserParams[HAL_MTR1].numCtrlTicksPerSpeedTick)
            {
                // Reset the Position execution counter.
                stCntPosition[HAL_MTR1] = 0;

                if((STPOSMOVE_getStatus(st_obj[HAL_MTR1].posMoveHandle) == ST_MOVE_IDLE) && (gMotorVars[HAL_MTR1].RunPositionProfile == true))
                {
					// Get the configuration for SpinTAC Position Move
					STPOSMOVE_setCurveType(st_obj[HAL_MTR1].posMoveHandle, gMotorVars[HAL_MTR1].SpinTAC.PosMoveCurveType);
					STPOSMOVE_setPositionStep_mrev(st_obj[HAL_MTR1].posMoveHandle, gMotorVars[HAL_MTR1].PosStepInt_MRev,gMotorVars[HAL_MTR1].PosStepFrac_MRev);
					STPOSMOVE_setVelocityLimit(st_obj[HAL_MTR1].posMoveHandle, _IQmpy(gMotorVars[HAL_MTR1].MaxVel_krpm, gSpeed_krpm_to_pu_sf[HAL_MTR1]));
					STPOSMOVE_setAccelerationLimit(st_obj[HAL_MTR1].posMoveHandle, _IQmpy(gMotorVars[HAL_MTR1].MaxAccel_krpmps, gSpeed_krpm_to_pu_sf[HAL_MTR1]));
					STPOSMOVE_setDecelerationLimit(st_obj[HAL_MTR1].posMoveHandle, _IQmpy(gMotorVars[HAL_MTR1].MaxDecel_krpmps, gSpeed_krpm_to_pu_sf[HAL_MTR1]));
					STPOSMOVE_setJerkLimit(st_obj[HAL_MTR1].posMoveHandle, _IQ20mpy(gMotorVars[HAL_MTR1].MaxJrk_krpmps2, _IQtoIQ20(gSpeed_krpm_to_pu_sf[HAL_MTR1])));
					// Enable the SpinTAC Position Profile Generator
					STPOSMOVE_setEnable(st_obj[HAL_MTR1].posMoveHandle, true);
					// clear the position step command
					gMotorVars[HAL_MTR1].PosStepInt_MRev = 0;
					gMotorVars[HAL_MTR1].PosStepFrac_MRev = 0;
					gMotorVars[HAL_MTR1].RunPositionProfile = false;
				}

                // The next instruction executes SpinTAC Velocity Move
                // This is the speed profile generation
                STPOSMOVE_run(st_obj[HAL_MTR1].posMoveHandle);

                // The next instruction executes SpinTAC Position Control and places
                // its output in Idq_ref_pu.value[1], which is the input reference
                // value for the q-axis current controller.
                gIdq_ref_pu[HAL_MTR1].value[1] = ST_runPosCtl(stHandle[HAL_MTR1]);
            }
            else
            {
                // increment counter
            	stCntPosition[HAL_MTR1]++;
            }

            // generate the motor electrical angle
            if(gUserParams[HAL_MTR1].motor_type == MOTOR_Type_Induction)
            {
                // update the electrical angle for the SLIP module
                SLIP_setElectricalAngle(slipHandle[HAL_MTR1], ENC_getElecAngle(encHandle[HAL_MTR1]));
                // compute the amount of slip
                SLIP_run(slipHandle[HAL_MTR1]);
                // set magnetic angle
                angle_pu = SLIP_getMagneticAngle(slipHandle[HAL_MTR1]);
            }
            else
            {
                angle_pu = ENC_getElecAngle(encHandle[HAL_MTR1]);
            }

            speed_pu = STPOSCONV_getVelocity(st_obj[HAL_MTR1].posConvHandle);
        }
        else
        {  // the alignment procedure is in effect

        	// force motor angle and speed to 0
        	angle_pu = _IQ(0.0);
        	speed_pu = _IQ(0.0);

        	// set D-axis current to Rs estimation current
            gIdq_ref_pu[HAL_MTR1].value[0] = _IQ(USER_MOTOR_RES_EST_CURRENT/USER_IQ_FULL_SCALE_CURRENT_A);
            // set Q-axis current to 0
            gIdq_ref_pu[HAL_MTR1].value[1] = _IQ(0.0);

            // save encoder reading when forcing motor into alignment
            if(gUserParams[HAL_MTR1].motor_type == MOTOR_Type_Pm)
            {
                ENC_setZeroOffset(encHandle[HAL_MTR1], (uint32_t)(HAL_getQepPosnMaximum(halHandleMtr[HAL_MTR1]) - HAL_getQepPosnCounts(halHandleMtr[HAL_MTR1])));
            }

            // if alignment counter exceeds threshold, exit alignment
            if(gAlignCount[HAL_MTR1]++ >= gUserParams[HAL_MTR1].ctrlWaitTime[CTRL_State_OffLine])
            {
                gMotorVars[HAL_MTR1].Flag_enableAlignment = false;
                gAlignCount[HAL_MTR1] = 0;
                gIdq_ref_pu[HAL_MTR1].value[0] = _IQ(0.0);
            }
        }

        // Get the reference value for the d-axis current controller.
        refValue = gIdq_ref_pu[HAL_MTR1].value[0];

        // Get the actual value of Id
        fbackValue = gIdq_pu[HAL_MTR1].value[0];

        // The next instruction executes the PI current controller for the
        // d axis and places its output in Vdq_pu.value[0], which is the
        // control voltage along the d-axis (Vd)
        PID_run(pidHandle[HAL_MTR1][1],refValue,fbackValue,&(gVdq_out_pu[HAL_MTR1].value[0]));

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

        // get the actual value of Iq
        fbackValue = gIdq_pu[HAL_MTR1].value[1];

        // The voltage limits on the output of the q-axis current controller
        // are dynamic, and are dependent on the output voltage from the d-axis
        // current controller.  In other words, the d-axis current controller
        // gets first dibs on the available voltage, and the q-axis current
        // controller gets what's left over.  That is why the d-axis current
        // controller executes first. The next instruction calculates the
        // maximum limits for this voltage as:
        // Vq_min_max = +/- sqrt(Vbus^2 - Vd^2)
        outMax_pu = _IQsqrt(_IQ(USER_MAX_VS_MAG_PU * USER_MAX_VS_MAG_PU)
                - _IQmpy(gVdq_out_pu[HAL_MTR1].value[0],gVdq_out_pu[HAL_MTR1].value[0]));

        // Set the limits to +/- outMax_pu
        PID_setMinMax(pidHandle[HAL_MTR1][2],-outMax_pu,outMax_pu);

        // The next instruction executes the PI current controller for the
        // q axis and places its output in Vdq_pu.value[1], which is the
        // control voltage vector along the q-axis (Vq)
        PID_run(pidHandle[HAL_MTR1][2],refValue,fbackValue,&(gVdq_out_pu[HAL_MTR1].value[1]));

        // The voltage vector is now calculated and ready to be applied to the
        // motor in the form of three PWM signals.  However, even though the
        // voltages may be supplied to the PWM module now, they won't be
        // applied to the motor until the next PWM cycle. By this point, the
        // motor will have moved away from the angle that the voltage vector
        // was calculated for, by an amount which is proportional to the
        // sampling frequency and the speed of the motor.  For steady-state
        // speeds, we can calculate this angle delay and compensate for it.
        ANGLE_COMP_run(angleCompHandle[HAL_MTR1],speed_pu,angle_pu);
        angle_pu = ANGLE_COMP_getAngleComp_pu(angleCompHandle[HAL_MTR1]);

        // compute the sine and cosine phasor values which are part of the inverse
        // Park transform calculations. Once these values are computed,
        // they are copied into the IPARK module, which then uses them to
        // transform the voltages from DQ to Alpha/Beta reference frames.
        phasor.value[0] = _IQcosPU(angle_pu);
        phasor.value[1] = _IQsinPU(angle_pu);

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

        // Run the inverse Park module.  This converts the voltage vector from
        // synchronous frame values to stationary frame values.
        IPARK_run(iparkHandle[HAL_MTR1],&gVdq_out_pu[HAL_MTR1],&Vab_pu);

        // These 3 statements compensate for variations in the DC bus by adjusting the
        // PWM duty cycle. The goal is to achieve the same volt-second product
        // regardless of the DC bus value.  To do this, we must divide the desired voltage
        // values by the DC bus value.  Or...it is easier to multiply by 1/(DC bus value).
        oneOverDcBus = _IQdiv(_IQ(1.0), gAdcData[HAL_MTR1].dcBus);//EST_getOneOverDcBus_pu(estHandle[HAL_MTR1]);
        Vab_pu.value[0] = _IQmpy(Vab_pu.value[0],oneOverDcBus);
        Vab_pu.value[1] = _IQmpy(Vab_pu.value[1],oneOverDcBus);

        // Now run the space vector generator (SVGEN) module.
        // There is no need to do an inverse CLARKE transform, as this is
        // handled in the SVGEN_run function.
        SVGEN_run(svgenHandle[HAL_MTR1],&Vab_pu,&(gPwmData[HAL_MTR1].Tabc));
    }
    else if(gMotorVars[HAL_MTR1].Flag_enableOffsetcalc == true)
    {
        runOffsetsCalculation(HAL_MTR1);
    }
    else  // gMotorVars.Flag_Run_Identify = 0
    {
        // disable the PWM
        HAL_disablePwm(halHandleMtr[HAL_MTR1]);

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

    // write to the PWM compare registers, and then we are done!
    HAL_writePwmData(halHandleMtr[HAL_MTR1],&gPwmData[HAL_MTR1]);

    HAL_setGpioLow(halHandle,GPIO_Number_12);

    return;
} // end of motor1_ISR() function


interrupt void motor2_ISR(void)
{
  // Declaration of local variables
  static _iq angle_pu = _IQ(0.0);
  _iq speed_pu = _IQ(0.0);
  _iq oneOverDcBus;
  MATH_vec2 Iab_pu;
  MATH_vec2 Vab_pu;
  MATH_vec2 phasor;

  HAL_setGpioHigh(halHandle,GPIO_Number_20);

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

  // convert the ADC data
  HAL_readAdcDataWithOffsets(halHandle,halHandleMtr[HAL_MTR2],&gAdcData[HAL_MTR2]);

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


  // run Clarke transform on current.  Three values are passed, two values
  // are returned.
  CLARKE_run(clarkeHandle_I[HAL_MTR2],&gAdcData[HAL_MTR2].I,&Iab_pu);

  // compute the sine and cosine phasor values which are part of the
  // Park transform calculations. Once these values are computed,
  // they are copied into the PARK module, which then uses them to
  // transform the voltages from Alpha/Beta to DQ reference frames.
  phasor.value[0] = _IQcosPU(angle_pu);
  phasor.value[1] = _IQsinPU(angle_pu);

  // set the phasor in the Park transform
  PARK_setPhasor(parkHandle[HAL_MTR2],&phasor);

  // Run the Park module.  This converts the current vector from
  // stationary frame values to synchronous frame values.
  PARK_run(parkHandle[HAL_MTR2],&Iab_pu,&gIdq_pu[HAL_MTR2]);

  // compute the electrical angle
  ENC_calcElecAngle(encHandle[HAL_MTR2], HAL_getQepPosnCounts(halHandleMtr[HAL_MTR2]));

  if(stCntPosition[HAL_MTR2] >= gUserParams[HAL_MTR2].numCtrlTicksPerSpeedTick)
  {
  	// Calculate the feedback position, this must always be ran in order to ensure there are no jumps
  	ST_runPosConv(stHandle[HAL_MTR2], encHandle[HAL_MTR2], slipHandle[HAL_MTR2], &gIdq_pu[HAL_MTR2], gUserParams[HAL_MTR2].motor_type);
  }

  // run the appropriate controller
  if(gMotorVars[HAL_MTR2].Flag_Run_Identify)
  {
	  // Declaration of local variables.
	  _iq refValue;
	  _iq fbackValue;
	  _iq outMax_pu;

	  // check if the motor should be forced into encoder slignment
	  if(gMotorVars[HAL_MTR2].Flag_enableAlignment == false)
	  {
	      gMotorVars[HAL_MTR2].MaxVel_krpm = _IQ(3);
          gMotorVars[HAL_MTR2].MaxAccel_krpmps = _IQ(65);
          gMotorVars[HAL_MTR2].MaxDecel_krpmps = _IQ(65);
          gMotorVars[HAL_MTR2].MaxJrk_krpmps2 = _IQ20(350);
		  // when appropriate, run SpinTAC Position Control
		  // This mechanism provides the decimation for the speed loop.
		  if(stCntPosition[HAL_MTR2] >= gUserParams[HAL_MTR2].numCtrlTicksPerSpeedTick)
		  {
			  // Reset the Position execution counter.
			  stCntPosition[HAL_MTR2] = 0;

			  if((STPOSMOVE_getStatus(st_obj[HAL_MTR2].posMoveHandle) == ST_MOVE_IDLE) && (gMotorVars[HAL_MTR2].RunPositionProfile == true))
			  {
				// Get the configuration for SpinTAC Position Move
				STPOSMOVE_setCurveType(st_obj[HAL_MTR2].posMoveHandle, gMotorVars[HAL_MTR2].SpinTAC.PosMoveCurveType);
				STPOSMOVE_setPositionStep_mrev(st_obj[HAL_MTR2].posMoveHandle, gMotorVars[HAL_MTR2].PosStepInt_MRev,  gMotorVars[HAL_MTR2].PosStepFrac_MRev);
				STPOSMOVE_setVelocityLimit(st_obj[HAL_MTR2].posMoveHandle, _IQmpy(gMotorVars[HAL_MTR2].MaxVel_krpm, gSpeed_krpm_to_pu_sf[HAL_MTR2]));
				STPOSMOVE_setAccelerationLimit(st_obj[HAL_MTR2].posMoveHandle, _IQmpy(gMotorVars[HAL_MTR2].MaxAccel_krpmps, gSpeed_krpm_to_pu_sf[HAL_MTR2]));
				STPOSMOVE_setDecelerationLimit(st_obj[HAL_MTR2].posMoveHandle, _IQmpy(gMotorVars[HAL_MTR2].MaxDecel_krpmps, gSpeed_krpm_to_pu_sf[HAL_MTR2]));
				STPOSMOVE_setJerkLimit(st_obj[HAL_MTR2].posMoveHandle, _IQ20mpy(gMotorVars[HAL_MTR2].MaxJrk_krpmps2, _IQtoIQ20(gSpeed_krpm_to_pu_sf[HAL_MTR2])));
				// Enable the SpinTAC Position Profile Generator
				STPOSMOVE_setEnable(st_obj[HAL_MTR2].posMoveHandle, true);
				// clear the position step command
				gMotorVars[HAL_MTR2].PosStepInt_MRev = 0;
				gMotorVars[HAL_MTR2].PosStepFrac_MRev = 0;
				gMotorVars[HAL_MTR2].RunPositionProfile = false;
			}

			  // The next instruction executes SpinTAC Velocity Move
			  // This is the speed profile generation
			  STPOSMOVE_run(st_obj[HAL_MTR2].posMoveHandle);

			  // The next instruction executes SpinTAC Position Control and places
			  // its output in Idq_ref_pu.value[1], which is the input reference
			  // value for the q-axis current controller.
			  gIdq_ref_pu[HAL_MTR2].value[1] = ST_runPosCtl(stHandle[HAL_MTR2]);
		  }
		  else
		  {
			  // increment counter
			  stCntPosition[HAL_MTR2]++;
		  }

		  // generate the motor electrical angle
		  if(gUserParams[HAL_MTR2].motor_type == MOTOR_Type_Induction)
		  {
			  // update the electrical angle for the SLIP module
			  SLIP_setElectricalAngle(slipHandle[HAL_MTR2], ENC_getElecAngle(encHandle[HAL_MTR2]));
			  // compute the amount of slip
			  SLIP_run(slipHandle[HAL_MTR2]);
			  // set magnetic angle
			  angle_pu = SLIP_getMagneticAngle(slipHandle[HAL_MTR2]);
		  }
		  else
		  {
			  angle_pu = ENC_getElecAngle(encHandle[HAL_MTR2]);
		  }

		  speed_pu = STPOSCONV_getVelocity(st_obj[HAL_MTR2].posConvHandle);
	  }
	  else
	  {  // the alignment procedure is in effect

		  // force motor angle and speed to 0
		  angle_pu = _IQ(0.0);
		  speed_pu = _IQ(0.0);

		  // set D-axis current to Rs estimation current
		  gIdq_ref_pu[HAL_MTR2].value[0] = _IQ(USER_MOTOR_RES_EST_CURRENT_2/USER_IQ_FULL_SCALE_CURRENT_A_2);
		  // set Q-axis current to 0
		  gIdq_ref_pu[HAL_MTR2].value[1] = _IQ(0.0);

		  // save encoder reading when forcing motor into alignment
		  if(gUserParams[HAL_MTR2].motor_type == MOTOR_Type_Pm)
		  {
			  ENC_setZeroOffset(encHandle[HAL_MTR2], (uint32_t)(HAL_getQepPosnMaximum(halHandleMtr[HAL_MTR2]) - HAL_getQepPosnCounts(halHandleMtr[HAL_MTR2])));
		  }

		  // if alignment counter exceeds threshold, exit alignment
		  if(gAlignCount[HAL_MTR2]++ >= gUserParams[HAL_MTR2].ctrlWaitTime[CTRL_State_OffLine])
		  {
			  gMotorVars[HAL_MTR2].Flag_enableAlignment = false;
			  gAlignCount[HAL_MTR2] = 0;
			  gIdq_ref_pu[HAL_MTR2].value[0] = _IQ(0.0);
		  }
	  }

	  // Get the reference value for the d-axis current controller.
	  refValue = gIdq_ref_pu[HAL_MTR2].value[0];

	  // Get the actual value of Id
	  fbackValue = gIdq_pu[HAL_MTR2].value[0];

	  // The next instruction executes the PI current controller for the
	  // d axis and places its output in Vdq_pu.value[0], which is the
	  // control voltage along the d-axis (Vd)
	  PID_run(pidHandle[HAL_MTR2][1],refValue,fbackValue,&(gVdq_out_pu[HAL_MTR2].value[0]));

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

	  // get the actual value of Iq
	  fbackValue = gIdq_pu[HAL_MTR2].value[1];

	  // The voltage limits on the output of the q-axis current controller
	  // are dynamic, and are dependent on the output voltage from the d-axis
	  // current controller.  In other words, the d-axis current controller
	  // gets first dibs on the available voltage, and the q-axis current
	  // controller gets what's left over.  That is why the d-axis current
	  // controller executes first. The next instruction calculates the
	  // maximum limits for this voltage as:
	  // Vq_min_max = +/- sqrt(Vbus^2 - Vd^2)
	  outMax_pu = _IQsqrt(_IQ(USER_MAX_VS_MAG_PU_2 * USER_MAX_VS_MAG_PU_2)
			  - _IQmpy(gVdq_out_pu[HAL_MTR2].value[0],gVdq_out_pu[HAL_MTR2].value[0]));

	  // Set the limits to +/- outMax_pu
	  PID_setMinMax(pidHandle[HAL_MTR2][2],-outMax_pu,outMax_pu);

	  // The next instruction executes the PI current controller for the
	  // q axis and places its output in Vdq_pu.value[1], which is the
	  // control voltage vector along the q-axis (Vq)
	  PID_run(pidHandle[HAL_MTR2][2],refValue,fbackValue,&(gVdq_out_pu[HAL_MTR2].value[1]));

	  // The voltage vector is now calculated and ready to be applied to the
	  // motor in the form of three PWM signals.  However, even though the
	  // voltages may be supplied to the PWM module now, they won't be
	  // applied to the motor until the next PWM cycle. By this point, the
	  // motor will have moved away from the angle that the voltage vector
	  // was calculated for, by an amount which is proportional to the
	  // sampling frequency and the speed of the motor.  For steady-state
	  // speeds, we can calculate this angle delay and compensate for it.
	  ANGLE_COMP_run(angleCompHandle[HAL_MTR2],speed_pu,angle_pu);
	  angle_pu = ANGLE_COMP_getAngleComp_pu(angleCompHandle[HAL_MTR2]);


	  // compute the sine and cosine phasor values which are part of the inverse
	  // Park transform calculations. Once these values are computed,
	  // they are copied into the IPARK module, which then uses them to
	  // transform the voltages from DQ to Alpha/Beta reference frames.
	  phasor.value[0] = _IQcosPU(angle_pu);
	  phasor.value[1] = _IQsinPU(angle_pu);

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

	  // Run the inverse Park module.  This converts the voltage vector from
	  // synchronous frame values to stationary frame values.
	  IPARK_run(iparkHandle[HAL_MTR2],&gVdq_out_pu[HAL_MTR2],&Vab_pu);

	  // These 3 statements compensate for variations in the DC bus by adjusting the
	  // PWM duty cycle. The goal is to achieve the same volt-second product
	  // regardless of the DC bus value.  To do this, we must divide the desired voltage
	  // values by the DC bus value.  Or...it is easier to multiply by 1/(DC bus value).
	  oneOverDcBus = _IQdiv(_IQ(1.0), gAdcData[HAL_MTR2].dcBus);
	  Vab_pu.value[0] = _IQmpy(Vab_pu.value[0],oneOverDcBus);
	  Vab_pu.value[1] = _IQmpy(Vab_pu.value[1],oneOverDcBus);

	  // Now run the space vector generator (SVGEN) module.
	  // There is no need to do an inverse CLARKE transform, as this is
	  // handled in the SVGEN_run function.
	  SVGEN_run(svgenHandle[HAL_MTR2],&Vab_pu,&(gPwmData[HAL_MTR2].Tabc));
  }
  else if(gMotorVars[HAL_MTR2].Flag_enableOffsetcalc == true)
  {
	  runOffsetsCalculation(HAL_MTR2);
  }
  else  // gMotorVars.Flag_Run_Identify = 0
  {
	  // disable the PWM
	  HAL_disablePwm(halHandleMtr[HAL_MTR2]);

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

  // write to the PWM compare registers, and then we are done!
  HAL_writePwmData(halHandleMtr[HAL_MTR2],&gPwmData[HAL_MTR2]);

  HAL_setGpioLow(halHandle,GPIO_Number_20);

  return;
} // end of motor2_ISR() function


void pidSetup(HAL_MtrSelect_e mtrNum)
{
  // This equation uses the scaled maximum voltage vector, which is
  // already in per units, hence there is no need to include the #define
  // for USER_IQ_FULL_SCALE_VOLTAGE_V
  _iq maxVoltage_pu = _IQ(gUserParams[mtrNum].maxVsMag_pu *
                          gUserParams[mtrNum].voltage_sf);


  float_t fullScaleCurrent = gUserParams[mtrNum].iqFullScaleCurrent_A;
  float_t fullScaleVoltage = gUserParams[mtrNum].iqFullScaleVoltage_V;
  float_t IsrPeriod_sec = 1.0e-6 * gUserParams[mtrNum].pwmPeriod_usec *
                          gUserParams[mtrNum].numPwmTicksPerIsrTick;
  float_t Ls_d = gUserParams[mtrNum].motor_Ls_d;
  float_t Ls_q = gUserParams[mtrNum].motor_Ls_q;
  float_t Rs = gUserParams[mtrNum].motor_Rs;

  // This lab assumes that motor parameters are known, and it does not
  // perform motor ID, so the R/L parameters are known and defined in
  // user.h
  float_t RoverLs_d = Rs / Ls_d;
  float_t RoverLs_q = Rs / Ls_q;

  // For the current controller, Kp = Ls*bandwidth(rad/sec)  But in order
  // to be used, it must be converted to per unit values by multiplying
  // by fullScaleCurrent and then dividing by fullScaleVoltage.  From the
  // statement below, we see that the bandwidth in rad/sec is equal to
  // 0.25/IsrPeriod_sec, which is equal to USER_ISR_FREQ_HZ/4. This means
  // that by setting Kp as described below, the bandwidth in Hz is
  // USER_ISR_FREQ_HZ/(8*pi).
  _iq Kp_Id = _IQ((0.25 * Ls_d * fullScaleCurrent) / (IsrPeriod_sec
              * fullScaleVoltage));

  // In order to achieve pole/zero cancellation (which reduces the
  // closed-loop transfer function from a second-order system to a
  // first-order system), Ki must equal Rs/Ls.  Since the output of the
  // Ki gain stage is integrated by a DIGITAL integrator, the integrator
  // input must be scaled by 1/IsrPeriod_sec.  That's just the way
  // digital integrators work.  But, since IsrPeriod_sec is a constant,
  // we can save an additional multiplication operation by lumping this
  // term with the Ki value.
  _iq Ki_Id = _IQ(RoverLs_d * IsrPeriod_sec);

  // Now do the same thing for Kp for the q-axis current controller.
  // If the motor is not an IPM motor, Ld and Lq are the same, which
  // means that Kp_Iq = Kp_Id
  _iq Kp_Iq = _IQ((0.25 * Ls_q * fullScaleCurrent) / (IsrPeriod_sec
              * fullScaleVoltage));

  // Do the same thing for Ki for the q-axis current controller.  If the
  // motor is not an IPM motor, Ld and Lq are the same, which means that
  // Ki_Iq = Ki_Id.
  _iq Ki_Iq = _IQ(RoverLs_q * IsrPeriod_sec);

  // There are two PI controllers; two current
  // controllers.  Each PI controller has two coefficients; Kp and Ki.
  // So you have a total of four coefficients that must be defined.
  // This is for the Id current controller
  pidHandle[mtrNum][1] = PID_init(&pid[mtrNum][1],sizeof(pid[mtrNum][1]));
  // This is for the Iq current controller
  pidHandle[mtrNum][2] = PID_init(&pid[mtrNum][2],sizeof(pid[mtrNum][2]));

  stCntPosition[mtrNum] = 0;  // Set the counter for decimating the speed
                              // controller to 0

  // The following instructions load the parameters for the d-axis
  // current controller.
  // P term = Kp_Id, I term = Ki_Id, D term = 0
  PID_setGains(pidHandle[mtrNum][1],Kp_Id,Ki_Id,_IQ(0.0));

  // Largest negative voltage = -maxVoltage_pu, largest positive
  // voltage = maxVoltage_pu
  PID_setMinMax(pidHandle[mtrNum][1],-maxVoltage_pu,maxVoltage_pu);

  // Set the initial condition value for the integrator output to 0
  PID_setUi(pidHandle[mtrNum][1],_IQ(0.0));

  // The following instructions load the parameters for the q-axis
  // current controller.
  // P term = Kp_Iq, I term = Ki_Iq, D term = 0
  PID_setGains(pidHandle[mtrNum][2],Kp_Iq,Ki_Iq,_IQ(0.0));

  // The largest negative voltage = 0 and the largest positive
  // voltage = 0.  But these limits are updated every single ISR before
  // actually executing the Iq controller. The limits depend on how much
  // voltage is left over after the Id controller executes. So having an
  // initial value of 0 does not affect Iq current controller execution.
  PID_setMinMax(pidHandle[mtrNum][2],_IQ(0.0),_IQ(0.0));

  // Set the initial condition value for the integrator output to 0
  PID_setUi(pidHandle[mtrNum][2],_IQ(0.0));
}


void runOffsetsCalculation(HAL_MtrSelect_e mtrNum)
{
  uint16_t cnt;

  // enable the PWM
  HAL_enablePwm(halHandleMtr[mtrNum]);

  for(cnt=0;cnt<3;cnt++)
    {
      // Set the PWMs to 50% duty cycle
      gPwmData[mtrNum].Tabc.value[cnt] = _IQ(0.0);

      // reset offsets used
      gOffsets_I_pu[mtrNum].value[cnt] = _IQ(0.0);
      gOffsets_V_pu[mtrNum].value[cnt] = _IQ(0.0);

      // run offset estimation
      FILTER_FO_run(filterHandle[mtrNum][cnt],gAdcData[mtrNum].I.value[cnt]);
      FILTER_FO_run(filterHandle[mtrNum][cnt+3],gAdcData[mtrNum].V.value[cnt]);
    }

  if(gOffsetCalcCount[mtrNum]++ >= gUserParams[mtrNum].ctrlWaitTime[CTRL_State_OffLine])
    {
      gMotorVars[mtrNum].Flag_enableOffsetcalc = false;
      gOffsetCalcCount[mtrNum] = 0;

      for(cnt=0;cnt<3;cnt++)
        {
          // get calculated offsets from filter
          gOffsets_I_pu[mtrNum].value[cnt] = FILTER_FO_get_y1(filterHandle[mtrNum][cnt]);
          gOffsets_V_pu[mtrNum].value[cnt] = FILTER_FO_get_y1(filterHandle[mtrNum][cnt+3]);

          // clear filters
          FILTER_FO_setInitialConditions(filterHandle[mtrNum][cnt],_IQ(0.0),_IQ(0.0));
          FILTER_FO_setInitialConditions(filterHandle[mtrNum][cnt+3],_IQ(0.0),_IQ(0.0));
        }
    }

  return;
} // end of runOffsetsCalculation() function


//! \brief  Call this function to fix 1p6. This is only used for F2806xF/M
//! \brief  implementation of InstaSPIN (version 1.6 of ROM) since the
//! \brief  inductance calculation is not done correctly in ROM, so this
//! \brief  function fixes that ROM bug.
void softwareUpdate1p6(EST_Handle handle,USER_Params *pUserParams)
{
  float_t iqFullScaleVoltage_V = pUserParams->iqFullScaleVoltage_V;
  float_t iqFullScaleCurrent_A = pUserParams->iqFullScaleCurrent_A;
  float_t voltageFilterPole_rps = pUserParams->voltageFilterPole_rps;
  float_t motorLs_d = pUserParams->motor_Ls_d;
  float_t motorLs_q = pUserParams->motor_Ls_q;

    float_t fullScaleInductance = iqFullScaleVoltage_V
                    / (iqFullScaleCurrent_A
                    * voltageFilterPole_rps);
    float_t Ls_coarse_max = _IQ30toF(EST_getLs_coarse_max_pu(handle));
    int_least8_t lShift = ceil(log(motorLs_d / (Ls_coarse_max
                         * fullScaleInductance)) / log(2.0));
    uint_least8_t Ls_qFmt = 30 - lShift;
    float_t L_max = fullScaleInductance * pow(2.0,lShift);
    _iq Ls_d_pu = _IQ30(motorLs_d / L_max);
    _iq Ls_q_pu = _IQ30(motorLs_q / L_max);

    // store the results
    EST_setLs_d_pu(handle,Ls_d_pu);
    EST_setLs_q_pu(handle,Ls_q_pu);
    EST_setLs_qFmt(handle,Ls_qFmt);

    return;
} // end of softwareUpdate1p6() function


//! \brief     Setup the Clarke transform for either 2 or 3 sensors.
//! \param[in] handle             The clarke (CLARKE) handle
//! \param[in] numCurrentSensors  The number of current sensors
void setupClarke_I(CLARKE_Handle handle,const uint_least8_t numCurrentSensors)
{
    _iq alpha_sf,beta_sf;

    // initialize the Clarke transform module for current
    if(numCurrentSensors == 3)
    {
        alpha_sf = _IQ(MATH_ONE_OVER_THREE);
        beta_sf = _IQ(MATH_ONE_OVER_SQRT_THREE);
    }
    else if(numCurrentSensors == 2)
    {
        alpha_sf = _IQ(1.0);
        beta_sf = _IQ(MATH_ONE_OVER_SQRT_THREE);
    }
    else
    {
        alpha_sf = _IQ(0.0);
        beta_sf = _IQ(0.0);
    }

    // set the parameters
    CLARKE_setScaleFactors(handle,alpha_sf,beta_sf);
    CLARKE_setNumSensors(handle,numCurrentSensors);

    return;
} // end of setupClarke_I() function


//! \brief     Setup the Clarke transform for either 2 or 3 sensors.
//! \param[in] handle             The clarke (CLARKE) handle
//! \param[in] numVoltageSensors  The number of voltage sensors
void setupClarke_V(CLARKE_Handle handle,const uint_least8_t numVoltageSensors)
{
    _iq alpha_sf,beta_sf;

    // initialize the Clarke transform module for voltage
    if(numVoltageSensors == 3)
    {
        alpha_sf = _IQ(MATH_ONE_OVER_THREE);
        beta_sf = _IQ(MATH_ONE_OVER_SQRT_THREE);
    }
    else
    {
        alpha_sf = _IQ(0.0);
        beta_sf = _IQ(0.0);
    }

    // In other words, the only acceptable number of voltage sensors is three.
    // set the parameters
    CLARKE_setScaleFactors(handle,alpha_sf,beta_sf);
    CLARKE_setNumSensors(handle,numVoltageSensors);

    return;
} // end of setupClarke_V() function


//! \brief     Update the global variables (gMotorVars).
//! \param[in] handle  The estimator (EST) handle
void updateGlobalVariables(EST_Handle handle, const uint_least8_t mtrNum)
{
	uint32_t profile_mticks, profile_ticks;

    // get the speed estimate
    gMotorVars[mtrNum].Speed_krpm = _IQmpy(STPOSCONV_getVelocityFiltered(st_obj[mtrNum].posConvHandle), gSpeed_pu_to_krpm_sf[mtrNum]);

    // Get the DC buss voltage
    gMotorVars[mtrNum].VdcBus_kV = _IQmpy(gAdcData[mtrNum].dcBus,
            _IQ(gUserParams[mtrNum].iqFullScaleVoltage_V / 1000.0));

    // read Vd and Vq vectors per units
    gMotorVars[mtrNum].Vd = gVdq_out_pu[mtrNum].value[0];
    gMotorVars[mtrNum].Vq = gVdq_out_pu[mtrNum].value[1];

    // calculate vector Vs in per units: (Vs = sqrt(Vd^2 + Vq^2))
    gMotorVars[mtrNum].Vs = _IQsqrt(_IQmpy(gMotorVars[mtrNum].Vd,gMotorVars[mtrNum].Vd)
            + _IQmpy(gMotorVars[mtrNum].Vq,gMotorVars[mtrNum].Vq));

    // read Id and Iq vectors in amps
    gMotorVars[mtrNum].Id_A = _IQmpy(gIdq_pu[mtrNum].value[0],
            _IQ(gUserParams[mtrNum].iqFullScaleCurrent_A));
    gMotorVars[mtrNum].Iq_A = _IQmpy(gIdq_pu[mtrNum].value[1],
            _IQ(gUserParams[mtrNum].iqFullScaleCurrent_A));

    // calculate vector Is in amps:  (Is_A = sqrt(Id_A^2 + Iq_A^2))
    gMotorVars[mtrNum].Is_A = _IQsqrt(_IQmpy(gMotorVars[mtrNum].Id_A,gMotorVars[mtrNum].Id_A)
            + _IQmpy(gMotorVars[mtrNum].Iq_A,gMotorVars[mtrNum].Iq_A));

    // gets the Position Controller status
    gMotorVars[mtrNum].SpinTAC.PosCtlStatus = STPOSCTL_getStatus(st_obj[mtrNum].posCtlHandle);

    // get the inertia setting
    gMotorVars[mtrNum].SpinTAC.InertiaEstimate_Aperkrpm = _IQmpy(STPOSCTL_getInertia(st_obj[mtrNum].posCtlHandle), _IQ(((float_t)gUserParams[mtrNum].motor_numPolePairs / (0.001 * 60.0 * gUserParams[mtrNum].iqFullScaleFreq_Hz)) * gUserParams[mtrNum].iqFullScaleCurrent_A));

    // get the friction setting
    gMotorVars[mtrNum].SpinTAC.FrictionEstimate_Aperkrpm = _IQmpy(STPOSCTL_getFriction(st_obj[mtrNum].posCtlHandle), _IQ(((float_t)gUserParams[mtrNum].motor_numPolePairs / (0.001 * 60.0 * gUserParams[mtrNum].iqFullScaleFreq_Hz)) * gUserParams[mtrNum].iqFullScaleCurrent_A));

    // get the Position Controller error
    gMotorVars[mtrNum].SpinTAC.PosCtlErrorID = STPOSCTL_getErrorID(st_obj[mtrNum].posCtlHandle);

    // get the Position Move status
    gMotorVars[mtrNum].SpinTAC.PosMoveStatus = STPOSMOVE_getStatus(st_obj[mtrNum].posMoveHandle);

    // get the Position Move profile time
    STPOSMOVE_getProfileTime_tick(st_obj[mtrNum].posMoveHandle, &profile_mticks, &profile_ticks);
    gMotorVars[mtrNum].SpinTAC.PosMoveTime_mticks = profile_mticks;
    gMotorVars[mtrNum].SpinTAC.PosMoveTime_ticks = profile_ticks;

    // get the Position Move error
    gMotorVars[mtrNum].SpinTAC.PosMoveErrorID = STPOSMOVE_getErrorID(st_obj[mtrNum].posMoveHandle);

    // get the Position Converter error
    gMotorVars[mtrNum].SpinTAC.PosConvErrorID = STPOSCONV_getErrorID(st_obj[mtrNum].posConvHandle);

    return;
} // end of updateGlobalVariables() function

void ST_runPosConv(ST_Handle handle, ENC_Handle encHandle, SLIP_Handle slipHandle, MATH_vec2 *Idq_pu, MOTOR_Type_e motorType)
{
	ST_Obj *stObj = (ST_Obj *)handle;

	// get the electrical angle from the ENC module
    STPOSCONV_setElecAngle_erev(stObj->posConvHandle, ENC_getElecAngle(encHandle));

    if(motorType ==  MOTOR_Type_Induction) {
      // The CurrentVector feedback is only needed for ACIM
      // get the vector of the direct/quadrature current input vector values from CTRL
      STPOSCONV_setCurrentVector(stObj->posConvHandle, Idq_pu);
    }

	// run the SpinTAC Position Converter
	STPOSCONV_run(stObj->posConvHandle);

	if(motorType ==  MOTOR_Type_Induction) {
	  // The Slip Velocity is only needed for ACIM
	  // update the slip velocity in electrical angle per second, Q24
	  SLIP_setSlipVelocity(slipHandle, STPOSCONV_getSlipVelocity(stObj->posConvHandle));
	}
}

_iq ST_runPosCtl(ST_Handle handle)
{
	_iq iqReference;
	ST_Obj *stObj = (ST_Obj *)handle;

	// provide the updated references to the SpinTAC Position Control
	STPOSCTL_setPositionReference_mrev(stObj->posCtlHandle, STPOSMOVE_getPositionReference_mrev(stObj->posMoveHandle));
	STPOSCTL_setVelocityReference(stObj->posCtlHandle, STPOSMOVE_getVelocityReference(stObj->posMoveHandle));
	STPOSCTL_setAccelerationReference(stObj->posCtlHandle, STPOSMOVE_getAccelerationReference(stObj->posMoveHandle));
	// provide the feedback to the SpinTAC Position Control
	STPOSCTL_setPositionFeedback_mrev(stObj->posCtlHandle, STPOSCONV_getPosition_mrev(stObj->posConvHandle));

	// Run SpinTAC Position Control
	STPOSCTL_run(stObj->posCtlHandle);

	// Provide SpinTAC Position Control Torque Output to the FOC
	iqReference = STPOSCTL_getTorqueReference(stObj->posCtlHandle);

	return iqReference;
}
interrupt void QEP_Index_ISR(void) // Funci�n que se encarga de llevar a cero grados los rotores
{
    HAL_Obj_mtr *obj_mtr = (HAL_Obj_mtr *)halHandle;
    HAL_Obj *obj = (HAL_Obj *)halHandle;
//    QEP_Obj *qep = (QEP_Obj *)obj_mtr->qepHandle;

    // Limpiar el "interrupt flag"
    QEP_clear_interrupt_flag(obj_mtr->qepHandle, QEINT_Iel);

    // Acknowledge interrupt from PIE group 5
    PIE_clearInt(obj->pieHandle,PIE_GroupNumber_5);

    gIndexOcurre++;

    return;
}

interrupt void QEP_Index_ISR(void); 
short gIndexOcurre = 0; //counter of interruptions

void main(void)
{

 // setup the encoder module
    ENC_setup(encHandle[HAL_MTR1], 1, USER_MOTOR_NUM_POLE_PAIRS, USER_MOTOR_ENCODER_LINES, 0, USER_IQ_FULL_SCALE_FREQ_Hz, USER_ISR_FREQ_Hz, 8000.0);
    ENC_setup(encHandle[HAL_MTR2], 1, USER_MOTOR_NUM_POLE_PAIRS_2, USER_MOTOR_ENCODER_LINES_2, 0, USER_IQ_FULL_SCALE_FREQ_Hz_2, USER_ISR_FREQ_Hz_2, 8000.0);

///   M C >>>>>>>>>>>>>
    HAL_Obj_mtr *obj_mtr = (HAL_Obj_mtr *)halHandle;
    HAL_Obj *obj = (HAL_Obj *)halHandle;
    obj_mtr = (HAL_Obj_mtr *)halHandle;
//    QEP_Obj *qep = (QEP_Obj *)obj_mtr->qepHandle;

    QEP_clear_all_interrupt_flags(obj_mtr->qepHandle); // Limpiar todas las banderas de interrupción
    QEP_disable_all_interrupts(obj_mtr->qepHandle);    // Deshabilitar todas las interrupciones

    PIE_enableInt( obj->pieHandle, PIE_GroupNumber_5, PIE_InterruptSource_EQEP1 ); //Grupo 5 donde se encuentra la interrupcion de EQEP1
    QEP_enable_interrupt(obj_mtr->qepHandle, QEINT_Iel); //Habilitar el bit de interrupción correspondiente al pulso de Index
    CPU_enableInt(obj->cpuHandle,CPU_IntNumber_5);   //Habilitar el grupo 5 en las interrupciones de la CPU

    ///   M C >>>>>>>>>>>>>

//>>>> Configuracion de la interrupcion del index <<<<<<<<<<<<//

    PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;

    ENABLE_PROTECTED_REGISTER_WRITE_MODE;

    pie->EQEP1_INT = &QEP_Index_ISR;

    DISABLE_PROTECTED_REGISTER_WRITE_MODE;

    //>>>> Configuracion de la interrupcion del index <<<<<<<<<<<<//
    // enable the ADC interrupts
    HAL_enableAdcInts(halHandle);

    // enable global interrupts
    HAL_enableGlobalInts(halHandle);

    // enable debug interrupts
    HAL_enableDebugInt(halHandle);

    // disable the PWM
    HAL_disablePwm(halHandleMtr[HAL_MTR1]);
    HAL_disablePwm(halHandleMtr[HAL_MTR2]);
}

interrupt void QEP_Index_ISR(void) //Interruption function at the end of the file
{
    HAL_Obj_mtr *obj_mtr = (HAL_Obj_mtr *)halHandle;
    HAL_Obj *obj = (HAL_Obj *)halHandle;
//    QEP_Obj *qep = (QEP_Obj *)obj_mtr->qepHandle;

    // Limpiar el "interrupt flag"
    QEP_clear_interrupt_flag(obj_mtr->qepHandle, QEINT_Iel);

    // Acknowledge interrupt from PIE group 5
    PIE_clearInt(obj->pieHandle,PIE_GroupNumber_5);

    gIndexOcurre++;

    return;
}