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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

[寧靜清幽的平衡小車進程帖]

[復制鏈接]
跳轉到指定樓層
樓主
本帖最后由 寧靜清幽 于 2016-2-5 11:24 編輯

組裝曬圖
來幾發小車照片,曬一曬。
小車主控板正面照片




小車主控板反面照片


主控板給我的感覺:板子質量杠杠的,焊工也是棒棒噠,沒有什么質量問題


小車底盤反面照片



全身照片


感覺小車帥帥噠。
基礎實驗
  
1.      Keil工程模板的建立

2.      LED指示燈實驗

這兩個實驗就放一塊了,Keil工程模板的建立在圖中了,不知道這樣算不算完成,好多文件還沒有寫呢,做以后的實驗再補充。

LED指示燈實驗主函數代碼在下圖就不再貼出來了



all_header.h的代碼如下
  1. #ifndef __all_head_
  2. #define __all_head_

  3. #include "STC15W4Kxx.h"
  4. #include <intrins.h>
  5. #include "Delay.h"

  6. #endif
復制代碼


Delay.h的代碼和all_header.h的代碼格式一樣,也不貼啦。
還是貼一下吧。
  1. #ifndef __Delay_
  2. #define __Dealy_
  3. #include <intrins.h>
  4. void Delay300ms();                //@20.000MHz
  5. #endif
復制代碼
在貼一下Delay.c的代碼吧!
  1. #include "Delay.h"
  2. void Delay300ms()                //@20.000MHz
  3. {
  4.         unsigned char i, j, k;
  5.         _nop_();
  6.         _nop_();
  7.         i = 23;
  8.         j = 205;
  9.         k = 120;
  10.         do
  11.         {
  12.                 do
  13.                 {
  14.                         while (--k);
  15.                 } while (--j);
  16.         } while (--i);
  17. }
復制代碼
最后來張效果圖

打死我,我也不會說這個程序里面控制的兩個LED,但是只有一個亮。這個問題實在是無關緊要啦

3.      UART串口通訊實驗

還是先上個效果圖


寫好程序編譯,在左側選好單片機型號,串口號,用的是內部時鐘,填好IRC頻率,為了方便通信嘛,就選的11.0592M。
在右側最下面的藍色框中,選好串口好,波特率,無校驗位,停止位1位。上面兩個藍色框就是效果圖了
對了,還得用安卓數據線把小車和電腦連起來,裝上CP2102的驅動。
再上代碼
主函數main代碼:
  1. #include "all_header.h"

  2. void main()
  3. {        
  4.         Uart1Init();
  5.         EA=1;
  6.                 while(1);
  7. }
  8. void UART1() interrupt 4 using 1
  9. {
  10.         unsigned char date;
  11.         if (RI)
  12.         {        
  13.                 RI=0;
  14.                 date=SBUF;
  15.                 UART1SendByte(date);
  16.         }
  17.         if (TI)
  18.         {
  19.                 TI=0;
  20.         }
  21. }
復制代碼

all_header.h頭文件代碼:
  1. #ifndef __all_head_
  2. #define __all_head_


  3. #include "STC15W4Kxx.h"
  4. #include <intrins.h>
  5. //#include "Delay.h"
  6. #include "UART1.h"

  7. #endif
復制代碼
UART1.h代碼:
  1. #ifndef _UART_H_  
  2. #define _UART_H_  

  3. #include "STC15W4Kxx.h"

  4. void Uart1Init(void);
  5. void UART1SendByte(unsigned char TxD1);

  6. #endif  
復制代碼
UART1.c代碼:
  1. #include "UART1.h"

  2. void Uart1Init(void)                //115200bps@11.0592MHz
  3. {
  4.         SCON = 0x50;                //8位數據,可變波特率
  5.         AUXR |= 0x01;                //串口1選擇定時器2為波特率發生器
  6.         AUXR |= 0x04;                //定時器2時鐘為Fosc,即1T
  7.         T2L = 0xE8;                //設定定時初值
  8.         T2H = 0xFF;                //設定定時初值
  9.         AUXR |= 0x10;                //啟動定時器2
  10. }


  11. void UART1SendByte(unsigned char TxD1)  
  12. {   
  13.     SBUF=TxD1;  
  14.     while(TI == 0);
  15.     TI=0;   
  16. }
復制代碼

串口通信實驗就算是完成了

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發
ID:94185 發表于 2016-2-5 18:05 來自手機 | 只看該作者
666
回復

使用道具 舉報

板凳
ID:104166 發表于 2016-2-5 22:12 | 只看該作者
4.      PWM驅動電機實驗
還是先上效果圖打算傳視頻來著,不過不會傳


