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.

TMS320F280049C: Code to spin a BLDC motor using C2000 & DRV816x

Part Number: TMS320F280049C
Other Parts Discussed in Thread: LAUNCHXL-F280049C, DRV8161EVM, DRV8161, C2000WARE

Tool/software:

Hello,

I am using the LAUNCHXL-F280049C with the 100 pin F280049CPZS. I am trying to get a BLDC motor to spin using the launchpad and 3x DRV816x motor drivers. I have built a PCB that is similar to the DRV816x EVM and have jumped the following signals from the launchpad to the motor driver board. The motor driver board takes PVDD (24V 1A), GVDD (12V 1A), 5Vin (5V 1A), as well as 3.3V from the launchpad.

MCU Pin Number MCU Signal (GPIO / ADC / Power)
Motor Driver Signal
1 3.3V
3.3V (Logic Power)
2 PGA1/3/5_GND CSAREF_C
4 GPIO40 HALL_C
6 ADCINB3/VDAC CSAREF_B
8 ADCIN4 CSAREF_C
11 GPIO59 nFAULT_C
12 GPIO23 nFAULT_B
13 GPIO39 nFAULT_A
22 GND GND
23 ADCINA5 VSEN_A
24 ADCINB0 VSEN_B
25 ADCINC2 VSEN_C
26 ADCINB1 SEN_PVDD
27 ADCINB2 ISEN_C
28 ADCINC0 ISEN_B
29 ADCINA9 ISEN_A
30 ADCINA1 CSAREF_A
33 GPIO30 HALL_B
34 GPIO58 HALL_A
35 GPIO5 INL_C (PWM3B)
36 GPIO4
INH_C (PWM3A)
37 GPIO9 INL_B (PWM5B)
38 GPIO8
INH_B (PWM5A)
39 GPIO11 INL_A (PWM6B)
40 GPIO10
INH_A (PWM6A)


