Chia sẻ Điều khiển động cơ bằng phương pháp PID hiển thị LCD

daotruongpro

http://vtechpro.vn
#1
- PID (Proportional Integral Derivative) là một cơ chế phản hồi vòng điều khiển phương pháp điều khiển này được sử dụng rộng rãi trong các hệ thông điều khiển công nghiệp - bộ điều khiển PID được sử dụng phổ biến nhất trong số các bộ điều khiển phản hồi.
- Một bộ điều khiển PID tính toán một giá trị "sai số" là hiệu số giữa giá trị đo thông số biến đổi và giá trị đặt mong muốn. Bộ điều khiển sẽ thực hiện giảm tối đa sai số bằng cách điều chỉnh giá trị điều khiển đầu vào. Trong trường hợp không có kiến thức cơ bản về quá trình, bộ điều khiển PID là bộ điều khiển tốt nhất.[1] Tuy nhiên, để đạt được kết quả tốt nhất, các thông số PID sử dụng trong tính toán phải điều chỉnh theo tính chất của hệ thống-trong khi kiểu điều khiển là giống nhau, các thông số phải phụ thuộc vào đặc thù của hệ thống.
=> Để hiểu và làm được làm được đề tài này các bạn phải hiểu biết khá nhiều kiến thức bao gồm cả toán học và vật lý..., khi hiểu được các kiến thức này các bạn phải ứng dụng được các thuật toán trong Vi điều khiển tuy bỏ ra mất hơi nhiều thời gian nhưng sẽ nhận lại được nhiều thứ hơn khi các bạn ứng dụng phương pháp này vào cụ thể một cái gì đó.
Các bạn tham khảo tài liệu ở đây để hiểu rõ hơn về thuật toán, kiến thức về PID: Điều khiển Động cơ DC servo (PID)
Đây là bài demo còn thực tế thì mình đã làm nó chạy rồi, khá ổn định, tốc độ update liên tục, hiện tại chưa tìm thấy mạch in để up lên đây cho các bạn. see again!
+, Khi chạy chương trình nhấn Start => nhấn Up để tăng actual => và sự đáp ứng của động cơ
2013-09-18_190722.png


