在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<s id="cmphk"><label id="cmphk"></label></s>
    <span id="cmphk"><var id="cmphk"></var></span>
    <dfn id="cmphk"><var id="cmphk"></var></dfn>
    <menu id="cmphk"><thead id="cmphk"></thead></menu>

    <address id="cmphk"></address>

      <dfn id="cmphk"></dfn>
      
      
      <span id="cmphk"></span>

      <object id="cmphk"><tt id="cmphk"></tt></object>
      1. 新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 增量式PID的stm32實現(xiàn),整定過程

        增量式PID的stm32實現(xiàn),整定過程

        作者: 時間:2016-11-28 來源:網(wǎng)絡(luò) 收藏
      2. void TIM5_PWMINPUT_INIT(u16 arr,u16 psc)
      3. {
      4. TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;//TIM的初始化結(jié)構(gòu)體
      5. NVIC_InitTypeDef NVIC_InitStructure;//中斷配置
      6. TIM_ICInitTypeDefTIM5_ICInitStructure;//TIM4PWM配置結(jié)構(gòu)體
      7. GPIO_InitTypeDef GPIO_InitStructure;//IO口配置結(jié)構(gòu)體
      8. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);//Open TIM4 clock
      9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//open gpioB clock
      10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//GPIO 1
      11. GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;//浮空輸入 上拉輸入
      12. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      13. GPIO_Init(GPIOA, &GPIO_InitStructure);
      14. TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個更新事件裝入活動的自動重裝載寄存器周期的值
      15. TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時鐘頻率除數(shù)的預(yù)分頻值
      16. TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時鐘分割:TDTS = Tck_tim
      17. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上計數(shù)模式
      18. TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時間基數(shù)單位
      19. NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
      20. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
      21. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      22. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      23. NVIC_Init(&NVIC_InitStructure);
      24. TIM5_ICInitStructure.TIM_Channel = TIM_Channel_2;
      25. TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
      26. TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
      27. TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
      28. TIM5_ICInitStructure.TIM_ICFilter = 0x3;//Filter:過濾
      29. TIM_PWMIConfig(TIM5, &TIM5_ICInitStructure);//PWM輸入配置
      30. TIM_SelectInputTrigger(TIM5, TIM_TS_TI2FP2);//選擇有效輸入端
      31. TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);//配置為主從復(fù)位模式
      32. TIM_SelectMasterSlaveMode(TIM5, TIM_MasterSlaveMode_Enable);//啟動定時器的被動觸發(fā)
      33. TIM_ITConfig(TIM5, TIM_IT_CC2|TIM_IT_Update, ENABLE);//中斷配置
      34. TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中斷標(biāo)志位
      35. TIM_Cmd(TIM5, ENABLE);
      36. }
      37. void TIM5_IRQHandler(void)
      38. {
      39. {
      40. if (TIM_GetITStatus(TIM5, TIM_IT_CC2) != RESET)//捕獲1發(fā)生捕獲事件
      41. {
      42. duty_TIM5=TIM_GetCapture1(TIM5); //采集占空比
      43. if(TIM_GetCapture2(TIM5)>600)period_TIM5=TIM_GetCapture2(TIM5);
      44. CollectFlag_TIM5 = 0;
      45. }
      46. }
      47. TIM_ClearITPendingBit(TIM5, TIM_IT_CC2|TIM_IT_Update); //清除中斷標(biāo)志位
      48. }
      49. 復(fù)制代碼


        PID部分:
        準(zhǔn)備部分:先定義PID結(jié)構(gòu)體:
        1. typedef struct
        2. {
        3. int setpoint;//設(shè)定目標(biāo)
        4. int sum_error;//誤差累計
        5. float proportion ;//比例常數(shù)
        6. float integral ;//積分常數(shù)
        7. float derivative;//微分常數(shù)
        8. int last_error;//e[-1]
        9. int prev_error;//e[-2]
        10. }PIDtypedef;
        復(fù)制代碼

        這里注意一下成員的數(shù)據(jù)類型,依據(jù)實際需要來定的。
        在文件中定義幾個關(guān)鍵變量:
        1. floatKp =0.32; //比例常數(shù)
        2. floatTi =0.09 ; //積分時間常數(shù)
        3. float Td =0.0028 ;//微分時間常數(shù)
        4. #define T0.02 //采樣周期
        5. #define KiKp*(T/Ti)// Kp Ki Kd 三個主要參數(shù)
        6. #define KdKp*(Td/T)
        復(fù)制代碼

        C語言好像用#define 什么什么對程序不太好,各位幫忙寫個優(yōu)化辦法看看呢? 用const?

        PID.H里面主要的幾個函數(shù):
        1. void PIDperiodinit(u16 arr,u16 psc);//PID 采樣定時器設(shè)定
        2. void incPIDinit(void);//初始化,參數(shù)清零清零
        3. int incPIDcalc(PIDtypedef*PIDx,u16 nextpoint);//PID計算
        4. void PID_setpoint(PIDtypedef*PIDx,u16 setvalue);//設(shè)定 PID預(yù)期值
        5. void PID_set(float pp,float ii,float dd);//設(shè)定PIDkp ki kd三個參數(shù)
        6. void set_speed(float W1,float W2,float W3,float W4);//設(shè)定四個電機(jī)的目標(biāo)轉(zhuǎn)速
        復(fù)制代碼


        PID處理過程:
        岔開一下:這里我控制的是電機(jī)的轉(zhuǎn)速w,實際上電機(jī)的反饋波形的頻率f、電機(jī)轉(zhuǎn)速w、控制信號PWM的占空比a三者是大致線性的正比的關(guān)系,這里強(qiáng)調(diào)這個的目的是
        因為樓主在前期一直搞不懂我控制的轉(zhuǎn)速怎么和TIM4輸出的PWM的占空比聯(lián)系起來,后來想清楚里面的聯(lián)系之后通過公式把各個系數(shù)算出來了。

        正題:控制流程是這樣的,首先我設(shè)定我需要的車速(對應(yīng)四個輪子的轉(zhuǎn)速),然后PID就是開始響應(yīng)了,它先采樣電機(jī)轉(zhuǎn)速,得到偏差值E,帶入PID計算公式,得到調(diào)整量也就是最終更改了PWM的占空比,不斷調(diào)節(jié),直到轉(zhuǎn)速在穩(wěn)態(tài)的一個小范圍上下浮動。
        上面講到的“得到調(diào)整量”就是增量PID的公式:
        1. int incPIDcalc(PIDtypedef *PIDx,u16 nextpoint)
        2. {
        3. int iError,iincpid;
        4. iError=PIDx->setpoint-nextpoint;//當(dāng)前誤差
        5. iincpid=//增量計算
        6. PIDx->proportion*(iError-PIDx->last_error)
        7. +PIDx->integral*iError
        8. +PIDx->derivative*(iError-2*PIDx->last_error+PIDx->prev_error);
        9. PIDx->prev_error=PIDx->last_error; //存儲誤差,便于下次計算
        10. PIDx->last_error=iError;
        11. return(iincpid) ;
        12. }
        復(fù)制代碼

        注釋掉的是第一種寫法,沒注釋的是第二種以Kp KI kd為系數(shù)的寫法,實際結(jié)果是一樣的。
        處理過程放在了TIM6,溢出周期時間就是是PID里面采樣周期(區(qū)分于反饋信號的采樣,反饋信號采樣是1M的頻率)
        相關(guān)代碼:
        1. void TIM6_IRQHandler(void)//采樣時間到,中斷處理函數(shù)
        2. {
        3. if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)//更新中斷
        4. {
        5. frequency1=1000000/period_TIM4; //通過捕獲的波形的周期算出頻率
        6. frequency2=1000000/period_TIM1;
        7. frequency3=1000000/period_TIM2;
        8. frequency4=1000000/period_TIM5;
        9. PID1.sum_error+=(incPIDcalc(&PID1,frequency1));//計算增量并累加
        10. pwm1=PID1.sum_error*4.6875 ; //pwm1 代表將要輸出PWM的占空比
        11. frequency1=0; //清零
        12. period_TIM4=0;
        13. PID2.sum_error+=(incPIDcalc(&PID2,frequency2));//計算增量并累加 Y=Y+Y
        14. pwm2=PID2.sum_error*4.6875 ; //將要輸出PWM的占空比
        15. frequency2=0;
        16. period_TIM1=0;
        17. PID3.sum_error+=(incPIDcalc(&PID3,frequency3));//常規(guī)PID控制
        18. pwm3=PID3.sum_error*4.6875 ; //將要輸出PWM的占空比
        19. frequency3=0;
        20. period_TIM2=0;
        21. PID4.sum_error+=(incPIDcalc(&PID4,frequency4));//計算增量并累加
        22. pwm4=PID4.sum_error*4.6875 ; //將要輸出PWM的占空比
        23. frequency4=0;
        24. period_TIM5=0;
        25. }
        26. TIM_SetCompare(pwm1,pwm2,pwm3,pwm4);//重新設(shè)定PWM值
        27. TIM_ClearITPendingBit(TIM6, TIM_IT_Update); //清除中斷標(biāo)志位
        28. }
        復(fù)制代碼


        上面幾個代碼是PID實現(xiàn)的關(guān)鍵部分

        整定過程:
        辦法有不少,這里用的是先KP,再TI,再TD,在微調(diào)。其他的辦法特別是有個尼古拉斯法我發(fā)現(xiàn)不適合我這個控制對象。
        先Kp,就是消除積分和微分部分的影響,這里我糾結(jié)過到底是讓Ti 等于一個很大的值讓Ki=Kp*(T/Ti)里面的KI接近零,還是直接定義KI=0,TI=0.
        然后發(fā)現(xiàn)前者沒法找到KP使系統(tǒng)震蕩的臨界值,第二個辦法可以得到預(yù)期的效果:即KP大了會產(chǎn)生震蕩,小了會讓系統(tǒng)穩(wěn)定下來,當(dāng)然這個時候是有穩(wěn)態(tài)誤差的。
        隨后把積分部分加進(jìn)去,KI=Kp*(T/Ti)這個公式用起來,并且不斷調(diào)節(jié)TI 。TI太大系統(tǒng)穩(wěn)定時間比較長。
        然后加上Kd=Kp*(Td/T),對于系統(tǒng)響應(yīng)比較滯后的情況效果好像好一些,我這里的電機(jī)反映挺快的,所以Td值很小。
        最后就是幾個參數(shù)調(diào)節(jié)一下,讓波形好看一點(diǎn)。這里的波形實際反映的是采集回來的轉(zhuǎn)速值,用STM32的DAC功能輸出和轉(zhuǎn)速對應(yīng)的電壓,用示波器采集的。
        上一頁 1 2 下一頁

        關(guān)鍵詞: 增量式PIDstm32整定過

        評論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