先是逆時針加速再減速,后是順時針加速再減速。
是時候上代碼了
main.c:
  1. #include "all_header.h"
  2. //20MHZ
  3. void main()
  4. {        int i,temp=0;
  5.         PWMInit();
  6.         P2M0=0x02;      //芯片上電后所有與PWM相關的IO口均為高阻態
  7.         P2M1=0x00;        //將PWM2和PWM3IO 設置為強上拉(推挽)
  8.         P3M0=0x80;        //其余的P2P3口為弱上拉
  9.         P3M1=0x00;
  10.                 while(1)
  11.                 {        for(i=0;i<100;i++)//逆時針加速
  12.                         {
  13.                         temp+=200;
  14.                         PWM2T1=20000-temp;
  15.                         Delay25ms();
  16.                         }
  17.                         for(i=0;i<100;i++)//逆時針減速
  18.                         {
  19.                         temp-=200;
  20.                         PWM2T1=20000-temp;
  21.                         Delay25ms();
  22.                         }//上面的兩個循環執行完后,PWM2T1=20000就不用再重新賦值了
  23.                         for(i=0;i<100;i++)//順時針加速
  24.                         {
  25.                         temp+=200;
  26.                         PWM3T1=20000-temp;
  27.                         Delay25ms();
  28.                         }
  29.                         for(i=0;i<100;i++)//順時針減速
  30.                         {
  31.                         temp-=200;
  32.                         PWM3T1=20000-temp;
  33.                         Delay25ms();
  34.                         }
  35.                 }
  36. }
