esp32c3开发板通过micropython的ubluetooth库连蓝牙设备
ESP32-C3开发板是一款高性能、低功耗的微控制器,搭载了Espressif自家的RISC-V处理器。通过MicroPython,一种面向微控制器的精简版Python编程语言,开发者可以轻松地为ESP32-C3编写代码。MicroPython的ubluetooth库使得ESP32-C3能够通过蓝牙与各种设备进行通信。
使用ubluetooth库,ESP32-C3可以作为蓝牙主机或从机,实现与蓝牙设备的配对、连接和数据传输。开发者可以利用这个库来创建蓝牙低功耗(BLE)应用,如智能家居设备、健康监测设备等。通过简单的Python代码,ESP32-C3可以发送和接收蓝牙信号,实现设备间的无线通信。这使得ESP32-C3成为一个多功能、易于编程的蓝牙解决方案,适合各种物联网项目。
首先学习一下蓝牙通讯的机制
蓝牙通讯介绍
蓝牙通信是一种无线通信技术,用于在短距离内(通常在10米以内)连接不同的电子设备,如手机、平板电脑、笔记本电脑、耳机、扬声器等。蓝牙通信的机制主要包括以下几个方面:
1. 频率和调制
蓝牙通信使用2.4 GHz的工业、科学和医疗(ISM)频段。为了避免与其他无线设备的干扰,蓝牙采用了频率跳跃扩频(FHSS)技术。在通信过程中,蓝牙设备会在79个不同的频率通道上进行跳变,每秒跳变1600次,从而减少干扰和提高通信的稳定性。
2. 设备配对和连接
蓝牙设备之间的通信需要先进行配对和连接:
- 配对:两个设备通过交换密钥建立信任关系。配对过程通常需要用户确认,以确保安全性。
- 连接:配对成功后,设备可以建立稳定的连接,进行数据传输。
3. 主从设备
蓝牙通信采用主从模式:
- 主设备:控制连接和数据传输的设备,可以同时连接多个从设备。
- 从设备:被主设备控制的设备,通常只能连接一个主设备。
4. 服务和特征
蓝牙低功耗(BLE)协议中,设备通过服务和特征来交换数据:
- 服务:一组相关的特征集合,代表设备的某种功能或数据类型。
- 特征:具体的数据点,可以被读取、写入或通知。
5. 广播和扫描
- 广播:设备通过广播包发送信息,其他设备可以通过扫描接收这些信息。
- 扫描:设备监听周围的广播包,以发现可连接的蓝牙设备和服务。
6. 数据传输协议
蓝牙通信使用多种协议层来确保数据的可靠传输:
- 物理层(PHY):负责实际的无线信号传输。
- 链路层(LL):管理设备的连接状态、数据包的发送和接收。
- 主机控制接口(HCI):提供主机和控制器之间的通信接口。
- 逻辑链路控制和适配协议(L2CAP):负责数据的分段、重组和错误控制。
- 属性协议(ATT):在BLE中用于服务的发现和数据的读写操作。
7. 安全机制
蓝牙通信包括多种安全措施:
- 加密:使用AES加密算法保护数据传输。
- 认证:通过配对过程中的PIN码或OOB(Out of Band)数据进行设备身份验证。
- 授权:确保只有经过授权的设备才能访问特定的服务和特征。
8. 功耗管理
特别是对于BLE,功耗管理是一个关键因素:
- 低功耗模式:设备可以在不需要通信时进入休眠状态,减少能量消耗。
- 连接间隔:调整主从设备之间的连接间隔,平衡数据传输速率和能耗。
总之,蓝牙通信通过一系列复杂的协议和技术,实现了设备间的短距离、低功耗、安全的无线数据传输。
实践
准备好esp32c3开发板,进入micropython交互环境,输入如下代码:
蓝牙测试代码1
import ubluetooth
import utime
import machineclass BLEServer:def __init__(self):self.ble = ubluetooth.BLE()self.ble.active(True)self.ble.irq(self.ble_irq)self.register_service()self.connected = Falsedef register_service(self):# 创建一个UUID为"12345678-1234-5678-1234-56789abcdef0"的服务service_uuid = ubluetooth.UUID('12345678-1234-5678-1234-56789abcdef0')service = self.ble.gatts_register_services([(service_uuid, ((ubluetooth.UUID('12345678-1234-5678-1234-56789abcdef1'), ubluetooth.FLAG_READ),))])self.service_handle = service[0]self.char_handle = service[1]# 设置Characteristic的初始值self.ble.gatts_write(self.char_handle, b'Hello, BLE!')def ble_irq(self, event, data):if event == 1:# Central设备连接self.connected = Trueprint("Device connected")elif event == 2:# Central设备断开连接self.connected = Falseprint("Device disconnected")# 重置广告,以便再次被发现self.ble.gap_advertise(100, adv_data=self.ble.config('mac') + b'\x02\x01\x06' + b'\x11\x07' + ubluetooth.UUID('12345678-1234-5678-1234-56789abcdef0').bytes)def start_advertising(self):# 开始广告,以便Central设备可以发现这个Peripheralself.ble.gap_advertise(100, adv_data=self.ble.config('mac') + b'\x02\x01\x06' + b'\x11\x07' + ubluetooth.UUID('12345678-1234-5678-1234-56789abcdef0').bytes)def main():ble_server = BLEServer()ble_server.start_advertising()while True:if ble_server.connected:# 可以在这里添加逻辑来处理连接状态passutime.sleep(1)if __name__ == "__main__":main()
但是这段代码有问题,
蓝牙测试代码2
后来用了这段文心生成的代码:
# 文心的例子
import ubluetooth
import machine
import time# 初始化蓝牙
ble = ubluetooth.BLE()
ble.active(True)# 定义服务UUID
# SERVICE_UUID = '12345678-1234-5678-1234-56789abcdef0'
# CHARACTERISTIC_UUID = '12345678-1234-5678-1234-56789abcdef1'# 创建BLE服务和特性
def ble_init():# services = (# (# ubluetooth.UUID(SERVICE_UUID),# (# (ubluetooth.UUID(CHARACTERISTIC_UUID), ubluetooth.FLAG_NOTIFY | ubluetooth.FLAG_READ),# ),# ),# )# ((_srv_handle, _char_handle), ) = ble.gatts_register_services(services)NUS_UUID = 'AE25A5C1-4601-143C-12BB-8BC45A18749C'RX_UUID = 'AE25A5C2-4601-143C-12BB-8BC45A18749C'TX_UUID = 'AE25A5C3-4601-143C-12BB-8BC45A18749C'BLE_NUS = ubluetooth.UUID(NUS_UUID)BLE_RX = (ubluetooth.UUID(RX_UUID), ubluetooth.FLAG_WRITE)# BLE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY)ELE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY | ubluetooth.FLAG_READ)BLE_UART = (BLE_NUS, (BLE_TX, BLE_RX,))SERVICES = (BLE_UART, )((tx, rx),) = ble.gatts_register_services(SERVICES)# 获取特性的句柄以发送通知# char_handle = _char_handle[0]char_handle = tx# 启动广播ble.gap_advertise(100, bytearray(b'ESP32-C3 BLE Test'))return char_handle# BLE中断处理函数
def ble_irq(event, data):if event == ubluetooth.IRQ_GAP_CONNECTED:print("BLE device connected")elif event == ubluetooth.IRQ_GAP_DISCONNECTED:print("BLE device disconnected")# 可以选择在这里重新开始广播# 注册BLE中断处理函数
ble.irq(ble_irq)# 初始化BLE并获取特性句柄
char_handle = ble_init()# 发送通知的数据
notification_data = b'Hello, ESP32-C3 BLE!'
ble.gatts_notify(char_handle, notification_data)
print("Notification sent:", notification_data)# try:
# while True:
# # 检查是否有连接的设备
# if ble.gatts_get_conn_handle():
# # 发送通知
# ble.gatts_notify(char_handle, notification_data)
# print("Notification sent:", notification_data)# # 等待一段时间再发送下一次通知
# time.sleep(5)
# except KeyboardInterrupt:
# print("Exiting")
# finally:
# # 清理BLE资源
# ble.active(False)
# machine.deepsleep() # 可选:使设备进入深度睡眠模式以节省电源
手机安装蓝牙测试app:BLE调试助手
在华为手机的“应用市场”,查找“BLE调试助手”,安装该app应用。
打开“BLE调试助手”,找到开发板的蓝牙。小窍门,开发板的蓝牙,一般没有诸如“oppo”、小米、amazfit等字样,而且如果手机和开发板距离较近,信号会比较强,比如-50db左右
蓝牙通讯测试
在开发板发送数据,比如:
notification_data = b'Hello, ESP32-C3 BLE!'
ble.gatts_notify(char_handle, notification_data)notification_data = b'123456'
ble.gatts_notify(char_handle, notification_data)
这段代码可以让esp32c3发送信息,然后用手机app“BLE调试助手”接收,接收信息截图
最后六位数字,31-36,就是发送的数字1-6的ASCII编码。
注意:不知道是否没有清空缓冲的原因,每点一次“接收”,都会再接收最后一次的信息。比如里面的连续多次31、32 ,就是测试时发送了“12”两个字母,但是点了多次接收导致的。
调试
这句有报错:>>> char_handle = ble_init()
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 10, in ble_init ValueError: need more than 1 values to unpack
按照一言的提示,查看封包情况:
services = ((ubluetooth.UUID(SERVICE_UUID),((ubluetooth.UUID(CHARACTERISTIC_UUID), ubluetooth.FLAG_NOTIFY | ubluetooth.FLAG_READ),),),
)result = ble.gatts_register_services(services)
print(result) # 打印结果以查看结构
输出:
((16,),)
感觉这个封包有问题啊,调整一下:
services = ((ubluetooth.UUID(SERVICE_UUID),((ubluetooth.UUID(CHARACTERISTIC_UUID), ubluetooth.FLAG_NOTIFY | ubluetooth.FLAG_READ),),),)((_srv_handle), ((_char_handle), _ ),), ) = ble.gatts_register_services(services)
封包和解包这里太头疼了,直接用下面的代码:
NUS_UUID = 'AE25A5C1-4601-143C-12BB-8BC45A18749C'RX_UUID = 'AE25A5C2-4601-143C-12BB-8BC45A18749C'TX_UUID = 'AE25A5C3-4601-143C-12BB-8BC45A18749C'BLE_NUS = ubluetooth.UUID(NUS_UUID)BLE_RX = (ubluetooth.UUID(RX_UUID), ubluetooth.FLAG_WRITE)# BLE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY)ELE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY | ubluetooth.FLAG_READ)BLE_UART = (BLE_NUS, (BLE_TX, BLE_RX,))SERVICES = (BLE_UART, )((tx, rx),) = ble.gatts_register_services(SERVICES)# 获取特性的句柄以发送通知# char_handle = _char_handle[0]char_handle = tx
相关文章:
esp32c3开发板通过micropython的ubluetooth库连蓝牙设备
ESP32-C3开发板是一款高性能、低功耗的微控制器,搭载了Espressif自家的RISC-V处理器。通过MicroPython,一种面向微控制器的精简版Python编程语言,开发者可以轻松地为ESP32-C3编写代码。MicroPython的ubluetooth库使得ESP32-C3能够通过蓝牙与各…...
leetcode hot100【LeetCode 35.搜索插入位置】java实现
LeetCode 35.搜索插入位置 题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用 O(log n) 的时间复杂度来实现。 示例 1: 输入: nums [1,3,5,6…...
我们要用平凡来诠释非凡
#孟晚舟香港中文大学演讲# #华为价值观念# #并非站在山顶才能被看见# #传递正确的价值观# #如果信仰有颜色,那一定是中国红# #送给自己的价值理念# 在信息大爆炸的时代,很多同学都希望尽可能的抓取更多的知识,尽可能的不要遗漏任何热点…...
synchronized和volatile区别
synchronized和volatile是Java并发编程中两种重要的同步机制,它们之间存在明显的区别。以下是对这两者的详细比较: 一、基本定义与作用 synchronized 是一个用于实现线程同步的关键字。可以用来锁住方法或代码块,从而确保在同一时刻只有一个…...
125.验证回文串-力扣(LeetCode)
题目: 解题思路: 首先进行移除非字母数字字符,并将大写字符转换为小写字符的操作。这个过程中,主要利用快慢指针的方式来进行移除操作,通过加32将大写字符转换为小写字符。完成后,将前一半的数据与后一半的…...
线程间通信:wait和notify
线程间通信:wait和notify 1、Object的wait和notify方法 Java中的Object类提供了两个重要的方法,用于线程间的通信和同步:wait()方法和notify()方法 wait()方法的定义 方法签名:public final void wait() throws InterruptedEx…...
风险识别和管理的工具
1.风险识别工具和根本原因识别在项目管理中非常重要,常用的工具包括 因果图根本原因识别RCA鱼骨图 因果图 因果图是一种图形工具,用于识别问题或风险的根本原因。它通过将问题或风险因素与可能的根本原因联系起来,帮助团队更深入地了解问…...
qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能
一、前言 主要功能如下: 1.实现文件夹的下载和删除,网上很多资料都是单独对某个路径的文件操作的,并不能对文件夹操作 2.实现目标机中含中文名称自动转码,有些系统编码方式不同,下载出来的文件会乱码 3.实现ftp功能…...
为何数据库推荐将IPv4地址存储为32位整数而非字符串?
目录 一、IPv4地址在数据库中的存储方式? 二、IPv4地址的存储方式比较 (一)字符串存储 vs 整数存储 (二)IPv4地址"192.168.1.8"说明 三、数据库推荐32位整数存储方式原理 四、存储方式对系统性能的影响…...
Mybatis框架之责任链模式 (Chain of Responsibility Pattern)
在 MyBatis 框架中,责任链模式 (Chain of Responsibility Pattern) 被广泛应用于多个功能模块中,例如 插件拦截器、SQL 执行流程中的拦截器链、动态 SQL 的解析与处理等。这种设计模式为 MyBatis 提供了高度的扩展性和灵活性,使其能够轻松应对…...
C++ Stack和Queue---单向守护与无尽等待:数据结构的诗意表达
公主请阅 容器适配器容器适配器的特点 栈和队列的模拟实现deque的介绍1. 内存开销较高2.随机访问性能略低于 vector3. 与指针或迭代器的兼容性r4. 不适合用于需要频繁中间插入和删除的场景5. 在特定平台上的实现不一致6. 缺乏shrink_to_fit支持总结 题目 priority_queue 优先级…...
深入理解Java包装类与泛型的应用
今天我将带领大家进入Java包装类和泛型应用的学习。 我的个人主页 我的Java-数据结构专栏 :Java-数据结构,希望能帮助到大家。 一、Java包装类基础 二、Java泛型基础 三、Java包装类与泛型的结合 四、Java泛型进阶 五、Java包装类与泛型实战 一、Ja…...
【机器学习chp4】特征工程
推荐文章1,其中详细分析了为什么L1正则化可以实现特征选择(特征剔除) 【王木头 L1、L2正则化】三个角度理解L1、L2正则化的本质-CSDN博客 推荐文章2,里面详细分析了奇异值分解 【线性代数】矩阵变换-CSDN博客 本文遗留问题&#…...
LeetCode螺旋矩阵
快一个月没刷题了,最近工作有些忙,今天闲下来两小时,刷一道 题目描述 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4…...
第十五届蓝桥杯JAVA的B组题目详情解析
(第一个填空太简单,就不写了,根本不用代码,直接excel计算) 目录 蓝桥杯第二个填空,类斐波那契循环数 蓝桥杯JAVA.b组第三题 -分布式队列(模拟) 食堂(蓝桥杯D题) 编辑 星际旅行(Floyd佛洛依德) 其余的有点变态,感觉学了好像…...
在几分钟内将数据从 Oracle 迁移到 ClickHouse
ClickHouse 是一个开源的面向列的数据库管理系统。它在实时数据处理方面的出色性能显着增强了数据分析和业务洞察力。将数据从 Oracle 迁移到 ClickHouse 可以释放数据在决策中的力量,这是单独使用 Oracle 无法实现的。 本教程介绍如何使用 BladePipe 将数据从 Orac…...
ASP.NET MVC宠物商城系统
该系统采用B/S架构,使用C#编程语言进行开发,以ASP.NET MVC框架为基础,以Visual Studio 2019为开发工具,数据库采用SQL Server进行保存数据。系统主要功能包括登录注册、宠物展示、个人中心、我的订单、购物车、用户管理、宠物类别…...
完整http服务器
目录 背景目标描述技术特点开发环境WWW客户端浏览发展史服务端http发展史http分层概览 背景 http协议被广泛使用,从移动端,pc浏览器,http无疑是打开互联网应用窗口的重要协议,http在网络应用层中的地位不可撼动,是能…...
【专题】2024AIGC创新应用洞察报告汇总PDF洞察(附原数据表)
原文链接:https://tecdat.cn/?p38310 在科技日新月异的今天,人工智能领域正以前所未有的速度发展,AIGC(人工智能生成内容)成为其中最耀眼的明珠。从其应用场景的不断拓展,到对各行业的深刻变革࿰…...
形态学图像处理(Morphological Image Processing)
形态学图像处理(Morphological Image Processing) 前言 本博客为个人总结数字图像处理一课所写,并给出适当的扩展和相应的demo。 写博客跟做 checkpoint 很像,毕竟个人还不能达到那种信手拈来的境界,忘了就是从零开始训练࿰…...
【IDER、PyCharm】免费AI编程工具完整教程:ChatGPT Free - Support Key call AI GPT-o1 Claude3.5
文章目录 CodeMoss 简介CodeMoss 的模型集成如何安装和配置 CodeMossIDER 插件安装步骤 CodeMoss 的实战使用AI 问答功能代码优化与解释优化这段代码解释这段代码 文件上传与对话联网查询与 GPT 助手联网查询GPT 助手 提升开发效率的最佳实践结语更多文献 CodeMoss 简介 CodeM…...
C++11的一些实用特性
1.统一的列表初始化 在C98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。 //统一的列表初始化 struct Date {int year;int month;int day; };void test1() {Date d1 { 2024,11,14 };int array1[] { 1, 2, 3, 4, 5 };int array2[5] { …...
23种设计模式-观察者(Observer)设计模式
文章目录 一.什么是观察者模式?二.观察者模式的结构三.观察者模式的应用场景四.观察者模式的优缺点五.观察者模式的实现(C示例)六.观察者模式的实现(JAVA示例)七.代码解释八.总结 类图: 观察者设计模式类图…...
【CUDA】Branch Divergence and Unrolling Loop
目录 一、避免分支发散 1.1 并行规约问题 1.2 并行规约中的发散 二、UNrolling Loops 一、避免分支发散 控制流有时依赖于 thread 索引。同一个warp中,一个条件分支可能导致性能很差。通过重新组织数据获取模式可以减少或避免 warp divergence。具体问题查看下…...
深度学习:卷积神经网络的计算复杂度,顺序操作,最大路径长度
卷积层的计算复杂度 在深度学习中,卷积层的计算复杂度主要取决于卷积核的大小、输入和输出的通道数量、以及输入序列的长度。具体来说,卷积层的计算复杂度可以通过以下几个因素来计算: 卷积核大小 k:卷积核的大小决定了每次卷积操…...
springboot 配置文件中 multipart.max-file-size 各个版本的写法
由于springboot具有几个版本,不同版本对于文件上传最大限制的配置也有所不同。 所以要注意springboot本身的版本,不然会一直报错 在springboot1.3版本中: multipart.maxFileSize在springboot1.4与springboot1.5版本中: spring…...
linux 中mysql查看慢日志
1、到mysql容器,先登录到数据库,查看是否开启 mysql -h 127.0.0.1 -uroot -p SHOW VARIABLES LIKE slow_query_log; 2、如果没有开启,需要先开启 set global slow_query_log ON; 3、查看慢日志文件 SHOW VARIABLES LIKE slow_query_log…...
单片机的基本组成与工作原理
单片机(Microcontroller Unit, MCU)是一种将计算机的主要部分集成在一个芯片上的小型计算机系统。它通常包括中央处理器(CPU)、存储器(Memory)、输入输出接口(I/O Ports)、定时器/计…...
智慧隧道和智慧交通
通过引入先进的物联网技术,将各种硬件设备如传感器、摄像头、控制系统等有效地连接并管理起来,以实现道路安全和交通流畅的目标。这些设备将能够实时监控和控制隧道内的各种设备和系统,从而提高道路安全、提升驾驶体验并降低管理成本。 在这个…...
List、Set、Map详解和区别
在 Java 中,List、Set、Map是常用的集合类型,它们各自具有不同的特点和用途,以下是对它们的详细介绍及区别分析: List(列表) 特点: 有序性:List中的元素是有序的,即元素…...
西安市住房和城乡建设局门户网站/站长网站优化公司
实体类中包含对象属性从后台传回到前台表单,后台提示错误: at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183) at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsFiel…...
网站被提示危险网站/百度手机助手下载安卓
有的朋友长时间没有使用电脑,在使用的时候可能会遇到0x80073712,然而自己对于0x80073712的处理方法又不太了解,就感觉0x80073712非常棘手,下面小编为大家介绍一下0x80073712的处理方法:window10更新出错 代码 0x800737…...
模板网站官网/会计培训班一般收费多少
相关题目与解析2017年6月1日,()开始施行。A.中华人民共和国计算机信息系统安全保护条例B.计算机信息系统国际物理安全是计算机信息系统安全的保障,保证计算机信息系统各种设备的物理安全是保障整个网络系统安全的前提。()计算机信息系统的安全保护&#…...
网站的搜索功能怎么做/大连百度关键词优化
Redis6 10.3)AOF(Append Only File) 10.3.1)AOF简介 以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件…...
互动营销型网站建设/电商线上推广渠道
HashMap中阈值的设计1.HashMap的长度为什么必须是2的次幂?2.加载因子为什么是0.75?3.处理冲突的几种方法4.equals()和hashCode()在HashMap中的重要性1.HashMap的长度为什么必须是2的次幂? 为了实现一个尽量分布均匀的hash函数,利…...
徐州有哪些做网站/平台推广引流怎么做
elasticsearch集群,有时候可能需要修改配置,增加硬盘,扩展内存等操作,需要对节点进行维护升级。但是业务不能停,如果直接kill掉节点,可能导致数据丢失。而且集群会认为该节点挂掉了,就开始转移数…...