ESP32:蓝牙BLE控制M3508电机
ESP32:蓝牙BLE控制M3508电机

先给各位朋友拜个年,祝大家新春快乐,事事顺利,身体健康啊!
还是熟悉的3508,内容概述:
- ESP32主控
- 蓝牙BLE通信
- 使用实时系统(FreeRTOS)
- 使用ESP32的TWAI总线(CAN)
ESP32使用ESP-IDF v4.3开发,仓库地址放在文末。
目录
ESP32的TWAI(CAN)
概览与对比
有人说ESP32没有CAN总线控制器,其实不然,只不过它被称作TWAI,two-wire automotive interface。这也是ESP32可以用来控制大疆M3508、M2006等电机的根本原因。由于官方放出的资料很少,所以不被大家所熟知。
ESP32的CAN控制器在功能上比STM32略逊一筹,同时技术披露较少,其硬件设计参数基本都是未知的。但从另一方面说,整体配置使用比STM32更简单一些的,特别是结合实时系统提供的一些组件,不需要过多的考虑中断等问题。
最大区别在于,STM32有三组FIFO和灵活分配的filter,ESP32则采用收发buffer,控制器硬件将接受到的消息放入buffer中,软件驱动再把buffer中的报文处理过后放入queue,用户应用读取queue获取报文,发送同理。
反馈的获取
ESP32没有提供中断回调函数接口。意味着STM32上使用接收中断来更新电机反馈的方法是行不通的,为保证反馈量的实时性,有以下三种方法可以选择:
- 使用优先级合适的任务进行轮询
- 利用定时器中断回调进行轮询
- 利用TWAI控制器的alert查询阻塞读取
由于我使用的FreeRTOS的tick为10ms,而大疆C620电调的发送速率默认为1KHz,所以我使用了第一个方法来获取电机反馈数据。创建一个从queue中读取报文的任务,不断阻塞查询queue,计算更新反馈数据。
蓝牙BLE
ESP32的最大亮点就是支持WiFi、蓝牙协议栈,使用蓝牙代替串口的应用场景无需多言。其中低功耗蓝牙BLE非常合适少量文本数据的发送。下面简要介绍几个蓝牙BLE概念。
GAP
GAP定义了设备的广播行为,例如手机可以扫描到很多蓝牙BLE设备便是靠GAP。GAP把设备分成两种:中心设备(Central)、外围设备(Peripheral),外围设备对外不断广播,中心设备扫描、接收广播。发现后进而建立连接,再利用下文的GATT协议进行数据传输。
举例来说,我们的手机往往扮演中心设备的角色,而智能手环、智能家居、蓝牙耳机、电动牙刷等设备则是外围设备。
GATT
利用GAP发现并连接相应设备后,就可以开始传输数据了。蓝牙BLE的数据传输建立在GATT协议上,它定义了BLE设备之间如何传输数据。GATT把设备分为Client和Server,其中命令与请求由Client主动发起,Server被动接受。
请注意:GATT的Client、Server身份与GAP的中心、外围设备没有任何关系,它们可以任意搭配,甚至可以既是Server又是Client。
参考:Getting Started with Bluetooth Low Energy:https://www.oreilly.com/library/view/getting-started-with/9781491900550/ch04.html
在本例中,运行着GATT Server的ESP32在建立连接前主动对外广播,充当外围设备。手机作为GATT Client,可以主动发起数据传输。
下面是典型的GATT Server的数据层级结构图,服务端上可以同时提供多个Service让客户端选择,每个Service内可以有多个Characteristic,其中就保存着数据的内容和描述。客户端请求的时候就可以单独请求某个Service里的某个Characteristic包含的数据。

