Table of Contents
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);
}
I’ve tried to implement above project but I’ve following errors:
Building file: “../ABC.c”
Invoking: C2000 Compiler
“C:/ti/ccs1271/ccs/tools/compiler/ti-cgt-c2000_22.6.1.LTS/bin/cl2000″ -v28 -ml -mt –cla_support=cla1 –float_support=fpu32 –tmu_support=tmu0 –vcu_support=vcu2 –include_path=”C:/ti/ccs1271/ccs/tools/compiler/ti-cgt-c2000_22.6.1.LTS/include” –include_path=”driver_inclusive_terminology_mapping.h” –include_path=”C:/ti/DC_Motor_Speed_Control_Potentiometer_using_TMS320/device/driverlib” –include_path=”C:/ti/c2000/C2000Ware_5_02_00_00/device_support/f2837xd/common/include” –include_path=”C:/ti/c2000/C2000Ware_5_02_00_00/device_support/f2837xd/common/include” –include_path=”C:/ti/c2000/C2000Ware_5_02_00_00/device_support/f2837xd/headers/include” –advice:performance=all –define=CPU1 –define=_FLASH -g –diag_warning=225 –diag_wrap=off –display_error_number –abi=coffabi –preproc_with_compile –preproc_dependency=”ABC.d_raw” “../ABC.c”
>> Compilation failure
subdir_rules.mk:9: recipe for target ‘ABC.obj’ failed
“C:/ti/c2000/C2000Ware_5_02_00_00/device_support/f2837xd/common/include/driverlib.h”, line 45: fatal error #1965: cannot open source file “inc/hw_memmap.h”
1 catastrophic error detected in the compilation of “../ABC.c”.
Compilation terminated.
gmake: *** [ABC.obj] Error 1
gmake: Target ‘all’ not remade because of errors.
**** Build Finished ****
Can you guide to solve this