基于Arduino的蓝牙通信

本文介绍了如何在Arduino小车上实现蓝牙遥控,包括使用BT05蓝牙模块、AT指令、数据结构设计(布尔值与字符值)以及软串口调试。作者详细阐述了硬件配置、AT指令应用和两种不同的数据设计方法的比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于Arduino的蓝牙通信

前言: 本文主要以Arduino小车中的蓝牙遥控作为案例来讲解蓝牙通信。了解相关编程和数据设计。
功能和结构上:一个舵机控制小车前排车轮转向(模拟阿克曼转向结构),另外两个舵机控制车前部两轴云台,云台上放置ESP32 CAM用来拍摄。超声波传感器用来自动避障、三路红外用来巡线。


本例中用到的硬件:
主控UNO或Nano,
扩展板1块(板载有源蜂鸣器和蓝牙接口),
TT马达4个,
舵机3个,
超声波传感器1个,
三路红外传感器1个,
ESP32 CAM1个,
电源等


1.了解蓝牙模块

1.1.介绍

BT05 低功耗4.0蓝牙

  • 超低待机功耗 90uA~400uA
  • 超远连接距离100英尺/60米
  • 超快反应速度 0.4秒
  • 兼容iOS等多平台
  • 收发无字节限制,最高可达3K Bytes/秒

AT 指令只能在模块未连接状态下才能生效,一旦蓝牙模块与设备连接上,蓝牙模块即进入数据透传模式

AT指令集指南

1.2.引脚连接方式

  • 准备TTL转USB模块和蓝牙模块:(用Arduino板CH340再通过软串口同样可以在串口调试器上调试,不需要转接器)
    在这里插入图片描述
  • 连接线路
    在这里插入图片描述

2.串口调试助手(拓展,用于了解蓝牙AT命令)

2.1.打开即用串口助手

串口调试助手sscom下载

2.2.基础介绍

  • 1.确认端口号正确,而且没有被占用(这很重要,否则打开串口失败,例如Arduino IDE选中了该COM号之后在这里选同一个就会报警告);
  • 2.勾选“加回车换行”,这样在输入指令时就不需要加回车换行;
  • 3.波特率设置与蓝牙默认的保持一致(一般默认9600);
    在这里插入图片描述
    更多获取蓝牙信息的操作请看上文AT指令集指南

3.蓝牙调试APP作为小车遥控器

3.1.安装APP(安卓)

下载安装(与串口调试同链接)

3.2.APP使用介绍

来自大佬的教程

4.蓝牙通信数据设计

从功能上考虑遥控时需要通信的数据结构,一种是布尔值,一种是字符值。什么情况下用布尔值,例如控制小车左转弯,当你按下按钮发送信息左转,松手就不左转,只有动作和不动作两种情况,所以用布尔值。当你遥控小车想要不同速度行驶,这时发送速度信息就是速度值,是一个过程变化的量,用一个字节-128~127作为通信。同理,舵机控制转向左右角度值也是过程变化的量,同样各占用一个字节

4.1.蓝牙助手端数据设计

在这里插入图片描述
云台和单点控制组成一字节,剩下运动模式继续排在下一字节。移动方向摇杆和速度滑杆使用单独一字节。
APP内的数据结构设置:
在这里插入图片描述
这里面的逻辑值设置先后排序与下一节中代码设计有对应关系,不能乱调换位置。关于数据传输、数据帧等更多相关详细内容欢迎查看之前博文串行通信

4.2.主控板端代码数据设计

数据位为5个字节,加上包头、校验和包尾共8个字节的蓝牙数据包。

byte RX_package[8] = {0};
typedef struct      //5字节分布:
{
  byte ControlMode; //遥控八位:bit0~7:原地左转0x01、原地右转0x02、云台左转0x04、云台右转0x08、云台向上0x10、云台向下0x20、方向盘回正0x40、蜂鸣器打开0x80;
  byte MoveMode;    //运动模式四位:bit0~3:自由控制模式0x01、避障模式0x02、循迹模式0x04、跟随模式0x08
  byte x_axis = 0;  //摇杆X轴
  byte y_axis = 0;  //摇杆Y轴
  byte speed = 0;   //速度控制(App端控件范围默认-128~127,要想速度从0开始,就要加上128)
}rx_buffer;

