![]() |
|
Tài trợ cho PIC Vietnam |
dsPIC - Bộ điều khiển tín hiệu số 16-bit Theo dự kiến của Microchip, vào khoảng năm 2011 dsPIC sẽ có doanh số lớn hơn PIC |
|
Ðiều Chỉnh | Xếp Bài |
![]() |
#1 |
Đệ tử 1 túi
Tham gia ngày: Dec 2008
Bài gửi: 25
: |
Giúp em chtr liên quan đến số fractional Q15 này với
em dựa vào 1 ví dụ của C30 về PID như này
Code:
#include <dsp.h> /* Variable Declaration required for each PID controller in your application */ /* Declare a PID Data Structure named, fooPID */ tPID fooPID; /* The fooPID data structure contains a pointer to derived coefficients in X-space and */ /* pointer to controler state (history) samples in Y-space. So declare variables for the */ /* derived coefficients and the controller history samples */ fractional abcCoefficient[3] __attribute__ ((section (".xbss, bss, xmemory"))); fractional controlHistory[3] __attribute__ ((section (".ybss, bss, ymemory"))); /* The abcCoefficients referenced by the fooPID data structure */ /* are derived from the gain coefficients, Kp, Ki and Kd */ /* So, declare Kp, Ki and Kd in an array */ fractional kCoeffs[] = {0,0,0}; /* Main function demonstrating the use of PID(), PIDInit() and PIDCoeffCalc() functions from DSP library in MPLAB C30 v2.0 and higher */ int main (void) { /* Step 1: Initialize the PID data structure, fooPID */ fooPID.abcCoefficients = &abcCoefficient[0]; /*Set up pointer to derived coefficients */ fooPID.controlHistory = &controlHistory[0]; /*Set up pointer to controller history samples */ PIDInit(&fooPID); /*Clear the controler history and the controller output */ kCoeffs[0] = Q15(0.7); kCoeffs[1] = Q15(0.2); kCoeffs[2] = Q15(0.07); PIDCoeffCalc(&kCoeffs[0], &fooPID); /*Derive the a,b, & c coefficients from the Kp, Ki & Kd */ /* Step 2: Use the PID Controller */ fooPID.controlReference = Q15(0.74) ; /*Set the Reference Input for your controller */ fooPID.measuredOutput = Q15(0.453) ; /*Typically the measuredOutput variable is a plant response*/ /*measured from an A/D input or a sensor. */ /*In this example we manually set it to some value for */ /*demonstration but the user should note that this value will */ /*keep changing in a real application*/ while (1) /*We use a while(1) loop here for demonstration purposes.*/ { /*Typically, the PID calculation may be triggered off a timer*/ /*or A/D interrupt */ PID(&fooPID); /*Call the PID controller using the new measured input */ /*The user may place a breakpoint on "PID(&fooPID)", halt the debugger,*/ /*tweak the measuredOutput variable within the watch window */ /*and then run the debugger again */ } } Code:
/* Dat PID Data Structure voi ten fooPID */ tPID fooPID; /* The fooPID data structure contains a pointer to derived coefficients in X-space and */ /* pointer to controler state (history) samples in Y-space. So declare variables for the */ /* derived coefficients and the controller history samples */ /* Voi iPID duoc khai bao nhu sau typedef struct { fractional* abcCoefficients; // coeffs derived from Kp, Ki & Kd fractional* controlHistory; // state variables (delay line)in Y-data fractional controlOutput; // PID Controller Output fractional measuredOutput; // Measured Output sample fractional controlReference; // Reference Input sample } tPID; */ fractional abcCoefficient[3] __attribute__ ((section (".xbss, bss, xmemory"))); fractional controlHistory[3] __attribute__ ((section (".ybss, bss, ymemory"))); int PWM_duty; //Chuong trinh khoi tao thong so PID //------------------------------------------------------------------------------ void PID_init(void) { /* The abcCoefficients referenced by the fooPID data structure */ /* are derived from the gain coefficients, Kp, Ki and Kd */ /* Dat cac he so Kp, Ki and Kd trong mang sau*/ fractional kCoeffs[] = {0,0,0}; //Step 1: Khoi tao PID data structure, fooPID fooPID.abcCoefficients = &abcCoefficient[0]; //Set up pointer to derived coefficients fooPID.controlHistory = &controlHistory[0]; //Set up pointer to controller history samples PIDInit(&fooPID); //Clear the controler history and the controller output kCoeffs[0] = Q15(0.9); // Kp = 1 kCoeffs[1] = Q15(0); // Ki = 0 kCoeffs[2] = Q15(0); // Kd = 0 PIDCoeffCalc(&kCoeffs[0], &fooPID); // Tinh cac he so a,b, & c tu Kp, Ki & Kd */ // a = abcCoefficients[0] = Kp + Ki + Kd // b = abcCoefficients[1] = -(Kp + 2*Kd) // c = abcCoefficients[2] = Kd } //Chuong trinh xu ly ngat Timer 2 sau 10ms //------------------------------------------------------------------------------ void __attribute__((__interrupt__)) _T2Interrupt(void) { _T2IF = 0; //Xoa co ngat fooPID.controlReference = Q15(ADCBUF0 >> 1) ; // controlReference la dai luong dat // O day la toc do dc dat tu bien tro dieu chinh toc do thong qua bo ADC fooPID.measuredOutput = Q15(POSCNT * 0x0003) ; // measuredOutput dai luong do ve // La toc do do encoder dua ve /* Chinh xac gia tri dat la ADC, bo ADC 10bit gia tri 0 - 504, tuong ung 0 - 17.5 vong/s (20v/s la gia tri toc do dat giói han tren) tuong ung 0 - 168 xung/10ms ( 1 vong quay thi có 960 xung) Gia tri toc do doc ve là so xung/10ms (POSCNT/10ms) */ PID(&fooPID); /* controlOutput[n] = controlOutput[n-1] + controlHistory[n] * abcCoefficient[0] + controlHistory[n-1] * abcCoefficient[1] + controlHistory[n-2] * abcCoefficient[2] Trong do abcCoefficient[0] = Kp + Ki + Kd abcCoefficient[1] = -(Kp + 2*Kd) abcCoefficient[2] = Kd ControlHistory[n] = MeasuredOutput[n] - ReferenceInput[n] */ PWM_duty = fooPID.controlOutput; if (PWM_duty > 504 ) //Chan gia tri tren { PWM_duty = 504;} if (PWM_duty < 0 ) //Chan gia tri duoi { PWM_duty = 0;} PDC1 = PWM_duty ; POSCNT = 0; } em lấy 9 bit trong ADCBUF0, giá trị từ 0 đến 504 thì tương đuơng dutt cycle từ 0 đến 100%, ứng với tốc độ từ 0 đến 20v/s, giá trị đặt của em là giá trị ở ADCBUF0>>1 từ 0 đến 504 giá trị phẩn hồi e quy đổi về là sô xung/ 10ms, và cũng tính toán theo 1 tỉ lệ để dc từ 0 đến 504, sau khi nạp vào chip thì động cơ ko điều khiển dc, chạy lờ đờ và rất giật. Theo em nghĩ là với thời gian trích mẫu 10ms thì và với bộ dsp thì vdk thừa sức tính toán các hàm trong chtr ngắt, nên em loại bỏ nguyên nhân vdk ko đủ thời gian tính toán PID Em đọc tài liều thì thấy định dang fractional Q15 thì có giá trị từ -1.0 đến (1.0 – 2^-15) thì ở đoặn này fooPID.controlReference = Q15(ADCBUF0 >> 1) ; fooPID.measuredOutput = Q15(POSCNT * 0x0003) ; // so xung nhân với 3 thì giá tri (ADCBUF0 >> 1) và (POSCNT * 0x0003) lúc này trở thành số fractional Q15 đúng ko ah, như vậy giá trị đặt và phản hổi về nằm trong [-1;1), do đó sau 1 tính toan trong hàm PID(&fooPID) thì cho ta kết quả fooPID.controlOutput là số fractional, em nghĩ là giá trị nạp vào PDC1 là số nguyên từ 0 đên 504, nen em khai báo 1 biến int PWM_duty và cho PWM_duty=fooPID.controlOutput, để chuyển số fractional thành số int tương ứng em ví du số fractional fooPID.controlOutput= 0x4001 = 2-1 + 2-15 = 0.5 + .000030518 = 0.500030518 thì PWM_duty = 0x4001 = 214 + 20 = 16384 + 1 = 16385 em nghĩ như thế có đúng ko, nếu đúng thì chtr của em phải chạy đúng chứ đằng này động cơ lại chạy giật, Bác nào xem hộ em sai chỗ nào vơi |
![]() |
![]() |
Ðiều Chỉnh | |
Xếp Bài | |
|
|