復制代碼
pwm.c:
  1. #include "PWM.h"
  2. void PWMInit()
  3. {
  4.         P_SW2|=0x80;                                    //使能訪問XSFR
  5.         PWMCFG = 0x00;          //配置PWM初始化電平為低電平
  6.         PWMCKS = 0x00;          //選擇PWM的時鐘為Fosc/(0+1)=20M
  7.         PWMC = 20001;                //設置PWM周期 PWM頻率為 PWM時鐘頻率(上行代碼)20M/20001=1k
  8.        
  9.         PWM2T1 = 20000;                //設置PWM2第一次反轉的PWM計數
  10.         PWM2T2 = 20001;                //設置PWM2第二次反轉的PWM計數

  11.         PWM3T1 = 20000;                 
  12.         PWM3T2 = 20001;
  13.        
  14.         PWM2CR=0x00;                 //輸出管腳為P3.7 無PWM中斷,無PWM反轉中斷
  15.         PWM3CR=0x00;                //輸出管腳為P2.1 無PWM中斷,無PWM反轉中斷
  16.         PWMCR |= 0x03;                //使能PWM2 PWM3輸出
  17.         PWMCR |= 0x80;          //使能PWM博興發生器,PWM計數器開始計數
復制代碼
就貼出這兩個主要的代碼吧!全部代碼打包!
PWM驅動電機實驗.zip (41 KB, 下載次數: 12)

回復

使用道具 舉報

地板
ID:104166 發表于 2016-2-6 00:20 | 只看該作者
bjyxyc 發表于 2016-2-6 00:03
用什么型號的芯片呢

IPA15w4k61s4
回復

使用道具 舉報

5#
ID:104166 發表于 2016-2-21 16:36 | 只看該作者
5.      編碼器數據采集實驗

先上一張速度圖像(用的wps表格畫的)



這是在2.5秒內加速到最大,延遲300毫秒,再在2.5秒內減速的圖像,一共兩個這樣的過程。
如何采集速度:
電機上有霍爾編碼器:電機轉一圈回輸出11個左右的脈沖(脈沖個數有編碼器決定),通過配置單片機的定時器3和定時器4,使其對外部脈沖計數,配置定時器1使其每隔8毫秒讀出脈沖來,再通過串口發給電腦,這樣就采集到了速度。
配置定時器1的代碼:
  1. void Timer1Init(void)                //8毫秒@20.000MHz
  2. {
  3.         AUXR &= 0xBF;                //定時器時鐘12T模式
  4.         TMOD &= 0x0F;                //設置定時器模式
  5.         TL1 = 0xEB;                //設置定時初值
  6.         TH1 = 0xCB;                //設置定時初值
  7.         TF1 = 0;                //清除TF1標志
  8.         TR1 = 1;                //定時器1開始計時
  9.         ET1 = 1;                //允許定時器1中斷

  10. }
復制代碼
配置定時器3、4的代碼:
  1. void Timer_3_4_Init(void)
  2. {

  3.   T4T3M |= 0xCC;        //允許定時器3、4運行對外部脈沖計數
  4.   IE2 &= 0x1F;        //進制定時器3、4產生中斷
  5. }
復制代碼

主函數MAIN和定時器1中斷代碼:
  1. #include "all_header.h"
  2. //20M晶振
  3. int num=0;
  4. void main()
  5. {        int i,temp=0;
  6.         PWMInit();        //PWM初始化
  7.         Uart1Init();        //串口1初始化
  8.         Timer1Init();        //定時器1初始化
  9.         Timer_3_4_Init();//定時器3 4初始化
  10.         P2M0=0x02;      //芯片上電后所有與PWM相關的IO口均為高阻態
  11.         P2M1=0x00;        //將PWM2和PWM3所在的IO口設置為強上拉(推挽)
  12.         P3M0=0x80;        //取余的P2P3口為弱上拉(準雙向扣)
  13.         P3M1=0x00;
  14.         EA=1;                //允許總中斷
  15.         T3L=0;
  16.         T3H=0;
  17.                 while(1)
  18.                 {        for(i=0;i<100;i++)//正傳加速
  19.                         {
  20.                         temp+=200;
  21.                         PWM2T1=20000-temp;
  22.                         Delay25ms();
  23.                         }
  24.                         Delay300ms();//延遲300毫秒
  25.                         for(i=0;i<100;i++)//正傳減速
  26.                         {
  27.                         temp-=200;
  28.                         PWM2T1=20000-temp;
  29.                         Delay25ms();
  30.                         }
  31.                 }
  32. }

  33. void Timer1_Int() interrupt 3
  34. {
  35.         num=(T3H<<8)+T3L; //獲取脈沖個數
  36.         T4T3M&=        0x77;        //關閉定時器3、4
  37.         T3H=T3L=0;        //脈沖個數清零
  38.         T4T3M |= 0xCC;        //將定時器3、4做計數用并開啟定時器3、4
  39.         UART1SendByte(num);//發送num低8位(8毫秒內最大在17左右,num的低8位計數就夠)
  40. }
復制代碼

實驗所有代碼: 編碼器數據采集.zip (45.88 KB, 下載次數: 12)


回復

使用道具 舉報

6#
ID:104166 發表于 2016-2-21 23:23 | 只看該作者
6.傳感器數據采集實驗
還是先上一張圖

上圖是我找了一個認為平衡時,陀螺儀輸出的原始數據,可以大致認為Y軸加速度的零點漂移大約為-390,X軸角速度零點漂移大約為-17。
如何得到的這些數據:
      MPU6050是一個可以測加速度和角速度的6軸傳感器(里面還有一個溫度傳感器),單片機通過IIC協議和MPU6050通信,配置MPU6050,定時通信讀出數據,將這些數據通過串口1發送給電腦。
下面是配置MPU6050的代碼:
  1. void InitMPU6050()
  2. {
  3.         Single_WriteI2C(PWR_MGMT_1, 0x00);        //正常啟用
  4.         Single_WriteI2C(SMPLRT_DIV, 0x07);        //采樣率 = 陀螺儀的輸出率 / (1 + SMPLRT_DIV)
  5.         Single_WriteI2C(CONFIG, 0x04);                //Accelerometer:21hz 8.5ms ; Gyroscope:20hz 8.3ms
  6.         Single_WriteI2C(GYRO_CONFIG, 0x18);        //+-2000°/s
  7.         Single_WriteI2C(ACCEL_CONFIG, 0x00);        //+-2g不自檢
  8. }
復制代碼
讀取數據的代碼:

  1. int GetData(unsigned char REG_Address)
  2. {
  3.         unsigned int H;
  4.         unsigned char L;
  5.         H=Single_ReadI2C(REG_Address);
  6.         L=Single_ReadI2C(REG_Address+1);
  7.         return (H<<8)+L;   //和成數據
  8. }
復制代碼
MPU6050常用寄存器:

  1. //****************************************
  2. //定義MPU6050內部寄存器地址
  3. //****************************************

  4. #define        SMPLRT_DIV                0x19        //陀螺儀采樣率0x07(125Hz)
  5. #define        CONFIG                        0x1A        //低通濾波頻率
  6. #define        GYRO_CONFIG                0x1B        //陀螺儀自檢及測量范圍
  7. #define        ACCEL_CONFIG        0x1C        //加速度自檢測量范圍
  8. #define        ACCEL_XOUT_H        0x3B
  9. #define        ACCEL_XOUT_L        0x3C
  10. #define        ACCEL_YOUT_H        0x3D
  11. #define        ACCEL_YOUT_L        0x3E
  12. #define        ACCEL_ZOUT_H        0x3F
  13. #define        ACCEL_ZOUT_L        0x40
  14. #define        TEMP_OUT_H                0x41
  15. #define        TEMP_OUT_L                0x42
  16. #define        GYRO_XOUT_H                0x43
  17. #define        GYRO_XOUT_L                0x44       
  18. #define        GYRO_YOUT_H                0x45
  19. #define        GYRO_YOUT_L                0x46
  20. #define        GYRO_ZOUT_H                0x47
  21. #define        GYRO_ZOUT_L                0x48
  22. #define        PWR_MGMT_1                0x6B        //電源管理 0x00正常啟用
復制代碼

IIC的代碼就不貼啦,最后打包。

主函數MAIN代碼
  1. #include "all_header.h"
  2. //20M晶振
  3. int ACCEL,GYRO;
  4. void main()
  5. {       
  6. //設置所有IO口為弱上拉
  7.         P1M0=0x00;
  8.         P1M1=0x00;
  9.         P2M0=0x00;
  10.         P2M1=0x00;
  11.         P3M0=0x00;
  12.         P3M1=0x00;
  13.         P4M0=0x00;
  14.         P4M1=0x00;
  15.         P5M0=0x00;
  16.         P5M1=0x00;
  17.         Uart1Init();        //串口1初始化
  18.         Timer1Init();        //定時器1初始化8ms中斷

  19.         InitMPU6050();        //初始化MPU6050
  20.         Delay300ms();
  21.                 EA=1;        開總中斷
  22.                 while(1)
  23.                 {       
  24.                 }
  25. }

  26. void Timer1_Int() interrupt 3        //定時器18ms中斷
  27. {
  28.        
  29.         ACCEL=GetData(ACCEL_YOUT_H);        //讀取Y軸加速度
  30.         GYRO=GetData(GYRO_XOUT_H);        //讀取X軸角速度
  31.         UART1SendByte(ACCEL);                //發送加速度低八位
  32.         UART1SendByte(ACCEL>>8);        //發送加速度高八位
  33.         UART1SendByte(GYRO);
  34.         UART1SendByte(GYRO>>8);
  35. }
復制代碼
本實驗代碼 傳感器數據采集.zip (53.16 KB, 下載次數: 9)


回復

使用道具 舉報

7#
ID:77578 發表于 2016-2-23 20:36 | 只看該作者
你串口助手很好啊,是什么?
回復

使用道具 舉報

8#
ID:104166 發表于 2016-2-23 22:31 | 只看該作者
moyuqilin 發表于 2016-2-23 20:36
你串口助手很好啊,是什么?

為了看數據方便,就動手寫了這么個不能再簡陋的助手。
回復

使用道具 舉報

9#
ID:104166 發表于 2016-2-24 17:09 | 只看該作者
7.      無線通訊實驗(藍牙)沒有nRF24l0(不會玩,以后得鼓搗鼓搗),而且小車上有藍牙,就用藍牙啦
先上圖


左邊用的是手機藍牙串口助手,發送的 hello world,右邊在電腦串口助手接收到的。一共用了單片機上的2個串口,串口2和藍牙相連接,串口1和電腦連接。在電腦上選好串口號和波特率校驗位,停止位,燒寫上程序就可以通信啦。
數據流向:手機藍牙-->藍牙模塊-->單片機串口2-->串口1-->電腦串口助手。感覺實際上還是串口通信,藍牙默認的波特率是115200,名稱是HMSoft,喵大應該是提前設置好了,通過命令可以更改藍牙的一些參數。
下面是代碼:
串口1 、2初始化代碼:

  1. void Uart1Init(void)                //115200bps@20.000MHz
  2. {
  3.         SCON = 0x50;
  4.         AUXR |= 0x01;
  5.         AUXR |= 0x04;       
  6.         T2L = 0xD5;
  7.         T2H = 0xFF;
  8.         AUXR |= 0x10;
  9.         ES=1;
  10. }
  11. void Uart2Init(void)                //115200bps@20.000MHz
  12. {
  13.         S2CON = 0x50;                //8位數據,可變波特率
  14.         AUXR |= 0x04;                //定時器2時鐘為Fosc,即1T
  15.         T2L = 0xD5;                //設定定時初值
  16.         T2H = 0xFF;                //設定定時初值
  17.         AUXR |= 0x10;                //啟動定時器2
  18.         IE2 |=0x01;                /允許定時器2中斷
  19. }
復制代碼

串口1發送數據代碼:

  1. void UART1SendByte(unsigned char TxD1)  
  2. {   
  3.     SBUF=TxD1;  
  4.     while(TI == 0);//等待發送完成
  5.     TI=0;   
  6. }
復制代碼

Main代碼:

  1. #include "all_header.h"
  2. //20MH
  3. void main()
  4. {               

  5.         //P13 I/O口設置為弱上拉
  6.         P1M0=0x00;
  7.         P1M1=0x00;
  8.         P3M0=0x00;
  9.         P3M1=0x00;
  10.         Uart1Init();
  11.         Uart2Init();
  12.         EA=1;
  13.                 while(1);
  14. }
  15. void  Interrupt_Uart2(void) interrupt  8 using 1         //125hz
  16. {
  17.         if(S2CON & 0x01)
  18.         {
  19.                 S2CON&=~0x01;
  20.                 UART1SendByte(S2BUF);
  21.         }
  22. }
復制代碼
無線通訊實驗就算完成啦




閃亮.gif (667.5 KB, 下載次數: 282)

閃亮.gif

長亮.gif (311.88 KB, 下載次數: 254)

長亮.gif
回復

使用道具 舉報

10#
ID:104166 發表于 2016-2-26 01:10 | 只看該作者
進階實驗:

1.     多傳感器數據融合



看了喵大和網上的資料,用互補濾波進行數據融合就可以滿足,但要調節好比例權重(不知道這樣說有沒有為題),我用的也是互補濾波。
下面就是我所觀察到的實驗結果:(紅色線為融合后的數據,黑色線為由加速度算出的角度,縱軸的單位就是度,一個像素代表1度,我沒有軟件中寫坐標)

圖1:
圖1是加速度比例權重(此圖為0.1)比較大的圖像,其代碼為CarAngle=0.9*(CarAngle+GyroSpeed*0.008)+0.1*AccelAngle;
小車稍微有點震動,加速度就會變化,但是車體的角度并沒有變化,微小的晃動是噪聲,所以由加速度算出來的角度也會有很多噪聲,加速度權重過大,就會摻雜更多的噪聲,不能反應真實的車體角度。
圖2是車體直立突然到向一個方向,待一會,然后直立,再反相倒的車體角度的圖像。圖中的那些突起的黑線,是轉小車時突然停止產生的,車體的角度并沒有那樣的突變(先變大在減。圀w角度而只是增大然后突然不變,在由于加速度比例權重過大,可以看到融合后的圖像(紅色線)也不能真實反應車體的角度。
圖2:
圖2是加速度比例權重適當(此圖為0.005)的數據融合圖像。其代碼為CarAngle=0.995*(CarAngle+GyroSpeed*0.008)+0.005*AccelAngle;

可以看到在那些黑線突起地方,紅線也平滑的變化,能夠反應真實的車體角度變化。
圖3:
圖3是車體一開始就有一定的傾斜角的情況下供電的圖像(剛開始時黑色線(也就是由加速度算出的角度)能夠反應車體的真是角度),進行數據融合之前沒有給車體角度賦初值(就是先先將由加速度算出的角度賦給車體角度變量)就會出現這樣的情況。在代碼中有賦初值的注釋。
圖4:
圖4是進行數據融合之前,給車體角度賦初值得圖像,在剛開始的圖像部分,黑色線被紅色先覆蓋了。這樣無論小車在什么角度開機,總能夠確保一開機融合后的角度都是正確的。
下面是MAIN代碼:
  1. #include "all_header.h"
  2. //20MHz
  3. int AccelData;
  4. int GyrolData;
  5. float AccelAngle;
  6. float GyroSpeed;
  7. float CarAngle;
  8. float GyroAngle;
  9. int temp;
  10. void main()
  11. {       
  12.         //設置所有IO口為準雙向口
  13.         P0M0=0x00;
  14.         P0M1=0x00;
  15.         P1M0=0x00;
  16.         P1M1=0x00;
  17.         P2M0=0x00;
  18.         P2M1=0x00;
  19.         P3M0=0x00;
  20.         P3M1=0x00;
  21.         P4M0=0x00;
  22.         P4M1=0x00;
  23.         P5M0=0x00;
  24.         P5M1=0x00;
  25.         InitMPU6050();//MPU6050初始化
  26.         Delay300ms();
  27.         Uart1Init();//串口1初始化
  28.         AccelData=GetData(ACCEL_YOUT_H);
  29.         AccelAngle=(float)(AccelData-370)/16384.0f;
  30.         //I在此先將由加速度算出的角度給CarAngle,
  31.         //來確保一開機,融合后的角度就是正確的。
  32.         CarAngle=AccelAngle*57.2957795f;
  33.         Timer1Init();//定時器1初始化
  34.         Delay300ms();
  35.         EA=1;
  36.                 while(1);
  37. }
  38. void  Interrupt_Timer1(void) interrupt  3         //125hz
  39. {
  40.         AccelData=GetData(ACCEL_YOUT_H);        //獲取Y軸加速度
  41.         GyrolData=GetData(GYRO_XOUT_H);                //獲取X軸角速度
  42.         AccelAngle=(float)(AccelData-370)/16384.0f;//出去零點偏移,就是你得到角度(單位是弧度)
  43.         AccelAngle=AccelAngle*57.2957795f;// 180/3.1415926535898弧度轉換為度
  44.         temp=(int)AccelAngle;                //強制轉換為整形量
  45.         UART1SendByte(temp);                //發低八位
  46.         UART1SendByte(temp>>8);        //發高八位
  47.         GyroSpeed=(float)(GyrolData-(-17))/16.4f;
  48.         CarAngle=0.995*(CarAngle+GyroSpeed*0.008)+0.005*AccelAngle;//互補濾波
  49.         temp=(int)CarAngle;
  50.         UART1SendByte(temp);
  51.         UART1SendByte(temp>>8);
  52. }
復制代碼

實驗代碼: 數據融合.zip (51.21 KB, 下載次數: 7)
回復

使用道具 舉報

11#
ID:94185 發表于 2016-2-27 17:47 | 只看該作者
寧靜清幽 發表于 2016-2-26 01:10
進階實驗:

1.     多傳感器數據融合

非常好。繼續加油。把小車都學透~
回復

使用道具 舉報

12#
ID:79544 發表于 2016-3-8 10:37 | 只看該作者
真是高手,佩服啊,長見識啦,謝謝分享
回復

使用道具 舉報

13#
ID:104166 發表于 2016-3-9 21:35 | 只看該作者
騰飛的龍 發表于 2016-3-8 10:37
真是高手,佩服啊,長見識啦,謝謝分享

啥高手,參數調不好,上面的都是跟著喵大學的!
回復

使用道具 舉報

14#
ID:104166 發表于 2016-3-24 12:55 | 只看該作者
進階實驗

2.     PID調試

關于小車PID的調試,也在網上找了好多資料,也看了喵大的角度環視頻,調試經驗有從網上學的也有些自己簡單的體會。
原來沒接觸的時候也是一頭霧水(畢竟不是學自控的孩子),后來在網上搜了一些資料,對這些基本概念也有了大概的了解,下面說一下我對PID的了解吧!1)我對PID的理解:PID分增量式和位置式,增量式的計算結果是在上一次的控制量基礎上需要增加的量,或減少的量;位置式的每一次計算都是一個新的控制量的大小,而不是增加量,也不知道這說對不對(表達能力有限)。喵大的貌似是位置式,我的代碼也是參考喵大的。PID控制一定要有反饋,要不然何談控制(有點像廢話)。PID控制就是比例P、積分I、微分控制D,這些運算是對于偏差來說的。    (1)比例運算:對偏差進行比例運算,就是偏差乘上一個系數,把這個偏差放大或縮小,對于平衡小車角度環來說,偏差角度=目標角度-當前角度,目標角度就是平衡時候的角度,就是0嘍,比例控制量=偏差*比例系數,偏差大了,就是小車傾斜程度大了,我們給小車的電機大點電壓,使小車加速運動,來減小偏差,從而使小車趨向平衡,同理,偏差小,給電機的電壓小點,這就是比例控制,比例參數過小,小車“沒勁”,不能抵消自身重力,太大的話,大幅度搖擺太厲害。
    (2)積分運算:對偏差進行積分,就是把偏差進行累加,偏差和=偏差和+偏差*積分系數;只要出現偏差,通過累加就會使偏差和變大,我們給電機的電壓就要大,來使小車趨向平衡,直到偏差和為零的時候,積分這一部分對電壓控制沒有貢獻。相對于比例參數來說,積分系數是很小的,但積分系數過小累加和變化不明顯,控制也就不明顯,過大,即出現了一個很小的誤差,通過積分系數放大了好多,累加和也會變得很大,使系統不穩定。
    (3)微分控制:就是偏差對時間求導,得到的是偏差的變化率。對于小車的角度環來說偏差d=C-f(t);C就是我們目標角度,是一個恒定值,一般是0,f(t)是當前的角度值,偏差d對時間求導=常數C對時間求導+f(t)對時間求導,常數的導數是0,所以偏差d對時間求導相當于角度對時間求導,得到的是角速度,角速度可以直接從陀螺儀上面獲取,就不用我們運算了,不過我們注意角速度的正負號。角速度的正負號代表小車像前還是向后倒下了,可以自己規定。角速度的絕對值代表小車倒下的速度,小車倒下的速度越快,我們就要給小車電機更大的電壓,來抵消小車倒下,微分控制起到加快調節的作用。微分控制量=角速度*微分系數,我們把角速度乘以一個系數(也就是微分系數)就得到微分控制部分的控制量的大小了。微分系數太小也不能抵消小車的倒下,太大了會使小車小幅度高頻震蕩,容易燒驅動。
以上只是我的簡單理解,有什么不對或者不全的地方還請大家指出,共同進步。
2)調試
關于平衡車的控制,用到了兩個環的控制,分別是角度環和速度環,角度環用PD,速度環用PI,在只有角度環的時候我也用過PID,以可以達到平衡,但是由于沒有速度環,小車不一定跑到哪了。
寫一下主要的公式:

    角度環:角度偏差d_Angle=SetAngle-CarAngle;     AngleCtrlOut=d_Angle*P_Angle+w*D_Angle;    w是角速度,在這之前還要對小車的角度進行濾波,前面的實驗有過介紹,AngleCtrlOut是角度環的PWM輸出
    速度環:速度偏差d_Speed=SetSpeed-CarSeed;  Car_I=Car_I+d_Speed*I_Speed;    SpeedCtrlOut=d_Speed*P_Speed+CarI;  SpeedCtrlOut是速度環的PWM輸出。這些系數與單片機PWM的最大量有關系,比如單片機PWM的最大量是10000;在調角度環的時候一般是先讓微分系數D_Angle=0,先只調比例系數,這樣AngleCtrlOut=d_Angle*P_Angl;當偏差角度 d_Angle=10度,比例系數P_Angle=10,AngleCtrlOut才=100,小車PWM輸出占PWM最大量的1%,理論上小車電機的轉速為最快轉速的1%(實際上達不到,也有可能死區電壓都沒過),這樣小車沒有足夠的加速度來克服重力使車達到平衡。比例系數P_Angle還需要調大。但是當單片機PWM的最大量是256的時候,偏差角度 d_Angle=10度,比例系數P_Angle=10的時候,AngleCtrlOut還是=100,約占PWM最大量的39%,這個系數可能還靠點譜,所以說這些系數PWM最大量是有關系的。
    調試這些系數的過程:先調角度環,再速度環。關于反饋類型說的文鄒鄒點:角度環是負反饋,速度環是正反饋。說的通俗點:角度環中,偏差角度變大時,小車要控制偏差角度減小,就是讓車輪朝著倒下的方向加速轉。速度環中,速度變大,我們得給小車更快的速度,讓小車追上自己,保持平衡。在調試的時候,可以分別調一下兩個環,注意參數的正負,保證每個環,都是使車輪朝向小車傾斜的方向轉就行了,在只有速度環時,手動轉一個車輪,另一個車輪會慢慢轉起來,最終兩個車輪越轉越快。
    調角度環時,一般是先讓微分系數D_Angle=0,先只調比例系數,調到能使小車站起來,在平衡位置來回的擺動,再稍微增加比例系數,加入微分系數D_Angle,微分系數D_Angle從小到大。調到小車能夠比較穩定的平衡,這時候,你輕推小車,小車會朝著一個方向加速跑過去,直至倒下。這個也是正常的,當然小車能接近平衡跑的越遠說明參數越好,加入速度環可以解決這個問題,如果不加速度環,在角度環里面加入對偏差的積分(累加偏差),也能使小車平衡。只是對小車的速度沒法控制。
    調速度環時,一般是先讓積分系數I_Speed=0,先只調比例系數,由0開始增加,調到你推一下小車,小車能有足夠的加速度來使小車保持平衡,這時小車新的平衡位置不再原地了,感覺小車能夠很好的保持平衡之后,這時再加速度積分,加入速度積分后,小車會趨向于原地平衡
    我的理解就是這些,有什么不對或者不全的還請大家指出來,一塊討論共同學習哈。我自己感覺對于車速控制的理解還不夠深,對于兩個車輪速度分別控制還有待加強。
    挺感謝喵大的這個平臺的,給我提供了學習平衡車基礎,有機會讓我這樣的平衡車入門級玩家能從頭到尾深刻了解平衡車的原理。給這個網站平臺點個贊,給喵大的開源精神點個贊,給喵大的熱心腸點個贊。
    本想弄點圖片的,電池,又讓我弄過放了,廢了,平衡充接電池的時候,接反了一下,燈不亮了,平衡沖也出問題了。唉我勒個去,我也是被自己整無語了。在下個實驗中在上圖片吧。

