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/DRV8301-69M-KIT: Insufficient Current from DRV8301-69M Kit

Part Number: DRV8301-69M-KIT
Other Parts Discussed in Thread: MOTORWARE, DRV8301, DRV8305

Tool/software: Code Composer Studio

To whom it may concern,

I used the Motorware_Hal Tutorial to read the DRV8301-69M potentiometer and then wrote some of my own code to link the potentiometer reading to the IqRef_A variable. 


When I turn my system on, it is fine unloaded. However when I turn the potentiometer to 100% and put some load on the system it just stops instead of resisting. I would have expected the current to increase all the way up to 36A to resist the load. For a video of what I mean, please seen video below:

https://youtube/qlHlYSG68UI

Any help would be appreciated. I'm sure it's an issue with my PU scaling or something similar.


James

  • My User.h file

    The only lines of code I added in Lab4a.c were;

    _iq gPotentiometer = _IQ(0.0);

    gPotentiometer = HAL_readPotentiometerData(halHandle)

    and then in "

    void update IqRef(CTRL_Handle handle)

    {

    _iq iq_ref = _IQmpy(gPotentiometer,_IQ(1.0/USER_IQ_FULL_SCALE_CURRENT_A));     <------- I CHANGED THIS LINE TO USE gPotentiometer

    // set the speed reference so that the forced angle rotates in the correct direction for startup
      if(_IQabs(gMotorVars.Speed_krpm) < _IQ(0.01))
        {
          if(iq_ref < _IQ(0.0))
            {
              CTRL_setSpd_ref_krpm(handle,_IQ(-0.01));
            }
          else if(iq_ref > _IQ(0.0))
            {
              CTRL_setSpd_ref_krpm(handle,_IQ(0.01));
            }
        }

      // Set the Iq reference that use to come out of the PI speed control
      CTRL_setIq_ref_pu(handle, iq_ref);

      return;
    } // end of updateIqRef() function

    8322.user.h

  • Hi James,

    Your post is being moved to the C2000 forum for better support.

    While waiting for a reply from the experts, this post may help some: www.digikey.com/.../5325766
  • Hi Rick,

    Thanks for the forum change. I'm pretty committed to using the DRV8301-69M kit as I chose it due to the advantages Instaspin provides and those evaluation boards unfortunately aren't rated to the same power as the DRV8301-69M board. Once I get this sorted, I should have enough to finish my project so really trying to get it done.

    James
  • James,

    Sorry for the delayed response. Can you please tell me where in lab4a.c you call HAL_readPotentiometerData()?

    Sean
  • Hi Sean, no problems. Thank you for the response!

    Here is my Lab4a.c file, I'm really hoping i've made a mistake in the software and not damaged the hardware somehow.


    Cheers,

    James

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    //! \file   solutions/instaspin_foc/src/proj_lab04a.c
    //! \brief  Using InstaSPIN�FOC only as a torque controller FPU32
    //!
    //! (C) Copyright 2011, Texas Instruments, Inc.

    //! \defgroup PROJ_LAB04A PROJ_LAB04A
    //@{

    //! \defgroup PROJ_LAB04A_OVERVIEW Project Overview
    //!
    //! Running InstaSPIN�FOC only as a Torque controller FPU32
    //!

    // **************************************************************************
    // the includes

    // system includes
    #include <math.h>
    #include "main.h"

    #ifdef FLASH
    #pragma CODE_SECTION(mainISR,"ramfuncs");
    #endif

    // Include header files used in the main function


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

    #define LED_BLINK_FREQ_Hz   5


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

    uint_least16_t gCounter_updateGlobals = 0;

    bool Flag_Latch_softwareUpdate = true;

    CTRL_Handle ctrlHandle;

    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(halHandle,"rom_accessed_data");
    #endif

    HAL_Handle halHandle;

    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(gUserParams,"rom_accessed_data");
    #endif

    USER_Params gUserParams;

    HAL_PwmData_t gPwmData = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};

    HAL_AdcData_t gAdcData;

    _iq gMaxCurrentSlope = _IQ(0.0);

    #ifdef FAST_ROM_V1p6
    CTRL_Obj *controller_obj;
    #else
    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(ctrl,"rom_accessed_data");
    #endif
    CTRL_Obj ctrl;                //v1p7 format
    #endif

    uint16_t gLEDcnt = 0;

    volatile MOTOR_Vars_t gMotorVars = MOTOR_Vars_INIT;

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

    #ifdef CSM_ENABLE
    extern uint16_t *econst_start, *econst_end, *econst_ram_load;
    extern uint16_t *switch_start, *switch_end, *switch_ram_load;
    #endif
    #endif


    #ifdef DRV8301_SPI
    // Watch window interface to the 8301 SPI
    DRV_SPI_8301_Vars_t gDrvSpi8301Vars;
    #endif
    #ifdef DRV8305_SPI
    // Watch window interface to the 8305 SPI
    DRV_SPI_8305_Vars_t gDrvSpi8305Vars;
    #endif

    _iq gFlux_pu_to_Wb_sf;

    _iq gFlux_pu_to_VpHz_sf;

    _iq gTorque_Ls_Id_Iq_pu_to_Nm_sf;

    _iq gTorque_Flux_Iq_pu_to_Nm_sf;

    _iq gPotentiometer = _IQ(0.0); //value updating from HAL

    bool gSw1; //global variable for Switch 1, stored as a boolean variable as it is on or off

    bool gSw2; //global variable for Switch 2, stored as a boolean variable as it is on or off

    // **************************************************************************
    // the functions

    void main(void)
    {
      uint_least8_t estNumber = 0;

    #ifdef FAST_ROM_V1p6
      uint_least8_t ctrlNumber = 0;
    #endif

      // 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);

      #ifdef CSM_ENABLE
      //copy .econst to unsecure RAM
      if(*econst_end - *econst_start)
      {
         memCopy((uint16_t *)&econst_start,(uint16_t *)&econst_end,(uint16_t *)&econst_ram_load);
      }

      //copy .switch ot unsecure RAM
      if(*switch_end - *switch_start)
      {
        memCopy((uint16_t *)&switch_start,(uint16_t *)&switch_end,(uint16_t *)&switch_ram_load);
      }
      #endif
      #endif

      // initialize the hardware abstraction layer
      halHandle = HAL_init(&hal,sizeof(hal));


      // check for errors in user parameters
      USER_checkForErrors(&gUserParams);


      // store user parameter error in global variable
      gMotorVars.UserErrorCode = USER_getErrorCode(&gUserParams);


      // do not allow code execution if there is a user parameter error
      if(gMotorVars.UserErrorCode != USER_ErrorCode_NoError)
        {
          for(;;)
            {
              gMotorVars.Flag_enableSys = false;
            }
        }


      // initialize the user parameters
      USER_setParams(&gUserParams);


      // set the hardware abstraction layer parameters
      HAL_setParams(halHandle,&gUserParams);


      // initialize the controller
    #ifdef FAST_ROM_V1p6
      ctrlHandle = CTRL_initCtrl(ctrlNumber, estNumber);          //v1p6 format (06xF and 06xM devices)
      controller_obj = (CTRL_Obj *)ctrlHandle;
    #else
      ctrlHandle = CTRL_initCtrl(estNumber,&ctrl,sizeof(ctrl));    //v1p7 format default
    #endif


      {
        CTRL_Version version;

        // get the version number
        CTRL_getVersion(ctrlHandle,&version);

        gMotorVars.CtrlVersion = version;
      }


      // set the default controller parameters
      CTRL_setParams(ctrlHandle,&gUserParams);


      // setup faults
      HAL_setupFaults(halHandle);


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


      // enable the ADC interrupts
      HAL_enableAdcInts(halHandle);


      // enable global interrupts
      HAL_enableGlobalInts(halHandle);


      // enable debug interrupts
      HAL_enableDebugInt(halHandle);


      // disable the PWM
      HAL_disablePwm(halHandle);


    #ifdef DRV8301_SPI
      // turn on the DRV8301 if present
      HAL_enableDrv(halHandle);
      // initialize the DRV8301 interface
      HAL_setupDrvSpi(halHandle,&gDrvSpi8301Vars);
    #endif

    #ifdef DRV8305_SPI
      // turn on the DRV8305 if present
      HAL_enableDrv(halHandle);
      // initialize the DRV8305 interface
      HAL_setupDrvSpi(halHandle,&gDrvSpi8305Vars);
    #endif

      // enable DC bus compensation
      CTRL_setFlag_enableDcBusComp(ctrlHandle, true);


      // compute scaling factors for flux and torque calculations
      gFlux_pu_to_Wb_sf = USER_computeFlux_pu_to_Wb_sf();
      gFlux_pu_to_VpHz_sf = USER_computeFlux_pu_to_VpHz_sf();
      gTorque_Ls_Id_Iq_pu_to_Nm_sf = USER_computeTorque_Ls_Id_Iq_pu_to_Nm_sf();
      gTorque_Flux_Iq_pu_to_Nm_sf = USER_computeTorque_Flux_Iq_pu_to_Nm_sf();


      for(;;) //this is where the enable sys flag is set, needs to be set by gSW1 or gSW2
      {
        // Waiting for enable system flag to be set
        while(!(gMotorVars.Flag_enableSys));

        // Dis-able the Library internal PI.  Iq has no reference now
        CTRL_setFlag_enableSpeedCtrl(ctrlHandle, false);

        // loop while the enable system flag is true
        while(gMotorVars.Flag_enableSys)
          {
            CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle;

            // increment counters
            gCounter_updateGlobals++;

            // enable/disable the use of motor parameters being loaded from user.h
            CTRL_setFlag_enableUserMotorParams(ctrlHandle,gMotorVars.Flag_enableUserParams);

            // enable/disable Rs recalibration during motor startup
            EST_setFlag_enableRsRecalc(obj->estHandle,gMotorVars.Flag_enableRsRecalc);

            // enable/disable automatic calculation of bias values
            CTRL_setFlag_enableOffset(ctrlHandle,gMotorVars.Flag_enableOffsetcalc);


            if(CTRL_isError(ctrlHandle))
              {
                // set the enable controller flag to false
                CTRL_setFlag_enableCtrl(ctrlHandle,false);

                // set the enable system flag to false
                gMotorVars.Flag_enableSys = false;

                // disable the PWM
                HAL_disablePwm(halHandle);
              }
            else
              {
                // update the controller state
                bool flag_ctrlStateChanged = CTRL_updateState(ctrlHandle);

                // enable or disable the control
                CTRL_setFlag_enableCtrl(ctrlHandle, gMotorVars.Flag_Run_Identify); // this is where the SW1 or 2 will change Flag_Run_Identify

                if(flag_ctrlStateChanged)
                  {
                    CTRL_State_e ctrlState = CTRL_getState(ctrlHandle);

                    if(ctrlState == CTRL_State_OffLine)
                      {
                        // enable the PWM
                        HAL_enablePwm(halHandle);
                      }
                    else if(ctrlState == CTRL_State_OnLine)
                      {
                        if(gMotorVars.Flag_enableOffsetcalc == true)
                        {
                          // update the ADC bias values
                          HAL_updateAdcBias(halHandle);
                        }
                        else
                        {
                          // set the current bias
                          HAL_setBias(halHandle,HAL_SensorType_Current,0,_IQ(I_A_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Current,1,_IQ(I_B_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Current,2,_IQ(I_C_offset));

                          // set the voltage bias
                          HAL_setBias(halHandle,HAL_SensorType_Voltage,0,_IQ(V_A_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Voltage,1,_IQ(V_B_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Voltage,2,_IQ(V_C_offset));
                        }

                        // Return the bias value for currents
                        gMotorVars.I_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Current,0);
                        gMotorVars.I_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Current,1);
                        gMotorVars.I_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Current,2);

                        // Return the bias value for voltages
                        gMotorVars.V_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Voltage,0);
                        gMotorVars.V_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Voltage,1);
                        gMotorVars.V_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Voltage,2);

                        // enable the PWM
                        HAL_enablePwm(halHandle);
                      }
                    else if(ctrlState == CTRL_State_Idle)
                      {
                        // disable the PWM
                        HAL_disablePwm(halHandle);
                        gMotorVars.Flag_Run_Identify = false;
                      }

                    if((CTRL_getFlag_enableUserMotorParams(ctrlHandle) == true) &&
                      (ctrlState > CTRL_State_Idle) &&
                      (gMotorVars.CtrlVersion.minor == 6))
                      {
                        // call this function to fix 1p6
                        USER_softwareUpdate1p6(ctrlHandle);
                      }

                  }
              }


            if(EST_isMotorIdentified(obj->estHandle))
              {
                // set the current ramp
                EST_setMaxCurrentSlope_pu(obj->estHandle,gMaxCurrentSlope);
                gMotorVars.Flag_MotorIdentified = true;


                if(Flag_Latch_softwareUpdate)
                {
                  Flag_Latch_softwareUpdate = false;

                  USER_calcPIgains(ctrlHandle);
                }

              }
            else
              {
                Flag_Latch_softwareUpdate = true;

                // the estimator sets the maximum current slope during identification
                gMaxCurrentSlope = EST_getMaxCurrentSlope_pu(obj->estHandle);
              }


            // when appropriate, update the global variables
            if(gCounter_updateGlobals >= NUM_MAIN_TICKS_FOR_GLOBAL_VARIABLE_UPDATE)
              {
                // reset the counter
                gCounter_updateGlobals = 0;

                updateGlobalVariables_motor(ctrlHandle);
              }

            // update Iq reference
            updateIqRef(ctrlHandle);

            // enable/disable the forced angle
            EST_setFlag_enableForceAngle(obj->estHandle,gMotorVars.Flag_enableForceAngle);

            // enable or disable power warp
            CTRL_setFlag_enablePowerWarp(ctrlHandle,gMotorVars.Flag_enablePowerWarp);

    #ifdef DRV8301_SPI
            HAL_writeDrvData(halHandle,&gDrvSpi8301Vars);

            HAL_readDrvData(halHandle,&gDrvSpi8301Vars);
    #endif
    #ifdef DRV8305_SPI
            HAL_writeDrvData(halHandle,&gDrvSpi8305Vars);

            HAL_readDrvData(halHandle,&gDrvSpi8305Vars);
    #endif

          } // end of while(gFlag_enableSys) loop


        // disable the PWM
        HAL_disablePwm(halHandle);

        // set the default controller parameters (Reset the control to re-identify the motor)
        CTRL_setParams(ctrlHandle,&gUserParams);
        gMotorVars.Flag_Run_Identify = false;

      } // end of for(;;) loop

    } // end of main() function


    interrupt void mainISR(void)
    {
      // toggle status LED
      if(gLEDcnt++ > (uint_least32_t)(USER_ISR_FREQ_Hz / LED_BLINK_FREQ_Hz))
      {
        HAL_toggleLed(halHandle,(GPIO_Number_e)HAL_Gpio_LED2);
        gLEDcnt = 0;
      }


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


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


      // run the controller
      CTRL_run(ctrlHandle,halHandle,&gAdcData,&gPwmData);


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


      // setup the controller
      CTRL_setup(ctrlHandle);
      //update Potentiometer reading
      gPotentiometer = HAL_readPotentiometerData(halHandle);

      //update Switch values
      gSw1 = HAL_readGpio(halHandle, HAL_GPIO_SW1); //switch 1 value

      gSw2 = HAL_readGpio(halHandle, HAL_GPIO_SW2); //switch 2 value

      return;
    } // end of mainISR() function


    void updateGlobalVariables_motor(CTRL_Handle handle)
    {
      CTRL_Obj *obj = (CTRL_Obj *)handle;
      int32_t tmp;

      // get the speed estimate
      gMotorVars.Speed_krpm = EST_getSpeed_krpm(obj->estHandle);

      // get the torque estimate
      gMotorVars.Torque_Nm = USER_computeTorque_Nm(handle, gTorque_Flux_Iq_pu_to_Nm_sf, gTorque_Ls_Id_Iq_pu_to_Nm_sf);

      // when calling EST_ functions that return a float, and fpu32 is enabled, an integer is needed as a return
      // so that the compiler reads the returned value from the accumulator instead of fpu32 registers
      // get the magnetizing current
      tmp = EST_getIdRated(obj->estHandle);
      gMotorVars.MagnCurr_A = *((float_t *)&tmp);

      // get the rotor resistance
      tmp = EST_getRr_Ohm(obj->estHandle);
      gMotorVars.Rr_Ohm = *((float_t *)&tmp);

      // get the stator resistance
      tmp = EST_getRs_Ohm(obj->estHandle);
      gMotorVars.Rs_Ohm = *((float_t *)&tmp);

      // get the stator inductance in the direct coordinate direction
      tmp = EST_getLs_d_H(obj->estHandle);
      gMotorVars.Lsd_H = *((float_t *)&tmp);

      // get the stator inductance in the quadrature coordinate direction
      tmp = EST_getLs_q_H(obj->estHandle);
      gMotorVars.Lsq_H = *((float_t *)&tmp);

      // get the flux in V/Hz in floating point
      tmp = EST_getFlux_VpHz(obj->estHandle);
      gMotorVars.Flux_VpHz = *((float_t *)&tmp);

      // get the flux in Wb in fixed point
      gMotorVars.Flux_Wb = USER_computeFlux(handle, gFlux_pu_to_Wb_sf);

      // get the controller state
      gMotorVars.CtrlState = CTRL_getState(handle);

      // get the estimator state
      gMotorVars.EstState = EST_getState(obj->estHandle);

      // Get the DC bus voltage
      gMotorVars.VdcBus_kV = _IQmpy(gAdcData.dcBus,_IQ(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0));

      return;
    } // end of updateGlobalVariables_motor() function


    void updateIqRef(CTRL_Handle handle)
    {
      _iq iq_ref = _IQmpy(gPotentiometer,_IQ(1.0/USER_IQ_FULL_SCALE_CURRENT_A)); //changed from gMotorVars.IqRef_A, WORKED!!!

      // set the speed reference so that the forced angle rotates in the correct direction for startup
      if(_IQabs(gMotorVars.Speed_krpm) < _IQ(0.01))
        {
          if(iq_ref < _IQ(0.0))
            {
              CTRL_setSpd_ref_krpm(handle,_IQ(-0.01));
            }
          else if(iq_ref > _IQ(0.0))
            {
              CTRL_setSpd_ref_krpm(handle,_IQ(0.01));
            }
        }

      // Set the Iq reference that use to come out of the PI speed control
      CTRL_setIq_ref_pu(handle, iq_ref);

      return;
    } // end of updateIqRef() function


    //@} //defgroup
    // end of file

  • Hi ,

    Was my implementation correct in the Lab4a.c file above or have I made some mistake?

    Regards,

    James
  • James,

    Can you please try moving HAL_readPotentiometerData() call out of the ISR and instead calling it right before updateIqRef(). I don't see anything glaringly wrong with your implementation, perhaps it's a timing issue as the ISR can update the value in the middle of the Iq reference update function

    Sean
  • Thanks Sean,

    I've moved it out and surprisingly it spun in reverse. No change with the original issue, it does only pull 3.6 - 4 amps (10% of rated current) so that's interesting.
  • Can you confirm that your EVM isn't damaged?
  • Hi Sean, I can confirm that I have now solved the problem.
    Having gone through the Hal_tutorial meticulously and ending up with the above code and issue, I then found this forum post last night and changed my code which worked. e2e.ti.com/.../1800127

    I changed my code to this;

    void updateIqRef(CTRL_Handle handle)
    {
    _iq iq_ref = _IQmpy(gMotorVars.IqRef_A,_IQ(-30/USER_IQ_FULL_SCALE_CURRENT_A)); //changed from gMotorVars.IqRef_A, WORKED!!! using positive value makes motor run in reverse. changing value to -30 instead of -1 fixed big issue!

    I didn't have to change it to millions as per the other forum post but simply to -30 for it to work up to ~11A so far. The board is fine, not getting hot and the motor is running very well.
    Thanks for all your responses and assistance!
  • Great James. For my reference, did you end up assigning gPotentiometer to IqRef_A at some point in the main for loop? Or in the ISR?

    Sean
  • Sean, I took it out of the ISR and added it to the main for loop. Interesting to note that when I did this, the direction of motor rotation changed. This is why the value is -(x), in my case -30, in the equation and not a positive value.
  • Hi James,

    Had any update on your side? Could you please a description on adc setup and read about the meter? And what's the equation for setting Iq reference?