举例说明,某款智能手环作为GATT Server,定义了电量和运动两个Service。电量服务内有一个Characteristic保存着电池电量百分比,手机请求它即可获得手环电量。运动Service内有步数、消耗卡路里、睡眠时间等Characteristic,手机可以在需要的时候分别请求这些数据。
由于蓝牙协议内容较多,这里暂不展开,后面有机会可以进一步深入讨论。
ESP32 API
为了使用BLE,首先要把蓝牙外设驱动、硬件初始化,按照之前说的,为了建立连接我们要初始化GAP,为了传输数据要初始化GATT。具体表现为要为GAP、GATT注册处理事件的回调函数。
ret = esp_ble_gatts_register_callback(gatts_event_handler);
//错误处理
ret = esp_ble_gap_register_callback(gap_event_handler);
//错误处理
ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID);
//错误处理
这些回调函数使用switch语句判断由底层驱动传递上来的事件编号,并给出处理步骤,我们对其中的读写事件处理进行修改,使其符合我们的数据传输需求。
结合前面完成的TWAI驱动、移植的PID程序,电机控制程序基本完成。
实际上手
使用微信上的BLE调试小程序或者Nordic Connect软件都可以,后者较为专业简洁,但两者功能上差别不大。

向图中的Characteristic发送速度目标值,会触发ESP_GATTS_WRITE_EVT事件,在处理中加入解析并向发送设备返回一个notify告知写入成功:
char data[30];
memcpy(data,param->write.value,param->write.len);
data[param->write.len]=0;
moto_pid.target=atof(data);
printf("resetting target:%.2f\n",moto_pid.target);
sprintf(data,"SET TARGET:%.2f",moto_pid.target);
if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){//发送notice
esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id,
gl_profile_tab[PROFILE_A_APP_ID].char_handle,
strlen(data),(unsigned char *)data, false);}
当按下左边的获取按钮时,会触发ESP_GATTS_READ_EVT事件,使用response让Client获得图中的速度值:
char spd[20];
sprintf(spd,"speed:%hd",moto_chassis->speed_rpm);
rsp.attr_value.len = strlen(spd);
memcpy(rsp.attr_value.value,spd,rsp.attr_value.len);
esp_ble_gatts_send_response(gatts_if, param->read.conn_id,
param->read.trans_id,
ESP_GATT_OK, &rsp);
总结
临近年关,事也多,心也燥。这次本是简单的移植,文章却一直拖到正月初二才写完。涉及蓝牙协议栈的东西不敢多说,还需要多加研究。最后,祝大家新春快乐,工作顺利,身体健康!
工程仓库地址:GitHub:https://github.com/HuXioAn/ESP32-M3508-BLE
技术新人,水平有限,文中纰漏请一定指出,如有其他意见也请不吝赐教。更多嵌入式相关内容请移步公众号,来找我聊聊天吧:

欢迎转载,转载请注明作者与原文地址。
作者:胡小安
原文地址:https://www.cnblogs.com/huxiaoan/p/15861624.html
ESP32:蓝牙BLE控制M3508电机的更多相关文章
- 蓝牙BLE实用教程
蓝牙BLE实用教程 Bluetooth BLE 欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 设置 里的修改模板来改变新建文章的内容. 1.蓝牙BLE常见问答 Q: Smart Re ...
- 蓝牙(BLE)应用框架接口设计和应用开发——以TI CC2541为例
本文从功能需求的角度分析一般蓝牙BLE单芯片的应用框架(SDK Framework)的接口设计过程,并以TI CC2541为例说明BLE的应用开发方法. 一.应用框架(Framework) 我们熟知的 ...
- 深入浅出低功耗蓝牙(BLE)协议栈
深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解蓝牙"连接"?如果蓝牙协议只有ATT没有GATT会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称 ...
- 蓝牙BLE实用教程(转载)
欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 设置 里的修改模板来改变新建文章的内容. 1.蓝牙BLE常见问答 Q: Smart Ready 和 Smart 以及传统蓝牙之间是什么关 ...
- 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体解释
转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50909410 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体 ...
- 深入浅出讲解低功耗蓝牙(BLE)协议栈
详解BLE连接建立过程https://www.cnblogs.com/iini/p/8972635.html 详解BLE 空中包格式—兼BLE Link layer协议解析https://www.cn ...
- 蓝牙BLE: ATT协议层中属性(Attribute)
ATT(Attribute Protocol)属性层是GATT和GAP的基础,它定义了BLE协议栈上层的数据结构和组织方式. 属性(Attribute)概念是ATT层的核心,ATT层定义了属性的内容, ...
- 蓝牙BLE: 蓝牙(BLE)协议栈
蓝牙协议是通信协议的一种,一般而言,我们把某个协议的实现代码称为协议栈(protocol stack),BLE协议栈就是实现低功耗蓝牙协议的代码,理解和掌握BLE协议是实现BLE协议栈的前提.当前的蓝 ...
- 蓝牙 BLE 协议学习: 001-BLE协议栈整体架构
背景 在深入BLE协议帧之前,我们先看一下BLE协议栈整体架构. 转载自:<深入浅出低功耗蓝牙(BLE)协议栈> 架构 如上图所述,要实现一个BLE应用,首先需要一个支持BLE射频的芯片, ...
随机推荐
- 《HelloGitHub》第 69 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...
- Causal Intervention for Weakly-Supervised Semantic Segmentation
目录 概 主要内容 普通的弱监督语义分割 因果模型 训练流程 代码 Zhang D., Zhang H., Tang J., Hua X. and Sun Q. Causal Intervention ...
- Chapter 3 Observational Studies
目录 概 3.1 3.2 Exchangeability 3.3 Positivity 3.4 Consistency First Second Fine Point 3.1 Identifiabil ...
- 3 - 基于ELK的ElasticSearch 7.8.x技术整理 - 高级篇( 偏理论 )
4.ES高级篇 4.1.集群部署 集群的意思:就是将多个节点归为一体罢了( 这个整体就有一个指定的名字了 ) 4.1.1.window中部署集群 - 了解即可 把下载好的window版的ES中的dat ...
- 编写Java程序_输入三个整数x,y,z,请把这三个数由小到大输出,请写出实现代码。(3种方法)
要求说明: 输入三个整数x,y,z,请把这三个数由小到大输出. 实现代码: 第1种方法: import java.util.Scanner; public class xyzMaxMin{ publi ...
- 《MySQL数据操作与查询》- 综合项目 - 学生管理系统
<MySQL数据操作与查询>综合项目需求 一.系统整体功能 维护学生信息.老师信息和成绩信息. 支持按多种条件组合查询学生信息和成绩信息. 二.系统的信息需求 一个班级有一个讲师一个班主任 ...
- 编写Java程序,以继承和多态思想模拟饲养员喂养不同动物的不同行为
返回本章节 返回作业目录 需求说明: 以继承和多态思想模拟饲养员喂养不同动物的不同行为 动物园有饲养员和动物,其中动物有老虎.马.猴子.羊.狼等. 饲养员对不同的动物有不同的喂养行为. 实现思路: 以 ...
- 抛弃go-micro,使用极简微服务框架Bull
简介 Bull是一款基于GO语言的极简微服务框架. 使用GRPC作为RPC协议,使用ETCD作为注册中心. 框架目前已经实现了服务注册.服务发现(客户端轮训)功能. 整体架构 代码地址 https:/ ...
- Ubuntu18.04升级内核后修改grub文件启动顺序
采坑:之前线上的服务器内核是4.15.0,后面有的服务跑不起来,说是要升级内核,于是就升级了,然后改了/etc/default/grub的启动顺序,改错了就启动不起来了,哈哈.后面多次尝试还是改成功了 ...
- js 动态设置键值对数组 ,类似于 java 的Map 类型
1.前言 我想设置一个数据 var json = {a1 :1 , a2 :2 , a3 :3 .....} 这样的动态数据 ,怎么写呢? 2.正确写法 var json = []; for ...