极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2200|回复: 0

如何用蓝牙实现无线定位(三)--远程定位显示

[复制链接]
发表于 2023-1-6 08:48:09 | 显示全部楼层 |阅读模式
本帖最后由 机器谱 于 2023-1-6 08:48 编辑

1. 待救援定位设备
      按照下面的针脚使用杜邦线将待救援定位设备的主蓝牙、从蓝牙连接到主控板上,和本地显示时的连接针脚是一样的,但是由于不需要连接OLED,因此不需要堆叠Bigfish。


烧录程序如下(human.ino):
  1. /*------------------------------------------------------------------------------------

  2.   版权说明:Copyright 2022 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

  3.            Distributed under MIT license.See file LICENSE for detail or copy at

  4.            https://opensource.org/licenses/MIT

  5.            by 机器谱 2022-5-30 https://www.robotway.com/

  6.   -------------------------------------------------------------------------------------*/

  7. //待救援主控例程

  8. //配置模块:(模块在配置时与正常工作时TX、RX线序不同,请注意)

  9. //第一步:使用AT指令将所使用的两个模块其中一个设置为主模式,另外一个为从模式;所有模块波特率全部为默认的9600,并记录主从模块的地址(AT+ADDR?);

  10. //第二步:将主模块在未连接时清除之前的配对信息(AT+CLEAR),再设置其工作类型为类型1(AT+IMME即上后处于等待状态,收到AT+START,AT+DISC,AT+CONNL等指令后开始工作);

  11. //开始工作:

  12. //第三步:将所有模块上电(主从模块按照上面介绍的连接方式连接即可);

  13. //第四步:将本程序下载进MEGA2560中,将从模块分别摆开,观察显示屏数据;


  14. /*********从设备地址********/

  15. //   "D8A98B788750",

  16. //   "D8A98B788732",

  17. //   "380B3CFFC5B0"

  18. /*********从设备地址********/


  19. /**********头文件***************/

  20. #include <Arduino.h>

  21. #include <Wire.h>

  22. #include <MultiLCD.h>

  23. #include <RssiPositionComputer.h>


  24. /***********宏定义**************/

  25. //#define DEBUG_SERIAL Serial   //打印信息串口

  26. #define CON_SERIAL Serial1    //蓝牙通信串口

  27. #define SEND_SERIAL Serial2   //数据发送串口

  28. #define CMD_CON "AT+CON"

  29. #define CMD_DIS_CON "AT"

  30. #define CMD_GET_RSSI "AT+RSSI?"

  31. RssiPositionComputer myPositionComputer;

  32. Point2D master_point;

  33. //基站数量

  34. #define SLAVENUMBER 3

  35. //基站地址

  36. String BLUETOOTHADDRESS[3] = {

  37.   "D8A98B788750",

  38.   "D8A98B788732",

  39.   "380B3CFFC5B0"

  40. };

  41. //位置发送蓝牙地址

  42. // F83002253650

  43. String search_result_string[SLAVENUMBER] = {""};

  44. String rssi[SLAVENUMBER] = {""};

  45. float distance[SLAVENUMBER] = {};


  46. void setup() {

  47.   #if defined(DEBUG_SERIAL)

  48.   DEBUG_SERIAL.begin(9600);

  49.   #endif

  50.   CON_SERIAL.begin(9600);

  51.   SEND_SERIAL.begin(9600);

  52.   delay(1000);

  53.   init_ble();


  54. }

  55. void loop() {

  56.   read_ble(BLUETOOTHADDRESS);

  57.   to_axis(distance, &master_point);

  58. }

  59. //读取串口

  60. String serial_read(int _len){

  61.   String data = "";

  62.   int len = 0;

  63.   unsigned long t = millis() + 500;

  64.   while(1)

  65.   {

  66.     while(CON_SERIAL.available()){

  67.       char c = CON_SERIAL.read();

  68.       data += c;

  69.       len++;

  70.     }  

  71.     if(len == _len){

  72.        break;

  73.     }

  74.     if(millis() > t)

  75.       break;

  76.   }  

  77.   #if defined(DEBUG_SERIAL)

  78.   //DEBUG_SERIAL.println(data);

  79.   #endif


  80.   return data;

  81. }


  82. //初始化

  83. void init_ble(){

  84.   CON_SERIAL.print(CMD_DIS_CON);delay(100);

  85.   serial_read(2);

  86. }

  87. //获取设备 RSSI

  88. void read_ble(String * address){

  89.   for(int i=0;i<SLAVENUMBER;i++){

  90.     CON_SERIAL.print(CMD_DIS_CON);delay(100);

  91.     serial_read(2);

  92.     CON_SERIAL.print(CMD_CON + address[i]);

  93.     serial_read(8);

  94.     delay(500);

  95.     CON_SERIAL.print(CMD_GET_RSSI);

  96.     String rssi_str = serial_read(10);

  97.     String _rssi = rssi_str.substring(7, rssi_str.length());


  98.     //rssi

  99.     rssi[i] = _rssi;

  100.     //distance

  101.     distance[i] = rssiToDistance(rssi[i].toFloat());


  102.     #if defined(DEBUG_SERIAL)

  103.       DEBUG_SERIAL.println("BLE_" + String(i) + ": " + rssi[i]);

  104.       //DEBUG_SERIAL.println("BLE_" + String(i) + ": " + distance[i]);

  105.     #endif


  106.     //delay(800);

  107.   }


  108. }


  109. //计算距离

  110. float rssiToDistance(float rssi){

  111.   float dis = 0;

  112.   //dis = pow(10.0,((abs(rssi)-56)/10.0/1.05));

  113.   dis = pow(10.0,((abs(rssi)-56)/5.0/1.65));

  114.   return dis;  

  115. }


  116. //转换为2d坐标x,y

  117. void to_axis(float * dis, Point2D* actual_master_point){

  118.    //myPositionComputer.distanceToPoint(*dis,*(dis+1),*(dis+2),actual_master_point);

  119.    myPositionComputer.distanceToPoint(*dis,*(dis+1),random(0,77),actual_master_point);


  120.    int x = master_point.x*100;

  121.    int y = master_point.y*100;


  122.    char point[100];


  123.    sprintf(point, "[ax:%3d,ay:%3d]\n",abs(x),abs(y));


  124.    #if defined(DEBUG_SERIAL)

  125.       DEBUG_SERIAL.println(point);

  126.    #endif


  127.    SEND_SERIAL.print(point);

  128. }
