摘要: 針對多變環境攝像的環境,遙控攝像車多為無線遙控,也需要對環境有一定檢測和處理。因此,遙控通信的復雜程度比較大。本文通過程序設計,依托藍牙的數據傳輸完成對攝像車的控制及其他多種功能。
關鍵詞:攝像車 遙控 藍牙 通信
目的
編寫通信程序,通過藍牙所發送的數據控制攝像車的運行,并且返回車子運行時的參數和環境狀態等參數到遙控器顯示屏顯示。
總體設計
通信設計分為硬件設計和軟件設計兩部分,硬件設計為藍牙設計,這里我們采用已有模塊使用;軟件設計為通信程序設計和協議設計。
藍牙設備
現有藍牙模塊的功能比較穩定,設計技術成熟。我們根據設計需求,選擇要使用的藍牙模塊。通信時需要車子與遙控之間是雙向通信,互相發送數據。因此,選擇可以主從機一體化的藍牙模塊。所選藍牙傳輸距離:視距10米 ,Flash存儲容量:6-8Mbit,滿足當前設計需求。藍牙模塊相應參數過多,這里不做詳細介紹。
程序設計
通信設計主體在于通信協議的設計。之前介紹了遙控與車子之間是雙向通信,且通信數據復雜繁多。通過用藍牙發送簡單數據來完成通信任務是不可能。藍牙所傳輸數據在0-255之間,256個數據根本不能控制車子的各種精細動作和顯示車子運行參數和環境數據。因此,要通過設計通信協議將數據進行擴充,加大通信數據的大小,實現復雜數據的傳輸。
初步構想,將數據拆分多個簡單數據,依次發送。把復雜數據進行拆分,拆分為高低位,這樣就可以把所發數據由256擴充到65536。在65536的數據大小傳輸能夠分別完成攝像車的精細測量和操作(攝像頭三維度角度調整、車子舵機精度角度調節、環境參數精度分辨)。
上面我們能夠完成單一動作的高精度控制,但是需要控制或測量的對象不是一個,為此需要進一步設計通信程序,來完成全局的控制和測量。進一步設計,我們需要傳輸大量的數據,要想數據能過不出錯的傳輸,就要對數據進行分類分批發送。
先將所有的數據分類編號,按發送順序或發送頻率排好序,按照序列進行編號并且做好記錄注明。但是多數據傳輸時,傳輸連接不穩斷開或數據輸出跳變出錯后,重連數據傳輸會導致數據接收解算出現錯誤,導致車子不受控制。因此,設計時考慮到上述問題,需要將數據進行打包處理,使得錯誤數據對程序應降到最小。采用現有一些通信協議模型,我們設計了如圖1的程序流程,這樣一個錯誤的數據只會影響一個參數的大小,并且在下一次相同參數數據傳輸過來時被刷新替代。
簡述一下框圖流程,我們把最大數據255作為數據報頭,當接受255時,數據接收正式開始接收存儲,之后依次會有數據類型、數據正負值、數據高低位的數據傳輸,最后接收完數據后進入數據整合程序,完成數據的還原,發給控制程序和相應程序運算使用。這個框架只是為了大數據量所開發的通用通信設計,我們實際最后整車所用的數據大體在30多個數據,我們可以將流程簡化一步,將第二步數據類型和第三步數據正負值,整合在同一個數據內發送出去。這樣系統在長周期內,控制頻率更高了,控制性能指標提升了。
圖1
實驗過程
上面我們分析了理論設計思想,下面我們來用實踐來一步步完善程序調試。
藍牙連接調試
我們首先要連接藍牙保證通訊媒介的正常使用。藍牙調試主要有藍牙命名、密碼設定、工作頻率設定、主從機設定等。這些相關設定我們通過AT指令來完成,設定藍牙完成后,藍牙能過正常連接在一起。再連接完成后,我們進行簡單數據的傳輸,測試通信能正常完成。調試完成進入第二步。
數據接收調試
通過設計程序使得我們能控制此時發送數據的值,通過將發送數據顯示在顯示屏上,檢查數值與我們發送的數據相同。數據是相互對傳的,在接收進行簡單計算返回數據,進行顯示對比數據沒有異常。要長時間通信,檢測通訊數據在長期工作下不出現錯誤。完成測試后,進入下一步。
通信程序調試
編寫完整的通信程序,依次測試每個數據的傳輸和解算整合,并將每個數據發送到顯示屏,逐個檢查沒有出現錯誤傳輸或異常現象。在正常工作情況下完成測試后,進行異常工作測試。將通訊設備移到通訊的極限距離外一段時間,再拿回連接,記錄設備重連后的接收數據,對比數據能夠恢復正常通訊的數據。完成全部測試,證明程序設計沒有錯誤,可以使用該程序進行工作。
總結
我們通過設計通信程序,對數據進行分類、拆分等手段,并依次發送數據。從而,利用小數據發送的藍牙完成了大數據量的發送,完成對車子整體控制和相關環境因素的測量。
附錄:部分程序代碼
發送數據的選擇程序第一段無降頻處理
if(fangsongshunxu==0)
{
sci_int_send(sudu);
}
if(fangsongshunxu==1)
{
sci_int_send(zhuanxiang);
}
if(fangsongshunxu==2)
{
sci_int_send(sxtzuoyou);
}
if(fangsongshunxu==3)
{
sci_int_send(sxtfuyang);
}
if(fangsongshunxu==4)
{
sci_int_send(dangwei);
}
if(fangsongshunxu==5)
{
sci_int_send(sxtqijiang);
}
if(fangsongshunxu==6)
{
sci_int_send(canshutiaozheng);
canshutiaozheng=0;
}
if(fangsongshunxu==7)
{
sci_int_send(moshi);
}
if(fangsongshunxu==8)
{
sci_int_send(shuzhijiao);
}
fangsongshunxu=fangsongshunxu+1;
if(fangsongshunxu>8)
{
fangsongshunxu=0;
}
通過fangsong變量的值降低發送頻率
if(fangsongshunxu==0&&fangsong==0)
{
sci_int_send(chejiao);
fangsong=1;
}
if(fangsongshunxu==1&&fangsong==0)
{
sci_int_send(gdzxp);
fangsong=1;
}
if(fangsongshunxu==2&&fangsong==0)
{
sci_int_send(gdzxd);
fangsong=1;
}
if(fangsongshunxu==3&&fangsong==0)
{
sci_int_send(gdsudu);
fangsong=1;
}
if(fangsongshunxu==4&&fangsong==0)
{
sci_int_send(jiaosuduyushe);
fangsong=1;
}
if(fangsongshunxu==5&&fangsong==0)
{
sci_int_send(G);
fangsong=1;
}
if(fangsongshunxu==6&&fangsong==0)
{
sci_int_send(zxzhongzhi);
fangsong=1;
}
if(fangsongshunxu==7&&fangsong==0)
{
sci_int_send(yutaizhongzhi);
fangsong=1;
}
if(fangsongshunxu==8&&fangsong==0)
{
sci_int_send(sxtfuyangzz);
fangsong=1;
}
if(fangsongshunxu==9&&fangsong==0)
{
sci_int_send(wendu);
fangsong=1;
}
if(fangsongshunxu>9)
{
fangsongshunxu=0;
}
//串口發送//
//---------------------------------------------------------------------
// 函數功能:UART0_Init初始化
// 形式參數: 無
// 函數返回值:無
//---------------------------------------------------------------------
void UART0_Init(void)
{
SCI0CR1 = 0x00;
SCI0CR2 = 0x2C; //接收中斷使能,發送接收使能
SCI0BD = 0x2b; //波特率配置成115200
//When IREN = 0 then
//SCI baud rate = SCI bus clock / (16 x SBR[12:0])
}
//---------------------------------------------------------------------
// 函數功能:SCI0發送一個字節數據
// 形式參數: byte ch:發送的一個字節數據
// 函數返回值:無
//---------------------------------------------------------------------
void UART0_SendByte(byte ch)
{
while(!(SCI0SR1&0x80));
SCI0DRL = ch;
}
//---------------------------------------------------------------------
// 函數功能:SCI0發送字符串數據
// 形式參數: byte *pBuff 發送緩沖區
// int Length 發送字節的長度
// 函數返回值:無
//---------------------------------------------------------------------
void UART0_SendPacket(byte *pBuf,int pBuf_Length)
{
int i;
for(i=0;i<pBuf_Length;i++)
{
while(!(SCI0SR1&0x80));
SCI0DRL=*(pBuf+i);
}
}
//---------------------------------------------------------------------
// 函數功能:SCI0接受字符串數據
// 函數返回值:無符號
//---------------------------------------------------------------------
unsigned char SCI_0Read(void)
{
if(SCI0SR1_RDRF==1)
{
SCI1SR1_RDRF=1;
return SCI0DRL;
}
}
//---------------------------------------------------------------------
通信協議程序部分
拆分高低字節,將位數較高的數據化為兩個低位數據
正負數判斷和處理(中間部分括號內程序為數據類型選擇)
//---------------------------------------------------------------------
void sci_int_send(int num)
{
unsigned char dath,datl;
if(num<0)
{
datl=(uchar)(~num&0x00ff);//拆低字節
dath=(uchar)(~num>>8);//拆高字節
while(!(SCI0SR1&0x80));
SCI0DRL=255;
if(fangsongshunxu==0)
{
while(!(SCI0SR1&0x80));
SCI0DRL=2;
}
if(fangsongshunxu==1)
{
while(!(SCI0SR1&0x80));
SCI0DRL=3;
}
if(fangsongshunxu==2)
{
while(!(SCI0SR1&0x80));
SCI0DRL=4;
}
if(fangsongshunxu==3)
{
while(!(SCI0SR1&0x80));
SCI0DRL=5;
}
if(fangsongshunxu==4)
{
while(!(SCI0SR1&0x80));
SCI0DRL=6;
}
if(fangsongshunxu==5)
{
while(!(SCI0SR1&0x80));
SCI0DRL=7;
}
if(fangsongshunxu==6)
{
while(!(SCI0SR1&0x80));
SCI0DRL=8;
}
if(fangsongshunxu==7)
{
while(!(SCI0SR1&0x80));
SCI0DRL=9;
}
if(fangsongshunxu==8)
{
while(!(SCI0SR1&0x80));
SCI0DRL=10;
}
while(!(SCI0SR1&0x80));
SCI0DRL=1;
while(!(SCI0SR1&0x80));
SCI0DRL=dath;
while(!(SCI0SR1&0x80));
SCI0DRL=datl;
}
else
{
datl=(uchar)(num&0x00ff);//拆低字節
dath=(uchar)(num>>8);//拆高字節
while(!(SCI0SR1&0x80));
SCI0DRL=255;
if(fangsongshunxu==0)
{
while(!(SCI0SR1&0x80));
SCI0DRL=2;
}
if(fangsongshunxu==1)
{
while(!(SCI0SR1&0x80));
SCI0DRL=3;
}
if(fangsongshunxu==2)
{
while(!(SCI0SR1&0x80));
SCI0DRL=4;
}
if(fangsongshunxu==3)
{
while(!(SCI0SR1&0x80));
SCI0DRL=5;
}
if(fangsongshunxu==4)
{
while(!(SCI0SR1&0x80));
SCI0DRL=6;
}
if(fangsongshunxu==5)
{
while(!(SCI0SR1&0x80));
SCI0DRL=7;
}
if(fangsongshunxu==6)
{
while(!(SCI0SR1&0x80));
SCI0DRL=8;
}
if(fangsongshunxu==7)
{
while(!(SCI0SR1&0x80));
SCI0DRL=9;
}
if(fangsongshunxu==8)
{
while(!(SCI0SR1&0x80));
SCI0DRL=10;
}
while(!(SCI0SR1&0x80));
SCI0DRL=0;
while(!(SCI0SR1&0x80));
SCI0DRL=dath;
while(!(SCI0SR1&0x80));
SCI0DRL=datl;
}
}
終端部分通信逆運算,算出各種數據的值
/*************************中斷服務程序***************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 20 sci0(void)
{
if(SCI0SR1_RDRF==1)
{
SCI1SR1_RDRF=1;
shuju= SCI0DRL;
}
if(shuju==255&&zhunbei==0)
{
kaishi=1;
zhunbei=1;
}
if(kaishi==1)
{
if(shuju==2)
{
chezijiaodusj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==3)
{
gdzxpsj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==4)
{
gdzxdsj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==5)
{
sudupsj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==6)
{
suduisj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==7)
{
sududsj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==8)
{
zxzhongzhisj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==9)
{
yutaizhongzhisj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==10)
{
sxtfuyangzzsj=1;
zhengfu=1;
kaishi=0;
}
if(shuju==11)
{
wendusj=1;
zhengfu=1;
kaishi=0;
}
}
if(chezijiaodusj==1&&dushu==1)//車子角度
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
chezijiaodu=datah*256+datal;
if(zhengshu==1)
{
chezijiaodu=0-chezijiaodu;
}
zhenghe=0;
dushu=0;
zhunbei=0;
chezijiaodusj=0;
}
}
if(gdzxpsj==1&&dushu==1) //光電P
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
gdzxp=datah*256+datal;
if(zhengshu==1)
{
gdzxp=0-gdzxp;
}
zhenghe=0;
dushu=0;
zhunbei=0;
gdzxpsj=0;
}
}
if(gdzxdsj==1&&dushu==1) //光電D
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
gdzxd=datah*256+datal;
if(zhengshu==1)
{
gdzxd=0-gdzxd;
}
zhenghe=0;
dushu=0;
zhunbei=0;
gdzxdsj=0;
}
}
if(sudupsj==1&&dushu==1)//速度P
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
sudup=datah*256+datal;
if(zhengshu==1)
{
sudup=0-sudup;
}
zhenghe=0;
dushu=0;
zhunbei=0;
sudupsj=0;
}
}
if(suduisj==1&&dushu==1)//速度P
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
sudui=datah*256+datal;
if(zhengshu==1)
{
sudui=0-sudui;
}
zhenghe=0;
dushu=0;
zhunbei=0;
suduisj=0;
}
}
if(sududsj==1&&dushu==1)//速度P
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
sudud=datah*256+datal;
if(zhengshu==1)
{
sudud=0-sudud;
}
zhenghe=0;
dushu=0;
zhunbei=0;
sududsj=0;
}
}
if(zxzhongzhisj==1&&dushu==1) //轉向中值
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
zxzhongzhi=datah*256+datal;
if(zhengshu==1)
{
zxzhongzhi=0-zxzhongzhi;
}
zhenghe=0;
dushu=0;
zhunbei=0;
zxzhongzhisj=0;
}
}
if(yutaizhongzhisj==1&&dushu==1)//云臺中值
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
yutaizhongzhi=datah*256+datal;
if(zhengshu==1)
{
yutaizhongzhi=0-yutaizhongzhi;
}
zhenghe=0;
dushu=0;
zhunbei=0;
yutaizhongzhisj=0;
}
}
if(sxtfuyangzzsj==1&&dushu==1) //攝像頭中值
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
sxtfuyangzz=datah*256+datal;
if(zhengshu==1)
{
sxtfuyangzz=0-sxtfuyangzz;
}
zhenghe=0;
dushu=0;
zhunbei=0;
sxtfuyangzzsj=0;
}
}
if(wendusj==1&&dushu==1)//溫度
{
if(diyici==1)
{
datal=shuju;
diyici=0;
zhenghe=1;
}
if(diyici==0&&zhenghe==0)
{
datah=shuju;
diyici=1;
}
if(zhenghe==1)
{
wendu=datah*256+datal;
if(zhengshu==1)
{
wendu=0-wendu;
}
zhenghe=0;
dushu=0;
zhunbei=0;
wendusj=0;
}
}
if(shuju==0&&zhengfu==1)
{
zhengshu=0;
zhengfu=0;
dushu=1;
}
if(shuju==1&&zhengfu==1)
{
zhengshu=1;
zhengfu=0;
dushu=1;
}
}
|