Mã:
/*****************************************************
This program was produced by the
CodeWizardAVR V2.04.4a Advanced
Automatic Program Generator
© Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : DKDC PP PID
Version : V1.0
Date    : 21/02/2013
Author  : Dao Xuan Truong
Company :
Comments:

Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/
#include <mega16.h>
#include <delay.h>
#include <math.h>
#include <stdio.h>
#include <lcd.h>
#include <stdlib.h>
#include <define.h>
#asm
   .equ __lcd_port=0x1B ;PORTA
#endasm
//Dinh nghia cac duong dieu khien motor
#define Sampling_time        25     //thoi gian lay mau (ms)
#define inv_Sampling_time    40     // 1/Sampling_time
#define PWM_Period            1023

bit StPlay=0; //bit cho phep start
long int Pulse,pre_Pulse;
long int rSpeed,Err , pre_Err; //thanh phan PID
long int Kp=300, Kd=1, Ki=1; //thanh phan PID
long int pPart=0, iPart=0, dPart=0; //thanh phan PID
char Ctrl_Speed=0;     //van toc can dieu khien (desired speed)
long int Output, absrSpeed;
unsigned char sample_count=0;
unsigned char dis[5]; //bo dem hien thi LCD
void Sys_init();
void Motor_Speed_PID(long int des_Speed);
void Checkphim(void);
void Program_init();
//chuong trinh ngat timer 2
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{    
    TCNT2=60; //gan gia tri khoi tao cho TCNT2
    if(StPlay==1)  //cho phep tang sample_count
    {
        sample_count++;
        Motor_Speed_PID(Ctrl_Speed);
    }
}
// chuong trinh ngat ngoai 0,phuc vu tang Ctrl_Speed
interrupt [EXT_INT0] void ext_int0_isr(void)
{
    if(StPlay==1)
        {
            if(Ctrl_Speed<36)
            Ctrl_Speed++;
            Led1=!Led1;
        }
}
// chuong trinh ngat ngoai 1,phuc vu giam Ctrl_Speed
interrupt [EXT_INT1] void ext_int1_isr(void)
{
    if(StPlay==1)
        {
            if(Ctrl_Speed>0)
            Ctrl_Speed--;
            Led2=!Led2;
        }
}
// chuong trinh ngat ngoai 2,phuc vu doc encoder
interrupt [EXT_INT2] void ext_int2_isr(void)
{
if (PINB==0) Pulse++;
    else Pulse--;
}
//chuong trinh dieu khien van toc bang PID
void Motor_Speed_PID(long int des_Speed){    
    rSpeed=Pulse-pre_Pulse;     //tinh van toc (trong sampling time)
    pre_Pulse=Pulse;            //luu lai gia tri Pulse: so xung
    Err=des_Speed-abs(rSpeed);  //tinh error (loi)
    pPart=Kp*Err;
    dPart=Kd*(Err-pre_Err)*inv_Sampling_time;
    iPart+=Ki*Sampling_time*(Err+pre_Err)/1000;
    Output +=pPart+dPart+iPart;     //cong thuc duoc bien doi vi la dieu khien van toc
    if (Output >=PWM_Period) Output=PWM_Period-1;
    if (Output <=0) Output=1;

    OCR1A=Output; //gan duty cycle cho OCR1A: update PWM
    pre_Err=Err;  //luu lai gia tri error
}

void main(void)
{
    Sys_init(); //Chuong trinh khoi tao chip
    lcd_init(16);//khoi tao LCD
    Program_init();//chuong trinh hien thi khi start
    //vong lap vo han
    while (1){
        Checkphim();//kiem tra phim bam
        switch (StPlay)
            {
                case 0:
                {
                        En=0; //tat den LCD
                        Led3=0;//led bao stop
                        OCR1A=0;//Xung ra =0
                        absrSpeed=0;//xoa toc do
                        sprintf(dis,"%i", absrSpeed);
                        lcd_gotoxy(11,0);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        sprintf(dis,"%i", Ctrl_Speed);
                        lcd_gotoxy(11,1);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        Checkphim();
                        break;
                }
                case 1:
                {
                    Led3=1;//led bao start
                    En=1;  //cho phep LCD sang
                    if (sample_count>=15)
                    { //hien thi sau 375ms
                        //------in van toc hien tai (tinh tren 25ms)
                        sample_count=0;
                        if(absrSpeed==Ctrl_Speed)Led4=0;
                        else Led4=!Led4;
                        absrSpeed=abs(rSpeed);
                        sprintf(dis,"%i", absrSpeed);
                        lcd_gotoxy(11,0);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        sprintf(dis,"%i", Ctrl_Speed);
                        lcd_gotoxy(11,1);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                    }
                    Checkphim();
                    break;
                }
            };
      }
}
void Program_init()
{
    Pulse=0;
    lcd_gotoxy(0,0);
    lcd_putsf("Program .");
    delay_ms(100);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ..");
    delay_ms(200);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ...");
    delay_ms(300);
    lcd_clear();
    lcd_gotoxy(0,0);
    lcd_putsf("Program .");
    delay_ms(100);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ..");
    delay_ms(200);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ...");
    delay_ms(300);
    Led1=Led2=Led3=Led4=0;
    En=1;
    lcd_gotoxy(0,0);
    lcd_putsf("DO AN TOT NGHIEP");
    lcd_gotoxy(0,1);
    lcd_putsf("DKDC BANG PP PID");
    delay_ms(100);
    Led1=Led2=Led3=Led4=1;
    lcd_clear();
    lcd_putsf("ACTUAL  :     ");
    lcd_gotoxy(0,1);
    lcd_putsf("PROGRESS:     "); 
    //---khoi dong gia tri PWM----------
    OCR1A=1;
    ICR1H=PWM_Period/256;
    ICR1L=PWM_Period%256;
}
void Checkphim(void)
{
    if(Sw1==0)
        {
            delay_ms(10);
            while(!Sw1);
            StPlay=1;
        }
    if(Sw2==0)
        {
            delay_ms(10);
            while(!Sw2);
            StPlay=0;
        }
}
void Sys_init()
{
    // Input/Output Ports initialization
    // Port A initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTA=0x00;
    DDRA=0x00;

    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTB=0xFF;
    DDRB=0x00;

    // Port C initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
    PORTC=0xFF;
    DDRC=0xFF;

    // Port D initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
    PORTD=0xf0;
    DDRD=0xf0;
    //Motor
    //MOTOR_DDR=0xF0;

    GICR|=0xE0;
    MCUCR=0x0A;
    MCUCSR=0x00;
    GIFR=0xE0;
    //---------------------------------------------------------------------------------
    //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
    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) ;
    //--------------------------------------------------------------------------------
    #asm ("sei")
}
[CODE]
 

Đính kèm

Sửa lần cuối:

ngocha

Kỹ sư
#2
cho tớ hỏi 1 chút là thông số kp ki kd dùng để điều khiển động cơ thì lấy ở đâu ah mod. Tớ thấy những động cơ to bằng cổ chân hoặc là dùng làm ô tô đồ chơi ấy có giống nhau không thế.
với lại những động cơ có encorder cỡ khoảng 1000 xung hay 100 xung thì làm thế nào vậy. Pro có thể hướng dẫn giúp anh chị em được không? cảm ơn nhiều
 

mroscar

Học sinh phổ thông
#3
- PID (Proportional Integral DerivativeProportional Integral Derivative) là một cơ chế phản hồi vòng điều khiển phương pháp điều khiển này được sử dụng rộng rãi trong các hệ thông điều khiển công nghiệp - bộ điều khiển PID được sử dụng phổ biến nhất trong số các bộ điều khiển phản hồi.
- Một bộ điều khiển PID tính toán một giá trị "sai số" là hiệu số giữa giá trị đo thông số biến đổi và giá trị đặt mong muốn. Bộ điều khiển sẽ thực hiện giảm tối đa sai số bằng cách điều chỉnh giá trị điều khiển đầu vào. Trong trường hợp không có kiến thức cơ bản về quá trình, bộ điều khiển PID là bộ điều khiển tốt nhất.[1] Tuy nhiên, để đạt được kết quả tốt nhất, các thông số PID sử dụng trong tính toán phải điều chỉnh theo tính chất của hệ thống-trong khi kiểu điều khiển là giống nhau, các thông số phải phụ thuộc vào đặc thù của hệ thống.
=> Để hiểu và làm được làm được đề tài này các bạn phải hiểu biết khá nhiều kiến thức bao gồm cả toán học và vật lý..., khi hiểu được các kiến thức này các bạn phải ứng dụng được các thuật toán trong Vi điều khiển tuy bỏ ra mất hơi nhiều thời gian nhưng sẽ nhận lại được nhiều thứ hơn khi các bạn ứng dụng phương pháp này vào cụ thể một cái gì đó.
Các bạn tham khảo tài liệu ở đây để hiểu rõ hơn về thuật toán, kiến thức về PID: Điều khiển Động cơ DC servo (PID)
Đây là bài demo còn thực tế thì mình đã làm nó chạy rồi, khá ổn định, tốc độ update liên tục, hiện tại chưa tìm thấy mạch in để up lên đây cho các bạn. see again!
+, Khi chạy chương trình nhấn Start => nhấn Up để tăng actual => và sự đáp ứng của động cơ
Xem đính kèm 12017

Mã:
/*****************************************************
This program was produced by the
CodeWizardAVR V2.04.4a Advanced
Automatic Program Generator
© Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
 
Project : DKDC PP PID
Version : V1.0
Date    : 21/02/2013
Author  : Dao Xuan Truong
Company :
Comments:
 
Chip type              : ATmega16
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size      : 0
Data Stack size        : 256
*****************************************************/
#include <mega16.h>
#include <delay.h>
#include <math.h>
#include <stdio.h>
#include <lcd.h>
#include <stdlib.h>
#include <define.h>
#asm
  .equ __lcd_port=0x1B ;PORTA