为了更好的调试蓝牙数据,采用了软串口,避免频繁拔掉rx/tx。同时避免串口阻塞,增加Serialcount清阻。下面的小样例测试代码用Nano板测试的,蓝牙的TX连接Nano的D4,RX连接D3引脚,可以获取到调试APP发来的信息。

#include<SoftwareSerial.h>
/*
*SoftwareSerial(rxPin, txPin, inverse_logic)
*rxPin:接收串行数据的引脚。
*txPin:传输串行数据的引脚。
*inverse_logic:用于反转输入位的含义(默认为正常逻辑)。如果设置,
                SoftwareSerial 将 RX 引脚上的低电平(引脚上通常为 0v)
                视为 1 位(空闲状态),将高电平(引脚上通常为 5V)视为 0 位
                。它还会影响写入 TX 引脚的方式。默认值为 false。
*/  
int myvalue =0;
int Serialcount = 0;
SoftwareSerial softSerial(4, 3);
byte RX_package[8] = {0};
typedef struct      //5字节分布:
{
  byte ControlMode; 
  byte MoveMode;    
  byte x_axis = 0;  //摇杆X轴
  byte y_axis = 0;  //摇杆Y轴
  byte speed = 0;   //速度控制
}rx_buffer;

rx_buffer RX_buffer;

void setup() {
  Serial.begin(9600);
  softSerial.begin(9600);
  // softSerial.listen();
  // Serial.println(softSerial.isListening());
}

void loop() {
  if(softSerial.available()>0){
    delay(1);
    if(softSerial.readBytes(RX_package,8)){
      if(RX_package[0] == 0xA5 && RX_package[7] == 0x5A){
        Serialcount =0;
        RX_buffer.ControlMode = RX_package[1];
        RX_buffer.MoveMode = RX_package[2];
        RX_buffer.x_axis = RX_package[3];
        RX_buffer.y_axis = RX_package[4];
        RX_buffer.speed = map(RX_package[5], -128, 127, 0, 255);//-128~127
      }else{
          Serialcount++;
          // Serial.println("getit");
          return;
      }
        Serial.print("[1]ControlMode:");
        Serial.print(RX_package[1]);
        Serial.print("[2]MoveMode:");
        Serial.print(RX_package[2]);
        Serial.print("[3]X:");
        //无符号byte类型在print打印时自动转成有符号类型,
        //如果不转为int8_t看到的数值就不是负数,而是更大的数
        Serial.print((int8_t)RX_buffer.x_axis);
        Serial.print("[4]Y:");
        Serial.print((int8_t)RX_buffer.y_axis);
        Serial.print("[5]speed:");
        Serial.println(RX_buffer.speed);
    }
  }else
    {
        delay(1);
        Serialcount++;
        if(Serialcount > 500)
        {
            Serialcount = 0;
            RX_buffer.ControlMode = 0; 
            RX_buffer.MoveMode = 0;
            RX_buffer.x_axis = 0;
            RX_buffer.y_axis = 0;
        }
    }
}

在调试过程中遇到小问题:在Arduino IDE中,Serial.print() 函数将整数类型自动解释为有符号整数,因此当你传递负数给 Serial.print() 函数时,它会将其解释为有符号整数进行打印,而不会打印负号。导致数值不正确,折腾了好一会儿,用一个(int8_t)搞定了。

打开串口监视器得到的信息与预期一致:

在这里插入图片描述

4.3.不一定的数据设计

直接一个按钮对应一个字节,按一下发一个字符。每一个指令都有对应一个字符,接收到一个字符证明就有一个按钮按下。


