找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 8157|回復(fù): 6
收起左側(cè)

安卓APP+STM32藍(lán)牙控制小車系統(tǒng)設(shè)計(jì)源碼與資料下載

[復(fù)制鏈接]
ID:347672 發(fā)表于 2018-6-8 17:10 | 顯示全部樓層 |閱讀模式
電機(jī)驅(qū)動(dòng)模塊、L298N
主控板、
藍(lán)牙通信模塊、FBT06_LPDB
android控制端等

4.1.1 main程序設(shè)計(jì)
主函數(shù)主要分為延遲時(shí)間初始化、串口接收模塊程序、電機(jī)初始化三部分。主函數(shù)的流程圖如圖4.1所示:
圖4.1 主函數(shù)流程圖
主函數(shù)程序代碼如下:
int main(void)
{  
delay_init(168);//延遲時(shí)間初始化
uart_init(9600);//串口初始化
Direction(1);//電機(jī)初始化
delay_ms(10);//延遲10ms
printf(" welcome to control the smart car!:\n\r");//輸入語句
while(1);
}
4.1.2 串口接收模塊程序
主控板接收到藍(lán)牙從串口傳來的數(shù)據(jù)后存入Res變量,然后通過分支程序來選擇執(zhí)行前進(jìn)、后退、左轉(zhuǎn)、右轉(zhuǎn)和停止等功能。該模塊的程序流程圖如圖2所示:
圖2 串口接收程序流程圖
4.1.3 修改PWM輸出值程序
該程序是基于“4_PWM的實(shí)現(xiàn)”中的程序改編的。代碼如下:
  1. void Change_PWM(int duty1,int duty2,int duty3,int duty4)
  2. {
  3.               SCB->AIRCR=0x05AF00;// 中斷優(yōu)先級(jí)分組 搶占:響應(yīng)=3:1
  4.   RCC->AHB1ENR|=(1<<2);// 打開GPIOC時(shí)鐘
  5.   GPIOC->MODER|=0x000AA000;// pc6789第二功能,推挽輸出
  6.   GPIOC->OSPEEDR|=0x000FF000;//輸出速度為100m
  7.   GPIOC->PUPDR|=0x00055000;//上拉

  8.   GPIOC->AFR[0]|=0x22000000;//pc6789的第二功能為AF2
  9.   GPIOC->AFR[1]|=0x00000022;

  10.   RCC->APB1ENR|=(1<<1);//打開TIM3時(shí)鐘
  11.   TIM3->PSC=83;//對(duì)84M時(shí)鐘進(jìn)行84分頻,使得計(jì)數(shù)頻率為1M
  12.   TIM3->ARR=10000;//周期為10ms
  13.   TIM3->EGR|=1;//產(chǎn)生一次更新時(shí)間

  14.   TIM3->CCMR1|=0x6060;//PWM模式1
  15.   TIM3->CCMR2|=0x6060;//PWM模式2

  16.   TIM3->CCR1=duty1;//1路PWM
  17.   TIM3->CCR2=duty2;//2路PWM
  18.   TIM3->CCR3=duty3;//3路PWM
  19.   TIM3->CCR4=duty4;//4路PWM

  20.   TIM3->CCER|=0x1111;//使能比較輸出

  21.   TIM3->CCMR1|=0x0808;//啟動(dòng)預(yù)裝載
  22.   TIM3->CCMR2|=0x8080;

  23.   TIM3->CR1|=1;//開始計(jì)時(shí)
  24. }
復(fù)制代碼

4.1.4 設(shè)置電機(jī)轉(zhuǎn)向程序
改程序?qū)㈦姍C(jī)驅(qū)動(dòng)模塊的8個(gè)輸入端口接到了主控板的8個(gè)GPIO口,通過推挽輸出,從而控制電機(jī)的轉(zhuǎn)向,代碼如下:
  1. void Direction(int direction)
  2. {
  3. SysTick_Config(SystemCoreClock / 1000); //時(shí)鐘中斷設(shè)為1ms
  4.               RCC->AHB1ENR |= 0x00000005; //使能GPIOA和GPIOD時(shí)鐘
  5.    RCC->APB2ENR |= (1<<14);  //使能syscfg時(shí)鐘
  6. if(direction==0)
  7. {
  8.    GPIOA->MODER &= 0xffff0000; //設(shè)置PA0,1,2,3為輸出
  9.    GPIOA->MODER |= 0x00005555;
  10.    GPIOA->OTYPER &= 0xFFFFff00; //設(shè)置PA0,1,2,3為推挽輸出
  11.    GPIOA->OSPEEDR &= 0xffff0000; //設(shè)置PA0,1,2,3的輸出速度為100M
  12.    GPIOA->OSPEEDR |= 0x0000ffff;
  13.    SYSCFG->CMPCR = 0x00000001; //使用IO補(bǔ)償單元
  14.    GPIOA->PUPDR &= 0xffffff00;  //設(shè)置PA0,1,2,3無上拉,無下拉
  15.    GPIOA->BSRRH = 0x00ff;  //復(fù)位GPIOA_BSRRH寄存器
  16.    GPIOA->BSRRL = 0x0055;                           
  17.               }
  18.               else
  19.               {
  20. GPIOA->MODER &= 0xffff0000; //設(shè)置PA0,1,2,3為輸出
  21.    GPIOA->MODER |= 0x0000005555;
  22.    GPIOA->OTYPER &= 0xFFFFff00; //設(shè)置PA0,1,2,3為推挽輸出
  23.    GPIOA->OSPEEDR &= 0xffff0000; //設(shè)置PA0,1,2,3的輸出速度為100M
  24.    GPIOA->OSPEEDR |= 0x0000ffff;
  25.    SYSCFG->CMPCR = 0x00000001; //使用IO補(bǔ)償單元
  26.    GPIOA->PUPDR &= 0xffffff00;  //設(shè)置PA0,1,2,3無上拉,無下拉
  27.    GPIOA->BSRRH = 0x00ff;  //復(fù)位GPIOA_BSRRH寄存器
  28.    GPIOA->BSRRL = 0x00AA;
  29. }
  30. }
