当前位置: 首页 > news >正文

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开发板是一款高性能、低功耗的微控制器&#xff0c;搭载了Espressif自家的RISC-V处理器。通过MicroPython&#xff0c;一种面向微控制器的精简版Python编程语言&#xff0c;开发者可以轻松地为ESP32-C3编写代码。MicroPython的ubluetooth库使得ESP32-C3能够通过蓝牙与各…...

leetcode hot100【LeetCode 35.搜索插入位置】java实现

LeetCode 35.搜索插入位置 题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用 O(log n) 的时间复杂度来实现。 示例 1: 输入: nums [1,3,5,6…...

我们要用平凡来诠释非凡

#孟晚舟香港中文大学演讲# #华为价值观念# #并非站在山顶才能被看见# #传递正确的价值观# #如果信仰有颜色&#xff0c;那一定是中国红# #送给自己的价值理念# 在信息大爆炸的时代&#xff0c;很多同学都希望尽可能的抓取更多的知识&#xff0c;尽可能的不要遗漏任何热点…...

synchronized和volatile区别

synchronized和volatile是Java并发编程中两种重要的同步机制&#xff0c;它们之间存在明显的区别。以下是对这两者的详细比较&#xff1a; 一、基本定义与作用 synchronized 是一个用于实现线程同步的关键字。可以用来锁住方法或代码块&#xff0c;从而确保在同一时刻只有一个…...

125.验证回文串-力扣(LeetCode)

题目&#xff1a; 解题思路&#xff1a; 首先进行移除非字母数字字符&#xff0c;并将大写字符转换为小写字符的操作。这个过程中&#xff0c;主要利用快慢指针的方式来进行移除操作&#xff0c;通过加32将大写字符转换为小写字符。完成后&#xff0c;将前一半的数据与后一半的…...

线程间通信:wait和notify

线程间通信&#xff1a;wait和notify 1、Object的wait和notify方法 Java中的Object类提供了两个重要的方法&#xff0c;用于线程间的通信和同步&#xff1a;wait()方法和notify()方法 wait()方法的定义 方法签名&#xff1a;public final void wait() throws InterruptedEx…...

风险识别和管理的工具

1.‌风险识别工具和根本原因识别在项目管理中非常重要&#xff0c;常用的工具包括 因果图根本原因识别RCA鱼骨图 因果图 因果图是一种图形工具&#xff0c;用于识别问题或风险的根本原因。它通过将问题或风险因素与可能的根本原因联系起来&#xff0c;帮助团队更深入地了解问…...

qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能

一、前言 主要功能如下&#xff1a; 1.实现文件夹的下载和删除&#xff0c;网上很多资料都是单独对某个路径的文件操作的&#xff0c;并不能对文件夹操作 2.实现目标机中含中文名称自动转码&#xff0c;有些系统编码方式不同&#xff0c;下载出来的文件会乱码 3.实现ftp功能…...

为何数据库推荐将IPv4地址存储为32位整数而非字符串?

目录 一、IPv4地址在数据库中的存储方式&#xff1f; 二、IPv4地址的存储方式比较 &#xff08;一&#xff09;字符串存储 vs 整数存储 &#xff08;二&#xff09;IPv4地址"192.168.1.8"说明 三、数据库推荐32位整数存储方式原理 四、存储方式对系统性能的影响…...

Mybatis框架之责任链模式 (Chain of Responsibility Pattern)

在 MyBatis 框架中&#xff0c;责任链模式 (Chain of Responsibility Pattern) 被广泛应用于多个功能模块中&#xff0c;例如 插件拦截器、SQL 执行流程中的拦截器链、动态 SQL 的解析与处理等。这种设计模式为 MyBatis 提供了高度的扩展性和灵活性&#xff0c;使其能够轻松应对…...

C++ Stack和Queue---单向守护与无尽等待:数据结构的诗意表达

公主请阅 容器适配器容器适配器的特点 栈和队列的模拟实现deque的介绍1. 内存开销较高2.随机访问性能略低于 vector3. 与指针或迭代器的兼容性r4. 不适合用于需要频繁中间插入和删除的场景5. 在特定平台上的实现不一致6. 缺乏shrink_to_fit支持总结 题目 priority_queue 优先级…...

深入理解Java包装类与泛型的应用

今天我将带领大家进入Java包装类和泛型应用的学习。 我的个人主页 我的Java-数据结构专栏 &#xff1a;Java-数据结构&#xff0c;希望能帮助到大家。 一、Java包装类基础 二、Java泛型基础 三、Java包装类与泛型的结合 四、Java泛型进阶 五、Java包装类与泛型实战 一、Ja…...

【机器学习chp4】特征工程

推荐文章1&#xff0c;其中详细分析了为什么L1正则化可以实现特征选择&#xff08;特征剔除&#xff09; 【王木头 L1、L2正则化】三个角度理解L1、L2正则化的本质-CSDN博客 推荐文章2&#xff0c;里面详细分析了奇异值分解 【线性代数】矩阵变换-CSDN博客 本文遗留问题&#…...

LeetCode螺旋矩阵

快一个月没刷题了&#xff0c;最近工作有些忙&#xff0c;今天闲下来两小时&#xff0c;刷一道 题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4…...

第十五届蓝桥杯JAVA的B组题目详情解析

(第一个填空太简单&#xff0c;就不写了,根本不用代码&#xff0c;直接excel计算) 目录 蓝桥杯第二个填空&#xff0c;类斐波那契循环数 蓝桥杯JAVA.b组第三题 -分布式队列(模拟) 食堂(蓝桥杯D题) ​编辑 星际旅行(Floyd佛洛依德) 其余的有点变态&#xff0c;感觉学了好像…...

在几分钟内将数据从 Oracle 迁移到 ClickHouse

ClickHouse 是一个开源的面向列的数据库管理系统。它在实时数据处理方面的出色性能显着增强了数据分析和业务洞察力。将数据从 Oracle 迁移到 ClickHouse 可以释放数据在决策中的力量&#xff0c;这是单独使用 Oracle 无法实现的。 本教程介绍如何使用 BladePipe 将数据从 Orac…...

ASP.NET MVC宠物商城系统

该系统采用B/S架构&#xff0c;使用C#编程语言进行开发&#xff0c;以ASP.NET MVC框架为基础&#xff0c;以Visual Studio 2019为开发工具&#xff0c;数据库采用SQL Server进行保存数据。系统主要功能包括登录注册、宠物展示、个人中心、我的订单、购物车、用户管理、宠物类别…...

完整http服务器

目录 背景目标描述技术特点开发环境WWW客户端浏览发展史服务端http发展史http分层概览 背景 http协议被广泛使用&#xff0c;从移动端&#xff0c;pc浏览器&#xff0c;http无疑是打开互联网应用窗口的重要协议&#xff0c;http在网络应用层中的地位不可撼动&#xff0c;是能…...

【专题】2024AIGC创新应用洞察报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38310 在科技日新月异的今天&#xff0c;人工智能领域正以前所未有的速度发展&#xff0c;AIGC&#xff08;人工智能生成内容&#xff09;成为其中最耀眼的明珠。从其应用场景的不断拓展&#xff0c;到对各行业的深刻变革&#xff0…...

形态学图像处理(Morphological Image Processing)

形态学图像处理(Morphological Image Processing) 前言 ‍ 本博客为个人总结数字图像处理一课所写&#xff0c;并给出适当的扩展和相应的demo。 写博客跟做 checkpoint​ 很像&#xff0c;毕竟个人还不能达到那种信手拈来的境界&#xff0c;忘了就是从零开始训练&#xff0…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...