![]() |
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> Code:
/* Dat PID Data Structure voi ten fooPID */ 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 |
ai giúp em với,
|
Code:
fooPID.controlReference = Q15(ADCBUF0 >> 1) ; // controlReference la dai luong dat Code:
#define Q15(X) \ Macro này dùng chuyển từ số thực dấu chấm động (float, double), hoặc hằng số trong khoảng từ -1 đến 1 - 2^(-15) sang Q15. Mình ko hiểu tại sao bạn lại gọi Code:
fooPID.controlReference = Q15(ADCBUF0 >> 1) ; // controlReference la dai luong dat Bạn nên bỏ cái Q15 đi. |
Em đã bỏ Q15 đi mà kết quả vẫn thế
đoặn này của mình là như thế này Code:
fooPID.controlReference = Q15(ADCBUF0 >> 1) ; // controlReference la dai luong dat em tính toán thế này: Giá trị đặt từ 0 đến 504 ưng với tốc độ từ 0 đến 20 vong/s ứng với từ 0 đến 168 xung/10ms vậy là số xung đọc về từ encoder sau 10ms (thời gian trich mẫu = 10ms) , phải nhân với 504/168 = 3 là POSCNT*3 (đây cũng là giá trị nguyên). Có phải bây h em cần chuyển ADCBUF0 >> 1 và POSCNT*3 thành số frac, sau kết quả tính toán ở hàm PID(&fooPID); thì được kết quả fooPID.controlOutput là số frac khi đó để đưa vào PDC1 thì mình phải chuyển lại fooPID.controlOutput từ frac sang int hả bác. Nếu đúng như thế thì bác có thể chỉ cho em cách chuyển từ int sang frac và ngc lại đuọc ko. hay ở đây có 1 cách giải quyết khác. Mong các bác giúp thằng em với |
Bạn đừng quan tâm tới Q15 hay frac, trình dịch coi nó là số nguyên cả.
Ở code mẫu có thể coi như gần đúng là tất cả các hệ số Kp, Kd, Ki của nó được nhân với 2^15, khi đó thay vì làm việc với các số trong khoảng (-1, 0.9999) nó làm việc với các số từ -32768 đến 32767. Giá trị tham khảo (ref), và giá trị lấy mẫu (e) của bạn ko nằm trong vùng (-1, 0.9999) nên bạn ko thể dùng Q15(ref) hoặc Q15(e). Theo như cách tính của bạn, ADC 10bit Giá trị ref maximum = 9bit = 511. Với thời gian lấy mẫu là 10ms điều này có nghĩa là bạn yêu cầu motor quay 511 hoặc 511/2 hoặc 511/4 xung encoder trong 10ms (tùy cấu hình bộ QEI, mình ko rành QEI của dsPIC) hay 511, 255.5, 127.75 vòng/giây nếu encoder 100 xung! Thực hiện điều khiển vận tốc đc bằng PID khá đơn giản, hoàn toàn có thể dùng 16F877A để thực hiện với thời gian lấy mẫu 10ms. Bạn nên tự viết code, đọc/sửa code mẫu có khi còn lâu hơn tự viết. Bạn nên tham khảo về PID ở đây http://www.picvietnam.com/forum/showthread.php?t=485 |
Trích:
|
Trích:
Áp dụng công thức của Q15 vào đây: Code:
kCoeffs[0] = Q15(0.7); |
Trích:
Cám ơn bác |
bác giúp em với, làm sao để kết quả fooPID.controlOutput nhận được là 1 số integer để đưa vào thanh ghi PDC1
|
nếu ADCBUF0 >> 1 của em là 0x01F8 là 504
và POSCNT là 124 xung/10ms (0x007C xung/10ms) ==> POSCNT*0x0003 = 327 ( 0x0174) vậy ControlHistory[n] = fooPID.controlReference - fooPID.measuredOutput = 0x01F8 - 0x0174 = 0x0084 = 132 ControlHistory[n] là số frac thì kết quả như này có đúng ko EM giả sử controlOutput[n] = controlHistory[n] * abcCoefficient[0] (coi các hệ số khác = 0) khi đó controlHistory[n] là số frac nhân với abcCoefficient[0] là số Q15 ví dụ abcCoefficient[0] = 0,7 controlOutput[n] là số frac khi đó controlOutput[n] = 0x0084 * 0,7 thì ra dạng số j, có phải là số frac ko, và nó có giá trị bằng bao nhiêu, em muốn chuyển sang số int để đưa vào thanh ghi PDC1 thì làm thế nào. còn số abcCoefficient[0] là số Q15 thì em muốn khai báo 1 số lơn hơn 1 thì làm thế nào Mong các bác nhiệt tình giúp em với, em đang bị bí phần này quá |
Ko ai giúp em với ah, bác nào biết thì chỉ giúp em 1 cái
|
Em đơi mãi mà ko có bác nào giúp em với, bác nào biết xin chỉ cho thằng em 1 đường,
Bác namqn ơi, bác giúp em với Help me |
Múi giờ GMT. Hiện tại là 10:40 AM. |
Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam