Está en la página 1de 6

Usando el timer0 para el control PID

#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
#include "lab7.h"
#include "monitorF28335.h"

#define EPWM1_TIMER_TBPRD 20000 // Period register


#define EPWM1_MAX_CMPA 1950
#define EPWM1_MIN_CMPA 50
#define EPWM1_MAX_CMPB 5000
#define EPWM1_MIN_CMPB 50

#define EPWM_CMP_UP 1
#define EPWM_CMP_DOWN 0
unsigned int i;
float u,v,ep,epa,kpp,kip,kdp,pr,kip,dt,ip,ipa,p,pa,w,ew;

void main(void)
{
DINT; //deshabilita interrupciones
DRTM; //deshabilita interrupciones real time mode
InitSysCtrl(); //inicializa el sistema como PLL,clocks,watcgdog
InitEPwm1Gpio();
InitSciaGpio(); // inicializa los pines scia para ser usados con su función sci
InitPieCtrl(); //inicializa el apoyo de interrupción de periféricos
IER = 0x0000; //limpia máscara de interrupciones
IFR = 0x0000; //limpia bandera de interrupciones
InitPieVectTable(); //inicializa tabla de interrupciones por defecto
// ISR para los timers de CPU
EALLOW; // Habilita cambio de registros

PieVectTable.TINT0 = &cpu_timer0_isr; //apuntar a subrutina interrupt de timer0


PieVectTable.XINT13 = &cpu_timer1_isr;//apuntar a subrutina interrupt de timer1
PieVectTable.TINT2 = &cpu_timer2_isr;//apuntar a subrutina interrupt de timer2
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;// Deshabilita cambio de registros
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0;
GpioDataRegs.GPASET.bit.GPIO2 = 1;
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;

GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1; // EQEP1A = GPIO20 (I) - Canal


A Encoder
GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1; // EQEP1B = GPIO21 (I) - Canal
B Encoder
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1; // EQEP1S = GPIO22 (I/O) - Fin
de Carrera
GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1; // EQEP1I = GPIO23 (I/O) -
Index Encoder
EDIS;

EQep1Regs.QDECCTL.bit.QSRC = 0;
EQep1Regs.QDECCTL.bit.SOEN = 0;
EQep1Regs.QDECCTL.bit.SPSEL = 0;
EQep1Regs.QDECCTL.bit.XCR = 0;
EQep1Regs.QDECCTL.bit.IGATE = 0;
EQep1Regs.QDECCTL.bit.QAP = 0;
EQep1Regs.QDECCTL.bit.QBP = 0;
EQep1Regs.QDECCTL.bit.QIP = 0;
EQep1Regs.QDECCTL.bit.QSP = 0;

EQep1Regs.QEPCTL.bit.PCRM=0;
EQep1Regs.QEPCTL.bit.SEI=2; // Inicializa el
contador de posición cuando hay un
EQep1Regs.QEPCTL.bit.IEI=0; // flanco de
subida en el STROBE (para el efecto rebote)
EQep1Regs.QEPCTL.bit.SWI=0;
EQep1Regs.QEPCTL.bit.SEL=0;
EQep1Regs.QEPCTL.bit.IEL=0;
EQep1Regs.QEPCTL.bit.QPEN=1;
EQep1Regs.QEPCTL.bit.QCLM=0;
EQep1Regs.QEPCTL.bit.UTE=1;
EQep1Regs.QEPCTL.bit.WDE=0;

EQep1Regs.QPOSMAX=0xffffffff; //0xffffffff
EQep1Regs.QUPRD=0xffffffff; //0xffffffff
EQep1Regs.QPOSINIT=0;
IniciaEPwm1();
InitCpuTimers(); // inicializa los Cpu Timers
ConfigCpuTimer(&CpuTimer0, 150, 5000); // a 150MHz 5000useg=5ms
ConfigCpuTimer(&CpuTimer1, 150, 5000); // a 150MHz 4500000uSeg = 4.5segundos
ConfigCpuTimer(&CpuTimer2, 150, 100000); // a 150MHz 100000uSeg = 0.1segundos
CpuTimer0Regs.TCR.all = 0x4001; // Arrancar timer T0 TSS bit = 0
CpuTimer1Regs.TCR.all = 0x4001; // Arrancar timer T0 TSS bit = 0
CpuTimer2Regs.TCR.all = 0x4001; // Arrancar timer T0 TSS bit = 0
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
//IER |= M_INT3; // Interrupción 3
//PieCtrlRegs.PIEIER3.bit.INTx1 = 1;

IER = M_INT1| M_INT13; // Interrupciones 1 y 13


IER |= M_INT14; // Aumentar interrupción 14
PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // la interrupción TINT0 pasa por el PIE
XIntruptRegs.XNMICR.bit.SELECT= 0; // asegura que TINT1 está conectado a INT13 y no
XNMI
EINT; //habilita interrupciones
ERTM;
IniciarSerial(); //Inicialización de los parámetros del puerto serial A
i=0;
u=6;
dt=0.005;
kp=
ki=
ep=0;
epa=0;
kpp=0.00000000000001;
kip=0;
kdp=0;
pr=500;
ip=0;
ipa=0;
kip=0.000000000000000000000001;
dt=0.001;
GpioDataRegs.GPADAT.bit.GPIO2 = 0;
p=0;
pa=0;
w=0;
ew=0;
do{ //hacer loop por lo menos una vez
IteraSerial();
}while(1); //Itera infinitamente
}

