THIẾT KẾ HỆ THỐNG ĐIỀU KHIỂN ĐỘNG CƠ BẰNG PID

Nhiệm vụ bộ PID :
 ·       Đưa sai lệch e(t) càng lớn thì thông qua thành phần tỉ lệ   thì tín hiệu điều chỉnh  u(t)  càng lớn.

·       Nếu  sai lệch e(t) chưa bằng  0 thì qua thành phần tích phân   , tín hiệu điều chỉnh vẫn được bộ PID tạo ra.

·       Nếu sự thay đổi của e(t) càng lớn do khâu tích phân  hiệu chỉnh làm tăng độ sai số lên, thông qua thành phần vi phân  phản ứng thích hợp của u(t) sẽ càng nhanh.

    Cách tính giải hệ thống PID ra hàm truyền toán học 


  Chọn Kp trước: thử bộ điều khiển P với đối tượng thật (hoặc mô phỏng), điều chỉnh Kp sao cho thời gian đáp ứng đủ nhanh, chấp nhận overshot nhỏ.

Thêm thành phần D để loại vọt lố,  tăng Kd từ từ, thử nghiệm và chọn giá trị thích hợp. Giá trị sai số  có thể sẽ xuất hiện.

Thêm thành phần I để giảm giá trị sai số . Nên tăng Ki từ bé đến lớn để giảm giá trị sai số đồng thời không để cho vọt lố xuất  hiện trở lại.

  Phần 1: Code CCS
Mã CCS:
#include <PIDtocdodongco.h>
/* Phan Hoang Thinh MSSV: 14130721 */

// # include <16F887.h>
#fuses HS NOWDT, NOPROTECT, NOLVP, NOBROWNOUT
// # sử dụng fast_io (d)
#include <string.h>
#include <stdlib.h>
#include <math.h>
// # include <lcd.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
// # sử dụng delay (clock = 20000000)
RS232 #use (baud = 9600, parity = N, xmit = PIN_C6, RCV = PIN_C7, bit = 8)
//DINH NGHIA CAC CHAN NUT NHAN HOAC 02 CHAN ENCODER
#define SW1 PIN_B0 //NGAT NGOAI 
#define SW2 PIN_B4
//DINH NGHIA CHAN TU CAM BIEN LM35
#define LM35 PIN_A1
//DINH NGHIA CHAN DIEU KHIEN DONG CO DUNG L298
#define DIR1 PIN_C0 // IN1
#define PWM PIN_C2 //CHAN DIEU RONG XUNG, ENA
#define dir2 PIN_C1 // IN2
//DINH NGHIA CAC BIEN 
//BIEN NHAN DU LIEU
unsigned int16 saisoKp = 0, saisoKi = 0;
nổi xoa_saiso, tong_saiso;
unsigned int16 saisoKp1 = 0, saisoKi1 = 0;
float xoa_saiso1,tong_saiso1;
char c_start,c_stop,c_tem; //bien tam luu ma bat dau và ket thúc
char s1[9]; //bi?n t?m luu d? li?u nh?n du?c t? máy tính
int k; // bi? N ch? S? cho m? ng d? li? u nh? n du? c
int biennhan; // bi?n báo hi?u dã nh?n d? li?u xong 
// int bien_goidongco;
// MOTOR BIÊN MA
char smthuan [] = "mt"; // dongcoquaythuan
int co_thuan; // bi?n báo tr?ng thái d?ng co quay thu?n
char smnghich [] = "mn"; // dongcoquaynghich
int co_nghich; //bi?n báo tr?ng thái d?ng co quay ngh?ch
char smstop [] = "ms"; // dongcongungchay
// luu y: neu nhan ma @td+"xxx"+x 
char smpwm [] = "td"; // ma_nap_pwm
// PID
char ppid [] = "kp"; // ma Kp
char ipid [] = "ki"; // ma Ki
char dpid [] = "kd"; // ma Kd
//Bien luu PID
long sppid;
long sipid;
long sdpid;
// CŨNG PWM
long ppwm; // bi?n luu giá tr? %PWM nh?n du?c t? máy tính 
int ngat;//báo tr?ng thái ng?t ngoài
int dem_t; // bi? N luu s? l? nd? m timer1