回復

使用道具 舉報

15#
ID:104166 發表于 2016-4-16 23:09 | 只看該作者
進階實驗
3.     實現平衡小車直立時處于靜止狀態
下面兩個圖片是小車靜止時受到干擾后小車運動的圖片

第一張圖的速度環是用的PI,第張圖用的是PD,可以看到第一張圖中:用手推車,車會回到原來的位置;第二張圖中:用手推車則不會會到原來的位置。下面是代碼:

  1. Speed_Least=(float)(g_iLeftMotorPluseSigma+g_iRightMotorPluseSigma)/2.0;//獲取速度

  2. g_iRightMotorPluseSigma=g_iLeftMotorPluseSigma=0;//速度清零
  3. g_fCarSpeed=Speed_Least*0.75+g_fCarSpeed*0.25;//速度濾波
  4. fDelta = g_iCarSpeedSet;//此處全局整形目標車速 g_iCarSpeedSet為零
  5. fDelta -= g_fCarSpeed;//得到速度偏差
  6. fP = fDelta*g_fcSpeed_P;//速度偏差乘上比例系數


復制代碼
上面代碼是兩個車速度環的公共代碼。

下面是第一個圖片中PI速度環的代碼:

  1. fI = fDelta*g_fcSpeed_I;速度偏差乘上積分系數
  2. g_fCarPosition += fI; //偏差累加,在開始初始化的時候g_fCarPosition是為零的
  3. /****************加入積分限幅*****************/
  4. if(g_fCarPosition>20000)g_fCarPosition=20000;
  5. if(g_fCarPosition<-20000)g_fCarPosition=-20000;
  6. /*********************************************/
  7. g_fSpeedCtrlOut = fP+g_fCarPosition;//速度環控制量輸出
