• Resolved

CCS/DRV8803EVM: How to control the output of the DRV8803EVM using a PWM output from the EK-TM4C1294XL

Intellectual 330 points

Replies: 30

Views: 156

Part Number: DRV8803EVM

Tool/software: Code Composer Studio

Hello,

I am trying to write code on the EK-TM4C1294XL that will produce a PWM wave that controls the DRV8803 on the DRV8803EVM board.


What I want to do is use the EK-TM4C1294XL to turn on and off a solenoid using the DRV8803EVM board, according to the DRV8803 datasheets I need to have a PWM to trigger the motor drive function of the DRV8803. On the DRV8803EVM board, I don't want to use the microcontroller because I am applying external signals from the EK-TM4C1294XL. From my understanding of the DRV8803 timing diagram, I need to have a PWM that will stay high until the solenoid needs to be turned on and then the PWM will go low, am I correct in this thinking?


Based on my understanding I have written the code below. However, when I connect the EK-TM4C1294XL to the DRV8803EVM board (which I believe I have set up correctly according to the diagram) I don't get anything from the outputs of the board. I have pasted the code I am using below.

////*****************************************************************************
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
//////*****************************************************************************
//////
////// This function sets up UART0 to be used for a console to display information
////// as the example is running.
//////
void
GetADC(void)
{
#if defined(TARGET_IS_TM4C129_RA0) ||                                         \
    defined(TARGET_IS_TM4C129_RA1) ||                                         \
    defined(TARGET_IS_TM4C129_RA2)
    uint32_t ui32SysClock;
#endif

    uint32_t pui32ADC0Value[1];
#if defined(TARGET_IS_TM4C129_RA0) ||                                         \
    defined(TARGET_IS_TM4C129_RA1) ||                                         \
    defined(TARGET_IS_TM4C129_RA2)
    ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                       SYSCTL_OSC_MAIN |
                                       SYSCTL_USE_PLL |
                                       SYSCTL_CFG_VCO_480), 20000000);
#else
    SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);
#endif

UARTprintf("ADC ->\n");
 //  UARTprintf("  Type: Single Ended\n");
 //  UARTprintf("  Samples: One\n");
 //  UARTprintf("  Update Rate: 250ms\n");
   UARTprintf("  Input Pin: AIN0/PE3\n\n");

   //
   // The ADC0 peripheral must be enabled for use.
   //
   SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

   //
   // For this example ADC0 is used with AIN0 on port E7.
   // The actual port and pins used may be different on your part, consult
   // the data sheet for more information.  GPIO port E needs to be enabled
   // so these pins can be used.
   // TODO: change this to whichever GPIO port you are using.
   //
   SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

   //
   // Select the analog ADC function for these pins.
   // Consult the data sheet to see which functions are allocated per pin.
   // TODO: change this to select the port/pin you are using.
   //
   GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

   //
   // Enable sample sequence 3 with a processor signal trigger.  Sequence 3
   // will do a single sample when the processor sends a signal to start the
   // conversion.  Each ADC module has 4 programmable sequences, sequence 0
   // to sequence 3.  This example is arbitrarily using sequence 3.
   //
   ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

   //
   // Configure step 0 on sequence 3.  Sample channel 0 (ADC_CTL_CH0) in
   // single-ended mode (default) and configure the interrupt flag
   // (ADC_CTL_IE) to be set when the sample is done.  Tell the ADC logic
   // that this is the last conversion on sequence 3 (ADC_CTL_END).  Sequence
   // 3 has only one programmable step.  Sequence 1 and 2 have 4 steps, and
   // sequence 0 has 8 programmable steps.  Since we are only doing a single
   // conversion using sequence 3 we will only configure step 0.  For more
   // information on the ADC sequences and steps, reference the datasheet.
   //
   ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE |
                            ADC_CTL_END);

   //
   // Since sample sequence 3 is now configured, it must be enabled.
   //
   ADCSequenceEnable(ADC0_BASE, 3);

   //
   // Clear the interrupt status flag.  This is done to make sure the
   // interrupt flag is cleared before we sample.
   //
   ADCIntClear(ADC0_BASE, 3);

   //
   // Sample AIN0 forever.  Display the value on the console.
   //
   int y;
   y=0;
   while(y<5)
   {
       //
       // Trigger the ADC conversion.
       //
       ADCProcessorTrigger(ADC0_BASE, 3);

       //
       // Wait for conversion to be completed.
       //
       while(!ADCIntStatus(ADC0_BASE, 3, false))
       {
       }

       //
       // Clear the ADC interrupt flag.
       //
       ADCIntClear(ADC0_BASE, 3);

       //
       // Read ADC Value.
       //
       ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);

       //
       // Display the AIN0 (PE3) digital value on the console.
       //
       UARTprintf("AIN0 = %4d\r", pui32ADC0Value[0]);
       UARTprintf("\n");
       //
       // This function provides a means of generating a constant length
       // delay.  The function delay (in cycles) = 3 * parameter.  Delay
       // 250ms arbitrarily.
       //