///////////////////////////////////////////////////////////////////////////////
//CHUONG TRINH NGAT RS232
//NEU DUNG MA SE LUU VAO S1, BIEN NHAN = 1, 
//NEU KHONG DUNG MA BIEN NHAN = 0
#int_rda
khoảng trống RDA_isr (void)
{
   c_tem=getc();//NHAN TUNG KI TU
   if (c_tem == '@') // xet ki tu bat dau "@"
   {
   c_start = c_tem;
   k = 0;
   s1 [k] = c_start;
   }
   if (c_tem=='x') //xet ki tu ket thuc "x"
   {
   c_stop = c_tem;
   s1 [k] = c_stop;
   }
   if (c_start == '@' && c_stop == 'x')
   {
   k = 0;
   biennhan=1;//bao hieu da nhan dung ma dau-cuoi
   c_start = 0;
   c_stop = 0;
    }
   khác
   {
   s1[k]=c_tem;
   a ++;
   if (k> = 9) {k = 0;}
   }
}
///////////////////////////////////////////////////////////////////////////////

//NGAT TIMER 1
# INT_TIMER1
khoảng trống ngattimer1 ()
{

// timer: DIV_BY_8
set_timer1(4856); // timer bat dau dem tu 4856 tuc la:
////                  4*8*[(2^16-1)-4856]
// T_interrupt = ----------------------- x 1 = 97 ms
// 20MHz
dem_t++; //moi lan tang khi timer 1 tran, tuong ung voi 100.000 us 
}
///////////////////////////////////////////////////////////////////////////////
//CHUONG TRINH DIEU KHIEN MOTOR
//CHUONG TRINH NHAN %PWM TU MAY TINH
/****************************************************************/
khoảng trống nappwm ()
{
char SPWM [3];
spwm[0]=s1[4]; //lay giá tri %PWM tu bien nhan theo quy dinh
SPWM [1] = s1 [5];
SPWM [2] = s1 [6];
PWM = atoi (PWM);
printf ( "% s% Lu% s \ n \ r", "@ Toc làm:", ppwm, "% x"); // gui PWM%
}
/****************************************************************/
làm mất hiệu lực napKp ()
{
ppid char [4];
ppid[0]=s1[4]; //lay giá tri %PWM tu bien nhan theo quy dinh
PPID [1] = S1 [5];
PPID [2] = S1 [6];
AppID = atoi (PID);
// sppid = (float) ppid;
printf ( "% s% Lu% s \ n \ r", "@ Kp:", sppid, "x"); // gui PWM%
}
/****************************************************************/
làm mất hiệu lực napKi ()
{
ipid [3] char;
ipid[0]=s1[4]; //lay giá tri %PWM tu bien nhan theo quy dinh
ipid [1] = S1 [5];
ipid [2] = S1 [6];
tẻ nhạt = atoi (ipid);
printf ( "% s% Lu% s \ n \ r", "@ Ki:", sipid, "x"); // gui PWM%
}
/****************************************************************/
làm mất hiệu lực napKd ()
{
char dpid [3];  
dpid[0]=s1[4]; //lay giá tri %PWM tu bien nhan theo quy dinh
dpid [1] = S1 [5];
dpid [2] = S1 [6];
sdpid = atoi (DPID);
printf ( "% s% Lu% s \ n \ r", "@ Kd:", sdpid, "x"); // gui PWM%
}
/***************Chuong trinh tinh PID********************/