復制代碼

下面是第二個圖片中PD速度環的代碼:

  1. fD = (fDelta-g_fcSpeedDerta)*g_fcSpeed_D;//得到速度的變化率
  2. g_fSpeedCtrlOut = fP+fD;<span style="line-height: 1.5;">//速度環控制量輸出</span>
復制代碼

所有代碼: 所有代碼.zip (144.52 KB, 下載次數: 36)
附件里的代碼跟喵大的差不多,我是照著喵大的代碼敲的,不過我的這個有些地方比較難看。我剛開始看喵大的代碼的時候,看著也頭大,后來我就先看程序名,看看這個程序的流程;看個大概了,之后再了解程序的細節,死扣每一句,之后慢慢理解了小車。

由衷感謝喵大的這個平臺,讓我學到了平衡小車的知識,感謝,感謝,感謝。


靜止1.gif (3.48 MB, 下載次數: 180)

靜止1

靜止1
回復

使用道具 舉報

16#
ID:102157 發表于 2016-4-21 10:47 | 只看該作者
厲害,大神,請接下我的膝蓋你做了轉向沒?
回復

使用道具 舉報

17#
ID:114829 發表于 2016-5-4 12:43 | 只看該作者
樓主能否給我一份具體的資料啊  ?
回復

使用道具 舉報

