#include <delay.h>
#include <mega16.h>
#include <math.h>
#include <stdio.h>
#include <alcd.h>
#include <stdlib.h>
//Dinh nghia cac duong dieu khien motor
#define MOTOR_DDR DDRD
#define MOTOR_PORT PORTD
#define Sampling_time 25 //thoi gian lay mau (ms)
#define inv_Sampling_time 40 // 1/Sampling_time
#define PWM_Period 8000 //8000 cycles = 1ms, f=8MHz
unsigned char toc_do_phai[8] = {15,17,19,21,23,25,27,29};
unsigned char toc_do_trai[8] = {15,17,19,21,23,25,27,29};
long int Pulse1,Pulse2, pre_Pulse1,pre_Pulse2;
long int rSpeed1,rSpeed2,Err1 ,Err2, pre_Err1,pre_Err2;
long int Kp1=40, Kd1=1, Ki1=1; //for speed control
long int Kp2=40, Kd2=1, Ki2=1; //for speed control
long int pPart1=0, iPart1=0, dPart1=0,pPart2=0, iPart2=0, dPart2=0; //PID gains
long int Ctrl_Speed1=5,Ctrl_Speed2=5; //van toc can dieu khien (desired speed)
long int Output1, absrSpeed1,Output2, absrSpeed2;
unsigned char sample_count=0;
//dieu khien van toc bang PID
void Motor1_Speed_PID(long int des_Speed1){
rSpeed1=Pulse1-pre_Pulse1; //tinh van toc (trong sampling time)
pre_Pulse1=Pulse1; //luu lai gia tri Pulse: so xung
Err1=des_Speed1-abs(rSpeed1); //tinh error (loi)
//cac thanh phan cua PID
pPart1=Kp1*Err1;
dPart1=Kd1*(Err1-pre_Err1)*inv_Sampling_time;
iPart1+=Ki1*Sampling_time*(Err1+pre_Err1)/1000;
Output1 +=pPart1+dPart1+iPart1; //cong thuc duoc bien doi vi la dieu khien van toc
//saturation
if (Output1 >=PWM_Period) Output1=PWM_Period-1;
if (Output1 <=0) Output1=1;
OCR1A=Output1; //gan duty cycle cho OCR1A: update PWM
pre_Err1=Err1; //luu lai gia tri error
}
void Motor2_Speed_PID(long int des_Speed2){
rSpeed2=Pulse2-pre_Pulse2; //tinh van toc (trong sampling time)
pre_Pulse2=Pulse2; //luu lai gia tri Pulse: so xung
Err2=des_Speed2-abs(rSpeed2); //tinh error (loi)
//cac thanh phan cua PID
pPart2=Kp2*Err2;
dPart2=Kd2*(Err2-pre_Err2)*inv_Sampling_time;
iPart2+=Ki2*Sampling_time*(Err2+pre_Err2)/1000;
Output2 +=pPart2+dPart2+iPart2; //cong thuc duoc bien doi vi la dieu khien van toc
//saturation
if (Output2 >=PWM_Period) Output2=PWM_Period-1;
if (Output2 <=0) Output2=1;
OCR1B=Output2; //gan duty cycle cho OCR1A: update PWM
pre_Err2=Err2; //luu lai gia tri error
}
void main(void){
unsigned char dis[5]; //bien tam, hien thi LCD
Pulse1=Pulse2=0;
//Encoder va cac chan nhap toc do
DDRB=0x00; //set PORTB as a input port to use the T0 input pin and INT2
PORTB=0xFF; //dien tro keo len (nhat la encoder)
//Motor
MOTOR_DDR=0xF0;
//ngat ngoai, cho encoder--------------------------------------------------------------
MCUCSR|=(0<<ISC11)|(0<<ISC01); //ngat INT1-INT0 la ngat canh xuong - Falling Edge
GICR |=(1<<INT0)|(1<<INT1); //Enable INT0-INT0
//---------------------------------------------------------------------------------
//dung timer 2 lam bo dinh thi 25ms, sampling time--------------------------------
TCCR2=(1<<CS22)|(1<<CS21)|(1<<CS20); //CS22=1, CS21=1, CS20=1: chon Prescaler=1024 (trang 125 datasheet)
TCNT2=60; //gan gia tri khoi tao cho T/C2 de duoc 25ms (truong hop f=8MHz)
TIMSK=(1<<TOIE2); // cho phep ngat khi co tran o T/C2
//--------------------------------------------------------------------------------
//dung timer1 lam PWM generator, Fast PWM mode 14: ICR1 chua time period
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
TCCR1B=(1<<WGM13) |(1<<WGM12) |(1<<CS10) ;
//--------------------------------------------------------------------------------
//**********LCD*************************
lcd_init(16);
lcd_clear();
lcd_putsf("TEST PID");
lcd_gotoxy(0,1);
lcd_putsf("DC Servo Motor");
delay_ms(100);
lcd_clear();
lcd_putsf("-Ac1: ");
lcd_putsf("-Ac2: ");
lcd_gotoxy(0,1);
lcd_putsf("-De1: ");
lcd_putsf("-De2: ");
//**********LCD*************************
//---khoi dong gia tri PWM----------
OCR1A=1;
OCR1B=1;
ICR1H=PWM_Period/256;
ICR1L=PWM_Period%256;
#asm ("sei")
//----------------------------------
while (1){
if (sample_count>=10){ //hien thi moi 250ms
Ctrl_Speed1=Ctrl_Speed2=PINB; //doc switches
//------in van toc hien tai (tinh tren 25ms)
absrSpeed1=abs(rSpeed1);
sprintf(dis,"%i", absrSpeed1);
lcd_gotoxy(5,0);
lcd_puts(dis);
lcd_putsf(" ");
//------in van toc mong muon (tinh tren 25ms)
sprintf(dis,"%i", Ctrl_Speed1);
lcd_gotoxy(5,1);
lcd_puts(dis);
lcd_putsf(" ");
//------in van toc mong muon (tinh tren 25ms)
absrSpeed2=abs(rSpeed2);
sprintf(dis,"%i", absrSpeed2);
lcd_gotoxy(13,0);
lcd_puts(dis);
lcd_putsf(" ");
//------in van toc mong muon (tinh tren 25ms)
sprintf(dis,"%i", Ctrl_Speed2);
lcd_gotoxy(13,1);
lcd_puts(dis);
lcd_putsf(" ");
sample_count=0;
}
}
}
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{ //update sampling time---------------
TCNT2=60; //gan gia tri khoi tao cho T/C2
sample_count++;
Motor1_Speed_PID(Ctrl_Speed1);
Motor2_Speed_PID(Ctrl_Speed2);
}
interrupt [EXT_INT0] void encoder_1(void)
{
if (PINB==0) Pulse1++;
else Pulse1--;
}
interrupt [EXT_INT1] void encoder_2(void)
{
if (PINB==0) Pulse2++;
else Pulse2--;
}
|