/*************************************************************/
//CHUONG TRINH MOTOR STOP
khoảng trống motostop ()
{
set_pwm1_duty (0);
// output_bit (PWM, 0);
output_bit(DIR1,0); // motor ngung khi Dir 1 và 2 = 0
output_bit (DIR2,0);
setup_ccp1 (CCP_OFF); // Ngung xu t PWM?
co_thuan=0; //reset tr?ng thái ch?y thu?n ngh?ch
co_nghich=0;
printf ( "% s \ n \ r", "@ mstopx");
nổi stop_DC = 0;
printf ( "% s% 3.0f% s \ n \ r", "@ PID", stop_DC, "x");
}
//CHUONG TRINH MOTOR CHAY THUAN
khoảng trống quaythuan ()
{

nổi pwm_t;
// nổi tinhpid; F = Kp * err +
pwm_t=(float)ppwm*512/100; //xung do 100% PWM thi duoc 512.0
// tinhpid = (float) sppid * pwm_t;
setup_ccp1(CCP_PWM); //cho phep xuat PWM kenh 1
output_bit (DIR1,1); // ch? N hu? Ng quay
output_bit (DIR2,0);
set_pwm1_duty ((int16) pwm_t);
// nổi = set_pwm1_duty ((int16) pwm_t) hihi;
nổi tocdo_pid;
nổi tocdo_t = (pwm_t * 60F) / 100; // 307
nổi tocdo = (pwm_t * 60F) / 102; // 301
/****************************************************************/
      nổi kpt_t, kit_t, kdt_t;
      kpt_t = (float) (sppid) / 100; // 40
      kit_t = (float) (sipid) / 100; // 5
      kdt_t=(float)(sdpid)/100;//0
     
      saisoKp = saisoKi;
      saisoKi = tocdo_t-tocdo;
      xoa_saiso = saisoKi-saisoKp;
      tong_saiso = saisoKp + saisoKi;
      nổi ab, ac, quảng cáo;
      ab = kpt_t * saisoKi;
      ac = kit_t * tong_saiso;
      ad=kdt_t*xoa_saiso;
      tocdo_pid = tocdo + ab + ac + quảng cáo;
/****************************************************************/
// set_pwm1_duty ((int16) pwm_t); // nap xung PWM
co_thuan=1;
printf ( "% s \ n \ r", "@ mthuanx");
/**************************/
// xungthinh = set_pwm1_duty ((int32) pwm_t); // nap xung PWM
// printf ( "% s% f% s \ r \ n", "@ DC", saisoKi, "x"); // vong / giay
printf ( "% s +% 3.0f% s \ n \ r", "@ PID", tocdo_pid, "x");
printf ( "% s +% 3.0f% s \ r \ n", "@ DC", tocdo, "x"); // vong / giay
// printf ( "% s +% 3.0f% s \ n \ r", "@ PID", tocdo_t, "x");
/*****************************/
}
//CHUONG TRINH MOTOR CHAY THUAN
khoảng trống quaynghich ()
{
nổi pwm_n;
pwm_n = (float) ppwm * 512/100;
setup_ccp1 (CCP_PWM);
output_bit (DIR1,0);
output_bit (DIR2,1);
set_pwm1_duty ((int16) pwm_n);
nổi tocdo1_pid;
nổi tocdo_n = (pwm_n * 60F) / 100; // 307
nổi tocdo_dat = (pwm_n * 60F) / 102; // 301
/****************************************************************/
      saisoKp1 = saisoKi1;
      saisoKi1 = tocdo_n-tocdo_dat;
      xoa_saiso1 = saisoKi1-saisoKp1;
      tong_saiso1 = saisoKp1 + saisoKi1;
      nổi kpn_t;
      nổi kin_t;
      kdn_t nổi;
     
      kpn_t = (float) (sppid) / 100; // 40
      kin_t = (float) (sipid) / 100; // 5
      kdn_t = (float) (sdpid) / 100; // 0
      nổi AB1, AC1, AD1;
      AB1 = kpn_t * saisoKi1;
      AC1 = kin_t * tong_saiso1;
      ad1=kdn_t*xoa_saiso1;
     
      tocdo1_pid = tocdo_dat AC1 + + + AB1 AD1;
/*********************************************************************/
co_nghich=1;
printf ( "% s \ n \ r", "@ mnghichx");
/****************************/
// nổi tocdo = (pwm_n * 60F) / 100;
printf ( "% s -% 3.0f% s \ r \ n", "@ PID", tocdo1_pid, "x"); // vong / giay
printf ( "% s -% 3.0f% s \ r \ n", "@ DC", tocdo_dat, "x"); // vong / giay
/***********************/
}
///////////////////////////////////////////////////////////////////////////////
//CHUONG TRINH XOA BIEN NHAN
khoảng trống xoanhan ()
{
int j;
for (j = 0; j <= 9; j ++) {s1 [j] = 0;}
}
///////////////////////////////////////////////////////////////////////////////
//CHUONG TRINH CON XET MA NHAN DUOC
khoảng trống xetma ()
{
   if ((biennhan) && (Ngát == 0))
   {
   if (strncmp (strstr (s1, smthuan), smthuan, 2) == 0) {quaythuan ();} // nau = “mt”
   if (strncmp (strstr (s1, smnghich), smnghich, 2) == 0) {quaynghich ();} // nau = “mn”
   if (strncmp (strstr (s1, smstop), smstop, 2) == 0) {motostop ();} // nau = “ms”
   if (strncmp (strstr (s1, smpwm), smpwm, 2) == 0) // nau = “td”
      {Nappwm ();}       
   if (strncmp (strstr (s1, ppid), ppid, 2) == 0) // nau = “kp”
      {NapKp ();}    
  if (strncmp (strstr (S1, ipid), ipid, 2) == 0) // con = "ki"
      {NapKi ();}
  if (strncmp (strstr (s1, dpid), dpid, 2) == 0) // nau = “kd”
      {NapKd ();                             
                   if (co_thuan) {quaythuan ();}
                   if (co_nghich) {quaynghich();}
      }
   xoanhan();
   biennhan = 0;
   }
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//CHUONG TRINH CHINH
void main ()
{
ext_int_edge(H_TO_L ); //quy dinh ngat ngoài tích cuc muc thap = canh xuong
enable_interrupts(INT_RDA);//cho phep ngat truyen thong
enable_interrupts(INT_TIMER1); // cho phép ngat timer1
enable_interrupts(GLOBAL); //cho phép ngat toàn cuc
setup_timer_2(T2_DIV_BY_16,127,1);//cài dat timer2
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8); // cài dat timer1
set_timer1 (4865);
delay_ms (10);
while (true)
{
xetma();//goi chuong trình xét mã nhan duoc tu máy tính
}
}

  Giao diện Visual Basic :