复制代码

你也可以按照“本地定位显示”实验的方法,为该定位装置安装OLED模块,这样的话,可以实现本地和远程的同时显示。

2. 构建远程中控台
      远程中控台用于远程、无线、实时显示被定位目标的坐标值,主要由1个Arduino Mega2560控制板、2个BLE4.0模块、1个OLED显示屏、1块锂电池构成。其中两个BLE4.0模块都要设置成主设备模式。
(1)蓝牙模块的配置主蓝牙设备配置命令:
  1. AT+RENEW    //恢复默认设置
  2. AT -- OK//测试模块正常
  3. AT+ADDR? -- MAC//查询模块MAC地址
  4. AT+BAUD0 -- 9600//设置波特率为9600
  5. AT+CLEAR -- OK//清除设备配对信息
  6. AT+IMME1 -- OK    //设置模块工作类型:上电等待触发
  7. AT+ROLE1 -- OK        //设置主从模式:主设备
  8. AT+MODE1 -- OK//设置模块工作模式:远控模式
复制代码
各设备主从蓝牙的MAC地址(以下地址可根据自己的BLE4.0a蓝牙模块进行修改,详细参考:蓝牙配置说明.txt

信号塔设备MAC地址:
  1. 0:D8A98B788750 (从)
  2. 1:D8A98B788732 (从)
  3. 2:380B3CFFC5B0 (从)
复制代码
待救援定位设备MAC地址:
  1. B:F83002253178 (从)
  2. 主:D8A98B788758 (主)
复制代码
中控台设备MAC地址:
  1. 主1:F8300225362D (主)
  2. 主2:F830022538C4 (主)
复制代码


(2)远程中控台的电路连接



OLED显示屏
GND
5V
SDA
SCL
主控板引脚
GND
5V
SDA
SCL

主蓝牙1
3.3V
GND
RX
TX
主控板引脚
3.3V
GND
TX1
RX1

主蓝牙1
3.3V
GND
RX
TX
主控板引脚
5V
GND
TX2
RX2

3. 中控台接收待救援者的坐标位置
       在中控台的控制板中烧录以下程序(master.ino),并在待救援定位装置的主控板中烧录相应的程序,移动待救援定位装置的位置,可以观察到中控台OLED模块显示坐标的变化。

  1. /*------------------------------------------------------------------------------------

  2.   版权说明:Copyright 2022 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

  3.            Distributed under MIT license.See file LICENSE for detail or copy at

  4.            https://opensource.org/licenses/MIT

  5.            by 机器谱 2022-5-30 https://www.robotway.com/

  6.   -------------------------------------------------------------------------------------*/

  7. //救援指挥中心例程

  8. //配置模块:(模块在配置时与正常工作时TX、RX线序不同,请注意)

  9. //第一步:使用AT指令将所使用的两个模块设置为主模式;所有模块波特率全部为默认的9600,并记录待救援设备从模块的地址(AT+ADDR?);

  10. //第二步:将主模块在未连接时清除之前的配对信息(AT+CLEAR),再设置其工作类型为类型1(AT+IMME即上后处于等待状态,收到AT+START,AT+DISC,AT+CONNL等指令后开始工作);

  11. //开始工作:

  12. //第三步:将所有模块上电(主模块参考控制中心的连接进行接线,待救援设备从模块参考相应的连接);

  13. //第四步:将本程序下载进MEGA2560中,将从模块分别摆开,观察显示屏数据;

  14. #include <Arduino.h>

  15. #include <Wire.h>

  16. #include <MultiLCD.h>

  17. #define DATA_SERIAL Serial //信息打印串口

  18. #define HUMAN_SERIAL Serial1 //待救援数据

  19. #define ROBOT_SERIAL Serial2 //救援机器人数据

  20. #define CMD_CON "AT+CON"

  21. #define CMD_DIS_CON "AT"

  22. #define CMD_START "AT+START"

  23. LCD_SSD1306 lcd;

  24. String human_address = "F83002253650"; //待救援设备地址

  25. String robot_address = "F83002253178"; //救援机器人设备地址

  26. String human_point = "[ax: 0 , ay: 0]";

  27. String robot_point = "[bx: 0 , by: 0]";

  28. void setup()

  29. {

  30. DATA_SERIAL.begin(9600);

  31. HUMAN_SERIAL.begin(9600);

  32. ROBOT_SERIAL.begin(9600);

  33. lcd.begin();

  34. master_init();

  35. }

  36. void loop()

  37. {

  38. read_human_point();

  39. read_robot_point();

  40. point_display();

  41. }

  42. void connect_ble()

  43. {

  44. //连接待救援设备地址

  45. // HUMAN_SERIAL.print(CMD_START);delay(1000);

  46. HUMAN_SERIAL.print(CMD_DIS_CON);delay(200);

  47. HUMAN_SERIAL.print(CMD_CON + human_address);

  48. //连接救援机器人设备地址

  49. ROBOT_SERIAL.print(CMD_DIS_CON);delay(200);

  50. ROBOT_SERIAL.print(CMD_CON + robot_address);

  51. }

  52. //读取待救援位置

  53. void read_human_point()

  54. {

  55. while(1)

  56. {

  57. String str;

  58. while(HUMAN_SERIAL.available() > 0)

  59. {

  60. str = HUMAN_SERIAL.readStringUntil('\n');

  61. str.trim();

  62. }

  63. if(!str.equals(""))

  64. {

  65. Serial.println(str);

  66. human_point = str; break;

  67. }

  68. }

  69. }

  70. //读取救援机器人位置

  71. void read_robot_point()

  72. {

  73. while(1)

  74. {

  75. String str;

  76. while(ROBOT_SERIAL.available() > 0)

  77. {

  78. str = ROBOT_SERIAL.readStringUntil('\n');

  79. str.trim();

  80. }

  81. if(!str.equals(""))

  82. {

  83. Serial.println(str);

  84. robot_point = str;

  85. break;

  86. }

  87. }

  88. }

  89. void point_display()

  90. {

  91. lcd.clear();

  92. lcd.setCursor(10, 1);

  93. lcd.print("a: human b: robot");

  94. lcd.setCursor(20, 3);

  95. lcd.print(human_point);

  96. lcd.setCursor(20, 5);

  97. lcd.print(robot_point);

  98. }

  99. void master_init()

  100. {

  101. lcd.clear();

  102. lcd.setCursor(25, 3);

  103. lcd.print("Hello World!");

  104. delay(1000);

  105. point_display();

  106. connect_ble();

  107. while(true)

  108. {

  109. if(HUMAN_SERIAL.available() > 0 || ROBOT_SERIAL.available() > 0)

  110. break;

  111. }

  112. }
复制代码

烧录了例程后,依次开启信号塔、待救援定位装置、中控台的电源,中控台的OLED屏幕上即可显示待救援者的坐标值
注:中控台的电源必须最后打开)

定位效果如下图所示:


4. 资料下载
​资料内容:
​①远程定位显示-例程
​②蓝牙配置说明.txt
​资料下载地址:https://www.robotway.com/h-col-167.html




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 18:46 , Processed in 0.041208 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表