復(fù)制代碼

4.2 android客戶端程序設(shè)計(jì)4.2.1 控制界面的布局
控制界面主要運(yùn)用了線性布局、相對(duì)布局和表格布局。整體采用線性布局,局部采用相對(duì)布局,而控制按鈕采用了表格布局?刂平缑娴牟季秩鐖D4.1所示:
圖4.1 控制界面的布局
4.2.2 布局的代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
<RelativeLayout
   android:id = "@+id/container"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:id= "@+id/edit_bottombar"
                android:layout_alignParentBottom = "true">
     <Button android:id="@+id/btn_disconnect"
                                          android:layout_width="65dp"
                                          android:layout_height="wrap_content"
                                          android:layout_alignParentLeft ="true"
                                          android:text="斷開"/>
                            <Button android:id="@+id/btn_msg_send"
                                          android:layout_width="65dp"
                                          android:layout_height="wrap_content"
                                          android:layout_alignParentRight ="true"
                                          android:text="發(fā)送"/>
                           
                            <EditText
                                android:id="@+id/MessageText"
                                android:layout_width="98dp"
                                android:layout_height="wrap_content"
                                android:layout_toRightOf="@+id/btn_disconnect"
                                android:hint="說點(diǎn)什么呢?"
                                android:textSize="15dip"
                                  />
              </RelativeLayout>
              <ListView
                   android:id="@+id/list"
                   android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_above="@id/edit_bottombar"
                   android:layout_below="@id/container"
                   android:layout_weight="1.0"
                   android:divider="#ffc6c6c6"
                   android:scrollingCache="false"
                   android:visibility="visible" />
              <TableLayout
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content" >
                   <TableRow
                       android:id="@+id/tableRow1"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content" >
                       <Button
                           android:id="@+id/button1"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:text="Button"
                           android:visibility="invisible" />
                       <Button
                           android:id="@+id/start"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:layout_marginRight="0dp"
                           android:text="start"
                           android:width="120px" />
                   </TableRow>
                   <TableRow
                       android:id="@+id/tableRow2"
                       android:layout_width="wrap_content"
                       android:layout_height="0dp"
                       android:layout_weight="1" >
                       <Button
                           android:id="@+id/left"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:layout_marginRight="0dp"
                           android:text="left"
                           android:width="120px" />
                       <Button
                           android:id="@+id/stop"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:text="stop"
                           android:width="120px" />
                       <Button
                           android:id="@+id/right"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:text="right"
                           android:width="120px" />
                   </TableRow>
                   <TableRow
                       android:id="@+id/tableRow3"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content" >
                       <Button
                           android:id="@+id/button2"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:text="Button"
                           android:visibility="invisible" />
                       <Button
                           android:id="@+id/back"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:text="Back" />
                   </TableRow>
              </TableLayout>
</RelativeLayout>
</LinearLayout>
4.2.3 android客戶端的界面如圖4.2所示:
圖4.2 android控制界面
4.2.4 發(fā)送按鈕的代碼
sendButton= (Button)findViewById(R.id.btn_msg_send);
sendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String msgText =editMsgView.getText().toString();//獲取編輯框內(nèi)的內(nèi)容
if (msgText.length()>0) {
              sendMessageHandle(msgText);//發(fā)送編輯框的內(nèi)容給串口            
              editMsgView.setText("");//清空編輯框
              editMsgView.clearFocus();
//close InputMethodManager
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                                          imm.hideSoftInputFromWindow(editMsgView.getWindowToken(), 0);
}
else
Toast.makeText(mContext, "發(fā)送內(nèi)容不能為空!", Toast.LENGTH_SHORT).show();
}
});
4.2.5 控制按鈕的代碼
以左轉(zhuǎn)按鈕為例:
sendButton= (Button)findViewById(R.id.left);
sendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String msgText ="1"; // 發(fā)送左轉(zhuǎn)命令“l(fā)”
if (msgText.length()>0) {
sendMessageHandle(msgText);//發(fā)送“l(fā)”給串口            
editMsgView.setText("");//清空編輯框
editMsgView.clearFocus();
//close InputMethodManager
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editMsgView.getWindowToken(), 0);
}
else
Toast.makeText(mContext, "發(fā)送內(nèi)容不能為空!", Toast.LENGTH_SHORT).show();
}
});
1.        系統(tǒng)創(chuàng)新