Mã Visual:

nhập khẩu Hệ thống
nhập khẩu System.ComponentModel
nhập khẩu System.IO.Ports

Công Lớp Form_PidDongCo
    không bodemnhan
    không tocdo
    Dim tocdo_pid

    Private Sub Form_PidDongCo_Load (người gửi Như Object , e Như EventArgs ) Xử lý MyBase Load
        Baotrangthai.Text = "Mời bạn mở cổng COM"
        MoCongCOM.Enabled = Đúng
        DongCOM.Enabled = False
        goi.Enabled = False
        Nhan.Enabled = False
    End Sub

    Private Sub MoCongCOM_Click (người gửi Như Object , e Như EventArgs ) Xử lý MoCongCOM.Click
        Nếu (SerialPort1.IsOpen) Sau đó,
            Exit Sub
        End If
        với SerialPort1
            .PortName = "COM1"
            .BaudRate = 9600
            .Parity = IO.Ports. chẵn lẻ .None
            .StopBits = IO.Ports. StopBits .Một
            .DataBits = 8
            .ReceivedBytesThreshold = 1
        End Với
        Thử
            SerialPort1.Open ()
            MoCongCOM.Enabled = False
            DongCOM.Enabled = Đúng
            goi.Enabled = Đúng
            Nhan.Enabled = True
            Baotrangthai.Text = "Cổng COM đã mở"
        Catch ex Như ngoại lệ
        End Try
    End Sub

    Private Sub DongCOM_Click (người gửi Như Object , e Như EventArgs ) Xử lý DongCOM.Click
        SerialPort1.Close ()
        MoCongCOM.Enabled = Đúng
        DongCOM.Enabled = False
        goi.Enabled = False
        Nhan.Enabled = False
        Baotrangthai.Text = "Mời bạn mở cổng COM"
    End Sub

    Private Sub Thoat_Click(sender As Object, e As EventArgs) Handles Thoat.Click
        If MsgBox("Bạn có muốn thoát khỏi chương trình?",
MsgBoxStyle .YesNo + MsgBoxStyle .Question, "Exit" ) =
MsgBoxResult .Yes Sau đó,
            Gần()
        EndIf
    End Sub

    Private Sub DataReceived (người gửi Như Object , e Như SerialDataReceivedEventArgs ) Xử lý SerialPort1.DataReceived
        Dim v_start Như Integer
        Dim v_stop Như Integer
        Dim v_tocdopid Như Integer
        Dim v_tocdo Như Integer
        Thử
            CheckForIllegalCrossThreadCalls = False
            bodemnhan + = SerialPort1.ReadExisting
            Nếu bodemnhan.Contains ( "@" ) Sau đó,
                Nếu bodemnhan.EndsWith ( "x" ) Sau đó,
                    SerialPort1.DiscardInBuffer ()
                    v_start = bodemnhan.IndexOf ( "@" )
                    v_stop = bodemnhan.IndexOf ( "x" )
                    Nếu bodemnhan.Contains ( "PID" ) Sau đó,
                        v_tocdopid = bodemnhan.IndexOf ( "PID" )
                        tocdo_pid = bodemnhan.Substring (v_tocdopid + 3, v_stop - (v_tocdopid + 2) - 1) + "Vọng / s"

                    ElseIf bodemnhan.Contains ( "DC" ) Sau đó,
                        v_tocdo = bodemnhan.IndexOf ( "DC" )
                        tocdo = bodemnhan.Substring (v_tocdo + 2, v_stop - (v_tocdo + 1) - 1) + "Vọng / s"

                    khác
                        Onhansukien.Text = bodemnhan.Substring (v_start + 1, v_stop - 1 - v_start)
                    EndIf
                    bodemnhan = ""
                EndIf
            EndIf
        Catch ex Như ngoại lệ
        End Try
    End Sub

    Private Sub Laymau_Tick (người gửi Như Object , e Như EventArgs ) Xử lý Laymau.Tick
        Thử
            Nếu SerialPort1.IsOpen Sau đó,
                nhandongco_pid.Text = tocdo_pid
                txt_dongcothucte.Text = tocdo
            EndIf
        Catch ex Như ngoại lệ

        End Try
    End Sub

    Private Sub Nhan_Click(sender As Object, e As EventArgs) Handles Nhan.Click
        Laymau.Start ()
    End Sub

    Private Sub SetTocDo_Click (người gửi Như Object , e Như EventArgs ) Xử lý SetTocDo.Click
        SerialPort1.Write ( "@ td +" + caidattocdo.Text + "x" )
    End Sub

    Private Sub quaynghich_Click (người gửi Như Object , e Như EventArgs ) Xử lý quaynghich.Click
        SerialPort1.Write ( "@mnx" )
    End Sub

    Private Sub quaythuan_Click (người gửi Như Object , e Như EventArgs ) Xử lý quaythuan.Click
        SerialPort1.Write ( "@mtx" )
    End Sub

    Private Sub button_stop_Click (người gửi Như Object , e Như EventArgs ) Xử lý button_stop.Click
        SerialPort1.Write ( "@msx" )
    End Sub

    Private Sub Goi_pid_Click (người gửi Như Object , e Như EventArgs ) Xử lý Goi_pid.Click
        SerialPort1.Write ( "@ kp +" + txt_kp.Text + "x" )
        SerialPort1.Write ( "@ ki +" + txt_kp.Text + "x" )
        SerialPort1.Write ( "@ kd +" + txt_kp.Text + "x" )
    End Sub

    Private Sub goi_Click (người gửi Như Object , e Như EventArgs ) Xử lý goi.Click
        SerialPort1.Write ( "@" + ogoi.Text + "x" )
    End Sub
End Lớp





Previous
Next Post »