#endasm
//Dinh nghia cac duong dieu khien motor
#define Sampling_time        25    //thoi gian lay mau (ms)
#define inv_Sampling_time    40    // 1/Sampling_time
#define PWM_Period         
 
bit StPlay=0; //bit cho phep start
long int Pulse,pre_Pulse;
long int rSpeed,Err , pre_Err; //thanh phan PID
long int Kp=300, Kd=1, Ki=1; //thanh phan PID
long int pPart=0, iPart=0, dPart=0; //thanh phan PID
char Ctrl_Speed=0;    //van toc can dieu khien (desired speed)
long int Output, absrSpeed;
unsigned char sample_count=0;
unsigned char dis[5]; //bo dem hien thi LCD
void Sys_init();
void Motor_Speed_PID(long int des_Speed);
void Checkphim(void);
void Program_init();
//chuong trinh ngat timer 2
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{       
    TCNT2=60; //gan gia tri khoi tao cho TCNT2
    if(StPlay==1)  //cho phep tang sample_count
    {
        sample_count++;
        Motor_Speed_PID(Ctrl_Speed);
    }
}
// chuong trinh ngat ngoai 0,phuc vu tang Ctrl_Speed
interrupt [EXT_INT0] void ext_int0_isr(void)
{
    if(StPlay==1)
        {
            if(Ctrl_Speed<36)
            Ctrl_Speed++;
            Led1=!Led1;
        }
}
// chuong trinh ngat ngoai 1,phuc vu giam Ctrl_Speed
interrupt [EXT_INT1] void ext_int1_isr(void)
{
    if(StPlay==1)
        {
            if(Ctrl_Speed>0)
            Ctrl_Speed--;
            Led2=!Led2;
        }
}
// chuong trinh ngat ngoai 2,phuc vu doc encoder
interrupt [EXT_INT2] void ext_int2_isr(void)
{
if (PINB==0) Pulse++;
    else Pulse--;
}
//chuong trinh dieu khien van toc bang PID
void Motor_Speed_PID(long int des_Speed){       
    rSpeed=Pulse-pre_Pulse;    //tinh van toc (trong sampling time)
    pre_Pulse=Pulse;            //luu lai gia tri Pulse: so xung
    Err=des_Speed-abs(rSpeed);  //tinh error (loi)
    pPart=Kp*Err;
    dPart=Kd*(Err-pre_Err)*inv_Sampling_time;
    iPart+=Ki*Sampling_time*(Err+pre_Err)/1000;
    Output +=pPart+dPart+iPart;    //cong thuc duoc bien doi vi la dieu khien van toc
    if (Output >=PWM_Period) Output=PWM_Period-1;
    if (Output <=0) Output=1;
   
    OCR1A=Output; //gan duty cycle cho OCR1A: update PWM   
    pre_Err=Err;  //luu lai gia tri error 
}
 
