初衷:
進一步降低學習門檻,使用純Python 編寫GUI 上位機,Python 易於編程,算法資料算法豐富。
TWR 算法上位機一般使用Deca官方提供的GUI上位機,使用QT C++編寫,代碼臃腫,不適合學習,同時三邊定位算法部分晦澀難懂。
之前在論壇開源了底層固件,再次補充一個開源版本上位機,實現了全流程的開源。
界面預覽:
源碼文件:
1.twr_51uwb_v2.py 主函數入口,同時處理TCP連接和界面顯示
2.twr_main.py 主要負責數據結構解析,並實現定位計算,這個文件有三邊定位算法,大家可以替換嘗試其他算法
3.Coordinate_process.py 基站坐標處理,匹配預設基站地址,確定基站坐標
4. globalvar.py 共享全局變量,主要多文件共享基站地址和坐標信息
5.mainwindow.py 界面文件,使用qtdesign 繪制,並使用pyuic 自動生成的文件
主要功能:
1 通過TCP 獲取信息,串口轉TCP參見視頻https://www.bilibili.com/video/BV1rv411p7Hj/
2 解析收到的數據並完成解算
3 在界面顯示基站和標簽相對位置
4 統計框中顯示標簽坐標
5 上位機支持多基站,並且可以根據checkbox 確認是否使能基站
6 支持調試接口,可以將想要的數據打印到調試界面
7 支持標簽history 定位點數量設定,默認5,最大20
8 支持標簽根據歷史信息顯示不同透明度
開發環境:
Python 3.6(64bit),推薦集成開發環境PyCharm 社區版
主要庫:pyqt5,numpy
其他:
目前找的三邊算法,只支持2D 定位,並且需要4個基站。大家可以根據需要替換定位算法。
tril2d = Trilateration()
tril2d.setDistances(Info['distance'])
tril2d.setAnthorCoor(Info['anthor'])
result_x, result_y = tril2d.trilaterate2D()
數據格式說明:
&&&:20$0005:AD$0001:0080:11#0002:0080:22#0003:0081:33#0004:0079:44$AA##
TODO
源碼:
論壇開源鏈接下載:http://51uwb.cn/forum.php?mod=viewthread&tid=401&extra=page%3D1
改上位機可以匹配我們全新開源固件,可以應用與隧道等復雜定位場景。目前可以使用已有代碼簡單修改為4基站,若干標簽定位。 多基站+若干標簽定位全新固件已經開發完成,鏈接 http://51uwb.cn/forum.php?mod=viewthread&tid=402&extra=page%3D1
同時該上位機支持現有BP30/BP400固件,只需要定位固件代碼修改3個地方:
1 修改最大基站數目
#define MAX_ANTHOR 4
2 修改tx_main.c 數據格式
static void Send_Dis_To_Anthor0(void)
{
// printf("Debug here");
static int framenum = 0 ;
char crc_byte = 0;
//only send this message to anthor0:short address equal 0x0001
msg_f_send.destAddr[0] =(0x0001) &0xFF;
msg_f_send.destAddr[1] = ((0x0001)>>8) &0xFF;
msg_f_send.seqNum = distance_seqnum;
msg_f_send.messageData[0]='M';
uint8 *pAnthor_Str = &msg_f_send.messageData[1];
int str_len = 0x20;
sprintf(pAnthor_Str, "&&&:%02X$%04X:%02X",str_len,SHORT_ADDR,msg_f_send.seqNum);//AA55 ANTHORID
pAnthor_Str = pAnthor_Str + 15;
//printf(pAnthor_Str);
//0001:A1B1:11#
uint16 shortaddress = 0x0001;
uint8 rssi = 0x11;
sprintf(pAnthor_Str, "%04X:%04X:%02X#",shortaddress,Final_Distance[0],rssi);
pAnthor_Str = pAnthor_Str + 13;
shortaddress = 0x0002;
rssi = 0x22;
sprintf(pAnthor_Str, "%04X:%04X:%02X#",shortaddress,Final_Distance[1],rssi);
pAnthor_Str = pAnthor_Str + 13;
shortaddress = 0x0003;
rssi = 0x33;
sprintf(pAnthor_Str, "%04X:%04X:%02X#",shortaddress,Final_Distance[2],rssi);
pAnthor_Str = pAnthor_Str + 13;
shortaddress = 0x0004;
rssi = 0x44;
sprintf(pAnthor_Str, "%04X:%04X:%02X$AA##",shortaddress,Final_Distance[3],rssi);
pAnthor_Str = pAnthor_Str + 17;
sprintf(pAnthor_Str, "\r\n");
while(msg_f_send.messageData[str_len] != '\n')
{
crc_byte =crc_byte^msg_f_send.messageData[str_len];
str_len++;
}
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, !GPIO_PIN_RESET);//PA node ,enable pa
dwt_writetxdata(11 + str_len,(uint8 *)&msg_f_send, 0) ; // write the frame data
dwt_writetxfctrl(11 + str_len, 0);
dwt_starttx(DWT_START_TX_IMMEDIATE);
while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
{ };
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);
framenum++;
LCD_Display_Distance();
}
3 修改rx_main.c 上傳數據量
case 'M':
USART_puts(&msg_f->messageData[1],72);
break;
說明:
按照如上修改固件,分別編譯標簽和4個基站,將定位距離數據通過地址為0x0001 的基站串口輸出,並通過串口轉WIFI模塊傳入到上位機。
整體TODO
上位機: 上位機動態選取最優4個基站定位(RSSI最大)
固件增強: 固件目前沒有提取RSSI,固定使用4基站,后期可以改成動態,通過動態發現周圍基站並測距,然后匯總。