Overview

In TMS320 PWM Tutorial, you are going to learn about what PWM is and how you can get the PWM output from the Analog pins of tms320. First, we will generate a PWM signal and then we will control it manually by adding the potentiometer.

What is PWM

This project involves a combination of PWM (Pulse Width Modulation) and ADC (Analog-Digital Converter) to drive a DC motor at different speeds.

PWM is a concept where a variable pulse voltage can be modulated from 0% to 100% duty cycle.
The duty cycle represents the time a pulse is high compared to the total duration of the pulse.

This image below represents a different percentage of the duty cycles of an XXms wave.

Control the speed of the motor using a Potentiometer.

Potentiometer connection and reading logic built

Now talking about the ADC, it’s a 12 bit analog to digital converter that converts all the analog values to 12-bit digital data i.e. (0-4096 for which it requires a reference voltage. The resolution or step-up voltage is 19.531mV. This means that for every 1.22070Mv rise in the analog input, ADC will increase the digital value by 1 starting from 0 and ending at 4096.

Now talking about the ADC, it’s a 12 bit analog to digital converter that converts all the analog values to 12-bit digital data i.e. (0-4096 for which it requires a reference voltage. The resolution or step-up voltage is 1.22070mV. This means that for every 1.22070Mv rise in the analog input, ADC will increase the digital value by 1 starting from 0 and ending at 4096.

The resolution depends upon the reference voltage as well as the type of ADC you’re using. Here the reference voltage is 5v, while I’m working on a 12 bit ADC therefore:

             Resolution = 5(Reference voltage)/4096(due to 12 bit i.e. 2^12=4096) = 1.22070mV

The output waveform of PWM signal

Step by step execution process

1st initialize the PWM GPIO Pins

/////  ////

void PinMux_init()
{
    EALLOW;
    //EPWM1 -> myEPWM1 Pinmux

    GpioCtrlRegs.GPAMUX1.all=0;// gpio 15 to gpio 0 a;; general purpouse I/O
    GpioCtrlRegs.GPAMUX1.bit.GPIO0=1;// epwm active
    EDIS;

}

2nd Configure the PWM Signal

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


void initEPWM1()
{

        EPwm1Regs.TBPRD = 4000;       // Set timer period 801 TBCLKs
        EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
        EPwm1Regs.TBCTR = 0x0000;
       // Set Compare values
        EPwm1Regs.CMPA.bit.CMPA = Adc_Result_1;    // Set compare A value
      // Setup counter mode
       EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
       EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
       EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
       EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

       EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;            // Set PWM1A on event A, up
      // count
       EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;          // Clear PWM1A on event A,
                                                    // down count

}

Here  EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;

EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;    // Clear PWM1A on event A, // down count                                  

Mean when your PWM pulses reach the setpoint(CMPA) then your pulse will be set to high and low

3rd configure the ADC resolution

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



void ConfigADC(uint32_t ADC_BASE)
{
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE=4;  // 200/4 50 MHz
//    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_4_0);

#if(EX_ADC_RESOLUTION == 12)
    {
        ADC_setMode(ADC_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
    }
#elif(EX_ADC_RESOLUTION == 16)
    {
      ADC_setMode(ADCA_BASE, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL);
    }
#endif
    ADC_setInterruptPulseMode(ADC_BASE, ADC_PULSE_END_OF_CONV);
    ADC_enableConverter(ADC_BASE);
    DEVICE_DELAY_US(1000);
    EDIS;
}

4th initialize the adc_soc

void initADC_SOC(void)
{
#if(EX_ADC_RESOLUTION == 12)
    {
        ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN0, 15);


    }
#elif(EX_ADC_RESOLUTION == 16)
    {
        ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN0,64);
    }
#endif
    ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);


    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);

    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);


}

// Convert, wait for completion, and store results

        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0);

   ////           // Store results

          Adc_Result_1= ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);

Final code

// how to control pwm pulses using adc


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "F2837xD_device.h"
#include "F28x_Project.h"
#include "F2837xD_Examples.h"

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

#define EX_ADC_RESOLUTION 12

void PinMux_init();
void initEPWM1();

void ConfigADC(uint32_t ADC_BASE);
void initADC_SOC(void);


uint16_t Adc_Result_1;
void main(void)
{
    Adc_Result_1=0;


    Device_init();
    Device_initGPIO();
    PinMux_init();
    Interrupt_initModule();
    Interrupt_initVectorTable();
    IER = 0x0000;
    IFR = 0x0000;

    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    ConfigADC(ADCA_BASE);
    initADC_SOC();
    EINT;
    ERTM;
    while(1)
    {


        // Convert, wait for completion, and store results
                   ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0);


                    while(ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1) == false)
                        {

                        }
                    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

                    ////           // Store results
                      Adc_Result_1= ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);

                       initEPWM1();
                       DEVICE_DELAY_US(10000);


    }



}


void PinMux_init()
{
    EALLOW;
    //EPWM1 -> myEPWM1 Pinmux

    GpioCtrlRegs.GPAMUX1.all=0;// gpio 15 to gpio 0 a;; general purpouse I/O
    GpioCtrlRegs.GPAMUX1.bit.GPIO0=1;// epwm active
    EDIS;

}



void initEPWM1()
{

        EPwm1Regs.TBPRD = 4000;       // Set timer period 801 TBCLKs
        EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;        // Phase is 0
        EPwm1Regs.TBCTR = 0x0000;
       // Set Compare values
        EPwm1Regs.CMPA.bit.CMPA = Adc_Result_1;    // Set compare A value
      // Setup counter mode
       EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
       EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
       EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
       EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

       EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;            // Set PWM1A on event A, up
      // count
       EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;          // Clear PWM1A on event A,
                                                    // down count

}




void ConfigADC(uint32_t ADC_BASE)
{
    EALLOW;
    AdcaRegs.ADCCTL2.bit.PRESCALE=4;  // 200/4 50 MHz
//    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_4_0);

#if(EX_ADC_RESOLUTION == 12)
    {
        ADC_setMode(ADC_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
    }
#elif(EX_ADC_RESOLUTION == 16)
    {
      ADC_setMode(ADCA_BASE, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL);
    }
#endif
    ADC_setInterruptPulseMode(ADC_BASE, ADC_PULSE_END_OF_CONV);
    ADC_enableConverter(ADC_BASE);
    DEVICE_DELAY_US(1000);
    EDIS;
}




void initADC_SOC(void)
{
#if(EX_ADC_RESOLUTION == 12)
    {
        ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN0, 15);


    }
#elif(EX_ADC_RESOLUTION == 16)
    {
        ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_SW_ONLY, ADC_CH_ADCIN0,64);
    }
#endif
    ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);


    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);

    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);


}


Output Waveforms

By Devilal

Leave a Reply

Your email address will not be published. Required fields are marked *