void main(void)
{
    Sys_init(); //Chuong trinh khoi tao chip
    lcd_init(16);//khoi tao LCD
    Program_init();//chuong trinh hien thi khi start
    //vong lap vo han
    while (1){
        Checkphim();//kiem tra phim bam
        switch (StPlay)
            {
                case 0:
                {
                        En=0; //tat den LCD
                        Led3=0;//led bao stop
                        OCR1A=0;//Xung ra =0
                        absrSpeed=0;//xoa toc do
                        sprintf(dis,"%i", absrSpeed);
                        lcd_gotoxy(11,0);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        sprintf(dis,"%i", Ctrl_Speed);
                        lcd_gotoxy(11,1);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        Checkphim();
                        break;
                }
                case 1:
                { 
                    Led3=1;//led bao start
                    En=1;  //cho phep LCD sang
                    if (sample_count>=15)
                    { //hien thi sau 375ms
                        //------in van toc hien tai (tinh tren 25ms)
                        sample_count=0;
                        if(absrSpeed==Ctrl_Speed)Led4=0;
                        else Led4=!Led4; 
                        absrSpeed=abs(rSpeed);
                        sprintf(dis,"%i", absrSpeed);
                        lcd_gotoxy(11,0);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        sprintf(dis,"%i", Ctrl_Speed);
                        lcd_gotoxy(11,1);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                    }
                    Checkphim();
                    break;
                }
            }; 
      }
}
void Program_init()
{
    Pulse=0;
    lcd_gotoxy(0,0);
    lcd_putsf("Program .");   
    delay_ms(100);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ..");   
    delay_ms(200);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ...");   
    delay_ms(300);
    lcd_clear();
    lcd_gotoxy(0,0);
    lcd_putsf("Program .");   
    delay_ms(100);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ..");   
    delay_ms(200);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ...");   
    delay_ms(300);
    Led1=Led2=Led3=Led4=0;
    En=1;
    lcd_gotoxy(0,0);   
    lcd_putsf("DO AN TOT NGHIEP");   
    lcd_gotoxy(0,1);
    lcd_putsf("DKDC BANG PP PID");
    delay_ms(100);
    Led1=Led2=Led3=Led4=1;
    lcd_clear();
    lcd_putsf("ACTUAL  :    ");   
    lcd_gotoxy(0,1);
    lcd_putsf("PROGRESS:    ");   
    //---khoi dong gia tri PWM----------   
    OCR1A=1;
    ICR1H=PWM_Period/256;
    ICR1L=PWM_Period%256;
}
void Checkphim(void)
{
    if(Sw1==0)
        { 
            delay_ms(10);
            while(!Sw1);
            StPlay=1;
        }
    if(Sw2==0)
        { 
            delay_ms(10);
            while(!Sw2);
            StPlay=0;
        } 
} 
void Sys_init()
{
    // Input/Output Ports initialization
    // Port A initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTA=0x00;
    DDRA=0x00;
 
    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTB=0xFF;
    DDRB=0x00;
 
    // Port C initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
    PORTC=0xFF;
    DDRC=0xFF;
 
    // Port D initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
    PORTD=0xf0;
    DDRD=0xf0;
    //Motor
    //MOTOR_DDR=0xF0;
   
    GICR|=0xE0;
    MCUCR=0x0A;
    MCUCSR=0x00;
    GIFR=0xE0;
    //---------------------------------------------------------------------------------
    //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
    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) ;
    //--------------------------------------------------------------------------------
    #asm ("sei")
}
[CODE]
Anh có thể viết chuyển chương trình này sang viết cho con PIC đc k? E cám ơn!
 

