久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6642|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

PID控制 卡爾曼濾波設(shè)計(jì)實(shí)現(xiàn)STM32單片機(jī)自平衡小車設(shè)計(jì)源碼

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:365793 發(fā)表于 2018-7-5 18:30 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
基于單片機(jī)平衡車設(shè)置
PID控制  卡爾曼濾波設(shè)計(jì)實(shí)現(xiàn)自平衡小車設(shè)計(jì)

單片機(jī)源程序如下:
  1. #include "sys.h"
  2. #include "usart.h"               
  3. //#include "delay.h"        

  4. // 編碼器:100線;電機(jī)減速比:150

  5. #include "ofme_led.h"


  6. #include "ofme_filter.h"
  7. #include "ofme_iic.h"
  8. #include "ofme_iic_dev.h"
  9. #include "ofme_pwm.h"
  10. #include "ofme_pid.h"
  11. #include "ofme_encoder.h"
  12. #include "ofme_io.h"
  13. #include "ofme_time.h"
  14. #include "ofme_ir_nec.h"

  15. #define PI (3.14159265)
  16. // 度數(shù)表示的角速度*1000
  17. #define MDPS (70)
  18. // 弧度表示的角速度
  19. #define RADPS ((float)MDPS*PI/180000)
  20. // 每個(gè)查詢周期改變的角度
  21. #define RADPT (RADPS/(-100))


  22. // 平衡的角度范圍;+-60度(由于角度計(jì)算采用一階展開,實(shí)際值約為46度)
  23. #define ANGLE_RANGE_MAX (60*PI/180)
  24. #define ANGLE_RANGE_MIN (-60*PI/180)

  25. // 全局變量
  26. pid_s sPID;                                        // PID控制參數(shù)結(jié)構(gòu)體
  27. float radian_filted=0;                // 濾波后的弧度
  28. accelerometer_s acc;                // 加速度結(jié)構(gòu)體,包含3維變量
  29. gyroscope_s gyr;                        // 角速度結(jié)構(gòu)體,包含3維變量
  30. int speed=0, distance=0;        // 小車移動(dòng)的速度,距離
  31. int tick_flag = 0;                        // 定時(shí)中斷標(biāo)志
  32. int pwm_speed = 0;                        // 電機(jī)pwm控制的偏置值,兩個(gè)電機(jī)的大小、正負(fù)相同,使小車以一定的速度前進(jìn)
  33. int pwm_turn = 0;                        // 電機(jī)pwm控制的差異值,兩個(gè)電機(jī)的大小相同,正負(fù)相反,使小車左、右轉(zhuǎn)向
  34. float angle_balance = 0;        // 小車的平衡角度。由于小車重心的偏移,小車的平衡角度不一定是radian_filted為零的時(shí)候


  35. // 定時(shí)器周期中斷,10ms
  36. void sys_tick_proc(void)
  37. {
  38.         static unsigned int i = 0;

  39.         tick_flag++;

  40.         i++;
  41.         if(i>=100) i=0;

  42.         if(i==0)                   // 綠燈的閃爍周期為1秒
  43.         {
  44.                 LED1_OFF();
  45.         }
  46.         else if(i==50)
  47.         {
  48.                 LED1_ON();
  49.         }
  50. }

  51. void control_proc(void)
  52. {
  53.         int i = ir_key_proc(); // 將紅外接收到的按鍵值,轉(zhuǎn)換為小車控制的相應(yīng)按鍵值。

  54.         switch(i)
  55.         {
  56.                 case KEY_TURN_LEFT:
  57.                         if(pwm_turn<500) pwm_turn += 50;
  58.                         break;
  59.                 case KEY_TURN_RIGHT:
  60.                         if(pwm_turn>-500) pwm_turn -= 50;
  61.                         break;
  62.                 case KEY_TURN_STOP:
  63.                         pwm_turn = 0;
  64.                         distance = 0;
  65.                         pwm_speed = 0;
  66.                         break;
  67.                 case KEY_SPEED_UP:
  68.                         if(pwm_speed<500) pwm_speed+=100;
  69.                         break;
  70.                 case KEY_SPEED_DOWN:
  71.                         if(pwm_speed>-500) pwm_speed-=100;
  72.                         break;
  73.                 case KEY_SPEED_0:
  74.                         pwm_speed = 0;
  75.                         break;
  76.                 case KEY_SPEED_F1:
  77.                         pwm_speed = 150;
  78.                         break;
  79.                 case KEY_SPEED_F2:
  80.                         pwm_speed = 300;
  81.                         break;
  82.                 case KEY_SPEED_F3:
  83.                         pwm_speed = 450;
  84.                         break;
  85.                 case KEY_SPEED_F4:
  86.                         pwm_speed = 600;
  87.                         break;
  88.                 case KEY_SPEED_F5:
  89.                         pwm_speed = 750;
  90.                         break;
  91.                 case KEY_SPEED_F6:
  92.                         pwm_speed = 900;
  93.                         break;
  94.                 case KEY_SPEED_B1:
  95.                         pwm_speed = -150;
  96.                 case KEY_SPEED_B2:
  97.                         pwm_speed = -300;
  98.                 case KEY_SPEED_B3:
  99.                         pwm_speed = -450;
  100.                         break;
  101.                 default:
  102.                         break;
  103.         }

  104.         pwm_turn *= 0.9;        // pwm_turn的值以0.9的比例衰減,使小車在接收到一個(gè)轉(zhuǎn)向信號后只轉(zhuǎn)動(dòng)一定的時(shí)間后停止轉(zhuǎn)動(dòng)。


  105.         speed = speed*0.7 +0.3*(encoder_read());        // 定周期(10ms)讀取編碼器數(shù)值得到實(shí)時(shí)速度,再對速度進(jìn)行平滑濾波
  106.          if(speed!=0)
  107.         {
  108.                 printf("speed: %d, dst: %d, pwm: %d \r\n", speed,distance,(int)(speed*6+distance*0.1));
  109.         }



  110.         encoder_write(0);                                                        // 編碼器值重新設(shè)為0

  111.         distance += speed;                                                        // 對速度進(jìn)行積分,得到移動(dòng)距離

  112.         if(distance>6000) distance = 6000;                        // 減少小車懸空、空轉(zhuǎn)對控制的影響
  113.         else if(distance<-6000) distance = -6000;

  114. }

  115. void balance_proc(void)
  116. {
  117.         static unsigned int err_cnt=0;

  118. //        float tFloat;
  119.         int pwm_balance;
  120. //        static float angle;
  121. //        float angle_t;
  122.         float radian, radian_pt;          // 當(dāng)前弧度及弧度的微分(角速度,角度值用弧度表示)

  123.         adxl345_read(&acc);                        // 讀取當(dāng)前加速度。由于傳感器按照的位置原因,傳感器的值在函數(shù)內(nèi)部經(jīng)過處理,變?yōu)樾≤嚨奶摂M坐標(biāo)系。
  124.         l3g4200d_read(&gyr);                // 讀取當(dāng)前角速度。同樣經(jīng)過坐標(biāo)系變換。


  125. // 此段程序用于傳感器出錯(cuò)時(shí)停止小車
  126.         err_cnt = err_cnt*115>>7;        // err_cnt以0.9的比例系數(shù)衰減(115>>7的值約為0.9,避免浮點(diǎn)數(shù),提高速度)
  127.         if(acc.flag != 0x0F || gyr.flag != 0x0F)   // 讀取的角度、角速度值有誤?赡苁请姶鸥蓴_、iic線太長等導(dǎo)致出錯(cuò)。
  128.         {
  129.                 LED0_ON();                // 亮紅燈
  130.                 err_cnt +=100;        // 等比數(shù)列,比例系數(shù)0.9(115>>7),常數(shù)項(xiàng)100;根據(jù)公式,連續(xù)10項(xiàng)的和約為657
  131.                 if(err_cnt>657) goto err;        // 當(dāng)連續(xù)發(fā)生約10次(約0.1秒)錯(cuò)誤則超過657而溢出。
  132.         }


  133. // 此段程序用于倒立或失重時(shí)停止小車
  134.         if(acc.z<=0)
  135.         {
  136.                 goto err;
  137.         }


  138. // 小車的虛擬x軸方向?yàn)樾≤嚽斑M(jìn)方向,虛擬y軸為小車左邊,虛擬z軸為小車上升方向。
  139. // 前傾角度為負(fù),后傾角度為正。
  140.         // 通過計(jì)算加速度分量,得到小車傾斜弧度(未濾波)
  141.         radian = (float)(acc.x)/acc.z;        //  一階展開:Q =f(x)=x-x^3/3+x^5/5+...+(-1)^k*x^(2k+1)/(2k+1)+...
  142.         // 通過角速度傳感器,得到小車的角速度(單位為 弧度/秒)
  143.         radian_pt = gyr.y*RADPT;
  144.         radian_filted = ofme_filter(radian_filted, radian, radian_pt);                // 互補(bǔ)濾波得到小車的傾斜角度

  145. // 此段程序用于小車傾斜角度過大時(shí),停止小車
  146.         if(radian_filted> ANGLE_RANGE_MAX || radian_filted<ANGLE_RANGE_MIN)
  147.         {
  148.                 goto err;
  149.         }

  150. // 通過PID計(jì)算,得到保持小車角度為零所需要的電機(jī)pwm輸出
  151.         pwm_balance = pid_proc(&sPID, radian_filted, radian_pt);
  152.         //        printf("%d\r\n",speed);
  153. // 通過小車移動(dòng)速度與移動(dòng)距離,調(diào)整小車平衡所需的pwm輸出
  154.         pwm_balance += (speed*6+distance*0.1);

  155. // 在pwm_balance的基礎(chǔ)上,加上速度分量與轉(zhuǎn)動(dòng)分量,調(diào)整小車兩個(gè)電機(jī)的轉(zhuǎn)速。
  156.         pwm_control(pwm_balance+pwm_speed+pwm_turn, pwm_balance+pwm_speed-pwm_turn);

  157. // 如果pwm超出有效值,紅燈亮。用于調(diào)試,了解系統(tǒng)狀態(tài)。
  158.         if(pwm_balance>=1000||pwm_balance<=-1000) LED1_ON();
  159.         LED0_OFF();
  160.         return;
  161. err:
  162.         puts("balance error.\r\n");
  163.         pwm_control(0, 0);                                   // 關(guān)閉電機(jī)
  164.         return;
  165. }


  166. int main(void)
  167. {
  168. //        int i=0, t;
  169. //        int pwm;
  170. //        float radian, radian_pt;

  171.           Stm32_Clock_Init(9);//系統(tǒng)時(shí)鐘設(shè)置
  172.         uart_init(72,57600); //串口1初始化   
  173.         hw_tick_start();   // 定時(shí)器周期性中斷,用于提供系統(tǒng)脈搏
  174. ////////////////////////////////////////////////////////////////////////////////
  175.         led_init();
  176.         pwm_init();
  177.         iic_init();
  178.         adxl345_init(&acc);
  179.         l3g4200d_init(&gyr);
  180.         hw_ir_init();
  181.         encoder_init();
  182.         while(0)
  183.         {
  184.                 if(tick_flag>100)
  185.                 {
  186.                         tick_flag = 0;
  187.                         printf("count: %d\r\n",encoder_read());

  188.                 }
  189.         }



  190. ////////////////////////////////////////////////////////////////////////////////
  191. //        pid_init(&sPID, 4500,0,-300);6000--350        ;8000--350;11000--350;
  192. //        pid_init(&sPID, 6000,0,-35000);
  193.         pid_init(&sPID, 7500,0,-35000);          // 調(diào)節(jié)PID參數(shù),后3個(gè)形參分別為:比例系數(shù)P,積分系數(shù)I,微分系數(shù)D
  194.         sPID.target = -3.5*PI/180;

  195.         radian_filted = 0;
  196.         adxl345_init(&acc);
  197.         l3g4200d_init(&gyr);
  198.         while(1)
  199.         {
  200.                 if(tick_flag)
  201.                 {
  202.                         tick_flag = 0;
  203.                         balance_proc();        // 調(diào)節(jié)小車,保持平衡
  204.                         control_proc();        // 根據(jù)遙控接收到的數(shù)據(jù),調(diào)整電機(jī)輸出參數(shù)
  205.                 }
  206.         }
  207. }