if (Serial1.available() > 0) {  //判断接收到的数据是否大于0
    char ser_val = Serial1.read();
    Serial.print("ser_val=");
    Serial.println(ser_val);
    switch (ser_val) {
      case 'S': F_MOD = 0; break;  //车轮停止转动
      case 'F': F_MOD = 1; Serial.print("FFFFF");break;  //前进
      case 'B': F_MOD = 2; break;  //后退
      case 'Q': F_MOD = 3; break;  //方向盘回正后 原地左转
      case 'E': F_MOD = 4; break;  //方向盘回正后 原地右转

      case 'H': servo_mod = 0; break;  //云台、方向盘停止转动

      case 'Z': servo_mod = 1; break;  //方向盘左转
      case 'X': servo_mod = 2; break;  //方向盘回正
      case 'C': servo_mod = 3; break;  //方向盘右转

      case 'O': servo_mod = 4; break;  //云台回正
      case 'I': servo_mod = 5; break;  //云台左转
      case 'P': servo_mod = 6; break;  //云台右转
      case 'A': servo_mod = 7; break;  //云台向上
      case 'D': servo_mod = 8; break;  //云台向下

      case 'J': Buzzer = true; break;   //蜂鸣器打开
      case 'K': Buzzer = false; break;  //蜂鸣器关闭

      case '4': Car_MOD = 0; break;    //自由控制模式
      case '5': Car_MOD = 1; break;    //避障模式
      case '6': Car_MOD = 2; Steer_middle(); break; //默认先回正方向,切寻迹模式
      case '7': Car_MOD = 3; break;  //跟随模式
      default: break;
    }
  }

总结:
后一种通信设计功能上同样可以实现,与前一种方式相比需要增加一些停止的指令,在按钮松开时要发送停止指令。同时设置的按钮指令也会更多,对于蓝牙调试APP中有限的按钮设置来说不太现实的。将布尔值的开关量用字符值来代替在通信效率上也差了一些。对于同一字节来讲每一条指令为互斥关系,按了前进就不能同时旋转舵机,而前一种数据设计一个字节包含多个操作,在实际应用上更灵活,整体代码关系更简单。

搞完后才感慨这次又了解了不少东西,蓝牙AT命令、软串口和借助CH340在串口调试助手上调试数据、数据类型的设计转换等等。明天元宵开耍!开心!

Arduino小车通常会搭配蓝牙模块用于无线控制,连接过程分为几个步骤: 1. **准备硬件**: - 准备一个带有蓝牙功能的Arduino扩展板(如 HC-05/HC-06 或 Adafruit Bluefruit LEUART)和一个Arduino主控板。 - 确保所有电子元件已正确安装并供电。 2. **软件设置**: - 安装Arduino IDE 并更新到最新版本。 - 在IDE中选择正确的Arduino核心库,如果是基于蓝牙的模块,可能需要下载对应的蓝牙库,例如 Adafruit_BluefruitLE 或 Arduino_Network。 3. **配置蓝牙模块**: - 在Arduino IDE 中新建或打开项目,将蓝牙模块作为子设备连接。在代码中定义好蓝牙端口号和名称(如果有的话)。 4. **编写代码**: - 使用提供的示例代码,初始化蓝牙,并监听来自智能手机或其他蓝牙设备的连接请求。当接到连接后,可以通过蓝牙发送控制指令,如移动命令、停止等。 5. **手机端应用**: - 下载支持蓝牙通信的应用,如Arduino Bluetooth Control或自建简单的蓝牙客户端程序,通过蓝牙Arduino发送指令。 6. **调试测试**: - 连接蓝牙,检查设备是否成功配对,并确认接收和发送数据是否正常。通过调整代码和手机应用中的参数,优化蓝牙连接性能。 相关问题-- 1. 如何在Arduino IDE中找到并添加蓝牙库? 2. 如果蓝牙连接不稳定,应该检查哪些方面的问题? 3. 除了蓝牙,还可以用什么方式远程控制Arduino小车?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安可瑞Ankory

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值