#if defined(TARGET_IS_TM4C129_RA0) ||                                         \
   defined(TARGET_IS_TM4C129_RA1) ||                                         \
   defined(TARGET_IS_TM4C129_RA2)
       SysCtlDelay(ui32SysClock / 12);
#else
       SysCtlDelay(SysCtlClockGet() / 12);
#endif
       y++;
   }
}
//////*****************************************************************************
void
InitConsole(void)
{
////////    //
//////Enable GPIO port A which is used for UART0 pins.
////////    // TODO: change this to whichever GPIO port you are using.
////////    //
   SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
////////
////////    //
////////    // Configure the pin muxing for UART0 functions on port A0 and A1.
////////    // This step is not necessary if your part does not support pin muxing.
////////    // TODO: change this to select the port/pin you are using.
////////    //
   GPIOPinConfigure(GPIO_PA0_U0RX);
   GPIOPinConfigure(GPIO_PA1_U0TX);
////////
////////    //
////////    // Enable UART0 so that we can configure the clock.
////////    //
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
////////
////////    //
////////    // Use the internal 16MHz oscillator as the UART clock source.
////////    //
  UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
////////
////////    //
////////    // Select the alternate (UART) function for these pins.
////////    // TODO: change this to select the port/pin you are using.
////////    //
   GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
////////
////////    //
////////    // Initialize the UART for console I/O.
////////    //
   UARTStdioConfig(0, 115200, 16000000);
}


//////*****************************************************************************
#if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
    defined(TARGET_IS_TM4C129_RA2)
    uint32_t g_ui32SysClock;
#endif
//////////
////////    //
//////    // Set the clocking to run directly from the external crystal/oscillator.
//////    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
//////    // crystal on your board.
//////    //
  #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
      defined(TARGET_IS_TM4C129_RA1) ||                                         \
       defined(TARGET_IS_TM4C129_RA2)
       // g_ui32SysClock = SysCtlClockSet((SYSCTL_XTAL_25MHZ| SYSCTL_OSC_MAIN | SYSCTL_USE_OSC), 1200000);
#else
  SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);
#endif
////

    uint32_t sysclock;
////
    void main()
    {
        float PWM_FREQ;
        float CPU_FREQ;
        float pwm_word;
        int t;
        int i;
        InitConsole();
     //   GetADC();
////
        PWM_FREQ = 64000; //31.250kHz
        CPU_FREQ = 1000000;
        pwm_word = (1/PWM_FREQ)*CPU_FREQ;
    sysclock = SysCtlClockFreqSet((SYSCTL_XTAL_16MHZ |
                                                         SYSCTL_OSC_MAIN |
                                                         SYSCTL_USE_PLL |
                                                         SYSCTL_CFG_VCO_480), CPU_FREQ);
  //  GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED);
        i=0;
while(i<20)
{
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1);//Set the clock speed
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); //Enable the correct port
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);//Enable the GPIO port
        GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_1);//Define the pine
        GPIOPinConfigure(GPIO_PG1_M0PWM5); //Comfigure the pin based on the datasheet
        PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);//Set the modes
       // UARTprintf("Gen config successful\n");
        PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, 300);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_5,PWMGenPeriodGet(PWM0_BASE, PWM_GEN_2)/128);
        PWMOutputState(PWM0_BASE, PWM_OUT_5_BIT, true);
        PWMGenEnable(PWM0_BASE, PWM_GEN_2);
        UARTprintf("Running1\n");
      //  GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, RED_LED);
     //   SysCtlDelay(20000000);
        i++;
        GetADC();
}
    t=0;
while(t<20)
{
      SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
       GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_2);
              GPIOPinConfigure(GPIO_PG0_M0PWM4);
              PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_DB_NO_SYNC);
              UARTprintf("Gen config successful\n");
              PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, pwm_word);
              PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, PWMGenPeriodGet(PWM0_BASE, PWM_GEN_2)/128);

              PWMOutputState(PWM0_BASE, PWM_OUT_4_BIT, true);
             PWMGenEnable(PWM0_BASE, PWM_GEN_2);
             UARTprintf("Running2\n");
         //    SysCtlDelay(20000000);
              t++;
              GetADC();
}
////

   }

Any help with this would be much appreciated. 

