|
前段時間搞了個平衡車,涉及stm32F3 步進電機驅動 陀螺儀mpu3050 加速度計adxl345(也可以用6軸mpu6050) 無線NRF24L01
當初最大問題是卡爾曼濾波(進行陀螺儀與加速度計的數據融合)和pid調節
對于卡爾曼濾波,經過自己不斷深究,其實也不是很復雜,核心是五大公式,涉及矩陣運算,思想是預測值 最優估計值 噪聲 協方差的概念,難點:一些參數選擇
b6c31d01d41c9e1714958f9c56d01d8f.png (89.73 KB, 下載次數: 199)
下載附件
2016-6-17 16:14 上傳
說下用卡爾曼濾波的出發點,陀螺儀 加速度計都可以得到角度,而陀螺儀是先得到角速度再經積分才得到角度, 陀螺儀相比加速度計短時間內動態性能好,得到角度精準,但本身有小漂移,隨著時間變長,不斷積分,誤差會越來越大,那就需要用加速度計進行校正
對于pid算法,里面涉及二級pid,首先要明白小車速度跟給步進電機的頻率是成正比的,就把頻率等效為速度
第一個pid,角度pid,通過測角度反饋給stm32f3產生頻率(速度)來進行平衡調節(即調節角度)
第二個pid,速度pid,由于角度調節產生了速度變化,而為了不改變設定的速度,需要進行速度調節,它的反饋來自不斷角度pid的結果(由于速度跟頻率成正比,不需要測速反饋)
難點:pid整定參數
dced2f010c1ef04643993a5e26c68477.jpg (1.28 MB, 下載次數: 190)
下載附件
2016-6-17 16:14 上傳
eed39bb1a85277ac150f8872704f0a55.jpg (1.28 MB, 下載次數: 186)
下載附件
2016-6-17 16:14 上傳
a7b8f3f8fde79ff6a9df96b46007ce63.jpg (746.21 KB, 下載次數: 183)
下載附件
2016-6-17 16:14 上傳
- /***********************************************
- 標題: 24L01.c
- 日期: 2013/12/27
- 版本:v1.0
- 功能: 初始化以spi及數據讀寫
- 說明:24l01的初始化及spi2的調用
- 注意:在24l01.h中的管腳配置
- *************************************************/
- #include "stm32f10x.h"
- #include "24l01.h"
- #include "spi.h"
- #include
-
- const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發送地址
- const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發送地址
-
- //初始化24L01的IO口
- void NRF24L01_Init(void)
- {
-
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD, ENABLE );
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//CE PB12
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_SetBits(GPIOB,GPIO_Pin_12);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_2|GPIO_Pin_3;//LSN
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- GPIO_SetBits(GPIOD,GPIO_Pin_8);
-
- GPIO_SetBits(GPIOD,GPIO_Pin_2);//LED1
- GPIO_SetBits(GPIOD,GPIO_Pin_3);//LED2
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; //上拉輸入
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- SPI2_Init(); //初始化SPI2
-
- Clr_NRF24L01_CE; //使能24L01 NRF24L01_CE
- Set_NRF24L01_CSN; //SPI片選取消 NRF24L01_CSN
- }
- //檢測24L01是否存在
- //返回值:0,成功;1,失敗
- u8 NRF24L01_Check(void)
- {
- u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
- u8 i;
- NRF24L01_Write_Buf(NRF24L01_WRITE_REG+TX_ADDR,buf,5);//寫入5個字節的地址.
- NRF24L01_Read_Buf(TX_ADDR,buf,5); //讀出寫入的地址
- for(i=0;i<5;i++)if(buf[i]!=0XA5)break;
- if(i!=5)return 1;//檢測24L01錯誤
- return 0; //檢測到24L01
- }
-
- //SPI寫寄存器
- //reg:指定寄存器地址
- //value:寫入的值
- u8 NRF24L01_Write_Reg(u8 reg,u8 value)
- {
- u8 status;
- Clr_NRF24L01_CSN; //使能SPI傳輸
- status =SPIx_ReadWriteByte(reg);//發送寄存器號
- SPIx_ReadWriteByte(value); //寫入寄存器的值
- Set_NRF24L01_CSN; //禁止SPI傳輸
- return(status); //返回狀態值
- }
- //讀取SPI寄存器值
- //reg:要讀的寄存器
- u8 NRF24L01_Read_Reg(u8 reg)
- {
- u8 reg_val;
- Clr_NRF24L01_CSN; //使能SPI傳輸
- SPIx_ReadWriteByte(reg); //發送寄存器號
- reg_val=SPIx_ReadWriteByte(0XFF);//讀取寄存器內容
- Set_NRF24L01_CSN; //禁止SPI傳輸
- return(reg_val); //返回狀態值
- }
- //在指定位置讀出指定長度的數據
- //reg:寄存器(位置)
- //*pBuf:數據指針
- //len:數據長度
- //返回值,此次讀到的狀態寄存器值
- u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
- {
- u8 status,u8_ctr;
- Clr_NRF24L01_CSN; //使能SPI傳輸
- status=SPIx_ReadWriteByte(reg);//發送寄存器值(位置),并讀取狀態值
- for(u8_ctr=0;u8_ctr<len;u8_ctr++)pbuf[u8_ctr]=spix_readwritebyte(0xff); 讀出數據
- Set_NRF24L01_CSN; //關閉SPI傳輸
- return status; //返回讀到的狀態值
- }
- //在指定位置寫指定長度的數據
- //reg:寄存器(位置)
- //*pBuf:數據指針
- //len:數據長度
- //返回值,此次讀到的狀態寄存器值
- u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
- {
- u8 status,u8_ctr;
- Clr_NRF24L01_CSN; //使能SPI傳輸
- status = SPIx_ReadWriteByte(reg);//發送寄存器值(位置),并讀取狀態值
- for(u8_ctr=0; u8_ctr<len; u8_ctr++)spix_readwritebyte(*pbuf++);="" 寫入數據=""
- Set_NRF24L01_CSN; //關閉SPI傳輸
- return status; //返回讀到的狀態值
- }
-
- //啟動NRF24L01發送一次數據
- //txbuf:待發送數據首地址
- //返回值:發送完成狀況
- u8 NRF24L01_TxPacket(u8 *txbuf)
- {
- u8 sta;
- Clr_NRF24L01_CE;
- NRF24L01_Write_Buf(NRF24L01_WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF 32個字節
- Set_NRF24L01_CE;//啟動發送
- while(NRF24L01_IRQ!=0);//等待發送完成
- sta=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志
- if(sta&MAX_TX)//達到最大重發次數
- {
- NRF24L01_Write_Reg(NRF24L01_FLUSH_TX,0xff);//清除TX FIFO寄存器
- return MAX_TX;
- }
- if(sta&TX_OK)//發送完成
- {
- return TX_OK;
- }
- return 0xff;//其他原因發送失敗
- }
- //啟動NRF24L01發送一次數據
- //txbuf:待發送數據首地址
- //返回值:0,接收完成;其他,錯誤代碼
- u8 NRF24L01_RxPacket(u8 *rxbuf)
- {
- u8 sta;
- sta=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志
- if(sta&RX_OK)//接收到數據
- {
- NRF24L01_Read_Buf(NRF24L01_RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據
- NRF24L01_Write_Reg(NRF24L01_FLUSH_RX,0xff);//清除RX FIFO寄存器
- return 0;
- }
- return 1;//沒收到任何數據
- }
-
- //該函數初始化NRF24L01到RX模式
- //設置RX地址,寫RX數據寬度,選擇RF頻道,波特率和LNA HCURR
- //當CE變高后,即進入RX模式,并可以接收數據了
- void RX_Mode(void)
- {
- Clr_NRF24L01_CE;
- NRF24L01_Write_Buf(NRF24L01_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//寫RX節點地址
-
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_AA,0x01); //使能通道0的自動應答
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_CH,40); //設置RF通信頻率
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_SETUP,0x0f);//設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式
- Set_NRF24L01_CE; //CE為高,進入接收模式
- }
-
- //該函數初始化NRF24L01到TX模式
- //設置TX地址,寫TX數據寬度,設置RX自動應答的地址,填充TX發送數據,選擇RF頻道,波特率和LNA HCURR
- //PWR_UP,CRC使能
- //當CE變高后,即進入RX模式,并可以接收數據了
- //CE為高大于10us,則啟動發送.
- void TX_Mode(void)
- {
- Clr_NRF24L01_CE;
- NRF24L01_Write_Buf(NRF24L01_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址
- NRF24L01_Write_Buf(NRF24L01_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK
-
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_AA,0x01); //使能通道0的自動應答
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_CH,40); //設置RF通道為40
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+RF_SETUP,0x0f); //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟
- NRF24L01_Write_Reg(NRF24L01_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
- Set_NRF24L01_CE;//CE為高,10us后啟動發送
- }
復制代碼
代碼資料(完美)見下
balance car nrf24l01程序 完美.zip
(6.43 MB, 下載次數: 243)
2016-6-17 14:43 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
平衡車卡爾曼濾波資料.zip
(1.2 MB, 下載次數: 213)
2016-6-17 14:43 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|