daotruongpro

http://vtechpro.vn
#4
cho tớ hỏi 1 chút là thông số kp ki kd dùng để điều khiển động cơ thì lấy ở đâu ah mod. Tớ thấy những động cơ to bằng cổ chân hoặc là dùng làm ô tô đồ chơi ấy có giống nhau không thế.
với lại những động cơ có encorder cỡ khoảng 1000 xung hay 100 xung thì làm thế nào vậy. Pro có thể hướng dẫn giúp anh chị em được không? cảm ơn nhiều
- Chào bạn. Theo lý thuyết, ta nên tìm hàm truyền tường minh từ các phương trình vật lí nhưng mình chưa thấy ai làm điều này thì phải.Thông thường việc chọn các thông số P,I,D được xác định bằn thực nghiệm dựa vào sự đáp ứng xung của hệ thống. Trước mình cũng thử nghiệm, mỗi lần thử nghiệm phải ghi các thông số ra khi cảm thấy hệ thống đáp ứng nhanh-ổn định thì mới OK.
- Cách thử nghiệm: Đây là cách các tiền bối trước đã để lại" Cấp tín hiệu đặt rồi thay đổi dần các thông số Kp, Ki, Kd cho phù hợp. Đầu tiên, mình sẽ làm cho hệ thống ổn định bằng cách cho Ki, Kd bằng 0. Sau đó tăng dần Kp lên. Khi Kp càng nhỏ thì Nyquist hệ hở càng xa điểm (-1,j0). Hệ chắc chắn sẽ ổn định. Nhưng đổi lại, đáp ứng sẽ lâu. Mình tăng dần Kp đến khi hệ thống bắt đầu dao động thì dừng lại. Để triệt tiêu sai số xác lập,mình sẽ tăng dần Ki lên, nhưng đổi lại, do Ki tăng, hệ thống sẽ rât có khả năng bị vọt lố, mình tăng cho đến khi đặc tính quá độ vọt lố chừng 10% thì dừng. Tiếp theo, mình sẽ tăng tiếp Kd. Khi Kd tăng thì rất có thể thời gian xác lập mình dài ra hơn một chút nhưng bù lại, bạn sẽ bù trừ được 10% vọt lố ở trên."
-Hoặc có thể dùng phương pháp hiệu chỉnh thông số bộ pid ziegler-nichols
- Với các động cơ có xung lơn như bạn nói phải dùng chức năng counter chứ dùng ngắt ngoài chắc không ổn !
Chúc bạn thành công!
 

Ideas

