找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8179|回復: 3
打印 上一主題 下一主題
收起左側

龍邱自平衡車清華方案自由滑行版(直立行走)源碼

[復制鏈接]
跳轉到指定樓層
樓主
ID:287806 發(fā)表于 2018-4-21 18:11 | 只看該作者 |只看大圖 回帖獎勵 |正序瀏覽 |閱讀模式
實物圖:

平衡車單片機源程序如下:
  1. /*
  2. **********************************************************
  3. 飛思卡爾智能車程序  直立行走例程
  4. 北京龍丘智能科技      
  5. Designed by longqiu
  6. E-mail:chiusir@yahoo.cn
  7. 軟件版本:V1.2
  8. ------------------------------------
  9. Code Warrior 5.1
  10. Target : MC9S12XS128
  11. Crystal: 16.000Mhz
  12. busclock:40.000MHz
  13. pllclock:80.000MHz
  14. ------------------------------------  
  15. 程序使用說明:  
  16. 該工程里寫出電磁組直立行走的參考方案,通過程序可以實現(xiàn)小車自由滑行。
  17. ==========================================================   
  18. 陀螺儀模塊電路說明:   
  19. 角度計算采用清華硬件電路,詳見40.pdf(電磁組直立行車參考設計方案20.pdf)
  20. 第54頁,圖3-23.一個運算放大器實現(xiàn)角度計算   
  21. ==========================================================
  22. 接線說明
  23. 清華版陀螺儀放置的時候,記得ENC-03在下,加速度在上
  24. 放置方向跟電機的接線也有關系的。  
  25. -----------------------------------------
  26. 單片機  | 龍邱陀螺儀模塊 |
  27. --------+----------------+---------------
  28. AD0     |  gyro角速度    |
  29. AD1     |  ang角度       |
  30. =========================================
  31. 單片機  |  電機驅(qū)動模塊  |  車模電機
  32. --------+----------------+---------------
  33. PP7     |  IN4     OUT1  |  右邊電機正
  34. PB1     |  IN3     OUT2  |  右邊電機負
  35. PB0     |  IN2     OUT3  |  左邊電機正
  36. PP3     |  IN1     OUT4  |  左邊電機負   
  37. 單片機5V|  Vmcu          |
  38. ===========================================================

  39. 調(diào)整步驟:
  40. 1.下載程序到單片機,
  41. 2.進入在線調(diào)試狀態(tài),
  42. 3.把車豎直立起來達到平衡狀態(tài),在線查看寄存器數(shù)值
  43.    根據(jù)平衡狀態(tài)下的ANG,確定ANG_center數(shù)值
  44.    根據(jù)平衡狀態(tài)下的GYRO,確定GYRO_center數(shù)值
  45. 4.中心數(shù)值確定后,再調(diào)整PD參數(shù)
  46.     P系數(shù)相當于倒立擺的回復力。這個參數(shù)應該大于重力加速度的等效數(shù)值車模才能夠保持直立。
  47.     隨著該參數(shù)逐步增大,車模開始能夠保持直立。進一步增大該參數(shù)會引起車模震蕩。
  48.     D系數(shù)相當于倒立擺的阻尼力。該參數(shù)可以有效抑制車模的的震蕩。當該參數(shù)過大的時候,車模開始抖動。

  49.     D系數(shù),先令D=0,然后逐步增加P,直到車模發(fā)生震蕩,再增加D消除震蕩,直到車模開始抖動;
  50.     然后增加P,消除抖動;
  51. 5.反復幾次后就可以找到適當?shù)腜,D。
  52. 6.小車基本平衡后用戶可以根據(jù)需要添加速度控制和尋線算法,比賽的重點就在這里,各盡其能!

  53. ==========================================================                                                                        

  54. ***********************************************************
  55. */
  56. #include <hidef.h>         
  57. #include "derivative.h"   

  58. #define PWM_DIR0  PORTB_PB0   //電機方向控制
  59. #define PWM_DIR1  PORTB_PB1   //電機方向控制

  60. word AD_CAIJI[2]={0,0};         //采集的AD數(shù)值臨時存放數(shù)組
  61. word AD_QIUHE[2]={0,0};         //求和臨時存放數(shù)組
  62. word AD_JUNZHI[2]={0,0};        //平均值
  63. volatile byte PIT_CNT=0;        //中斷計數(shù)
  64. volatile int  ANG=0;            //角度,前傾變大,后傾變小,平衡時候ANG_center =
  65. volatile int  GYRO=0;           //角速度,前傾變小,后傾變大,靜止時候為GYRO_center=?

  66. volatile int  PID1_P=15;         //P系數(shù),pwm3   
  67. volatile int  PID1_D=6;          //D系數(shù),pwm3
  68. volatile int  PID2_P=15;         //P系數(shù),pwm7
  69. volatile int  PID2_D=6;          //D系數(shù),pwm7
  70. volatile int  ANG_center =319;  //AD的初始值,每個模塊數(shù)值都不一樣,跟換模塊需要重新確定該值
  71. volatile int  GYRO_center=367;  //角速度初始值,電機不動時候靜止狀態(tài)下采集的數(shù)值
  72. volatile int  AD_number=20;     //求和數(shù)量
  73. volatile word DTY1=0;            //臨時變量
  74. volatile word DTY2=0;            //臨時變量
  75. volatile word DTYMAX=245;       //PWM占空比最大值

  76. #define FDOWN 253               //前向倒下時的角度數(shù)值
  77. #define BDOWN 190               //后向倒下

  78. void Delay_us(word x)
  79. {
  80.   byte i = 0,j = 0;
  81.         while(x--)
  82.         {
  83.           for(i=0;i<20;i++)
  84.             for(j=0;j<2;j++);         
  85.         }
  86.         return;
  87. }
  88. void Delay_ms(word x)
  89. {
  90.   byte i = 0,j = 0;
  91.         while(x--)
  92.         {
  93.           for(i=0;i<200;i++)
  94.             for(j=0;j<200;j++);         
  95.         }
  96.         return;           
  97. }

  98. /****************************初始化設備**************************************/
  99. void fAD_Init(void)
  100. {
  101.     ATD0CTL1=0b00100000;//   10 位精度
  102.     ATD0CTL2=0b01000000;//   禁止外部觸發(fā),標志位快速清零,中斷禁止
  103.     ATD0CTL3=0b10100000;/*   7;右對齊無符號;
  104.                              6~3:轉換序列長度為4;
  105.                              No FIFO模式,Freeze模式下繼續(xù)轉換?  */
  106.     ATD0CTL4=0b00000111;//   4AD采樣周期,ATDClock=[BusClock*0.5]/[PRS+1]  ; PRS=15, divider=32 ?
  107.     ATD0CTL5=0b00110000;//   特殊通道禁止,多通道采樣,掃描模式連續(xù)采樣,開始為 AN0
  108.     ATD0DIEN=0b00000000;//   禁止數(shù)字輸入   
  109.     return;
  110. }
  111. //-----PWM初始化程序------//
  112. void fPWM_Init(void)
  113. {
  114.     PWME=0x00;        /* 禁止PWM輸出*/
  115.     PWMCTL=0x00;      //通道不級聯(lián)
  116.     PWMCAE=0X00;      //0左對齊 1中心對齊
  117.     PWMPRCLK=0X11;    //2分頻
  118.     PWMCLK=0XFF;      /*時鐘選擇寄存器,  0選擇ClockX 1選擇ClockSX.
  119.                       通道0,1,4,5用ClockA或ClockSA,通道2,3,6,7用ClockB或ClockSB   
  120.                       設置后,0、1用ClockA,4、5用ClockSA,2、3用ClockB,6、7用ClockSB   */
  121.     PWMSCLA=50;       //ClockSA=ClockA/(2*PWMSCLA)=20000k/(2*50)=200KHZ
  122.     PWMSCLB=5;        //ClockSB=ClockA/(2*PWMSCLB)=20000k/(2*5)=2MHZ
  123.     PWMPOL=0X00;      //輸出極性選擇 0起始為低電平 1起始為高電平
  124.       
  125.     PWMPER1=250;      //200KHZ/250=800HZ  
  126.     PWMDTY1=100;      /*左對齊,起始輸出為高電平時,占空比=(PWMDTY3+1)/(PWMPER0+1) */  
  127.   
  128.     PWMPER3=250;      //2M/250=8KHZ                             
  129.     PWMDTY3=0;        /*左對齊,起始輸出為高電平時,占空比=(PWMDTY3+1)/(PWMPER0+1) */   
  130.     PWMPER7=250;                                   
  131.     PWMDTY7=0;      

  132.     PWME_PWME1=0;     //啟動PWM輸出
  133.     PWME_PWME3=1;
  134.     PWME_PWME7=1;  
  135.     return;
  136. }

  137. void SetBusCLK_40M(void)
  138. {   
  139.     CLKSEL=0X00;                                //disengage PLL to system
  140.     PLLCTL_PLLON=1;                        //turn on PLL
  141.     SYNR =0xc0 | 0x04;                        
  142.     REFDV=0x80 | 0x01;
  143.     POSTDIV=0x00;       //pllclock=2*osc*(1+SYNR)/(1+REFDV)=80MHz;
  144.     _asm(nop);          //BUS CLOCK=40M
  145.     _asm(nop);
  146.     while(!(CRGFLG_LOCK==1));          //when pll is steady ,then use it;
  147.     CLKSEL_PLLSEL =1;                        //engage PLL to system;
  148. }
  149. void fDEV_Init()
  150. {        
  151.           SetBusCLK_40M();
  152.           fAD_Init();
  153.     fPWM_Init();  
  154.     return;
  155. }  

  156. /***************     定時器函數(shù)1ms     *****/   
  157. void fPIT_Init(void)   //定時中斷初始化函數(shù) 1MS定時中斷設置
  158. {
  159.     PITCFLMT_PITE=0; //定時中斷通道關     
  160.     PITCE_PCE0=1;    //定時器通道 0使能  定時1ms用
  161.     PITMUX_PMUX0=1;  //定時器通道 0選擇8位計數(shù)器1
  162.     PITMTLD1=40-1;   //8位計數(shù)器0初值設定。40分頻,在 40MHzBusClock下,為 1MHz。即 1us.
  163.     PITLD0=1000-1;   //16位計數(shù)器初值設定。1000*1us=1ms
  164.     PITINTE_PINTE0=1;//開中斷,定時器中斷通道 0中斷使能   
  165.     PITCFLMT_PITE=1; //定時器通道使能
  166.     return;
  167. }

  168. void fAD_CAIJI(unsigned int *AD_val)    //AD采集兩個通道
  169. {
  170.           while(!ATD0STAT2_CCF0);//0通道轉換完成前等待,采集角速度
  171.           *AD_val=ATD0DR0;
  172.           AD_val++;
  173.           while(!ATD0STAT2_CCF1);//1通道轉換完成前等待,采集角度
  174.           *AD_val=ATD0DR1;           
  175.           return;
  176. }

  177. void fAD_QIUHE(void)
  178. {
  179.     word i;
  180.    
  181.    
  182.     for(i=0;i<AD_number;i++)
  183.       {
  184.         fAD_CAIJI(AD_CAIJI);                                            
  185.         AD_QIUHE[0]+=AD_CAIJI[0];     //獲取AD0通道值的20次和
  186.         AD_QIUHE[1]+=AD_CAIJI[1];     //獲取AD1通道值的20次和
  187.       }
  188.     return;   
  189. }   

  190. void fAD_QIUJUNZHI()                  //求平均值
  191. {
  192.     AD_JUNZHI[0]=(word)AD_QIUHE[0]/AD_number;
  193.     AD_JUNZHI[1]=(word)AD_QIUHE[1]/AD_number;
  194.     AD_QIUHE[0]=0;                     
  195.     AD_QIUHE[1]=0;
  196.     return;   
  197. }
  198.                                                      
  199. void fPWM_KONGZHI(void)               //電機控制
  200. {   
  201.     GYRO=AD_JUNZHI[0];                //求得角速度                                       
  202.     ANG =AD_JUNZHI[1];                //求得角度
  203.     /***********************正轉****************/
  204.     //角度,前傾變大,后傾變小,平衡時候ANG_center
  205.     /*
  206.     //摔倒處理
  207.     if ((ANG > FDOWN)|| (ANG < BDOWN) )
  208.     {
  209.         PWM_DIR0=1;            
  210.         PWM_DIR1=1;
  211.         PWMDTY7=PWMDTY3=0;
  212.         PWMPOL=0X00;
  213.         return;
  214.     } */
  215.     if (ANG > ANG_center)            
  216.     {   //   fAD_QIUJUNZHI();            
  217.         DTY1=((ANG - ANG_center ) * PID1_P + (GYRO_center-GYRO) / PID1_D);
  218.         DTY2=((ANG - ANG_center ) * PID2_P + (GYRO_center-GYRO) / PID2_D);     
  219.         if(DTY1>=DTYMAX) DTY1=DTYMAX;
  220.         if(DTY2>=DTYMAX) DTY2=DTYMAX;  
  221.         PWM_DIR0=1;            
  222.         PWM_DIR1=1;
  223.         PWMDTY3=(byte)DTY1;
  224.         PWMDTY7=(byte)DTY2;
  225.         
  226.         PWMPOL=0X00;      //輸出極性選擇 0起始為低電平 1起始為高電平        
  227.     }   
  228.     //Delay_us(5);        
  229.     /**********************反轉***************/
  230.     else if (ANG<ANG_center)              
  231.     {
  232.         DTY1=(( ANG_center - ANG ) * PID1_P + (GYRO - GYRO_center) / PID1_D );
  233.         DTY2=(( ANG_center - ANG ) * PID2_P + (GYRO - GYRO_center) / PID2_D );                        
  234.         if(DTY1>=DTYMAX) DTY1=DTYMAX;   
  235.         if(DTY2>=DTYMAX) DTY2=DTYMAX;         
  236.         PWM_DIR0=0;
  237.         PWM_DIR1=0;
  238.         PWMDTY3=(byte)DTY1;
  239.         PWMDTY7=(byte)DTY2;
  240.                PWMPOL=0Xff;               
  241.     }
  242.     return;   
  243. }

  244. void main(void)
  245. {
  246.     byte key=0;
  247.    
  248.     DDRA=0xFF;
  249.     PORTA=0x00;
  250.     DDRB=0XFF;
  251.     PORTB=0X00;  
  252.     DDRE=0;
  253.     fDEV_Init();
  254.     key=PORTE;
  255.     PWME_PWME1=1;     //啟動PWM輸出
  256.     //while(key==PORTE){//按下E口任意按鍵,退出自標定角度的初始值,蜂鳴器停止響
  257.         //fAD_QIUJUNZHI();      
  258.         //ANG_center=AD_JUNZHI[1]; //求得角度初始值
  259.         Delay_ms(5);
  260.     //}
  261.     PWME_PWME1=0;     //關閉PWM輸出
  262.     fPIT_Init();
  263.     EnableInterrupts;                     
  264.     for(;;)
  265.     {
  266.    
  267.     }
  268. }   

  269. #pragma CODE_SEG __NEAR_SEG NON_BANKED
  270. //1ms中斷
  271. void interrupt 66 PIT0_ISR(void)
  272. {
  273.     PITTF_PTF0=1;           //清中斷標志位
  274.     PIT_CNT++;
  275.    
  276.     if(PIT_CNT==1)
  277.     {      
  278.        fAD_QIUHE() ;        //取20次AD輸入的和        
  279.     }
  280.     else if(PIT_CNT==2)
  281.        fAD_QIUJUNZHI();     //20次AD輸入的平均值
  282.    
  283.     else if(PIT_CNT==3)
  284.       //ANGCulate();        //PD調(diào)節(jié)
  285.        fPWM_KONGZHI();      //電機pwm輸出
  286.     //else if(PIT_CNT==4)
  287.       // ANGControl();      //直立控制
  288. ……………………

  289. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:

龍邱自平衡車清華方案自由滑行版.rar (215.32 KB, 下載次數(shù): 54)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂1 踩
回復

使用道具 舉報

地板
ID:712298 發(fā)表于 2020-5-4 15:15 | 只看該作者
sadbkj 發(fā)表于 2019-4-30 00:13
大佬,這是用的啥軟件啊

這是Codewarrior 5.1,應該是基于XS128單片機的
回復

使用道具 舉報

板凳
ID:737781 發(fā)表于 2020-4-27 09:29 | 只看該作者
是龍邱k60的嗎
回復

使用道具 舉報

沙發(fā)
ID:417080 發(fā)表于 2019-4-30 00:13 | 只看該作者
大佬,這是用的啥軟件啊
回復

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復 返回頂部 返回列表