006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程

2023-11-07 18:59

本文主要是介绍006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程

一、问题提出

在平衡小车制作过程中,需要对KP/KD/KSP/KSI等PID系数进行调试,而平衡小车无法通过USB等进行有线调试,而ESP32-C3自带蓝牙+WIFI,使用WIFI比较吃算力,故选择通过蓝牙进行调参,同时能够将Angle/Encoder/PWM等数据回传至手机端进行查看。
在这里插入图片描述

二、合宙ESP32-C3自带蓝牙分析

前期通过查找资料,发现合宙ESP32-C3自带蓝牙不是经典蓝牙,无法使用BluetoothSerial.h进行编程,只能通过低功耗BLE使用蓝牙。
下面为需要用到的库,PIO环境自带,无需下载。

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

具体原理,没有理解明白,不在赘述。

三、蓝牙调试器分析

蓝牙调试器有3种模式,分别为对话模式、专业调试、按钮控制
需要特别注意的是其通信设置,也就是通信协议。
在这里插入图片描述

在这里插入图片描述

数据包结构为

包头数据校验和包尾
1字节bool为1字节1字节1字节
0xA50x5A

四、代码框架

/*********************头文件*********************/
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
/************************************************//********************基本设置********************/
/**/    hw_timer_t *timer=NULL;
/**/    void BClock_Init(int duty_ms);
/**/    static void IRAM_ATTR Timer0_CallBack(void);  //以上为定时器
/**/    void Short2Byte(short i,uint8_t *byte);
/**/    void Int2Byte(int i,uint8_t *byte);
/**/    void Float2Byte(float f,uint8_t *byte);       //以上为数据类型转BYTE
/************************************************/#define Step1_BlueTooth 1/*********************蓝牙BLE********************/    
/**/#if Step1_BlueTooth
/**/    BLEServer *pServer = NULL;
/**/    BLECharacteristic * pTxCharacteristic;
/**/    bool deviceConnected = false;
/**/    bool oldDeviceConnected = false;
/**/    uint8_t txValue = 0;
/**/    #define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
/**/    #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
/**/    #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
/**/    class MyServerCallbacks: public BLEServerCallbacks 
/**/    {
/**/        void onConnect(BLEServer* pServer) 
/**/        {
/**/            deviceConnected = true;
/**/        };
/**/    
/**/        void onDisconnect(BLEServer* pServer) 
/**/        {
/**/            deviceConnected = false;
/**/        }
/**/    };
/**/    void getBlueData(uint8_t *Value);
/**/    uint8_t modes[8];
/**/    class MyCallbacks: public BLECharacteristicCallbacks 
/**/    {
/**/        void onWrite(BLECharacteristic *pCharacteristic) 
/**/        {
/**/            std::string rxValue = pCharacteristic->getValue();
/**/            if (rxValue.length() > 0) 
/**/            {
/**/                for (int i = 0; i < rxValue.length(); i++)
/**/                {
/**/                    modes[i]=rxValue[i];
/**/                }
/**/                getBlueData(modes);
/**/            }
/**/        }
/**/    };
/**/    void BLEinit()
/**/    {
/**/        BLEDevice::init("BalanceCar");
/**/        pServer = BLEDevice::createServer();
/**/        pServer->setCallbacks(new MyServerCallbacks());
/**/        BLEService *pService = pServer->createService(SERVICE_UUID);
/**/        pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);                      
/**/        pTxCharacteristic->addDescriptor(new BLE2902());
/**/        BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
/**/        pRxCharacteristic->setCallbacks(new MyCallbacks());
/**/        pService->start();
/**/        pServer->getAdvertising()->start();
/**/        Serial.println("BLE is OK.");
/**/    }
/**/#endif 
/************************************************/void setup() 
{Serial.begin(115200);#if Step1_BlueToothBLEinit();#endifBClock_Init(1000);  //定时器单位为ms,发送数据至手机的频率
}//
以上不需要做任何修改
//
//+++++_____+++++_____+++++_____+++++_____+++++_____以上不需要做任何修改_____+++++_____+++++_____+++++_____+++++_____+++++//
//
以上不需要做任何修改
////
以下不需要做任何修改
//
//+++++_____+++++_____+++++_____+++++_____+++++_____以下不需要做任何修改_____+++++_____+++++_____+++++_____+++++_____+++++//
//
以下不需要做任何修改
//static void IRAM_ATTR Timer0_CallBack(void)
{BLEsendflag=true;
}void BClock_Init(int duty_ms)
{timer=timerBegin(0,80,true);timerAttachInterrupt(timer,Timer0_CallBack,true);timerAlarmWrite(timer,1000*duty_ms,true); // 单位us,定时模式,10mstimerAlarmEnable(timer); // 启动定时器
}void Short2Byte(short i,uint8_t *byte)
{unsigned long longdata=0;longdata=*(unsigned long *)&i;byte[1]=(longdata&0xFF00)>>8;byte[0]=(longdata&0x00FF);
}void Int2Byte(int i,uint8_t *byte)
{unsigned long longdata=0;longdata=*(unsigned long *)&i;byte[3]=(longdata&0xFF000000)>>24;byte[2]=(longdata&0x00FF0000)>>16;byte[1]=(longdata&0x0000FF00)>>8;byte[0]=(longdata&0x000000FF);
}void Float2Byte(float f,uint8_t *byte)
{unsigned long longdata=0;longdata=*(unsigned long *)&f;byte[3]=(longdata&0xFF000000)>>24;byte[2]=(longdata&0x00FF0000)>>16;byte[1]=(longdata&0x0000FF00)>>8;byte[0]=(longdata&0x000000FF);
}