Using the launchpad and motor driver board I have been able to get this motor to spin using the DRV8161EVM GUI (https://dev.ti.com/gallery/view/InternalBLDC/DRV8161-EVM-GUI/ver/0.1.4/). However, now I am trying to build a program within CCS to flash onto the C2000 that will give me motor motion without the use of the GUI. Simply, I just want to spin the motor after compiling on CCS. Is there some code available or could I get some assistance in writing a simple program on CCS to perform this task. I have already looked at the DRV8161_Sensored_Trapizoidal_GUI.c and  DRV8161_Sensored_Trapizoidal_6x_PWM.c for help. These programs are complex and I have had no progress trying to replicate them.

This is what my setup looks like. Launchpad (red), PCB board with 3x motor driver (green), Teknic motor (https://teknic.com/hudson-model/M-2311P-QN-08D/)


This is some code I have written for the launchpad that was flashed on CCS:

#include "driverlib.h"
#include "device.h"

//
// Constants
//
#define SYSCLK 100000000UL // 100 MHz system clock
#define PWM_FREQ 20000UL // 20 kHz PWM frequency
#define TBPRD (SYSCLK / (PWM_FREQ * 2)) // Timer period for up-down counter

//
// Pin definitions
//
#define PWM6A_GPIO 10 // GPIO10 (Pin 40)
#define PWM6B_GPIO 11 // GPIO11 (Pin 39)
#define PWM5A_GPIO 8 // GPIO8 (Pin 38)
#define PWM5B_GPIO 9 // GPIO9 (Pin 37)
#define PWM3A_GPIO 4 // GPIO4 (Pin 36)
#define PWM3B_GPIO 5 // GPIO5 (Pin 35)

//
// Function Prototypes
//
void initEPWMModules(void);
void initGPIOPins(void);
void setDutyCycle(uint16_t epwmBase, uint16_t dutyPercent);

void main(void)
{
//
// Initialize the device and GPIO
//
Device_init();
Device_initGPIO();

//
// Initialize GPIO pins for PWM
//
initGPIOPins();

//
// Initialize ePWM modules
//
initEPWMModules();

//
// Main loop: adjust duty cycle to 3% for all phases
//
while (1)
{
setDutyCycle(EPWM6_BASE, 3); // Phase A
setDutyCycle(EPWM5_BASE, 3); // Phase B
setDutyCycle(EPWM3_BASE, 3); // Phase C

DEVICE_DELAY_US(1000000); // 1 second delay
}
}

//
// Configure GPIO pins for PWM outputs
//
void initGPIOPins(void)
{
EALLOW;

// Configure GPIO for PWM outputs
GPIO_setPinConfig(GPIO_10_EPWM6A); // PWM6A
GPIO_setPinConfig(GPIO_11_EPWM6B); // PWM6B
GPIO_setPinConfig(GPIO_8_EPWM5A); // PWM5A
GPIO_setPinConfig(GPIO_9_EPWM5B); // PWM5B
GPIO_setPinConfig(GPIO_4_EPWM3A); // PWM3A
GPIO_setPinConfig(GPIO_5_EPWM3B); // PWM3B

EDIS;
}

//
// Initialize ePWM modules for complementary outputs
//
void initEPWMModules(void)
{
//
// Configure ePWM6 (Phase A)
//
EPWM_setTimeBasePeriod(EPWM6_BASE, TBPRD);
EPWM_setTimeBaseCounterMode(EPWM6_BASE, EPWM_COUNTER_MODE_UP_DOWN);
EPWM_setClockPrescaler(EPWM6_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

EPWM_setActionQualifierAction(EPWM6_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM6_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(EPWM6_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM6_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

//
// Configure ePWM5 (Phase B)
//
EPWM_setTimeBasePeriod(EPWM5_BASE, TBPRD);
EPWM_setTimeBaseCounterMode(EPWM5_BASE, EPWM_COUNTER_MODE_UP_DOWN);
EPWM_setClockPrescaler(EPWM5_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

//
// Configure ePWM3 (Phase C)
//
EPWM_setTimeBasePeriod(EPWM3_BASE, TBPRD);
EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP_DOWN);
EPWM_setClockPrescaler(EPWM3_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
}

//
// Set the duty cycle for the ePWM module
//
void setDutyCycle(uint16_t epwmBase, uint16_t dutyPercent)
{
uint16_t compareValue = (TBPRD * dutyPercent) / 100;
EPWM_setCounterCompareValue(epwmBase, EPWM_COUNTER_COMPARE_A, compareValue);
EPWM_setCounterCompareValue(epwmBase, EPWM_COUNTER_COMPARE_B, compareValue);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


When this code is ran on CCS, these are the resulting waveforms for PWM6A, PWM6B as well as the power pulled from the different supplies.


If I let this ccs code run longer, the mosfets begin to heat up but when GUI code is ran, the 24V supplies pulls around 0.3A.

EPWM6A waveform


EPWM6B waveform



For reference, this is how the waveforms look when using the DRV816 EVM, the waveform also toggles on and off.

PWM6A


PWM6B



Thank you.

  • Hi Adrian,

    Simply, I just want to spin the motor after compiling on CCS. Is there some code available or could I get some assistance in writing a simple program on CCS to perform this task

    Perhaps you could download via (CCS REX) Universal Motor Control software example, has GPIO switch function to start/stop motor without GUI, Follow the user guide for MCU conversion for x49c UMCSDK documents folder. Can you post a schematic of MOSFET phase drivers on green board? Note for non-stepper drive motor, PCB only require two NFET for direction spin control via Hall sensors.

    Regards

  • MotorDriverPCB.zip

    I've attached the zip of the altium design for the Green PCB (schematic and layout) it is heavily modeled after the DRV816EVM that TI provides.



  • I will also add screenshots if unable to download.

    Entire layout:


    PhaseA:

    Phase B:


    Phase C:


    Close Ups:





    From the launchpad, the signals in the table above are being wired to J8,J9,J10. This configuration works and is able to spin the motor using the TI GUI. However when using CCS to flash code, nothing works.

  •  You might follow the MotorControl SDK InstaSPIN Lab Guide to run the example labs within CCS, the guide can be found in 

    Guide: \ti\c2000\C2000Ware_MotorControl_SDK_<version>\solutions\common\sensorless_foc\docs\labs

    Example Labs: ti\c2000\C2000Ware_MotorControl_SDK_<version>\solutions\boostxl_drv8320rs\f28004x

    And you should make a few changes on the device and hardware configuration in hal.c, hal.h and user.h as below according to the board you used

    1. Change the PWM and ADC configuration in hal.c according to your own hardware board.

     

    1. Set correct parameters based on the hardware board in user.h

    #define USER_IQ_FULL_SCALE_VOLTAGE_V            (xx)

    #define USER_VOLTAGE_FILTER_POLE_Hz                (xx)

    #define USER_ADC_FULL_SCALE_VOLTAGE_V        (xx)

    #define USER_IQ_FULL_SCALE_CURRENT_A            (xx)

    #define USER_ADC_FULL_SCALE_CURRENT_A        (xx)

     

    1. make sure that the sign of the current coefficient in HAL_readADCDataWithOffsets() in hal.h matches the current sensing circuit. Refer to chapter 5.2.2 Current Feedback Polarity in InstaSPIN user's guide (https://www.ti.com/lit/spruhj1)  to set the sign of the current scale factor.

     

    HAL_readADCDataWithOffsets(HAL_Handle handle, HAL_ADCData_t *pADCData)

    {

        HAL_Obj *obj = (HAL_Obj *)handle;

     

        float32_t value;

     

        float32_t current_sf = -HAL_getCurrentScaleFactor(handle);

        float32_t voltage_sf = HAL_getVoltageScaleFactor(handle);

    ….

    }

     

    1. Set up the right v/f curve or reference current and speed based on the specification of the motor for running lab03 or lab04 to verify the board.
  • I will also add screenshots if unable to download.

    Adrian, 

    It seemed from your post the green board was your own custom design, not copy of TI motor driver DRV8161EVM. Why not add x49c MCU to the larger green board get rid of jumper wires or check TI store for MCU like x25c, x39c? 

    Consider twisting few jumper wires with a ground wire, same idea for critical feedback signals, e.g. Halls. The PVDD two extra MOSFETS add design cost that seemingly could be avoided. Being MCSDK does not leverage multilevel PWM phase drive signals. Extra cost two PVDD switches per-phase seems odd for speed/torque control LAB's, not seeing the schematic it is anyone guess why they even exist.

    TI past has never had a motor driver detached from LaunchXL PCB for sale TI store, was only design files provided. Yet the price $229.00 USD seems a bit high over Booster Pack boards of the similar category. Parallel NFETS seems odd for such low voltage/current phase drives. Perhaps consider single NFET can ease PCB space restrictions.

    Surprised TI NEXFETS were not used on green PCB design. DRV8320RS Booster 48A peak, 60V Max and LaunchXL-49c, firmware: MCSDK v5.02 and LaunchXL-25c with DRV8323RS, firmware: Universal MCSDK with BLDC drive option for Halls and GPIO command switch firmware option. The LaunchXL-49c and your green PCB via UMCSDK firmware (seemingly) supports SPI control registers DRV8161xx. Don't have to do custom coding for GPIO run switch, just add necessary symbol/s to project properties prior to compile. Check the web page DRV kits firmware LaunchXL compatibility chart for each SDK mentioned above to be sure.