18#
ID:145818 發表于 2016-11-2 22:11 | 只看該作者
不錯。。!值得學習!
回復

使用道具 舉報

19#
ID:200681 發表于 2017-5-14 17:31 | 只看該作者
值得學習學習,我也在做小車,希望最后能夠成功
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: a级在线免费 | 福利视频网站 | 青春草91 | 美女一级毛片 | av毛片 | 亚洲一区二区三区四区视频 | 浮生影院免费观看中文版 | 国产成人一区二区三区 | av资源中文在线天堂 | 精品一区二区在线观看 | 中文字幕精品视频在线观看 | 亚洲精品 在线播放 | 日韩国产中文字幕 | 日批av | 亚洲精品久久久久久久久久吃药 | 国产精品久久久久久一区二区三区 | 国产精品视频久久 | 久久精品国产久精国产 | 亚洲欧美综合精品久久成人 | 国产亚洲人成a在线v网站 | 波多野结衣先锋影音 | 亚洲精品高清视频 | 亚洲一区二区欧美 | chengrenzaixian| 综合一区二区三区 | 欧美一级二级在线观看 | 91国语清晰打电话对白 | 国内自拍偷拍一区 | 国产99久久久国产精品 | 波多野结衣亚洲 | 亚洲欧美另类在线观看 | 亚洲精品乱码久久久久久按摩观 | 久久综合伊人 | 久久久久国产精品午夜一区 | 国产精品网址 | 中文字幕一区二区三区四区 | 精品国产一区一区二区三亚瑟 | 国产精品免费一区二区 | 国产第一页在线播放 | 成人av网站在线观看 | 欧美精品网|