復(fù)制代碼

所有資料51hei提供下載:
balance-20130511.rar (287.53 KB, 下載次數(shù): 102)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:404223 發(fā)表于 2019-1-18 19:54 | 只看該作者
下來看看,怎么樣
回復(fù)

使用道具 舉報(bào)

板凳
ID:474952 發(fā)表于 2019-2-4 15:20 | 只看該作者
終于找了pid算法來穩(wěn)定電機(jī)在某個(gè)位置,帖子很棒,研究研究
回復(fù)

使用道具 舉報(bào)

地板
ID:437392 發(fā)表于 2019-2-20 22:08 | 只看該作者
十分不錯(cuò).
回復(fù)

使用道具 舉報(bào)

5#
ID:745708 發(fā)表于 2020-5-6 23:46 | 只看該作者
哥,你的程序有的行沒有程序,是空的 為什么
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久久精品久久 | 中文字幕一区二区三区精彩视频 | 婷婷中文字幕 | 国产黄色一级电影 | 日韩一区二区精品 | 国产精品一区二区久久精品爱微奶 | 国产精品三级 | 亚洲精品大片 | 久久久久国产精品 | 成人国产精品色哟哟 | 精品国产欧美一区二区三区成人 | 羞羞视频在线观看网站 | 国产欧美日韩一区 | 欧美一区二区激情三区 | 自拍偷拍中文字幕 | www.久久.com | 久久精品视频在线免费观看 | 91精品91久久久 | 日韩福利在线 | 一区二区三区日韩精品 | 国产中文 | 国产福利在线 | 在线视频 亚洲 | 欧美成人激情 | av电影手机在线看 | 日韩精品一区二区三区在线观看 | 天天爽夜夜操 | 国产免费视频 | 亚洲免费毛片 | 国产一区二区在线免费观看 | 国产精品免费一区二区三区 | 国产一级精品毛片 | 成年人视频免费在线观看 | 一区二区三区不卡视频 | 国产精品视频久久 | 国产亚洲精品久久久久久牛牛 | 在线看免费的a | 在线激情视频 | 国产综合精品一区二区三区 | 免费在线国产视频 | 97久久国产|