void IniciaEPwm1()
{
//configurado para 1mseg en el PWMA
//queremos que el PWM cuando este en 0, este alto
// Configurar TBCLK
EPwm1Regs.TBPRD = 25000; // Determina el periodo 801 TBCLKs
EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // La fase es 0
EPwm1Regs.TBCTR = 0x0000; // Contador a cero

// Configurar valores de los Comparadores


EPwm1Regs.CMPA.half.CMPA = 0; // Dar valor al comparador A
EPwm1Regs.CMPB = 0; // Dar valor al comparador B

// Configurar modo de conteo


EPwm1Regs.TBCTL.bit.CTRMODE = 00; // Contar hacia arriba y al llegar al periodo igual a cero
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Deshabilitar carga de fase
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 6; // Tasa del prescalador del SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = 1;

// Configurar shadowing modo de sombra


EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // cargar en cero
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

// Configurar acciones
EPwm1Regs.AQCTLA.bit.ZRO = 2; // PWMA en zero inicializa alto
EPwm1Regs.AQCTLA.bit.CAU = 1; // PWMA en el comparador, baja a zero

// Interrupción cuando se cambiaran los valores de comparación


//EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Seleccionar INT en evento Zero
//EPwm1Regs.ETSEL.bit.INTEN = 1; // Habilitar INT
//EPwm1Regs.ETPS.bit.INTPRD = ET_3RD; // Generar INT en el 3er evento

interrupt void cpu_timer0_isr(void)


//aca hacemos el controlador
{
CpuTimer0.InterruptCount++;
//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1; //alterna estado del led
T=((AdcRegs.ADCRESULT0 >>4)/4096)*180+20
Et=Tref-T; //error de t es de referencia menos valor de T
Cp=Kp*et //controlador proporcional
Ci=cia+ki*et*dt; //controlador integral
Cd=kd*(et-eta)/dt; //Control derivatido et=error temperatura eta= error temp anterior
Sc=cp+ci+cd;
EPwm1Regs.CMPA.half.CMPA=sc/3*25000;
Cia=ci;
Eta=et;

PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //Reconocer interrupt grupo1


}
//copiamos el inicializador de ADC del lab6
void iniciarRegADC(void)
{

AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS; // ADC module clock = 25MHz


AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK; // Modo Secuencial: Ancho del S/H =
(2+ACQ_PS)*ADC clock en ns
// En modo simultáneo sería: = (3+ACQ_PS)*ADC
clock en ns
AdcRegs.ADCTRL3.bit.SMODE_SEL = ADC_MODO; // Secuencial
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 1 Cascaded mode
AdcRegs.ADCTRL1.bit.CONT_RUN = 0; // No al modo contínuo
AdcRegs.ADCTRL1.bit.SEQ_OVRD = 0; // Deshabilitar Override, sin wrap around
ADCRESULT
AdcRegs.ADCCHSELSEQ1.all = 0x3210; // Selecionar canales 0-1-2-3
AdcRegs.ADCCHSELSEQ2.all = 0x7654;
AdcRegs.ADCCHSELSEQ3.all = 0xBA98;
AdcRegs.ADCCHSELSEQ4.all = 0xFEDC;
AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0xF; // Convertir y guardar 16 canales
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 0; // No habilitar interrupción SEQ1
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // Arranque inicial del ADC
}

interrupt void cpu_timer1_isr(void)


{
CpuTimer1.InterruptCount++;
GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; //alterna estado del led
// El Cpu reconoce solo la interrupción
i++;
p = EQep1Regs.QPOSCNT;
w = (p-pa)/dt;
ew= p-pa;
ep = pr - EQep1Regs.QPOSCNT;

ip = ipa + ep*kip*dt;
u = ip+ep*kpp;
ipa=ip;
pa = p;

if (u>12){
u=12;
v=u;
}
if (u<-12){(
u=-12);
v=-u;
}
if (u<-0){
v=-u;
}
else{
v=u;
}
if (u>=0){
EPwm1Regs.AQCTLA.bit.CBU = 1; // Set PWM1A en evento A, contar
arriba
EPwm1Regs.AQCTLA.bit.PRD = 2; // Clear PWM1A en evento A, contar
abajo
EPwm1Regs.AQCTLB.bit.CBU = 2; // Set PWM1B en evento B, contar
arriba
EPwm1Regs.AQCTLB.bit.PRD = 1;
GpioDataRegs.GPADAT.bit.GPIO2 = 1;
}
else{
EPwm1Regs.AQCTLA.bit.CBU = 2; // Set PWM1A en evento A, contar
arriba
EPwm1Regs.AQCTLA.bit.PRD = 1; // Clear PWM1A en evento A, contar
abajo
EPwm1Regs.AQCTLB.bit.CBU = 1; // Set PWM1B en evento B, contar
arriba
EPwm1Regs.AQCTLB.bit.PRD = 2;
GpioDataRegs.GPADAT.bit.GPIO2 = 1;
}
if ((ep<2) & (ep>-2)){
GpioDataRegs.GPADAT.bit.GPIO2 = 0;
}
EPwm1Regs.CMPB=(unsigned int)(v*20000/12.0);
//EPwm1Regs.CMPB=5000;
EDIS;
}

interrupt void cpu_timer2_isr(void)


{ EALLOW;
CpuTimer2.InterruptCount++;
//ResultadoADC[0]= AdcRegs.ADCRESULT0 >>4;
//ResultadoADC[1]= AdcRegs.ADCRESULT1 >>4;
AdcRegs.ADCTRL2.bit.SOC_SEQ1 = 1; // Arranque de conversión del ADC
// El Cpu reconoce solo la interrupción
EDIS;
}

También podría gustarte