不好意思再請教有關於PID程式
|
||||
---|---|---|---|---|
中級會員
|
因為我覺得我的程式流程有問題所以想請教大家
系統整體是有一個風扇馬達 吹動一個板子 使板子移動 在板子上有一個角度感測器 所以透過風扇馬達輸出的風 可以吹動板子 控制板子的角度 基本上風扇馬達跟感測器是兩個獨立的個體 由風扇馬達輸出0~12v 感測器由轉動的角度得到約0~1.2v 我們可以從風扇馬達吹出的風 在感測器上面得到相對應的關係 譬如 馬達輸出5v 得到角度為4度 此時感測器上面顯示0.3v 我是用感測器的電壓回授至AN0做AD轉換 然後控制命令是由CCP1輸出PWM給DRIVER放大至0~12V 我想請問的就是說 程式流程 我現在是這樣寫的: 我的控制命令u是介於0~1.2v 在經由轉換公式放大至0~5v 在經過放大電路至0~12v 回授電壓介於0~1.2v 我先用CCP1輸出PWM給馬達(因為馬達沒動 感測器就沒有東西) 然後感測器出現電壓 此電壓回授至AN0跟剛剛的CCP1所輸出的電壓做相加減而得到誤差量在去做PID轉換 不知道這樣的做法可行嗎? 因為我現在寫好程式不過跑出來似乎不是那樣 Attach file: (0.00 KB)
發表於: 2008/11/21 17:00
|
|||
|
Re: 請問浮點數
|
||||
---|---|---|---|---|
中級會員
|
請問如下:
把浮點部份當作整數看一樣可以用 4.3-->0x04.4C-->0000 0100.0100 1100 把沒有用到的高位元去掉,左旋5次得到 1000 1001.1000 0000 浮點部份捨棄-->1000 1001-->0x89-->PWM 如果PWM要0~255階,數值要另外轉換。 如不轉換 1.2-->0x01.33-->0000 0001.0011 0011 0010 0110.0110 0000 0010 0110-->0x26-->PWM PWM階數範圍從0x26~0x89 那如果想把他轉成PWM要0~255階 該如何下手呢??
發表於: 2008/11/5 22:26
|
|||
|
Re: 請問PID程式問題
|
||||
---|---|---|---|---|
中級會員
|
如Eigen大大所說的
那我是不是該把控制命令與回授訊號還有誤差值 甚至其他定義都改為unsigned int 來處理呢?? 另外 我覺得我有一個模糊的觀念 在控制上我可以透過書本去計算得到kp ki kd值 也知道他們是比例積分微分關係 可是我有一個想法 假設我用最簡單的p控制來說 假如我控制命令減去回授 得到的誤差為0 代表此時輸出與輸入控制相等 達到控制 我有一個疑問就是那誤差為0時 我的p控制輸出為0 那p後面的輸出不就沒有動作? 譬如說控制命令6度 回授6度 相減得到0度 代表沒有誤差 此時p控制輸出為0 那輸出怎麼還會維持在6度?? 還是說我少寫一些程式判別??
發表於: 2008/11/5 13:43
|
|||
|
Re: 請問PID程式問題
|
||||
---|---|---|---|---|
中級會員
|
我是用來控制風扇馬達的
發表於: 2008/11/5 13:06
|
|||
|
Re: 請問PID程式問題
|
||||
---|---|---|---|---|
中級會員
|
另外一提
葛大哥說用MATLAB跑出來的KP KI KD值 並不能拿來用在我的PIC16F917使用 他說KP KI KD值 只能用測試法來調了 請問有經驗的 是這樣??
發表於: 2008/11/5 11:44
|
|||
|
Re: 請問PID程式問題
|
||||
---|---|---|---|---|
中級會員
|
剛剛有打給葛先生了
與他討論完後 建議把定義都改為unsigned char格式 再做Q格式運算 請問Q格式是怎樣做?? 有沒有例子呢?? 謝謝
發表於: 2008/11/5 10:38
|
|||
|
請問浮點數
|
||||
---|---|---|---|---|
中級會員
|
請問浮點數要怎樣運算才能在8BIT的微控制器
裡面使用?? 假如4.3-1.2所得到的數字 想把他放在 PWM 做輸出 可是PWM只有二進制 沒有辦法有浮點數輸出 該怎麼做??
發表於: 2008/11/4 16:07
|
|||
|
Re: 請問PID程式問題
|
||||
---|---|---|---|---|
中級會員
|
另外有沒有人在台中附近
是否可以直接跟有經驗的一起討論 因為有點趕 如果有人也想要一起討論 請回覆 謝謝
發表於: 2008/11/4 15:06
|
|||
|
Re: 請問PID程式問題
|
||||
---|---|---|---|---|
中級會員
|
#include <pic.h>
#include <pic16f91x.h> // for kp float kp; float command; float feedback; float error; //command - feedback float last_error; //上一次的誤差 bit signkp; float error_temp; float kp_temp; //for kd float error_difference; float last_error; bit signkd; float error_difference_temp; float kd_temp; float kd; //for ki float error_integral; bit signki; float error_integral_temp; float ki_temp; float ki; //for pwm float u; void delay5000(void) {unsigned int t; t=5000; while(--t); } void delay(unsigned char t) { while(--t); } void init_a2d(void) { INTCON = 0x00; OPTION = 0x80; //禁止PROTB上拉致能 OSCCON = 0x61; //選擇內部振盪器作時脈4MHz LCDCON = 0x00; //把LCD模組關閉 TMR2IF = 0; CCP2IF = 0; TMR2IE = 0; CCP2IE = 0; TMR2 = 0X00; CCP1CON = 0X00; //關閉CCP1 MODULE T2CON = 0X00; PR2 = 0XFF; ANSEL = 0x03; TRISA = 0X1F; PORTA = 0xFF; PORTC = 0xFF; TRISC = 0x00; GIE = 0; } void AD_Get(void) //讀ANO AN1值 { ADCON0= 0x00; // AN0 VDD VSS 右對稱 ADCON1= 0x10; // 轉換時脈2us ADON=1; // 打開AD delay(20); GODONE = 1; while(GODONE); CCP1CON = 0x0C; command = ADRESH; CCPR1L = command; T2CON = 0X05; } void an1_get() { ADCON0= 0x00; // AN1 VDD VSS 右對稱 ADCON1= 0x10; // 轉換時脈2us ADON=1; // 打開AD CHS0 = 1; CHS1 = 0; CHS2 = 0; delay(20); GODONE = 1; while(GODONE); feedback = ADRESH; } void kp_set(void) { kp = 0.5441; error = command - feedback; if(error<0) { signkp = 1; error_temp = -error; //command - feedback 為負 } else { signkp = 0; error_temp = error; //command - feedback 為正 } kp_temp = kp*error_temp; } void kd_set(void) { error_difference = error - last_error; //這週期的error減上週期的error if(error_difference<0) { signkd = 1; error_difference_temp = -error_difference; //error_difference = error - last_error 為負 } else { signkd = 0; error_difference_temp = error_difference; //error_difference = error - last_error 為正 } kd_temp = kd*error_difference_temp; last_error = error; } void ki_set(void) { ki = 0.22314; error_integral = error_integral - error; if(error_integral<0) { signki = 1; error_integral_temp = -error_integral; //error_difference = error - last_error 為負 } else { signki = 0; error_integral_temp = error_integral; //error_difference = error - last_error 為正 } ki_temp = ki*error_integral_temp; } void pwm_out(void) { //u = kp_temp+kd_temp+ki_temp; u = kp_temp+ki_temp; CCP1CON = 0x0C; CCPR1L = u; T2CON = 0x05; } void main(void) { init_a2d(); while(1) { AD_Get(); an1_get(); kp_set(); //kd_set(); ki_set(); pwm_out(); } } 附上程式 感謝各位
發表於: 2008/11/4 11:50
|
|||
|