Học sinh phổ thông
#5
Những cách trên đây là cách đơn giản nhất ! Nếu bạn muốn bỏ qua hàm truyền của đối tượng thì có thể sử dụng phương pháp auto turning để làm ! Lâu quá không làm về điều khiển nên chẳng nhớ j hết ! Chuẩn bị cần đến nó mà mất hết tài liệu ! Anh em nào hứng thú có thể tham gia trao đổi ! Mình sẽ làm trên MCU stm32 !
 

ngocha

Kỹ sư
#6
- Chào bạn. Theo lý thuyết, ta nên tìm hàm truyền tường minh từ các phương trình vật lí nhưng mình chưa thấy ai làm điều này thì phải.Thông thường việc chọn các thông số P,I,D được xác định bằn thực nghiệm dựa vào sự đáp ứng xung của hệ thống. Trước mình cũng thử nghiệm, mỗi lần thử nghiệm phải ghi các thông số ra khi cảm thấy hệ thống đáp ứng nhanh-ổn định thì mới OK.
- Cách thử nghiệm: Đây là cách các tiền bối trước đã để lại" Cấp tín hiệu đặt rồi thay đổi dần các thông số Kp, Ki, Kd cho phù hợp. Đầu tiên, mình sẽ làm cho hệ thống ổn định bằng cách cho Ki, Kd bằng 0. Sau đó tăng dần Kp lên. Khi Kp càng nhỏ thì Nyquist hệ hở càng xa điểm (-1,j0). Hệ chắc chắn sẽ ổn định. Nhưng đổi lại, đáp ứng sẽ lâu. Mình tăng dần Kp đến khi hệ thống bắt đầu dao động thì dừng lại. Để triệt tiêu sai số xác lập,mình sẽ tăng dần Ki lên, nhưng đổi lại, do Ki tăng, hệ thống sẽ rât có khả năng bị vọt lố, mình tăng cho đến khi đặc tính quá độ vọt lố chừng 10% thì dừng. Tiếp theo, mình sẽ tăng tiếp Kd. Khi Kd tăng thì rất có thể thời gian xác lập mình dài ra hơn một chút nhưng bù lại, bạn sẽ bù trừ được 10% vọt lố ở trên."
-Hoặc có thể dùng phương pháp hiệu chỉnh thông số bộ pid ziegler-nichols
- Với các động cơ có xung lơn như bạn nói phải dùng chức năng counter chứ dùng ngắt ngoài chắc không ổn !
Chúc bạn thành công!
cảm ơn mod
vậy là với mỗi 1 loại động cơ mình lại phải làm thí nghiệm từ đầu ạ.
Hay là khi chẳng may bị chết 1 encorder đang dùng (cỡ khoảng 100 xung) mà không kiếm được, bên cạnh có con 256 xung thì lắp vào và ngồi tính, và đo lại từ đầu hay sao ạ.
Mình thấy cái này bên lạc hồng họ ứng dụng vào robocon rất thành công.
Mới nhập môn nên có nhiều câu hơi ngây ngô mong bác thông cảm.
 

Trung Nghĩa

Học sinh trung cấp
#7
- PID (Proportional Integral DerivativeProportional Integral Derivative) là một cơ chế phản hồi vòng điều khiển phương pháp điều khiển này được sử dụng rộng rãi trong các hệ thông điều khiển công nghiệp - bộ điều khiển PID được sử dụng phổ biến nhất trong số các bộ điều khiển phản hồi.
- Một bộ điều khiển PID tính toán một giá trị "sai số" là hiệu số giữa giá trị đo thông số biến đổi và giá trị đặt mong muốn. Bộ điều khiển sẽ thực hiện giảm tối đa sai số bằng cách điều chỉnh giá trị điều khiển đầu vào. Trong trường hợp không có kiến thức cơ bản về quá trình, bộ điều khiển PID là bộ điều khiển tốt nhất.[1] Tuy nhiên, để đạt được kết quả tốt nhất, các thông số PID sử dụng trong tính toán phải điều chỉnh theo tính chất của hệ thống-trong khi kiểu điều khiển là giống nhau, các thông số phải phụ thuộc vào đặc thù của hệ thống.
=> Để hiểu và làm được làm được đề tài này các bạn phải hiểu biết khá nhiều kiến thức bao gồm cả toán học và vật lý..., khi hiểu được các kiến thức này các bạn phải ứng dụng được các thuật toán trong Vi điều khiển tuy bỏ ra mất hơi nhiều thời gian nhưng sẽ nhận lại được nhiều thứ hơn khi các bạn ứng dụng phương pháp này vào cụ thể một cái gì đó.
Các bạn tham khảo tài liệu ở đây để hiểu rõ hơn về thuật toán, kiến thức về PID: Điều khiển Động cơ DC servo (PID)
Đây là bài demo còn thực tế thì mình đã làm nó chạy rồi, khá ổn định, tốc độ update liên tục, hiện tại chưa tìm thấy mạch in để up lên đây cho các bạn. see again!
+, Khi chạy chương trình nhấn Start => nhấn Up để tăng actual => và sự đáp ứng của động cơ
Xem đính kèm 12017