自己需要做的只是在中间加上 void loop()

五、手机——>单片机解码

手机发送5个数据 bool(MotorStatus)、int16_t(kp)、int16_t(kd)、int16_t(ksp)、int16_t(ksi)
在这里插入图片描述

/*****************蓝牙发送接收数据*****************/
/**/#if Step1_BlueTooth
/**/    bool MotorStatus;//控制电机开关
/**/    int16_t kp,kd,ksp,ksi;
/**/    //以上为手机发送来的数据
/**/    bool BLEsendflag=false;//定时发送标志
/**/#endif  
/************************************************/void loop() 
{}#if Step1_BlueTooth
/**/    void getBlueData(uint8_t *Value)
/**/    {
/**/        MotorStatus=Value[1];
/**/        kp=(Value[3]<<8)+Value[2];  
/**/        kp=(Value[3]<<8)+Value[2];
/**/        kd=(Value[5]<<8)+Value[4];
/**/        ksp=(Value[7]<<8)+Value[6];
/**/        ksi=(Value[9]<<8)+Value[8];
/**/        Serial.printf("MotorStatus=%d,kp=%d,kd=%d,ksp=%d,ksi=%d\n",MotorStatus,kp,kd,ksp,ksi);
/**/    }
#endif 

六、单片机——>手机编码

单片机发送3个数据 short(PwmOut)、int(Encode_L)、float(Angle)
在这里插入图片描述

/*****************蓝牙发送接收数据*****************/
/**/#if Step1_BlueTooth
/**/    bool BLEsendflag=false;//定时发送标志/**/    
/**/    uint8_t BLEBUF[13];// 数据包的顺序为BOOL(1)/BYTE(1)/SHORT(2)/INT(4)/FLOAT4)
/**/    short PwmOut=-12;
/**/    int Encode_L=-34;
/**/    float Angle=5.6;
/**/#endif  
/************************************************/void loop() 
{if(deviceConnected&BLEsendflag){BLEsendflag=false;BLEBUF[0]=0xA5;//包头Short2Byte(PwmOut,&BLEBUF[1]);Int2Byte(PwmOut,&BLEBUF[3]);Float2Byte(Angle,&BLEBUF[7]);BLEBUF[11]=(uint8_t)((BLEBUF[1]+BLEBUF[2]+BLEBUF[3]+BLEBUF[4]+BLEBUF[5]+BLEBUF[6]+BLEBUF[7]+BLEBUF[8]+BLEBUF[9]+BLEBUF[10])&0xFF);BLEBUF[12]=0x5A;//包尾pTxCharacteristic->setValue(BLEBUF,13);pTxCharacteristic->notify();}
}

这篇关于006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/365646

相关文章

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

python连接本地SQL server详细图文教程

《python连接本地SQLserver详细图文教程》在数据分析领域,经常需要从数据库中获取数据进行分析和处理,下面:本文主要介绍python连接本地SQLserver的相关资料,文中通过代码... 目录一.设置本地账号1.新建用户2.开启双重验证3,开启TCP/IP本地服务二js.python连接实例1.

Python 安装和配置flask, flask_cors的图文教程

《Python安装和配置flask,flask_cors的图文教程》:本文主要介绍Python安装和配置flask,flask_cors的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,... 目录一.python安装:二,配置环境变量,三:检查Python安装和环境变量,四:安装flask和flas

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3