自從有了智能手機(jī),機(jī)器人的應(yīng)用也就多了一個(gè)新的方向:手機(jī)控制機(jī)器人。2005年日本第二大電信運(yùn)營商KDDI和機(jī)械制造商IBee KK聯(lián)合推出了第一款手機(jī)控制機(jī)器人。當(dāng)然了,想要操縱這種機(jī)器人,你首先需要使用KDDI網(wǎng)絡(luò),并且用戶的手機(jī)上,本身還需要帶有藍(lán)牙功能,然后再通過KDDI提供BREW方式下載機(jī)器人的驅(qū)動(dòng)程式和控制系統(tǒng)。不過這種機(jī)器人的價(jià)格卻相對(duì)高昂,預(yù)售市價(jià)約合人民幣15000元。隨著Android系統(tǒng)技術(shù)的普及,可以做個(gè)基于Android的客戶端,在小車上裝個(gè)接收藍(lán)牙信號(hào)的FBT藍(lán)牙接收模塊,然后就可以通過客戶端發(fā)送藍(lán)牙信號(hào),來對(duì)藍(lán)牙小車進(jìn)行控制控制,其接收可達(dá)15米,完全能適應(yīng)對(duì)小車的要求。其中這個(gè)FBT藍(lán)牙接收模塊是低耗能,這樣就把更多的能量用在小車的驅(qū)動(dòng)上。

小車需要很大的馬力和很好的靈活性以應(yīng)對(duì)不同的地形。這輛車的車輪使用四驅(qū)的直流電機(jī)來驅(qū)動(dòng)的,用PWM波來控制小車的速度,可以很方便的更改其速度,有主控板通過推挽輸出來控制電機(jī)的翻轉(zhuǎn)以讓車子進(jìn)行后退的速度。這樣就可以勝任對(duì)小車的要求。


2.        評(píng)測(cè)與結(jié)論
首先,給電源模塊上12v的電源,然后打開電機(jī)驅(qū)動(dòng)模塊開關(guān),同時(shí)將主控板的供電端連接到電源管理模塊。然后,在android手機(jī)上安裝“藍(lán)牙通信”應(yīng)用程序后,打開該APP,然后選擇“允許打開藍(lán)牙”。點(diǎn)擊設(shè)備列表中的“開始搜索按鈕”,在設(shè)備列表中選擇藍(lán)牙模塊的名字進(jìn)行連接。
              完成上述工作以后,就可以在手機(jī)上通過按下“start”、“l(fā)eft”、“stop”、“right”、“back”通過藍(lán)牙給小車發(fā)送“前進(jìn)”、“左轉(zhuǎn)”、“停止”、“右轉(zhuǎn)”、“后退”5個(gè)命令。小車可以解析命令輕松進(jìn)行前進(jìn)、后退、左轉(zhuǎn)、右轉(zhuǎn)和停止。



附錄
圖6-1 作品成果1
圖6-2 作品成果2


全部資料51hei下載地址:
硬件設(shè)計(jì)及文檔.zip (1.87 MB, 下載次數(shù): 119)
軟件源代碼及文檔.rar (639.46 KB, 下載次數(shù): 126)
基于stm32f4的藍(lán)牙控制小車_論文.doc (399 KB, 下載次數(shù): 83)

回復(fù)

使用道具 舉報(bào)

ID:243748 發(fā)表于 2018-6-25 06:56 來自觸屏版 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

ID:428445 發(fā)表于 2018-11-17 21:45 | 顯示全部樓層
感謝分享
回復(fù)

使用道具 舉報(bào)

ID:366466 發(fā)表于 2019-1-10 09:50 | 顯示全部樓層
很好的東西很有用
回復(fù)

使用道具 舉報(bào)

ID:673954 發(fā)表于 2019-12-25 20:47 | 顯示全部樓層
剛需,但是黑幣不夠 太痛苦了
回復(fù)

使用道具 舉報(bào)

ID:673954 發(fā)表于 2019-12-25 20:50 | 顯示全部樓層
牛逼!
回復(fù)

使用道具 舉報(bào)

ID:549580 發(fā)表于 2020-5-22 22:52 | 顯示全部樓層
這個(gè)APP怎么安裝啊

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表