Mã:
/*****************************************************
This program was produced by the
CodeWizardAVR V2.04.4a Advanced
Automatic Program Generator
© Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : DKDC PP PID
Version : V1.0
Date    : 21/02/2013
Author  : Dao Xuan Truong
Company :
Comments:

Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/
#include <mega16.h>
#include <delay.h>
#include <math.h>
#include <stdio.h>
#include <lcd.h>
#include <stdlib.h>
#include <define.h>
#asm
   .equ __lcd_port=0x1B ;PORTA
#endasm
//Dinh nghia cac duong dieu khien motor
#define Sampling_time        25     //thoi gian lay mau (ms)
#define inv_Sampling_time    40     // 1/Sampling_time
#define PWM_Period          

bit StPlay=0; //bit cho phep start
long int Pulse,pre_Pulse;
long int rSpeed,Err , pre_Err; //thanh phan PID
long int Kp=300, Kd=1, Ki=1; //thanh phan PID
long int pPart=0, iPart=0, dPart=0; //thanh phan PID
char Ctrl_Speed=0;     //van toc can dieu khien (desired speed)
long int Output, absrSpeed;
unsigned char sample_count=0;
unsigned char dis[5]; //bo dem hien thi LCD
void Sys_init();
void Motor_Speed_PID(long int des_Speed);
void Checkphim(void);
void Program_init();
//chuong trinh ngat timer 2
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{       
    TCNT2=60; //gan gia tri khoi tao cho TCNT2
    if(StPlay==1)  //cho phep tang sample_count
    {
        sample_count++;
        Motor_Speed_PID(Ctrl_Speed);
    }
}
// chuong trinh ngat ngoai 0,phuc vu tang Ctrl_Speed
interrupt [EXT_INT0] void ext_int0_isr(void)
{
    if(StPlay==1)
        {
            if(Ctrl_Speed<36)
            Ctrl_Speed++;
            Led1=!Led1;
        }
}
// chuong trinh ngat ngoai 1,phuc vu giam Ctrl_Speed
interrupt [EXT_INT1] void ext_int1_isr(void)
{
    if(StPlay==1)
        {
            if(Ctrl_Speed>0)
            Ctrl_Speed--;
            Led2=!Led2;
        }
}
// chuong trinh ngat ngoai 2,phuc vu doc encoder
interrupt [EXT_INT2] void ext_int2_isr(void)
{
if (PINB==0) Pulse++;
    else Pulse--;
}
//chuong trinh dieu khien van toc bang PID
void Motor_Speed_PID(long int des_Speed){       
    rSpeed=Pulse-pre_Pulse;     //tinh van toc (trong sampling time)
    pre_Pulse=Pulse;            //luu lai gia tri Pulse: so xung
    Err=des_Speed-abs(rSpeed);  //tinh error (loi)
    pPart=Kp*Err;
    dPart=Kd*(Err-pre_Err)*inv_Sampling_time;
    iPart+=Ki*Sampling_time*(Err+pre_Err)/1000;
    Output +=pPart+dPart+iPart;     //cong thuc duoc bien doi vi la dieu khien van toc
    if (Output >=PWM_Period) Output=PWM_Period-1;
    if (Output <=0) Output=1;
   
    OCR1A=Output; //gan duty cycle cho OCR1A: update PWM   
    pre_Err=Err;  //luu lai gia tri error 
}

void main(void)
{
    Sys_init(); //Chuong trinh khoi tao chip
    lcd_init(16);//khoi tao LCD
    Program_init();//chuong trinh hien thi khi start
    //vong lap vo han
    while (1){
        Checkphim();//kiem tra phim bam
        switch (StPlay)
            {
                case 0:
                {
                        En=0; //tat den LCD
                        Led3=0;//led bao stop
                        OCR1A=0;//Xung ra =0
                        absrSpeed=0;//xoa toc do
                        sprintf(dis,"%i", absrSpeed);
                        lcd_gotoxy(11,0);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        sprintf(dis,"%i", Ctrl_Speed);
                        lcd_gotoxy(11,1);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        Checkphim();
                        break;
                }
                case 1:
                {  
                    Led3=1;//led bao start
                    En=1;  //cho phep LCD sang
                    if (sample_count>=15)
                    { //hien thi sau 375ms
                        //------in van toc hien tai (tinh tren 25ms)
                        sample_count=0;
                        if(absrSpeed==Ctrl_Speed)Led4=0;
                        else Led4=!Led4; 
                        absrSpeed=abs(rSpeed);
                        sprintf(dis,"%i", absrSpeed);
                        lcd_gotoxy(11,0);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                        sprintf(dis,"%i", Ctrl_Speed);
                        lcd_gotoxy(11,1);
                        lcd_puts(dis);
                        lcd_putsf(" ");
                    }
                    Checkphim();
                    break;
                }
            };  
      }
}
void Program_init()
{
    Pulse=0;
    lcd_gotoxy(0,0);
    lcd_putsf("Program .");   
    delay_ms(100);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ..");   
    delay_ms(200);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ...");   
    delay_ms(300);
    lcd_clear();
    lcd_gotoxy(0,0);
    lcd_putsf("Program .");   
    delay_ms(100);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ..");   
    delay_ms(200);
    lcd_gotoxy(0,0);
    lcd_putsf("Program ...");   
    delay_ms(300);
    Led1=Led2=Led3=Led4=0;
    En=1;
    lcd_gotoxy(0,0);   
    lcd_putsf("DO AN TOT NGHIEP");   
    lcd_gotoxy(0,1);
    lcd_putsf("DKDC BANG PP PID");
    delay_ms(100);
    Led1=Led2=Led3=Led4=1;
    lcd_clear();
    lcd_putsf("ACTUAL  :     ");   
    lcd_gotoxy(0,1);
    lcd_putsf("PROGRESS:     ");    
    //---khoi dong gia tri PWM----------   
    OCR1A=1;
    ICR1H=PWM_Period/256;
    ICR1L=PWM_Period%256;
}
void Checkphim(void)
{
    if(Sw1==0)
        {  
            delay_ms(10);
            while(!Sw1);
            StPlay=1;
        }
    if(Sw2==0)
        {  
            delay_ms(10);
            while(!Sw2);
            StPlay=0;
        }  
}  
void Sys_init()
{
    // Input/Output Ports initialization
    // Port A initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTA=0x00;
    DDRA=0x00;

    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTB=0xFF;
    DDRB=0x00;

    // Port C initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
    PORTC=0xFF;
    DDRC=0xFF;

    // Port D initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
    // State7=1 State6=1 State5=1 State4=1 State3=1 State2=1 State1=1 State0=1
    PORTD=0xf0;
    DDRD=0xf0;
    //Motor
    //MOTOR_DDR=0xF0;
   
    GICR|=0xE0;
    MCUCR=0x0A;
    MCUCSR=0x00;
    GIFR=0xE0;
    //---------------------------------------------------------------------------------
    //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
    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) ;
    //--------------------------------------------------------------------------------
    #asm ("sei")
}
[CODE]
bạn ơi, đảo chiều động cơ thì cần cái gì vào đây nữa?
 

daotruongpro

http://vtechpro.vn
#8
Muốn đảo chiều động cơ thì sử dụng thêm các Relay để đảo cực tính của dòng điện cấp cho Motor
 

Trung Nghĩa

Học sinh trung cấp
#9
Muốn đảo chiều động cơ thì sử dụng thêm các Relay để đảo cực tính của dòng điện cấp cho Motor
sú dụng relay làm sao vậy bạn, minh cũng mới tìm hiểu mấy cái này nên ko có biết nhiều, chỉ cần đảo chiều ko cần điều khiển tốc độ. có code thì tốt.hihi
 

Quảng cáo Google