ESP32:蓝牙BLE控制M3508电机

先给各位朋友拜个年,祝大家新春快乐,事事顺利,身体健康啊!

还是熟悉的3508,内容概述:

  1. ESP32主控
  2. 蓝牙BLE通信
  3. 使用实时系统(FreeRTOS)
  4. 使用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上使用接收中断来更新电机反馈的方法是行不通的,为保证反馈量的实时性,有以下三种方法可以选择:

  1. 使用优先级合适的任务进行轮询
  2. 利用定时器中断回调进行轮询
  3. 利用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电机的更多相关文章

  1. 蓝牙BLE实用教程

    蓝牙BLE实用教程 Bluetooth BLE 欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 设置 里的修改模板来改变新建文章的内容. 1.蓝牙BLE常见问答 Q: Smart Re ...

  2. 蓝牙(BLE)应用框架接口设计和应用开发——以TI CC2541为例

    本文从功能需求的角度分析一般蓝牙BLE单芯片的应用框架(SDK Framework)的接口设计过程,并以TI CC2541为例说明BLE的应用开发方法. 一.应用框架(Framework) 我们熟知的 ...

  3. 深入浅出低功耗蓝牙(BLE)协议栈

    深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解蓝牙"连接"?如果蓝牙协议只有ATT没有GATT会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称 ...

  4. 蓝牙BLE实用教程(转载)

    欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 设置 里的修改模板来改变新建文章的内容. 1.蓝牙BLE常见问答 Q: Smart Ready 和 Smart 以及传统蓝牙之间是什么关 ...

  5. 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体解释

    转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50909410 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体 ...

  6. 深入浅出讲解低功耗蓝牙(BLE)协议栈

    详解BLE连接建立过程https://www.cnblogs.com/iini/p/8972635.html 详解BLE 空中包格式—兼BLE Link layer协议解析https://www.cn ...

  7. 蓝牙BLE: ATT协议层中属性(Attribute)

    ATT(Attribute Protocol)属性层是GATT和GAP的基础,它定义了BLE协议栈上层的数据结构和组织方式. 属性(Attribute)概念是ATT层的核心,ATT层定义了属性的内容, ...

  8. 蓝牙BLE: 蓝牙(BLE)协议栈

    蓝牙协议是通信协议的一种,一般而言,我们把某个协议的实现代码称为协议栈(protocol stack),BLE协议栈就是实现低功耗蓝牙协议的代码,理解和掌握BLE协议是实现BLE协议栈的前提.当前的蓝 ...

  9. 蓝牙 BLE 协议学习: 001-BLE协议栈整体架构

    背景 在深入BLE协议帧之前,我们先看一下BLE协议栈整体架构. 转载自:<深入浅出低功耗蓝牙(BLE)协议栈> 架构 如上图所述,要实现一个BLE应用,首先需要一个支持BLE射频的芯片, ...

随机推荐

  1. (gcd(a,b) == axorb)==>b = a-gcd(a,b)

    \((gcd(a,b) == axorb)==>b = a-gcd(a,b)\)的证明 \[(gcd(a,b) == axorb)==>b = a-gcd(a,b) \] 证明$$a-b& ...

  2. 「ARC096C」Everything on It

    Solution 容斥,钦定 \(i\) 个数 \(\leq 1\) 次. \[Ans=\sum_{i=0}^n (-1)^i\binom{n}{i}F(i) \] 其中 \(F(i)\) 表示有 \ ...

  3. salesforce零基础学习(一百一十)list button实现的一些有趣事情

    本篇参考: salesforce零基础学习(九十五)lightning out https://developer.salesforce.com/docs/component-library/docu ...

  4. Chapter 2 Randomized Experiments

    目录 概 2.1 Randomization 2.2 Conditional randomization 2.3 Standardization 2.4 Inverse probability wei ...

  5. 关于使用JupyterNotebook运行代码运行到一半会闪退的问题

    前几个星期使用Jupyter远程使用师兄的电脑跑了一段沐老师的代码学习,但是总是跑了一段就闪退,同时因为是远程桌面,远程桌面也被挤掉了. 具体表现就是:运行代码--表现正常,打印记录--远程桌面掉线- ...

  6. (五)React Ant Design Pro + .Net5 WebApi:后端环境搭建-Autofac注入+ 泛型仓储

    一. 简介 Autofac与.Net Core自带DI的区别,大佬级的文章数不胜数.我只是根据实际应用简单介绍(非常简单的那种) 1.批量注入,自带DI需要自己写循环反射注入,Autofac现成方法, ...

  7. .net core在linux下图片中文乱码

    不得不吐槽一下,.net core 2.2的System.Drawing在linux有很多坑,又是依赖libgdiplus,又是依赖gdiplus,依赖解决了又来了个中文乱码,怎的一声哀叹 这里做个笔 ...

  8. RabbitMQ使用 prefetch_count优化队列的消费,使用死信队列和延迟队列实现消息的定时重试,golang版本

    RabbitMQ 的优化 channel prefetch Count 死信队列 什么是死信队列 使用场景 代码实现 延迟队列 什么是延迟队列 使用场景 实现延迟队列的方式 Queue TTL Mes ...

  9. 正则验证&模态框

    在日常生活中,凡是需要表单验证的都会用到正则验证.下面拿一个简单的带有模态框的正则验证的小demo看一下     <style>         /* 遮罩层 */         .ma ...

  10. Python面向对象时最常见的3类方法

    为了节省读友的时间,先上结论(对于过程和细节感兴趣的读友可以继续往下阅读,一探究竟): [结论] 类中定义的方法类型 关键词 本质含义 如何定义 如何调用 使用场景举例 实例方法 一般无任何修饰时,默 ...