最简单DIY基于STM32F407探索者开发板的MPU6050陀螺仪姿态控制舵机程序
STM32庫函數(shù)開發(fā)系列文章目錄
第一篇:STM32F103ZET6單片機(jī)雙串口互發(fā)程序設(shè)計(jì)與實(shí)現(xiàn)
第二篇:最簡單DIY基于STM32單片機(jī)的藍(lán)牙智能小車設(shè)計(jì)方案
第三篇:最簡單DIY基于STM32F407探索者開發(fā)板的MPU6050陀螺儀姿態(tài)控制舵機(jī)程序
文章目錄
- STM32庫函數(shù)開發(fā)系列文章目錄
- 前言
- 一、最簡單DIY基于STM32F407探索者開發(fā)板的MPU6050陀螺儀姿態(tài)控制舵機(jī)程序是什么?
- 二、使用步驟
- 1.準(zhǔn)備硬件
- 2.準(zhǔn)備正點(diǎn)原子開源的MPU6050的代碼
- 3.準(zhǔn)備正點(diǎn)原子PWM輸出的代碼
- 4.修改源碼和組合源碼(這部分原創(chuàng))
- 三、運(yùn)行與調(diào)試
- 總結(jié)
前言
????daodanjishui物聯(lián)網(wǎng)核心原創(chuàng)技術(shù)之最簡單DIY基于STM32F407探索者開發(fā)板的MPU6050陀螺儀姿態(tài)控制舵機(jī)程序。
????市面上有各種開源STM32舵機(jī)控制器,但是有復(fù)雜的有簡單的,如果想快速入門stm32f407zgt6姿態(tài)傳感器的舵機(jī)控制,這個(gè)方案會(huì)給你一個(gè)快捷高效的方案。
一、最簡單DIY基于STM32F407探索者開發(fā)板的MPU6050陀螺儀姿態(tài)控制舵機(jī)程序是什么?
????我記得在“51單片機(jī)智能小設(shè)計(jì)”專欄中講述了51單片機(jī)如何通過寄存器激發(fā)PWM波控制sg90舵機(jī)的博文。但是由于51單片機(jī)資源有限,再加上復(fù)雜的姿態(tài)解算,很難同時(shí)完成姿態(tài)解算控制舵機(jī)的任務(wù),所以誕生了這個(gè)博文。
????這次的方案主要是:基于正點(diǎn)原子STM32F407探索者開發(fā)板和MPU6050陀螺儀來采集航向角從而使用IO口直接控制一個(gè)舵機(jī)翻轉(zhuǎn)。下面請看全家福:
????這次的程序使用的stm32庫函數(shù)來編程,說實(shí)話也修改了正點(diǎn)原子開發(fā)板配套的例程,正點(diǎn)原子移植了arduino版本的IIC控制MPU6050的庫才有了我這個(gè)下文,為了實(shí)現(xiàn)這個(gè)STM32舵機(jī)的控制,我查閱了網(wǎng)上很多有關(guān)舵機(jī)控制的資料和視頻,我?guī)缀鯔M掃了全部正點(diǎn)原子關(guān)于舵機(jī)控制的論壇帖子,有含金量的帖子基本上沒有多少,給出源碼的程序我覺得多多少少有點(diǎn)問題,也踩了很多坑!有些人會(huì)說:“daodanjishui你何必那么執(zhí)著呢?大把a(bǔ)rduino的庫給你使用來控制舵機(jī),控制MPU6050,你卻硬要從底層出發(fā)去控制舵機(jī)!”我說:“一個(gè)合格的軟硬件設(shè)計(jì)工程師至少要攻破底層,才能真正流暢地控制硬件。做到這一點(diǎn),隨隨便便去控制一個(gè)機(jī)械手又有何難呢?再寫一個(gè)上位機(jī)去控制舵機(jī)又有何難呢?再多寫一個(gè)手機(jī)控制舵機(jī)的APP又有何難?假如一直在用匿名四軸的上位機(jī)調(diào)試MPU6050,你能寫一個(gè)自己的上位機(jī)出來嗎?人家目前不開源,你還能寫出這樣的上位機(jī)么?呵呵”。到目前為止,我確實(shí)寫出了一個(gè)舵機(jī)控制的上位機(jī):最簡單DIY基于C#和51單片機(jī)上下位機(jī)一體化的PCA9685舵機(jī)控制程序,總之寫代碼是痛苦的,在這個(gè)吃快餐的時(shí)代最好的辦法就是復(fù)制粘貼“拿來主義”,但是并不是什么都可以拿的,有時(shí)候自己去嘗試的時(shí)候才發(fā)現(xiàn)沒有東西可以拿,只能硬著頭皮擼起袖子加油干。
優(yōu)酷視頻演示地址:https://v.youku.com/v_show/id_XNTAxMDg2NzE0OA==.html
直接觀看
最簡單DIY基于STM32F407探索者開發(fā)板的MPU6050陀螺儀姿態(tài)控制舵機(jī)程序
二、使用步驟
1.準(zhǔn)備硬件
1.1正點(diǎn)原子探索者開發(fā)板一個(gè),如果沒有的話用STM32F407ZGT6核心板也可以的,現(xiàn)在美國ST公司禁售該芯片,估計(jì)以后這個(gè)芯片就被淘汰了。
1.2舵機(jī)sg90一個(gè)。
1.3MPU6050模塊一個(gè)。
1.4正點(diǎn)原子4.3寸電容顯示屏一個(gè)。(如果沒有的話可以屏蔽該部分代碼)
2.準(zhǔn)備正點(diǎn)原子開源的MPU6050的代碼
我采用庫函數(shù)開發(fā),所以代碼直接使用該開發(fā)板配套的免費(fèi)開源源碼進(jìn)行二次開發(fā)。源碼來源:探索者光盤資料\A盤\4,程序源碼\2,標(biāo)準(zhǔn)例程-庫函數(shù)版本\實(shí)驗(yàn)32 MPU6050六軸傳感器實(shí)驗(yàn)
代碼如下(示例):
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "key.h" #include "lcd.h" #include "mpu6050.h" #include "inv_mpu.h" #include "inv_mpu_dmp_motion_driver.h" //ALIENTEK 探索者STM32F407開發(fā)板 實(shí)驗(yàn)32 //MPU6050六軸傳感器 實(shí)驗(yàn) -庫函數(shù)版本 //技術(shù)支持:www.openedv.com //淘寶店鋪:http://eboard.taobao.com //廣州市星翼電子科技有限公司 //作者:正點(diǎn)原子 @ALIENTEK//串口1發(fā)送1個(gè)字符 //c:要發(fā)送的字符 void usart1_send_char(u8 c) {while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,c); } //傳送數(shù)據(jù)給匿名四軸上位機(jī)軟件(V2.6版本) //fun:功能字. 0XA0~0XAF //data:數(shù)據(jù)緩存區(qū),最多28字節(jié)!! //len:data區(qū)有效數(shù)據(jù)個(gè)數(shù) void usart1_niming_report(u8 fun,u8*data,u8 len) {u8 send_buf[32];u8 i;if(len>28)return; //最多28字節(jié)數(shù)據(jù) send_buf[len+3]=0; //校驗(yàn)數(shù)置零send_buf[0]=0X88; //幀頭send_buf[1]=fun; //功能字send_buf[2]=len; //數(shù)據(jù)長度for(i=0;i<len;i++)send_buf[3+i]=data[i]; //復(fù)制數(shù)據(jù)for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i]; //計(jì)算校驗(yàn)和 for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]); //發(fā)送數(shù)據(jù)到串口1 } //發(fā)送加速度傳感器數(shù)據(jù)和陀螺儀數(shù)據(jù) //aacx,aacy,aacz:x,y,z三個(gè)方向上面的加速度值 //gyrox,gyroy,gyroz:x,y,z三個(gè)方向上面的陀螺儀值 void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz) {u8 tbuf[12]; tbuf[0]=(aacx>>8)&0XFF;tbuf[1]=aacx&0XFF;tbuf[2]=(aacy>>8)&0XFF;tbuf[3]=aacy&0XFF;tbuf[4]=(aacz>>8)&0XFF;tbuf[5]=aacz&0XFF; tbuf[6]=(gyrox>>8)&0XFF;tbuf[7]=gyrox&0XFF;tbuf[8]=(gyroy>>8)&0XFF;tbuf[9]=gyroy&0XFF;tbuf[10]=(gyroz>>8)&0XFF;tbuf[11]=gyroz&0XFF;usart1_niming_report(0XA1,tbuf,12);//自定義幀,0XA1 } //通過串口1上報(bào)結(jié)算后的姿態(tài)數(shù)據(jù)給電腦 //aacx,aacy,aacz:x,y,z三個(gè)方向上面的加速度值 //gyrox,gyroy,gyroz:x,y,z三個(gè)方向上面的陀螺儀值 //roll:橫滾角.單位0.01度。 -18000 -> 18000 對應(yīng) -180.00 -> 180.00度 //pitch:俯仰角.單位 0.01度。-9000 - 9000 對應(yīng) -90.00 -> 90.00 度 //yaw:航向角.單位為0.1度 0 -> 3600 對應(yīng) 0 -> 360.0度 void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw) {u8 tbuf[28]; u8 i;for(i=0;i<28;i++)tbuf[i]=0;//清0tbuf[0]=(aacx>>8)&0XFF;tbuf[1]=aacx&0XFF;tbuf[2]=(aacy>>8)&0XFF;tbuf[3]=aacy&0XFF;tbuf[4]=(aacz>>8)&0XFF;tbuf[5]=aacz&0XFF; tbuf[6]=(gyrox>>8)&0XFF;tbuf[7]=gyrox&0XFF;tbuf[8]=(gyroy>>8)&0XFF;tbuf[9]=gyroy&0XFF;tbuf[10]=(gyroz>>8)&0XFF;tbuf[11]=gyroz&0XFF; tbuf[18]=(roll>>8)&0XFF;tbuf[19]=roll&0XFF;tbuf[20]=(pitch>>8)&0XFF;tbuf[21]=pitch&0XFF;tbuf[22]=(yaw>>8)&0XFF;tbuf[23]=yaw&0XFF;usart1_niming_report(0XAF,tbuf,28);//飛控顯示幀,0XAF } int main(void) { u8 t=0,report=1; //默認(rèn)開啟上報(bào)u8 key;float pitch,roll,yaw; //歐拉角short aacx,aacy,aacz; //加速度傳感器原始數(shù)據(jù)short gyrox,gyroy,gyroz; //陀螺儀原始數(shù)據(jù)short temp; //溫度NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級分組2delay_init(168); //初始化延時(shí)函數(shù)uart_init(500000); //初始化串口波特率為500000LED_Init(); //初始化LED KEY_Init(); //初始化按鍵LCD_Init(); //LCD初始化MPU_Init(); //初始化MPU6050POINT_COLOR=RED;//設(shè)置字體為紅色 LCD_ShowString(30,50,200,16,16,"Explorer STM32F4"); LCD_ShowString(30,70,200,16,16,"MPU6050 TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2014/5/9");while(mpu_dmp_init()){LCD_ShowString(30,130,200,16,16,"MPU6050 Error");delay_ms(200);LCD_Fill(30,130,239,130+16,WHITE);delay_ms(200);}LCD_ShowString(30,130,200,16,16,"MPU6050 OK");LCD_ShowString(30,150,200,16,16,"KEY0:UPLOAD ON/OFF");POINT_COLOR=BLUE;//設(shè)置字體為藍(lán)色 LCD_ShowString(30,170,200,16,16,"UPLOAD ON "); LCD_ShowString(30,200,200,16,16," Temp: . C"); LCD_ShowString(30,220,200,16,16,"Pitch: . C"); LCD_ShowString(30,240,200,16,16," Roll: . C"); LCD_ShowString(30,260,200,16,16," Yaw : . C"); while(1){key=KEY_Scan(0);if(key==KEY0_PRES){report=!report;if(report)LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");else LCD_ShowString(30,170,200,16,16,"UPLOAD OFF");}if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0){ temp=MPU_Get_Temperature(); //得到溫度值MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度傳感器數(shù)據(jù)MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺儀數(shù)據(jù)if(report)mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);//用自定義幀發(fā)送加速度和陀螺儀原始數(shù)據(jù)if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));if((t%10)==0){ if(temp<0){LCD_ShowChar(30+48,200,'-',16,0); //顯示負(fù)號temp=-temp; //轉(zhuǎn)為正數(shù)}else LCD_ShowChar(30+48,200,' ',16,0); //去掉負(fù)號 LCD_ShowNum(30+48+8,200,temp/100,3,16); //顯示整數(shù)部分 LCD_ShowNum(30+48+40,200,temp%10,1,16); //顯示小數(shù)部分 temp=pitch*10;if(temp<0){LCD_ShowChar(30+48,220,'-',16,0); //顯示負(fù)號temp=-temp; //轉(zhuǎn)為正數(shù)}else LCD_ShowChar(30+48,220,' ',16,0); //去掉負(fù)號 LCD_ShowNum(30+48+8,220,temp/10,3,16); //顯示整數(shù)部分 LCD_ShowNum(30+48+40,220,temp%10,1,16); //顯示小數(shù)部分 temp=roll*10;if(temp<0){LCD_ShowChar(30+48,240,'-',16,0); //顯示負(fù)號temp=-temp; //轉(zhuǎn)為正數(shù)}else LCD_ShowChar(30+48,240,' ',16,0); //去掉負(fù)號 LCD_ShowNum(30+48+8,240,temp/10,3,16); //顯示整數(shù)部分 LCD_ShowNum(30+48+40,240,temp%10,1,16); //顯示小數(shù)部分 temp=yaw*10;if(temp<0){LCD_ShowChar(30+48,260,'-',16,0); //顯示負(fù)號temp=-temp; //轉(zhuǎn)為正數(shù)}else LCD_ShowChar(30+48,260,' ',16,0); //去掉負(fù)號 LCD_ShowNum(30+48+8,260,temp/10,3,16); //顯示整數(shù)部分 LCD_ShowNum(30+48+40,260,temp%10,1,16); //顯示小數(shù)部分 t=0;LED0=!LED0;//LED閃爍}}t++; } }3.準(zhǔn)備正點(diǎn)原子PWM輸出的代碼
因?yàn)榭刂贫鏅C(jī)需要用到PWM波,那么就需要用到PWM有關(guān)的開源代碼,代碼路徑是:探索者光盤資料\A盤\4,程序源碼\2,標(biāo)準(zhǔn)例程-庫函數(shù)版本\實(shí)驗(yàn)9 PWM輸出實(shí)驗(yàn)
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "pwm.h"//ALIENTEK 探索者STM32F407開發(fā)板 實(shí)驗(yàn)9 //PWM輸出實(shí)驗(yàn)-庫函數(shù)版本 //技術(shù)支持:www.openedv.com //淘寶店鋪:http://eboard.taobao.com //廣州市星翼電子科技有限公司 //作者:正點(diǎn)原子 @ALIENTEKint main(void) { u16 led0pwmval=0; u8 dir=1;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置系統(tǒng)中斷優(yōu)先級分組2delay_init(168); //初始化延時(shí)函數(shù)uart_init(115200);//初始化串口波特率為115200TIM14_PWM_Init(500-1,84-1); //84M/84=1Mhz的計(jì)數(shù)頻率,重裝載值500,所以PWM頻率為 1M/500=2Khz. while(1) //實(shí)現(xiàn)比較值從0-300遞增,到300后從300-0遞減,循環(huán){delay_ms(10); if(dir)led0pwmval++;//dir==1 led0pwmval遞增else led0pwmval--; //dir==0 led0pwmval遞減 if(led0pwmval>300)dir=0;//led0pwmval到達(dá)300后,方向?yàn)檫f減if(led0pwmval==0)dir=1; //led0pwmval遞減到0后,方向改為遞增TIM_SetCompare1(TIM14,led0pwmval); //修改比較值,修改占空比} }4.修改源碼和組合源碼(這部分原創(chuàng))
這里有兩部分原創(chuàng)的代碼:
(1)第一部分
(2)第二部分
//下面的測試代碼,讓舵機(jī)從0度轉(zhuǎn)到180,再回到0度,不斷循環(huán)led0pwmval=975;//0度TIM_SetCompare1(TIM14,led0pwmval);delay_ms(1000);led0pwmval=950;//45度TIM_SetCompare1(TIM14,led0pwmval);delay_ms(1000);led0pwmval=925;//90度TIM_SetCompare1(TIM14,led0pwmval);delay_ms(1000);led0pwmval=900;//135度TIM_SetCompare1(TIM14,led0pwmval);delay_ms(1000);led0pwmval=875;//180度TIM_SetCompare1(TIM14,led0pwmval);delay_ms(1000);說明:第一個(gè)部分是舵機(jī)控制的核心算法,我自己推導(dǎo)出來化簡的。第二部分是舵機(jī)測試程序,測試舵機(jī)固定動(dòng)作的。讀者根據(jù)這些代碼推敲出結(jié)果是沒有問題的,我當(dāng)時(shí)也花了不少時(shí)間去推敲。如果真的不想推敲了,請下載我最后附錄上的工程代碼。
三、運(yùn)行與調(diào)試
(1)功能說明:用MPU6050的姿態(tài)數(shù)據(jù)控制舵機(jī)翻轉(zhuǎn)0到180度,并且支持用匿名四軸上位機(jī)調(diào)試仿真波形和舵機(jī)狀態(tài),買家可以根據(jù)代碼改為多個(gè)舵機(jī)控制。
(2)代碼說明:用MDK5寫的庫函數(shù)代碼
(3)硬件說明:需要用到正點(diǎn)原子探索者開發(fā)板,配套他們自家的4.3寸電容屏,配套他們自己家的MPU6050模塊,一個(gè)其他家的SG90舵機(jī)。如果經(jīng)濟(jì)條件不錯(cuò)的買家就可以拿正點(diǎn)原子全家桶套裝來測試,連線基本上不用考慮,直接插上就能用,除了舵機(jī)那個(gè)數(shù)據(jù)線要自己接而已。要是想省錢,那就自己琢磨程序里面有注釋的IO管腳定義去自己接線了,同時(shí)也要考慮沒有接顯示屏?xí)龅绞裁村e(cuò)誤自己慢慢排查,反正接舵機(jī)的IO口是PA7,我是全家桶套裝的使用者,不需要考慮那么多
(4) 軟件說明:用了正點(diǎn)原子探索者庫函數(shù)版本 實(shí)驗(yàn)32 MPU6050六軸傳感器實(shí)驗(yàn) 的代碼進(jìn)行修改而成,正點(diǎn)原子的手冊也介紹的程序基本使用方法和代碼注釋,另外還可以使用匿名四軸的上位機(jī)來調(diào)試舵機(jī)。需要接上串口,波特率調(diào)到500000(最大)。如下圖所示:
仿真說明:姿態(tài)波形展示如下圖
舵機(jī)翻轉(zhuǎn)角度圖,航向角變化就是舵機(jī)角度的變化如下圖是0度
舵機(jī)翻轉(zhuǎn)角度圖,航向角變化就是舵機(jī)角度的變化如下圖是26度
舵機(jī)翻轉(zhuǎn)9度情況如下圖顯示
翻轉(zhuǎn)90度的舵機(jī)如下
????通過上面運(yùn)行與調(diào)試證明了程序狀態(tài)良好,達(dá)到博文提出的要求。
總結(jié)
????有些讀者說:為什么不用PCA9685控制舵機(jī)呢?其實(shí)我已經(jīng)推出,只不過這是STM32控制舵機(jī)的入門篇,不能一下子加大難度。
????擴(kuò)展說明:如果搞定了一個(gè)舵機(jī),那么就可以搞定多個(gè)舵機(jī),用庫函數(shù)寫代碼效率是很高的,不像我上次用51單片機(jī)控制舵機(jī)那么麻煩的,全部是配置寄存器和定時(shí)器。所以我稱之為最簡單的舵機(jī)控制程序,我寫的核心的代碼就幾行,能看懂的讀者就賺大了。剩下的就是正點(diǎn)原子的MPU6050示例代碼,不懂的讀者可以親自看看正點(diǎn)原子的教程文檔。
????下期預(yù)告:下期用stm32控制PCA9685模塊間接去集群控制多個(gè)舵機(jī),并且用紅外線遙控器控制舵機(jī)組成的機(jī)械臂,精彩不容錯(cuò)過,值得期待。
最后附上本博文代碼下載地址:https://www.cirmall.com/circuit/22260/
直接跳轉(zhuǎn)
正點(diǎn)原子相關(guān)代碼免費(fèi)下載
總結(jié)
以上是生活随笔為你收集整理的最简单DIY基于STM32F407探索者开发板的MPU6050陀螺仪姿态控制舵机程序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java版的mrp模拟器,mrp模拟器
- 下一篇: 手机游戏简要介绍