Thank you

  • Hi Rachel,

    Thank you for posting to the motor drives forum.

    I have a couple questions:

    1. did you remove the 0ohm resistors (R15-R18)? those should be removed when connecting an external micro-controller.
    2. If the answer to (1) is yes, is the EK-TM4C1294XL properly outputting the PWM signal? 
    3. If answer to (2) is yes, Is nENBL and RESET logic low? is the power supply (VM) on?

    Regards,
    Pablo Armet
    Motor Applications Team

  • In reply to Pablo Armet:

    Hello Pablo, 

    Here are the answers to your questions:

    1. Yes I did remove the 0ohm resistors. 

    2. The EK-TM4C1294XL is outputting a PWM signal but I don't think its the correct PWM signal to trigger the DRV8803... or that is my assumption because there is no output. 

    3. I do have nENBL and RESET floating (which should be fine because they have a pull-down resistor. VM is also powered on.  

    Thank you, 

    Rachel 

  • In reply to Rachel Roberts:

    Rachel,

    Thank you for the information.

    In regards to answer (2), what PWM frequency and duty cycle are you using for IN1, IN2, IN3, and IN4? 

    Regards,
    Pablo Armet
    Motor Applications Team

  • In reply to Pablo Armet:

    Pablo, 

    The PWM frequency for IN1 and IN2 is set at the frequency of 31.25 kHz (as specified by the DRV8803 which I think is right?). For the duty cycle, I have the period defined, the pulse width set, and the output state-defined but I don't think I defined a duty cycle anywhere. 

    Thanks, 

    Rachel

  • In reply to Rachel Roberts:

    Rachel,

    What is the ON time and OFF time for both IN1 and IN2? If the ON time of the PWM signal is too short, the FETs in the H-bridge may not be fully turning on.

    Regards,
    Pablo Armet
    Motor Applications Team

  • In reply to Pablo Armet:

    Pablo, 

    Right now I have a delay after turning it on for about 200000 seconds. The code below is how I am generating my PWM wave. I am not quite sure how to accomplish the ON and OFF state that you are talking about. 

    while(i<20)
    {
            SysCtlPWMClockSet(SYSCTL_PWMDIV_1);//Set the clock speed
            SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); //Enable the correct port
            SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);//Enable the GPIO port
            GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_1);//Define the pine
            GPIOPinConfigure(GPIO_PG1_M0PWM5); //Comfigure the pin based on the datasheet
            PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);//Set the modes
           // UARTprintf("Gen config successful\n");
            PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, 300);
            PWMPulseWidthSet(PWM0_BASE, PWM_OUT_5,PWMGenPeriodGet(PWM0_BASE, PWM_GEN_2)/128);
            PWMOutputState(PWM0_BASE, PWM_OUT_5_BIT, true);
            PWMGenEnable(PWM0_BASE, PWM_GEN_2);
            UARTprintf("Running1\n");
          //  GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, RED_LED);
         //   SysCtlDelay(20000000);
            i++;
            GetADC();
    }
        t=0;
    while(t<20)
    {
          SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
          SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
          SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
           GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_2);
                  GPIOPinConfigure(GPIO_PG0_M0PWM4);
                  PWMGenConfigure(PWM0_BASE, PWM_GEN_2, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_DB_NO_SYNC);
                  UARTprintf("Gen config successful\n");
                  PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, pwm_word);
                  PWMPulseWidthSet(PWM0_BASE, PWM_OUT_4, PWMGenPeriodGet(PWM0_BASE, PWM_GEN_2)/128);
    
                  PWMOutputState(PWM0_BASE, PWM_OUT_4_BIT, true);
                 PWMGenEnable(PWM0_BASE, PWM_GEN_2);
                 UARTprintf("Running2\n");
             //    SysCtlDelay(20000000);
                  t++;

    Thank you, 

    Rachel 

  • In reply to Rachel Roberts:

    Hi Rachel,

    Can you probe an oscilloscope to IN1 and IN2 to see the signals on a scope. I think that will be the easiest way to verify the ON time of the signal.

    Regards,
    Pablo Armet
    Motor Applications Team

  • In reply to Pablo Armet:

    Pablo, 

    I will be able to take an oscilloscope reading tomorrow. I will reply with the answer here. 

    Thank you for your patience. 

    Rachel

  • In reply to Rachel Roberts:

    Hello Pablo, 

    I have attached the measurements from IN1 and IN2 from the oscilloscope

  • In reply to Rachel Roberts:

    Hi Rachel,

    IN1 and IN2 signals are not 31.25kHz as you wrote in your code and don't appear to be proper PWM cycles. Did you take the measurements with the external u-controller connected to the DRV8803EVM?

    Overall, the signals don't look correct. Either the PWM signals from the external micro-controller are not correct, or the signals become distorted when connecting to the EVM. Can you run another quick test? Try measuring the PWM  output of IN1 and IN2 directly from the external microcontroller output without connecting to the EVM?

    Also, if you have a signal generator, can you apply a 31kHz (50% duty cycle) waveform at IN2 and tie IN1 to GND (0V). Then measure the voltage at the driver outputs. I want to figure out if it is the EVM or the external controller causing the problem.

    Regards,
    Pablo Armet
    Motor Applications Team